github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/builder/azure/arm/resource_resolver.go (about)

     1  package arm
     2  
     3  // Code to resolve resources that are required by the API.  These resources
     4  // can most likely be resolved without asking the user, thereby reducing the
     5  // amount of configuration they need to provide.
     6  //
     7  // Resource resolver differs from config retriever because resource resolver
     8  // requires a client to communicate with the Azure API.  A config retriever is
     9  // used to determine values without use of a client.
    10  
    11  import (
    12  	"fmt"
    13  	"strings"
    14  )
    15  
    16  type resourceResolver struct {
    17  	client                          *AzureClient
    18  	findVirtualNetworkResourceGroup func(*AzureClient, string) (string, error)
    19  	findVirtualNetworkSubnet        func(*AzureClient, string, string) (string, error)
    20  }
    21  
    22  func newResourceResolver(client *AzureClient) *resourceResolver {
    23  	return &resourceResolver{
    24  		client: client,
    25  		findVirtualNetworkResourceGroup: findVirtualNetworkResourceGroup,
    26  		findVirtualNetworkSubnet:        findVirtualNetworkSubnet,
    27  	}
    28  }
    29  
    30  func (s *resourceResolver) Resolve(c *Config) error {
    31  	if s.shouldResolveResourceGroup(c) {
    32  		resourceGroupName, err := s.findVirtualNetworkResourceGroup(s.client, c.VirtualNetworkName)
    33  		if err != nil {
    34  			return err
    35  		}
    36  
    37  		subnetName, err := s.findVirtualNetworkSubnet(s.client, resourceGroupName, c.VirtualNetworkName)
    38  		if err != nil {
    39  			return err
    40  		}
    41  
    42  		c.VirtualNetworkResourceGroupName = resourceGroupName
    43  		c.VirtualNetworkSubnetName = subnetName
    44  	}
    45  
    46  	return nil
    47  }
    48  
    49  func (s *resourceResolver) shouldResolveResourceGroup(c *Config) bool {
    50  	return c.VirtualNetworkName != "" && c.VirtualNetworkResourceGroupName == ""
    51  }
    52  
    53  func getResourceGroupNameFromId(id string) string {
    54  	// "/subscriptions/3f499422-dd76-4114-8859-86d526c9deb6/resourceGroups/packer-Resource-Group-yylnwsl30j/providers/...
    55  	xs := strings.Split(id, "/")
    56  	return xs[4]
    57  }
    58  
    59  func findVirtualNetworkResourceGroup(client *AzureClient, name string) (string, error) {
    60  	virtualNetworks, err := client.VirtualNetworksClient.ListAll()
    61  	if err != nil {
    62  		return "", err
    63  	}
    64  
    65  	resourceGroupNames := make([]string, 0)
    66  
    67  	for _, virtualNetwork := range *virtualNetworks.Value {
    68  		if strings.EqualFold(name, *virtualNetwork.Name) {
    69  			rgn := getResourceGroupNameFromId(*virtualNetwork.ID)
    70  			resourceGroupNames = append(resourceGroupNames, rgn)
    71  		}
    72  	}
    73  
    74  	if len(resourceGroupNames) == 0 {
    75  		return "", fmt.Errorf("Cannot find a resource group with a virtual network called %q", name)
    76  	}
    77  
    78  	if len(resourceGroupNames) > 1 {
    79  		return "", fmt.Errorf("Found multiple resource groups with a virtual network called %q, please use virtual_network_subnet_name and virtual_network_resource_group_name to disambiguate", name)
    80  	}
    81  
    82  	return resourceGroupNames[0], nil
    83  }
    84  
    85  func findVirtualNetworkSubnet(client *AzureClient, resourceGroupName string, name string) (string, error) {
    86  	subnets, err := client.SubnetsClient.List(resourceGroupName, name)
    87  	if err != nil {
    88  		return "", err
    89  	}
    90  
    91  	if len(*subnets.Value) == 0 {
    92  		return "", fmt.Errorf("Cannot find a subnet in the resource group %q associated with the virtual network called %q", resourceGroupName, name)
    93  	}
    94  
    95  	if len(*subnets.Value) > 1 {
    96  		return "", fmt.Errorf("Found multiple subnets in the resource group %q associated with the  virtual network called %q, please use virtual_network_subnet_name and virtual_network_resource_group_name to disambiguate", resourceGroupName, name)
    97  	}
    98  
    99  	subnet := (*subnets.Value)[0]
   100  	return *subnet.Name, nil
   101  }