opentofu/builtin/providers/azurerm/resourceid.go
James Nugent c3ce8b81ef provider/azurerm: Parse "resourcegroups" in IDs
When parsing resource IDs (probably incorrectly since they are URIs and
should therefore be opaque), we need to look for "resourcegroups" in
addition to "resourceGroups" because the Azure CDN resources return that
in their URIs.

Unfortunately the casing semantics of the rest of the string are not
clear, so downcasing the entire URI is probably best avoided. This is a
fix for a single case.
2016-01-19 11:32:16 -05:00

91 lines
2.5 KiB
Go

package azurerm
import (
"fmt"
"net/url"
"strings"
)
// ResourceID represents a parsed long-form Azure Resource Manager ID
// with the Subscription ID, Resource Group and the Provider as top-
// level fields, and other key-value pairs available via a map in the
// Path field.
type ResourceID struct {
SubscriptionID string
ResourceGroup string
Provider string
Path map[string]string
}
// parseAzureResourceID converts a long-form Azure Resource Manager ID
// into a ResourceID. We make assumptions about the structure of URLs,
// which is obviously not good, but the best thing available given the
// SDK.
func parseAzureResourceID(id string) (*ResourceID, error) {
idURL, err := url.ParseRequestURI(id)
if err != nil {
return nil, fmt.Errorf("Cannot parse Azure Id: %s", err)
}
path := idURL.Path
path = strings.TrimSpace(path)
if strings.HasPrefix(path, "/") {
path = path[1:]
}
if strings.HasSuffix(path, "/") {
path = path[:len(path)-1]
}
components := strings.Split(path, "/")
// We should have an even number of key-value pairs.
if len(components)%2 != 0 {
return nil, fmt.Errorf("The number of path segments is not divisible by 2 in %q", path)
}
// Put the constituent key-value pairs into a map
componentMap := make(map[string]string, len(components)/2)
for current := 0; current < len(components); current += 2 {
key := components[current]
value := components[current+1]
componentMap[key] = value
}
// Build up a ResourceID from the map
idObj := &ResourceID{}
idObj.Path = componentMap
if subscription, ok := componentMap["subscriptions"]; ok {
idObj.SubscriptionID = subscription
delete(componentMap, "subscriptions")
} else {
return nil, fmt.Errorf("No subscription ID found in: %q", path)
}
if resourceGroup, ok := componentMap["resourceGroups"]; ok {
idObj.ResourceGroup = resourceGroup
delete(componentMap, "resourceGroups")
} else {
// Some Azure APIs are weird and provide things in lower case...
// However it's not clear whether the casing of other elements in the URI
// matter, so we explicitly look for that case here.
if resourceGroup, ok := componentMap["resourcegroups"]; ok {
idObj.ResourceGroup = resourceGroup
delete(componentMap, "resourcegroups")
} else {
return nil, fmt.Errorf("No resource group name found in: %q", path)
}
}
// It is OK not to have a provider in the case of a resource group
if provider, ok := componentMap["providers"]; ok {
idObj.Provider = provider
delete(componentMap, "providers")
}
return idObj, nil
}