github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/azurerm/resourceid.go (about) 1 package azurerm 2 3 import ( 4 "fmt" 5 "net/url" 6 "strings" 7 ) 8 9 // ResourceID represents a parsed long-form Azure Resource Manager ID 10 // with the Subscription ID, Resource Group and the Provider as top- 11 // level fields, and other key-value pairs available via a map in the 12 // Path field. 13 type ResourceID struct { 14 SubscriptionID string 15 ResourceGroup string 16 Provider string 17 Path map[string]string 18 } 19 20 // parseAzureResourceID converts a long-form Azure Resource Manager ID 21 // into a ResourceID. We make assumptions about the structure of URLs, 22 // which is obviously not good, but the best thing available given the 23 // SDK. 24 func parseAzureResourceID(id string) (*ResourceID, error) { 25 idURL, err := url.ParseRequestURI(id) 26 if err != nil { 27 return nil, fmt.Errorf("Cannot parse Azure Id: %s", err) 28 } 29 30 path := idURL.Path 31 32 path = strings.TrimSpace(path) 33 if strings.HasPrefix(path, "/") { 34 path = path[1:] 35 } 36 37 if strings.HasSuffix(path, "/") { 38 path = path[:len(path)-1] 39 } 40 41 components := strings.Split(path, "/") 42 43 // We should have an even number of key-value pairs. 44 if len(components)%2 != 0 { 45 return nil, fmt.Errorf("The number of path segments is not divisible by 2 in %q", path) 46 } 47 48 var subscriptionID string 49 50 // Put the constituent key-value pairs into a map 51 componentMap := make(map[string]string, len(components)/2) 52 for current := 0; current < len(components); current += 2 { 53 key := components[current] 54 value := components[current+1] 55 56 // Catch the subscriptionID before it can be overwritten by another "subscriptions" 57 // value in the ID which is the case for the Service Bus subscription resource 58 if key == "subscriptions" && subscriptionID == "" { 59 subscriptionID = value 60 } else { 61 componentMap[key] = value 62 } 63 } 64 65 // Build up a ResourceID from the map 66 idObj := &ResourceID{} 67 idObj.Path = componentMap 68 69 if subscriptionID != "" { 70 idObj.SubscriptionID = subscriptionID 71 } else { 72 return nil, fmt.Errorf("No subscription ID found in: %q", path) 73 } 74 75 if resourceGroup, ok := componentMap["resourceGroups"]; ok { 76 idObj.ResourceGroup = resourceGroup 77 delete(componentMap, "resourceGroups") 78 } else { 79 // Some Azure APIs are weird and provide things in lower case... 80 // However it's not clear whether the casing of other elements in the URI 81 // matter, so we explicitly look for that case here. 82 if resourceGroup, ok := componentMap["resourcegroups"]; ok { 83 idObj.ResourceGroup = resourceGroup 84 delete(componentMap, "resourcegroups") 85 } else { 86 return nil, fmt.Errorf("No resource group name found in: %q", path) 87 } 88 } 89 90 // It is OK not to have a provider in the case of a resource group 91 if provider, ok := componentMap["providers"]; ok { 92 idObj.Provider = provider 93 delete(componentMap, "providers") 94 } 95 96 return idObj, nil 97 }