azure

package
v0.0.0-...-01a8556 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 25, 2024 License: Apache-2.0 Imports: 27 Imported by: 0

README

Azure Plugin

Introduction

This README provides guidance on adding new functions to the plugin and outlines the testing practices, including unit and integration testing.

Table of Contents

Getting Started

Local Development and Testing

If you're not working within the dev container, here are the steps to set up your local environment for testing and validation:

  1. Install Azure CLI: Ensure you have the Azure CLI installed by following the instructions in this guide. After installation, run az login to authenticate with your Azure account.

  2. Valid Azure Subscription: If you're testing the azure functions locally to ensure your code's functionality, make sure you have access to a valid Azure subscription. This subscription is necessary for authenticating your local testing with Azure services. It's important to note that most requests might require a valid resource ID, which typically includes a subscription ID and a resource group name. As the current assumption is that the resource group already exists, ensure that you have a valid subscription ID and that the necessary resource group has been created prior to running your testing code.

For local testing purposes, consider adding a main function within the plugin.go file. This can be used to execute your server logic independently and validate its behavior. Here's an example of how you can do this:

  1. Add a main function in plugin.go:

    func main() {
        c := context.Background()
        s := azurePluginServer{
            	orchestratorServerAddr: orchestratorServerAddr,
     	      azureCredentialGetter:  &AzureCredentialGetter{},
        }
    
        // Call the function you want to test
        resp, err := s.AddPermitListRules(c, &paragliderpb.PermitList{
            // Define the input parameters here
        })
    
        if err != nil {
            // Handle errors
        }
    
        // Use resp as needed
    }
    
    
  2. Run the server:

    go run .\pkg\azure\plugin.go .\pkg\azure\sdk_handler.go
    

Package Structure

The azure contains essential components and functionalities related to Azure integration. Within the azure package, you will find the following key files:

  • plugin.go: Serving as the primary entry point for the project, this file implements the core Paraglider API functions. It acts as the interface between the external API requests and the underlying logic within the azure package.
  • sdk_handler.go: This file encapsulates the communication with Azure Resource Manager (ARM) for managing Azure resources. It consolidates the actual server requests made to Azure, providing a streamlined approach for resource management.
  • integration_test.go: This file contains integration tests specifically focused on Azure functionality. It validates the plugin funcitonality and the server integration with azure services.
  • plugin_test.go: Dedicated to unit tests, this file ensures the reliability and correctness of the server implementation within the azure package.
  • sdk_handler_test.go: Focused solely on unit tests, this file tests the sdk_handler functionalities. It verifies that the the responses are handled appropriately by redirecting ARM requests to a fake server.

Adding a New Paraglider API fucntion to the Plugin

Follow these steps to ensure consistent structure and seamless integration.

  1. Open plugin.go:

    • Add a new function following the same structure as specified in Paraglider APIs. For example:
      func (s *azurePluginServer) GetPermitList(ctx context.Context, input *paragliderpb.GetPermitListRequest) (*paragliderpb.GetPermitListResponse, error) {
          // Implementation here
      }
      
  2. Initialize the Handler:

    • In your new API function, you might need to initialize the sdk handler. If the API requires specific information like subscription ID or resource group name, extract these details from the request and set up the handler. Example:
      resourceIdInfo, err := getResourceIDInfo(input.ResourceID)
      if err != nil {
          logger.Log.Printf("An error occurred while getting resource ID info: %+v", err)
          return nil, err
      }
      err = s.setupAzureHandler(resourceIdInfo)
      if err != nil {
          return nil, err
      }
      
  3. Handling ARM Requests:

    • If your new API needs to make ARM requests, check if the required functionality is already implemented in sdk_handler.go. If not, add a new function in the handler that wraps the Azure request. Call this new function from the plugin file. Any helper functionalities relevant only to Paraglider and the server can remain in plugin.
  4. Update Testing:

    • In plugin_test.go, provide a mocked implementation of your new handler function for testing purposes. For instance:
      func (m *mockAzureSDKHandler) NewHandlerFunction(ctx context.Context, args ...) (*armType, error) {
          // Mock implementation here
      }
      
    • Ensure that your mock function implements the corresponding AzureSDKHandler method signature.

Testing

When adding new functionality to the azure package, it's crucial to ensure that the code is thoroughly tested to maintain reliability and stability. The testing process is divided into unit tests and integration tests.

Unit Tests

All tests use a fake server as a replacement for actual Azure endpoints. The implementation can be found in test_utils.go.

  • Fake Server Setup:
    • If your new function involves making Azure requests, ensure that the fake server in test_utils.go is aware of these requests.
    • If the URL is already present but for a different request method, add your request method.
    • If your new request requires new state, add it to the fakeServerState struct.

Keep in mind that the fake server should be kept as minimal as possible. Tests should not depend heavily on the logic within it.

Integration Testing

Integration tests play a critical role in ensuring that the extended functionalities of the azure package interact seamlessly and consistently with the Azure environment. These tests create an isolated environment for each run by provisioning a dedicated resource group. The teardown process involves removing the resource group, thus effectively eliminating any resources that were created during testing.

Setup and Environment Variables
  1. Isolated Resource Group: Each integration test run creates a dedicated resource group to maintain an isolated environment. The resource group's name is prefixed by the GitHub run number when running in a GitHub Action workflow. For local testing, the run number is empty.
  2. INVISINETS_AZURE_SUBSCRIPTION_ID: When running tests locally, ensure that the environment variable INVISINETS_AZURE_SUBSCRIPTION_ID is set with your Azure subscription ID. For GitHub Actions, this subscription ID should be set as a secret in the repository.
Integration Test Function

The primary integration test function, TestAzurePluginIntegration, should orchestrate various scenarios to validate the extended features of the azure package. This function serves as a container for subtests, each targeting specific scenarios or functionalities. While this structure enables a single resource group for all subtests, you may need to refactor it when different scenarios demand separate resource groups to prevent interference between tests.

Adjusting Timeout for Local Testing

When running integration tests locally, you should adjust the test timeout to ensure completion within the expected time frame. If using tools like VSCode, the default timeout might be set to 30 seconds. In this context, consider increasing the timeout to accommodate the longer execution time of integration tests. A timeout of around 10 minutes (10m) can be a reasonable starting point.

By conducting thorough integration tests with dedicated resource groups, controlled environments, and comprehensive scenarios, you can confidently validate the robustness and effectiveness of your extended azure package functionalities.

Documentation

Index

Constants

View Source
const (
	VirtualMachineResourceType = "Microsoft.Compute/virtualMachines"
)

Variables

This section is empty.

Functions

func GetAndCheckResourceState

func GetAndCheckResourceState(ctx context.Context, handler *AzureSDKHandler, resourceID string, namespace string) (*resourceNetworkInfo, error)

Gets the resource and returns relevant networking state. Also checks that the resource is in the correct namespace.

func GetAzureSubscriptionId

func GetAzureSubscriptionId() string

Gets subscription ID defined in environment variable

func GetLastSegment

func GetLastSegment(ID string) (string, error)

getLastSegment returns the last segment of a resource ID.

func GetNetworkInfoFromResource

func GetNetworkInfoFromResource(ctx context.Context, handler *AzureSDKHandler, resourceID string) (*resourceNetworkInfo, error)

Gets the resource and returns relevant networking state

func GetResourceInfoFromResourceDesc

func GetResourceInfoFromResourceDesc(ctx context.Context, resource *paragliderpb.CreateResourceRequest) (*resourceInfo, error)

Gets basic resource information from the description Returns the resource name, ID, location, and whether the resource will require its own subnet in a struct

func GetTestVmParameters

func GetTestVmParameters(location string) armcompute.VirtualMachine

func GetVmIpAddress

func GetVmIpAddress(vmId string) (string, error)

TODO @seankimkdy: figure out how to merge this with Azure SDK handler

func InitializeServer

func InitializeServer(orchestratorAddr string) *azurePluginServer

func ReadAndProvisionResource

func ReadAndProvisionResource(ctx context.Context, resource *paragliderpb.CreateResourceRequest, subnet *armnetwork.Subnet, resourceInfo *ResourceIDInfo, sdkHandler *AzureSDKHandler, additionalAddressSpaces []string) (string, error)

Reads the resource description and provisions the resource with the given subnet

func RunPingConnectivityCheck

func RunPingConnectivityCheck(sourceVmResourceID string, destinationIPAddress string) (bool, error)

func Setup

func Setup(port int, orchestratorServerAddr string) *azurePluginServer

func SetupAzureTesting

func SetupAzureTesting(subscriptionId string, testName string) string

func SetupFakeAzureServer

func SetupFakeAzureServer(t *testing.T, fakeServerState *fakeServerState) (fakeServer *httptest.Server, ctx context.Context)

Sets up fake http server

func Teardown

func Teardown(fakeServer *httptest.Server)

func TeardownAzureTesting

func TeardownAzureTesting(subscriptionId string, resourceGroupName string)

Types

type AzureCredentialGetter

type AzureCredentialGetter struct {
	IAzureCredentialGetter
}

func (*AzureCredentialGetter) GetAzureCredentials

func (g *AzureCredentialGetter) GetAzureCredentials() (azcore.TokenCredential, error)

GetAzureCredentials returns an Azure credential. it uses the azidentity.NewDefaultAzureCredential() function to create a new Azure credential.

type AzureResourceHandler

type AzureResourceHandler interface {
	// contains filtered or unexported methods
}

Interface that must be implemented for a resource to be supported

type AzureSDKHandler

type AzureSDKHandler struct {
	// contains filtered or unexported fields
}

func (*AzureSDKHandler) AddSubnetToParagliderVnet

func (h *AzureSDKHandler) AddSubnetToParagliderVnet(ctx context.Context, namespace string, vnetName string, subnetName string, orchestratorAddr string) (*armnetwork.Subnet, error)

AddSubnetToParagliderVnet adds a subnet to an paraglider vnet

func (*AzureSDKHandler) AssociateNSGWithSubnet

func (h *AzureSDKHandler) AssociateNSGWithSubnet(ctx context.Context, subnetID string, nsgID string) error

func (*AzureSDKHandler) CreateAKSCluster

func (h *AzureSDKHandler) CreateAKSCluster(ctx context.Context, parameters armcontainerservice.ManagedCluster, clusterName string) (*armcontainerservice.ManagedCluster, error)

CreateAKSCluster creates a new AKS cluster with the given parameters and name

func (*AzureSDKHandler) CreateLocalNetworkGateway

func (h *AzureSDKHandler) CreateLocalNetworkGateway(ctx context.Context, name string, parameters armnetwork.LocalNetworkGateway) (*armnetwork.LocalNetworkGateway, error)

func (*AzureSDKHandler) CreateNetworkInterface

func (h *AzureSDKHandler) CreateNetworkInterface(ctx context.Context, subnetID string, location string, nicName string) (*armnetwork.Interface, error)

CreateNetworkInterface creates a new network interface with a dynamic private IP address

func (*AzureSDKHandler) CreateOrUpdateVirtualNetworkGateway

func (h *AzureSDKHandler) CreateOrUpdateVirtualNetworkGateway(ctx context.Context, name string, parameters armnetwork.VirtualNetworkGateway) (*armnetwork.VirtualNetworkGateway, error)

func (*AzureSDKHandler) CreateOrUpdateVirtualNetworkPeering

func (h *AzureSDKHandler) CreateOrUpdateVirtualNetworkPeering(ctx context.Context, virtualNetworkName string, virtualNetworkPeeringName string, parameters armnetwork.VirtualNetworkPeering) (*armnetwork.VirtualNetworkPeering, error)

func (*AzureSDKHandler) CreateOrUpdateVnetPeeringRemoteGateway

func (h *AzureSDKHandler) CreateOrUpdateVnetPeeringRemoteGateway(ctx context.Context, vnetName string, gatewayVnetName string, vnetToGatewayVnetPeering *armnetwork.VirtualNetworkPeering, gatewayVnetToVnetPeering *armnetwork.VirtualNetworkPeering) error

Creates (if not exists) or updates vnet peering to use remote gateway

func (*AzureSDKHandler) CreateParagliderVirtualNetwork

func (h *AzureSDKHandler) CreateParagliderVirtualNetwork(ctx context.Context, location string, vnetName string, addressSpace string) (*armnetwork.VirtualNetwork, error)

CreateParagliderVirtualNetwork creates a new paraglider virtual network with a default subnet with the same address space as the vnet

func (*AzureSDKHandler) CreatePublicIPAddress

func (h *AzureSDKHandler) CreatePublicIPAddress(ctx context.Context, name string, parameters armnetwork.PublicIPAddress) (*armnetwork.PublicIPAddress, error)

func (*AzureSDKHandler) CreateSecurityGroup

func (h *AzureSDKHandler) CreateSecurityGroup(ctx context.Context, resourceName string, location string, allowedCIDRs map[string]string) (*armnetwork.SecurityGroup, error)

func (*AzureSDKHandler) CreateSecurityRule

func (h *AzureSDKHandler) CreateSecurityRule(ctx context.Context, rule *paragliderpb.PermitListRule, nsgName string, ruleName string, resourceIpAddress string, priority int32) (*armnetwork.SecurityRule, error)

GetPermitListRuleFromNSGRulecurityRule creates a new security rule in a network security group (NSG).

func (*AzureSDKHandler) CreateSubnet

func (h *AzureSDKHandler) CreateSubnet(ctx context.Context, virtualNetworkName string, subnetName string, parameters armnetwork.Subnet) (*armnetwork.Subnet, error)

func (*AzureSDKHandler) CreateVirtualMachine

func (h *AzureSDKHandler) CreateVirtualMachine(ctx context.Context, parameters armcompute.VirtualMachine, vmName string) (*armcompute.VirtualMachine, error)

CreateVirtualMachine creates a new virtual machine with the given parameters and name

func (*AzureSDKHandler) CreateVirtualNetwork

func (h *AzureSDKHandler) CreateVirtualNetwork(ctx context.Context, name string, parameters armnetwork.VirtualNetwork) (*armnetwork.VirtualNetwork, error)

func (*AzureSDKHandler) CreateVirtualNetworkGatewayConnection

func (h *AzureSDKHandler) CreateVirtualNetworkGatewayConnection(ctx context.Context, name string, parameters armnetwork.VirtualNetworkGatewayConnection) (*armnetwork.VirtualNetworkGatewayConnection, error)

func (*AzureSDKHandler) CreateVnetPeering

func (h *AzureSDKHandler) CreateVnetPeering(ctx context.Context, vnet1Name string, vnet2Name string) error

Create Vnet Peering between two VNets, this is important in the case of a multi-region deployment For peering to work, two peering links must be created. By selecting remote virtual network, Azure will create both peering links.

func (*AzureSDKHandler) CreateVnetPeeringOneWay

func (h *AzureSDKHandler) CreateVnetPeeringOneWay(ctx context.Context, vnet1Name string, vnet2Name string, vnet2SubscriptionID string, vnet2ResourceGroupName string) error

Temporarily needed method to deal with the mess of AzureSDKHandlers TODO @seankimkdy: remove once AzureSDKHandler is no longer a mess

func (*AzureSDKHandler) DeleteSecurityRule

func (h *AzureSDKHandler) DeleteSecurityRule(ctx context.Context, nsgName string, ruleName string) error

DeleteSecurityRule deletes a security rule from a network security group (NSG).

func (*AzureSDKHandler) GetLocalNetworkGateway

func (h *AzureSDKHandler) GetLocalNetworkGateway(ctx context.Context, name string) (*armnetwork.LocalNetworkGateway, error)

func (*AzureSDKHandler) GetNetworkInterface

func (h *AzureSDKHandler) GetNetworkInterface(ctx context.Context, nicName string) (*armnetwork.Interface, error)

func (*AzureSDKHandler) GetParagliderVnet

func (h *AzureSDKHandler) GetParagliderVnet(ctx context.Context, vnetName string, location string, namespace string, orchestratorAddr string) (*armnetwork.VirtualNetwork, error)

GetParagliderVnet returns a valid paraglider vnet, a paraglider vnet is a vnet with a default subnet with the same address space as the vnet and there is only one vnet per location

func (*AzureSDKHandler) GetPermitListRuleFromNSGRule

func (h *AzureSDKHandler) GetPermitListRuleFromNSGRule(rule *armnetwork.SecurityRule) (*paragliderpb.PermitListRule, error)

GetPermitListRuleFromNSGRule returns a permit list rule from a network security group (NSG) rule.

func (*AzureSDKHandler) GetPublicIPAddress

func (h *AzureSDKHandler) GetPublicIPAddress(ctx context.Context, name string) (*armnetwork.PublicIPAddress, error)

func (*AzureSDKHandler) GetResource

func (h *AzureSDKHandler) GetResource(ctx context.Context, resourceID string) (*armresources.GenericResource, error)

func (*AzureSDKHandler) GetSecurityGroup

func (h *AzureSDKHandler) GetSecurityGroup(ctx context.Context, nsgName string) (*armnetwork.SecurityGroup, error)

GetSecurityGroup reutrns the network security group object given the nsg name

func (*AzureSDKHandler) GetSubnet

func (h *AzureSDKHandler) GetSubnet(ctx context.Context, virtualNetworkName string, subnetName string) (*armnetwork.Subnet, error)

func (*AzureSDKHandler) GetSubnetByID

func (h *AzureSDKHandler) GetSubnetByID(ctx context.Context, subnetID string) (*armnetwork.Subnet, error)

func (*AzureSDKHandler) GetVNet

func (h *AzureSDKHandler) GetVNet(ctx context.Context, vnetName string) (*armnetwork.VirtualNetwork, error)

GetVNet returns the virtual network with the given name

func (*AzureSDKHandler) GetVNetsAddressSpaces

func (h *AzureSDKHandler) GetVNetsAddressSpaces(ctx context.Context, prefix string) (map[string][]string, error)

GetVnetAddressSpaces returns a map of location to address space for all virtual networks (VNets) with a given prefix.

func (*AzureSDKHandler) GetVirtualNetwork

func (h *AzureSDKHandler) GetVirtualNetwork(ctx context.Context, name string) (*armnetwork.VirtualNetwork, error)

func (*AzureSDKHandler) GetVirtualNetworkGateway

func (h *AzureSDKHandler) GetVirtualNetworkGateway(ctx context.Context, name string) (*armnetwork.VirtualNetworkGateway, error)

func (*AzureSDKHandler) GetVirtualNetworkGatewayConnection

func (h *AzureSDKHandler) GetVirtualNetworkGatewayConnection(ctx context.Context, name string) (*armnetwork.VirtualNetworkGatewayConnection, error)

func (*AzureSDKHandler) GetVirtualNetworkPeering

func (h *AzureSDKHandler) GetVirtualNetworkPeering(ctx context.Context, virtualNetworkName string, virtualNetworkPeeringName string) (*armnetwork.VirtualNetworkPeering, error)

func (*AzureSDKHandler) InitializeClients

func (h *AzureSDKHandler) InitializeClients(cred azcore.TokenCredential) error

InitializeClients initializes the necessary azure clients for the necessary operations

func (*AzureSDKHandler) ListVirtualNetworkPeerings

func (h *AzureSDKHandler) ListVirtualNetworkPeerings(ctx context.Context, virtualNetworkName string) ([]*armnetwork.VirtualNetworkPeering, error)

func (*AzureSDKHandler) SetSubIdAndResourceGroup

func (h *AzureSDKHandler) SetSubIdAndResourceGroup(subid string, resourceGroupName string)

type IAzureCredentialGetter

type IAzureCredentialGetter interface {
	GetAzureCredentials() (azcore.TokenCredential, error)
}

type ResourceIDInfo

type ResourceIDInfo struct {
	SubscriptionID    string
	ResourceGroupName string
	ResourceName      string
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL