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 }