diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/constants.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/constants.go index 7c87d5e1f6c6..c9f2ac9b0659 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/constants.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/constants.go @@ -1,5 +1,7 @@ package cognitiveservicesaccounts +import "strings" + type CreatedByType string const ( @@ -9,6 +11,31 @@ const ( CreatedByTypeUser CreatedByType = "User" ) +func PossibleValuesForCreatedByType() []string { + return []string{ + string(CreatedByTypeApplication), + string(CreatedByTypeKey), + string(CreatedByTypeManagedIdentity), + string(CreatedByTypeUser), + } +} + +func parseCreatedByType(input string) (*CreatedByType, error) { + vals := map[string]CreatedByType{ + "application": CreatedByTypeApplication, + "key": CreatedByTypeKey, + "managedidentity": CreatedByTypeManagedIdentity, + "user": CreatedByTypeUser, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := CreatedByType(input) + return &out, nil +} + type KeyName string const ( @@ -16,6 +43,27 @@ const ( KeyNameKeyTwo KeyName = "Key2" ) +func PossibleValuesForKeyName() []string { + return []string{ + string(KeyNameKeyOne), + string(KeyNameKeyTwo), + } +} + +func parseKeyName(input string) (*KeyName, error) { + vals := map[string]KeyName{ + "key1": KeyNameKeyOne, + "key2": KeyNameKeyTwo, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := KeyName(input) + return &out, nil +} + type KeySource string const ( @@ -23,6 +71,27 @@ const ( KeySourceMicrosoftPointKeyVault KeySource = "Microsoft.KeyVault" ) +func PossibleValuesForKeySource() []string { + return []string{ + string(KeySourceMicrosoftPointCognitiveServices), + string(KeySourceMicrosoftPointKeyVault), + } +} + +func parseKeySource(input string) (*KeySource, error) { + vals := map[string]KeySource{ + "microsoft.cognitiveservices": KeySourceMicrosoftPointCognitiveServices, + "microsoft.keyvault": KeySourceMicrosoftPointKeyVault, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := KeySource(input) + return &out, nil +} + type NetworkRuleAction string const ( @@ -30,6 +99,27 @@ const ( NetworkRuleActionDeny NetworkRuleAction = "Deny" ) +func PossibleValuesForNetworkRuleAction() []string { + return []string{ + string(NetworkRuleActionAllow), + string(NetworkRuleActionDeny), + } +} + +func parseNetworkRuleAction(input string) (*NetworkRuleAction, error) { + vals := map[string]NetworkRuleAction{ + "allow": NetworkRuleActionAllow, + "deny": NetworkRuleActionDeny, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := NetworkRuleAction(input) + return &out, nil +} + type PrivateEndpointConnectionProvisioningState string const ( @@ -39,6 +129,31 @@ const ( PrivateEndpointConnectionProvisioningStateSucceeded PrivateEndpointConnectionProvisioningState = "Succeeded" ) +func PossibleValuesForPrivateEndpointConnectionProvisioningState() []string { + return []string{ + string(PrivateEndpointConnectionProvisioningStateCreating), + string(PrivateEndpointConnectionProvisioningStateDeleting), + string(PrivateEndpointConnectionProvisioningStateFailed), + string(PrivateEndpointConnectionProvisioningStateSucceeded), + } +} + +func parsePrivateEndpointConnectionProvisioningState(input string) (*PrivateEndpointConnectionProvisioningState, error) { + vals := map[string]PrivateEndpointConnectionProvisioningState{ + "creating": PrivateEndpointConnectionProvisioningStateCreating, + "deleting": PrivateEndpointConnectionProvisioningStateDeleting, + "failed": PrivateEndpointConnectionProvisioningStateFailed, + "succeeded": PrivateEndpointConnectionProvisioningStateSucceeded, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := PrivateEndpointConnectionProvisioningState(input) + return &out, nil +} + type PrivateEndpointServiceConnectionStatus string const ( @@ -47,6 +162,29 @@ const ( PrivateEndpointServiceConnectionStatusRejected PrivateEndpointServiceConnectionStatus = "Rejected" ) +func PossibleValuesForPrivateEndpointServiceConnectionStatus() []string { + return []string{ + string(PrivateEndpointServiceConnectionStatusApproved), + string(PrivateEndpointServiceConnectionStatusPending), + string(PrivateEndpointServiceConnectionStatusRejected), + } +} + +func parsePrivateEndpointServiceConnectionStatus(input string) (*PrivateEndpointServiceConnectionStatus, error) { + vals := map[string]PrivateEndpointServiceConnectionStatus{ + "approved": PrivateEndpointServiceConnectionStatusApproved, + "pending": PrivateEndpointServiceConnectionStatusPending, + "rejected": PrivateEndpointServiceConnectionStatusRejected, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := PrivateEndpointServiceConnectionStatus(input) + return &out, nil +} + type ProvisioningState string const ( @@ -59,6 +197,37 @@ const ( ProvisioningStateSucceeded ProvisioningState = "Succeeded" ) +func PossibleValuesForProvisioningState() []string { + return []string{ + string(ProvisioningStateAccepted), + string(ProvisioningStateCreating), + string(ProvisioningStateDeleting), + string(ProvisioningStateFailed), + string(ProvisioningStateMoving), + string(ProvisioningStateResolvingDNS), + string(ProvisioningStateSucceeded), + } +} + +func parseProvisioningState(input string) (*ProvisioningState, error) { + vals := map[string]ProvisioningState{ + "accepted": ProvisioningStateAccepted, + "creating": ProvisioningStateCreating, + "deleting": ProvisioningStateDeleting, + "failed": ProvisioningStateFailed, + "moving": ProvisioningStateMoving, + "resolvingdns": ProvisioningStateResolvingDNS, + "succeeded": ProvisioningStateSucceeded, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ProvisioningState(input) + return &out, nil +} + type PublicNetworkAccess string const ( @@ -66,6 +235,27 @@ const ( PublicNetworkAccessEnabled PublicNetworkAccess = "Enabled" ) +func PossibleValuesForPublicNetworkAccess() []string { + return []string{ + string(PublicNetworkAccessDisabled), + string(PublicNetworkAccessEnabled), + } +} + +func parsePublicNetworkAccess(input string) (*PublicNetworkAccess, error) { + vals := map[string]PublicNetworkAccess{ + "disabled": PublicNetworkAccessDisabled, + "enabled": PublicNetworkAccessEnabled, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := PublicNetworkAccess(input) + return &out, nil +} + type QuotaUsageStatus string const ( @@ -75,6 +265,31 @@ const ( QuotaUsageStatusUnknown QuotaUsageStatus = "Unknown" ) +func PossibleValuesForQuotaUsageStatus() []string { + return []string{ + string(QuotaUsageStatusBlocked), + string(QuotaUsageStatusInOverage), + string(QuotaUsageStatusIncluded), + string(QuotaUsageStatusUnknown), + } +} + +func parseQuotaUsageStatus(input string) (*QuotaUsageStatus, error) { + vals := map[string]QuotaUsageStatus{ + "blocked": QuotaUsageStatusBlocked, + "inoverage": QuotaUsageStatusInOverage, + "included": QuotaUsageStatusIncluded, + "unknown": QuotaUsageStatusUnknown, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := QuotaUsageStatus(input) + return &out, nil +} + type ResourceSkuRestrictionsReasonCode string const ( @@ -82,6 +297,27 @@ const ( ResourceSkuRestrictionsReasonCodeQuotaId ResourceSkuRestrictionsReasonCode = "QuotaId" ) +func PossibleValuesForResourceSkuRestrictionsReasonCode() []string { + return []string{ + string(ResourceSkuRestrictionsReasonCodeNotAvailableForSubscription), + string(ResourceSkuRestrictionsReasonCodeQuotaId), + } +} + +func parseResourceSkuRestrictionsReasonCode(input string) (*ResourceSkuRestrictionsReasonCode, error) { + vals := map[string]ResourceSkuRestrictionsReasonCode{ + "notavailableforsubscription": ResourceSkuRestrictionsReasonCodeNotAvailableForSubscription, + "quotaid": ResourceSkuRestrictionsReasonCodeQuotaId, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ResourceSkuRestrictionsReasonCode(input) + return &out, nil +} + type ResourceSkuRestrictionsType string const ( @@ -89,6 +325,27 @@ const ( ResourceSkuRestrictionsTypeZone ResourceSkuRestrictionsType = "Zone" ) +func PossibleValuesForResourceSkuRestrictionsType() []string { + return []string{ + string(ResourceSkuRestrictionsTypeLocation), + string(ResourceSkuRestrictionsTypeZone), + } +} + +func parseResourceSkuRestrictionsType(input string) (*ResourceSkuRestrictionsType, error) { + vals := map[string]ResourceSkuRestrictionsType{ + "location": ResourceSkuRestrictionsTypeLocation, + "zone": ResourceSkuRestrictionsTypeZone, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ResourceSkuRestrictionsType(input) + return &out, nil +} + type SkuTier string const ( @@ -99,6 +356,33 @@ const ( SkuTierStandard SkuTier = "Standard" ) +func PossibleValuesForSkuTier() []string { + return []string{ + string(SkuTierBasic), + string(SkuTierEnterprise), + string(SkuTierFree), + string(SkuTierPremium), + string(SkuTierStandard), + } +} + +func parseSkuTier(input string) (*SkuTier, error) { + vals := map[string]SkuTier{ + "basic": SkuTierBasic, + "enterprise": SkuTierEnterprise, + "free": SkuTierFree, + "premium": SkuTierPremium, + "standard": SkuTierStandard, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := SkuTier(input) + return &out, nil +} + type UnitType string const ( @@ -110,3 +394,34 @@ const ( UnitTypePercent UnitType = "Percent" UnitTypeSeconds UnitType = "Seconds" ) + +func PossibleValuesForUnitType() []string { + return []string{ + string(UnitTypeBytes), + string(UnitTypeBytesPerSecond), + string(UnitTypeCount), + string(UnitTypeCountPerSecond), + string(UnitTypeMilliseconds), + string(UnitTypePercent), + string(UnitTypeSeconds), + } +} + +func parseUnitType(input string) (*UnitType, error) { + vals := map[string]UnitType{ + "bytes": UnitTypeBytes, + "bytespersecond": UnitTypeBytesPerSecond, + "count": UnitTypeCount, + "countpersecond": UnitTypeCountPerSecond, + "milliseconds": UnitTypeMilliseconds, + "percent": UnitTypePercent, + "seconds": UnitTypeSeconds, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := UnitType(input) + return &out, nil +} diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account.go index edda0bbb26e0..c0ead3452d20 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account.go @@ -7,102 +7,118 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = AccountId{} + +// AccountId is a struct representing the Resource ID for a Account type AccountId struct { - SubscriptionId string - ResourceGroup string - Name string + SubscriptionId string + ResourceGroupName string + AccountName string } -func NewAccountID(subscriptionId, resourceGroup, name string) AccountId { +// NewAccountID returns a new AccountId struct +func NewAccountID(subscriptionId string, resourceGroupName string, accountName string) AccountId { return AccountId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, - Name: name, + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + AccountName: accountName, } } -func (id AccountId) String() string { - segments := []string{ - fmt.Sprintf("Name %q", id.Name), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Account", segmentsStr) -} - -func (id AccountId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.Name) -} - -// ParseAccountID parses a Account ID into an AccountId struct +// ParseAccountID parses 'input' into a AccountId func ParseAccountID(input string) (*AccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(AccountId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err - } - - resourceId := AccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } + var ok bool + id := AccountId{} - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.Name, err = id.PopSegment("accounts"); err != nil { - return nil, err + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - return &resourceId, nil + return &id, nil } -// ParseAccountIDInsensitively parses an Account ID into an AccountId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseAccountID method should be used instead for validation etc. +// ParseAccountIDInsensitively parses 'input' case-insensitively into a AccountId +// note: this method should only be used for API response data and not user input func ParseAccountIDInsensitively(input string) (*AccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(AccountId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := AccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + var ok bool + id := AccountId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - // find the correct casing for the 'accounts' segment - accountsKey := "accounts" - for key := range id.Path { - if strings.EqualFold(key, accountsKey) { - accountsKey = key - break - } + return &id, nil +} + +// ValidateAccountID checks that 'input' can be parsed as a Account ID +func ValidateAccountID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if resourceId.Name, err = id.PopSegment(accountsKey); err != nil { - return nil, err + + if _, err := ParseAccountID(v); err != nil { + errors = append(errors, err) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + return +} + +// ID returns the formatted Account ID +func (id AccountId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.AccountName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Account ID +func (id AccountId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("resourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("providers", "providers", "providers"), + resourceids.ResourceProviderSegment("microsoftCognitiveServices", "Microsoft.CognitiveServices", "Microsoft.CognitiveServices"), + resourceids.StaticSegment("accounts", "accounts", "accounts"), + resourceids.UserSpecifiedSegment("accountName", "accountValue"), } +} - return &resourceId, nil +// String returns a human-readable description of this Account ID +func (id AccountId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Account Name: %q", id.AccountName), + } + return fmt.Sprintf("Account (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account_test.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account_test.go index a6774b26fc0d..2fd310286d43 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_account_test.go @@ -6,13 +6,29 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = AccountId{} +var _ resourceids.ResourceId = AccountId{} -func TestAccountIDFormatter(t *testing.T) { - actual := NewAccountID("{subscriptionId}", "{resourceGroupName}", "{accountName}").ID() - expected := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}" +func TestNewAccountID(t *testing.T) { + id := NewAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.AccountName != "accountValue" { + t.Fatalf("Expected %q but got %q for Segment 'AccountName'", id.AccountName, "accountValue") + } +} + +func TestFormatAccountID(t *testing.T) { + actual := NewAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,66 +38,61 @@ func TestParseAccountID(t *testing.T) { Error bool Expected *AccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/RESOURCEGROUPS/{RESOURCEGROUPNAME}/PROVIDERS/MICROSOFT.COGNITIVESERVICES/ACCOUNTS/{ACCOUNTNAME}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -91,7 +102,7 @@ func TestParseAccountID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -100,12 +111,15 @@ func TestParseAccountID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } @@ -115,90 +129,110 @@ func TestParseAccountIDInsensitively(t *testing.T) { Error bool Expected *AccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", - Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", - Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/ACCOUNTS/{accountName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/AcCoUnTs/{accountName}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + AccountName: "aCcOuNtVaLuE", }, }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE/extra", + Error: true, + }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -208,7 +242,7 @@ func TestParseAccountIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -217,11 +251,14 @@ func TestParseAccountIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount.go index b9808995ef1b..aec2d9a947f6 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount.go @@ -7,121 +7,131 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = DeletedAccountId{} + +// DeletedAccountId is a struct representing the Resource ID for a Deleted Account type DeletedAccountId struct { - SubscriptionId string - LocationName string - ResourceGroup string - Name string + SubscriptionId string + Location string + ResourceGroupName string + AccountName string } -func NewDeletedAccountID(subscriptionId, locationName, resourceGroup, name string) DeletedAccountId { +// NewDeletedAccountID returns a new DeletedAccountId struct +func NewDeletedAccountID(subscriptionId string, location string, resourceGroupName string, accountName string) DeletedAccountId { return DeletedAccountId{ - SubscriptionId: subscriptionId, - LocationName: locationName, - ResourceGroup: resourceGroup, - Name: name, + SubscriptionId: subscriptionId, + Location: location, + ResourceGroupName: resourceGroupName, + AccountName: accountName, } } -func (id DeletedAccountId) String() string { - segments := []string{ - fmt.Sprintf("Name %q", id.Name), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - fmt.Sprintf("Location Name %q", id.LocationName), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Deleted Account", segmentsStr) -} - -func (id DeletedAccountId) ID() string { - fmtString := "/subscriptions/%s/providers/Microsoft.CognitiveServices/locations/%s/resourceGroups/%s/deletedAccounts/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.LocationName, id.ResourceGroup, id.Name) -} - -// ParseDeletedAccountID parses a DeletedAccount ID into an DeletedAccountId struct +// ParseDeletedAccountID parses 'input' into a DeletedAccountId func ParseDeletedAccountID(input string) (*DeletedAccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(DeletedAccountId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err - } - - resourceId := DeletedAccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } + var ok bool + id := DeletedAccountId{} - if resourceId.LocationName, err = id.PopSegment("locations"); err != nil { - return nil, err + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.Location, ok = parsed.Parsed["location"]; !ok { + return nil, fmt.Errorf("the segment 'location' was not found in the resource id %q", input) } - if resourceId.Name, err = id.PopSegment("deletedAccounts"); err != nil { - return nil, err + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - return &resourceId, nil + return &id, nil } -// ParseDeletedAccountIDInsensitively parses an DeletedAccount ID into an DeletedAccountId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseDeletedAccountID method should be used instead for validation etc. +// ParseDeletedAccountIDInsensitively parses 'input' case-insensitively into a DeletedAccountId +// note: this method should only be used for API response data and not user input func ParseDeletedAccountIDInsensitively(input string) (*DeletedAccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(DeletedAccountId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := DeletedAccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, - } + var ok bool + id := DeletedAccountId{} - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - // find the correct casing for the 'locations' segment - locationsKey := "locations" - for key := range id.Path { - if strings.EqualFold(key, locationsKey) { - locationsKey = key - break - } + if id.Location, ok = parsed.Parsed["location"]; !ok { + return nil, fmt.Errorf("the segment 'location' was not found in the resource id %q", input) } - if resourceId.LocationName, err = id.PopSegment(locationsKey); err != nil { - return nil, err + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - // find the correct casing for the 'deletedAccounts' segment - deletedAccountsKey := "deletedAccounts" - for key := range id.Path { - if strings.EqualFold(key, deletedAccountsKey) { - deletedAccountsKey = key - break - } + return &id, nil +} + +// ValidateDeletedAccountID checks that 'input' can be parsed as a Deleted Account ID +func ValidateDeletedAccountID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if resourceId.Name, err = id.PopSegment(deletedAccountsKey); err != nil { - return nil, err + + if _, err := ParseDeletedAccountID(v); err != nil { + errors = append(errors, err) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + return +} + +// ID returns the formatted Deleted Account ID +func (id DeletedAccountId) ID() string { + fmtString := "/subscriptions/%s/providers/Microsoft.CognitiveServices/locations/%s/resourceGroups/%s/deletedAccounts/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.Location, id.ResourceGroupName, id.AccountName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Deleted Account ID +func (id DeletedAccountId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("providers", "providers", "providers"), + resourceids.ResourceProviderSegment("microsoftCognitiveServices", "Microsoft.CognitiveServices", "Microsoft.CognitiveServices"), + resourceids.StaticSegment("locations", "locations", "locations"), + resourceids.UserSpecifiedSegment("location", "locationValue"), + resourceids.StaticSegment("resourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("deletedAccounts", "deletedAccounts", "deletedAccounts"), + resourceids.UserSpecifiedSegment("accountName", "accountValue"), } +} - return &resourceId, nil +// String returns a human-readable description of this Deleted Account ID +func (id DeletedAccountId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Location: %q", id.Location), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Account Name: %q", id.AccountName), + } + return fmt.Sprintf("Deleted Account (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount_test.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount_test.go index 4e3b0debd8f4..e887c11d4f1e 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_deletedaccount_test.go @@ -6,13 +6,33 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = DeletedAccountId{} +var _ resourceids.ResourceId = DeletedAccountId{} -func TestDeletedAccountIDFormatter(t *testing.T) { - actual := NewDeletedAccountID("{subscriptionId}", "{location}", "{resourceGroupName}", "{accountName}").ID() - expected := "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/deletedAccounts/{accountName}" +func TestNewDeletedAccountID(t *testing.T) { + id := NewDeletedAccountID("12345678-1234-9876-4563-123456789012", "locationValue", "example-resource-group", "accountValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.Location != "locationValue" { + t.Fatalf("Expected %q but got %q for Segment 'Location'", id.Location, "locationValue") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.AccountName != "accountValue" { + t.Fatalf("Expected %q but got %q for Segment 'AccountName'", id.AccountName, "accountValue") + } +} + +func TestFormatDeletedAccountID(t *testing.T) { + actual := NewDeletedAccountID("12345678-1234-9876-4563-123456789012", "locationValue", "example-resource-group", "accountValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group/deletedAccounts/accountValue" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,79 +42,72 @@ func TestParseDeletedAccountID(t *testing.T) { Error bool Expected *DeletedAccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing LocationName - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers", Error: true, }, - { - // missing value for LocationName - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/deletedAccounts/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group/deletedAccounts", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/deletedAccounts/{accountName}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group/deletedAccounts/accountValue", Expected: &DeletedAccountId{ - SubscriptionId: "{subscriptionId}", - LocationName: "{location}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + Location: "locationValue", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/PROVIDERS/MICROSOFT.COGNITIVESERVICES/LOCATIONS/{LOCATION}/RESOURCEGROUPS/{RESOURCEGROUPNAME}/DELETEDACCOUNTS/{ACCOUNTNAME}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group/deletedAccounts/accountValue/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -104,7 +117,7 @@ func TestParseDeletedAccountID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -113,15 +126,19 @@ func TestParseDeletedAccountID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.LocationName != v.Expected.LocationName { - t.Fatalf("Expected %q but got %q for LocationName", v.Expected.LocationName, actual.LocationName) + + if actual.Location != v.Expected.Location { + t.Fatalf("Expected %q but got %q for Location", v.Expected.Location, actual.Location) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } @@ -131,106 +148,132 @@ func TestParseDeletedAccountIDInsensitively(t *testing.T) { Error bool Expected *DeletedAccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // missing LocationName - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for LocationName - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/deletedAccounts/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/deletedAccounts/{accountName}", - Expected: &DeletedAccountId{ - SubscriptionId: "{subscriptionId}", - LocationName: "{location}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations", + Error: true, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}/resourceGroups/{resourceGroupName}/deletedaccounts/{accountName}", - Expected: &DeletedAccountId{ - SubscriptionId: "{subscriptionId}", - LocationName: "{location}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/LOCATIONS/{location}/resourceGroups/{resourceGroupName}/DELETEDACCOUNTS/{accountName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group/deletedAccounts", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/dElEtEdAcCoUnTs", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group/deletedAccounts/accountValue", Expected: &DeletedAccountId{ - SubscriptionId: "{subscriptionId}", - LocationName: "{location}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + Location: "locationValue", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/LoCaTiOnS/{location}/resourceGroups/{resourceGroupName}/DeLeTeDaCcOuNtS/{accountName}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/resourceGroups/example-resource-group/deletedAccounts/accountValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/dElEtEdAcCoUnTs/aCcOuNtVaLuE", Expected: &DeletedAccountId{ - SubscriptionId: "{subscriptionId}", - LocationName: "{location}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + Location: "lOcAtIoNvAlUe", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + AccountName: "aCcOuNtVaLuE", }, }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/dElEtEdAcCoUnTs/aCcOuNtVaLuE/extra", + Error: true, + }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -240,7 +283,7 @@ func TestParseDeletedAccountIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -249,14 +292,18 @@ func TestParseDeletedAccountIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.LocationName != v.Expected.LocationName { - t.Fatalf("Expected %q but got %q for LocationName", v.Expected.LocationName, actual.LocationName) + + if actual.Location != v.Expected.Location { + t.Fatalf("Expected %q but got %q for Location", v.Expected.Location, actual.Location) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location.go index ee53f0b34df6..f9fa484bd49c 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location.go @@ -7,89 +7,105 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = LocationId{} + +// LocationId is a struct representing the Resource ID for a Location type LocationId struct { SubscriptionId string - Name string + Location string } -func NewLocationID(subscriptionId, name string) LocationId { +// NewLocationID returns a new LocationId struct +func NewLocationID(subscriptionId string, location string) LocationId { return LocationId{ SubscriptionId: subscriptionId, - Name: name, + Location: location, } } -func (id LocationId) String() string { - segments := []string{ - fmt.Sprintf("Name %q", id.Name), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Location", segmentsStr) -} - -func (id LocationId) ID() string { - fmtString := "/subscriptions/%s/providers/Microsoft.CognitiveServices/locations/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.Name) -} - -// ParseLocationID parses a Location ID into an LocationId struct +// ParseLocationID parses 'input' into a LocationId func ParseLocationID(input string) (*LocationId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(LocationId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err - } - - resourceId := LocationId{ - SubscriptionId: id.SubscriptionID, + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } + var ok bool + id := LocationId{} - if resourceId.Name, err = id.PopSegment("locations"); err != nil { - return nil, err + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if id.Location, ok = parsed.Parsed["location"]; !ok { + return nil, fmt.Errorf("the segment 'location' was not found in the resource id %q", input) } - return &resourceId, nil + return &id, nil } -// ParseLocationIDInsensitively parses an Location ID into an LocationId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseLocationID method should be used instead for validation etc. +// ParseLocationIDInsensitively parses 'input' case-insensitively into a LocationId +// note: this method should only be used for API response data and not user input func ParseLocationIDInsensitively(input string) (*LocationId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(LocationId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := LocationId{ - SubscriptionId: id.SubscriptionID, + var ok bool + id := LocationId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.Location, ok = parsed.Parsed["location"]; !ok { + return nil, fmt.Errorf("the segment 'location' was not found in the resource id %q", input) } - // find the correct casing for the 'locations' segment - locationsKey := "locations" - for key := range id.Path { - if strings.EqualFold(key, locationsKey) { - locationsKey = key - break - } + return &id, nil +} + +// ValidateLocationID checks that 'input' can be parsed as a Location ID +func ValidateLocationID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if resourceId.Name, err = id.PopSegment(locationsKey); err != nil { - return nil, err + + if _, err := ParseLocationID(v); err != nil { + errors = append(errors, err) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + return +} + +// ID returns the formatted Location ID +func (id LocationId) ID() string { + fmtString := "/subscriptions/%s/providers/Microsoft.CognitiveServices/locations/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.Location) +} + +// Segments returns a slice of Resource ID Segments which comprise this Location ID +func (id LocationId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("providers", "providers", "providers"), + resourceids.ResourceProviderSegment("microsoftCognitiveServices", "Microsoft.CognitiveServices", "Microsoft.CognitiveServices"), + resourceids.StaticSegment("locations", "locations", "locations"), + resourceids.UserSpecifiedSegment("location", "locationValue"), } +} - return &resourceId, nil +// String returns a human-readable description of this Location ID +func (id LocationId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Location: %q", id.Location), + } + return fmt.Sprintf("Location (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location_test.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location_test.go index 1d2f588c81be..98c9dcc322b3 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_location_test.go @@ -6,13 +6,25 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = LocationId{} +var _ resourceids.ResourceId = LocationId{} -func TestLocationIDFormatter(t *testing.T) { - actual := NewLocationID("{subscriptionId}", "{location}").ID() - expected := "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}" +func TestNewLocationID(t *testing.T) { + id := NewLocationID("12345678-1234-9876-4563-123456789012", "locationValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.Location != "locationValue" { + t.Fatalf("Expected %q but got %q for Segment 'Location'", id.Location, "locationValue") + } +} + +func TestFormatLocationID(t *testing.T) { + actual := NewLocationID("12345678-1234-9876-4563-123456789012", "locationValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,53 +34,50 @@ func TestParseLocationID(t *testing.T) { Error bool Expected *LocationId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue", Expected: &LocationId{ - SubscriptionId: "{subscriptionId}", - Name: "{location}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + Location: "locationValue", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/PROVIDERS/MICROSOFT.COGNITIVESERVICES/LOCATIONS/{LOCATION}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -78,7 +87,7 @@ func TestParseLocationID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -87,9 +96,11 @@ func TestParseLocationID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.Location != v.Expected.Location { + t.Fatalf("Expected %q but got %q for Location", v.Expected.Location, actual.Location) } + } } @@ -99,74 +110,88 @@ func TestParseLocationIDInsensitively(t *testing.T) { Error bool Expected *LocationId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}", - Expected: &LocationId{ - SubscriptionId: "{subscriptionId}", - Name: "{location}", - }, + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers", + Error: true, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/locations/{location}", - Expected: &LocationId{ - SubscriptionId: "{subscriptionId}", - Name: "{location}", - }, + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/LOCATIONS/{location}", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue", Expected: &LocationId{ - SubscriptionId: "{subscriptionId}", - Name: "{location}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + Location: "locationValue", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}/providers/Microsoft.CognitiveServices/LoCaTiOnS/{location}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.CognitiveServices/locations/locationValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe", Expected: &LocationId{ - SubscriptionId: "{subscriptionId}", - Name: "{location}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + Location: "lOcAtIoNvAlUe", }, }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/lOcAtIoNs/lOcAtIoNvAlUe/extra", + Error: true, + }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -176,7 +201,7 @@ func TestParseLocationIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -185,8 +210,10 @@ func TestParseLocationIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.Location != v.Expected.Location { + t.Fatalf("Expected %q but got %q for Location", v.Expected.Location, actual.Location) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup.go index f47cf23c2da7..a6e8d486e69c 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup.go @@ -7,83 +7,103 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = ResourceGroupId{} + +// ResourceGroupId is a struct representing the Resource ID for a Resource Group type ResourceGroupId struct { - SubscriptionId string - ResourceGroup string + SubscriptionId string + ResourceGroupName string } -func NewResourceGroupID(subscriptionId, resourceGroup string) ResourceGroupId { +// NewResourceGroupID returns a new ResourceGroupId struct +func NewResourceGroupID(subscriptionId string, resourceGroupName string) ResourceGroupId { return ResourceGroupId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, } } -func (id ResourceGroupId) String() string { - segments := []string{ - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Resource Group", segmentsStr) -} - -func (id ResourceGroupId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup) -} - -// ParseResourceGroupID parses a ResourceGroup ID into an ResourceGroupId struct +// ParseResourceGroupID parses 'input' into a ResourceGroupId func ParseResourceGroupID(input string) (*ResourceGroupId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(ResourceGroupId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err - } - - resourceId := ResourceGroupId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } + var ok bool + id := ResourceGroupId{} - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - return &resourceId, nil + return &id, nil } -// ParseResourceGroupIDInsensitively parses an ResourceGroup ID into an ResourceGroupId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseResourceGroupID method should be used instead for validation etc. +// ParseResourceGroupIDInsensitively parses 'input' case-insensitively into a ResourceGroupId +// note: this method should only be used for API response data and not user input func ParseResourceGroupIDInsensitively(input string) (*ResourceGroupId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(ResourceGroupId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := ResourceGroupId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - resourceId := ResourceGroupId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + return &id, nil +} + +// ValidateResourceGroupID checks that 'input' can be parsed as a Resource Group ID +func ValidateResourceGroupID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if _, err := ParseResourceGroupID(v); err != nil { + errors = append(errors, err) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + return +} + +// ID returns the formatted Resource Group ID +func (id ResourceGroupId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Resource Group ID +func (id ResourceGroupId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("resourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), } +} - return &resourceId, nil +// String returns a human-readable description of this Resource Group ID +func (id ResourceGroupId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + } + return fmt.Sprintf("Resource Group (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup_test.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup_test.go index a20949b580b0..bf24b3ede653 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_resourcegroup_test.go @@ -6,13 +6,25 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = ResourceGroupId{} +var _ resourceids.ResourceId = ResourceGroupId{} -func TestResourceGroupIDFormatter(t *testing.T) { - actual := NewResourceGroupID("{subscriptionId}", "{resourceGroupName}").ID() - expected := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}" +func TestNewResourceGroupID(t *testing.T) { + id := NewResourceGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } +} + +func TestFormatResourceGroupID(t *testing.T) { + actual := NewResourceGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,53 +34,40 @@ func TestParseResourceGroupID(t *testing.T) { Error bool Expected *ResourceGroupId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - - { - // missing SubscriptionId - Input: "/", - Error: true, - }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", Expected: &ResourceGroupId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/RESOURCEGROUPS/{RESOURCEGROUPNAME}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -78,7 +77,7 @@ func TestParseResourceGroupID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -87,9 +86,11 @@ func TestParseResourceGroupID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } + } } @@ -99,74 +100,68 @@ func TestParseResourceGroupIDInsensitively(t *testing.T) { Error bool Expected *ResourceGroupId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}", - Expected: &ResourceGroupId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - }, + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}", - Expected: &ResourceGroupId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - }, + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", Expected: &ResourceGroupId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", Expected: &ResourceGroupId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", }, }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/extra", + Error: true, + }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -176,7 +171,7 @@ func TestParseResourceGroupIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -185,8 +180,10 @@ func TestParseResourceGroupIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription.go index f2278855e0b1..f61561cdc40b 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription.go @@ -7,69 +7,90 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = SubscriptionId{} + +// SubscriptionId is a struct representing the Resource ID for a Subscription type SubscriptionId struct { SubscriptionId string } +// NewSubscriptionID returns a new SubscriptionId struct func NewSubscriptionID(subscriptionId string) SubscriptionId { return SubscriptionId{ SubscriptionId: subscriptionId, } } -func (id SubscriptionId) String() string { - segments := []string{} - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Subscription", segmentsStr) -} - -func (id SubscriptionId) ID() string { - fmtString := "/subscriptions/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId) -} - -// ParseSubscriptionID parses a Subscription ID into an SubscriptionId struct +// ParseSubscriptionID parses 'input' into a SubscriptionId func ParseSubscriptionID(input string) (*SubscriptionId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(SubscriptionId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := SubscriptionId{ - SubscriptionId: id.SubscriptionID, - } + var ok bool + id := SubscriptionId{} - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err - } - - return &resourceId, nil + return &id, nil } -// ParseSubscriptionIDInsensitively parses an Subscription ID into an SubscriptionId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseSubscriptionID method should be used instead for validation etc. +// ParseSubscriptionIDInsensitively parses 'input' case-insensitively into a SubscriptionId +// note: this method should only be used for API response data and not user input func ParseSubscriptionIDInsensitively(input string) (*SubscriptionId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(SubscriptionId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := SubscriptionId{ - SubscriptionId: id.SubscriptionID, + var ok bool + id := SubscriptionId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + return &id, nil +} + +// ValidateSubscriptionID checks that 'input' can be parsed as a Subscription ID +func ValidateSubscriptionID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if _, err := ParseSubscriptionID(v); err != nil { + errors = append(errors, err) } - return &resourceId, nil + return +} + +// ID returns the formatted Subscription ID +func (id SubscriptionId) ID() string { + fmtString := "/subscriptions/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId) +} + +// Segments returns a slice of Resource ID Segments which comprise this Subscription ID +func (id SubscriptionId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + } +} + +// String returns a human-readable description of this Subscription ID +func (id SubscriptionId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + } + return fmt.Sprintf("Subscription (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription_test.go b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription_test.go index e54f8e4a0d5c..6ae263491dd0 100644 --- a/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/cognitiveservicesaccounts/id_subscription_test.go @@ -6,13 +6,21 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = SubscriptionId{} +var _ resourceids.ResourceId = SubscriptionId{} -func TestSubscriptionIDFormatter(t *testing.T) { - actual := NewSubscriptionID("{subscriptionId}").ID() - expected := "/subscriptions/{subscriptionId}" +func TestNewSubscriptionID(t *testing.T) { + id := NewSubscriptionID("12345678-1234-9876-4563-123456789012") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } +} + +func TestFormatSubscriptionID(t *testing.T) { + actual := NewSubscriptionID("12345678-1234-9876-4563-123456789012").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,40 +30,29 @@ func TestParseSubscriptionID(t *testing.T) { Error bool Expected *SubscriptionId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/{subscriptionId}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -65,7 +62,7 @@ func TestParseSubscriptionID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -74,6 +71,7 @@ func TestParseSubscriptionID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } + } } @@ -83,58 +81,46 @@ func TestParseSubscriptionIDInsensitively(t *testing.T) { Error bool Expected *SubscriptionId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", }, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}", - Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", - }, + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/extra", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}", + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}", - Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", - }, + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/extra", + Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -144,7 +130,7 @@ func TestParseSubscriptionIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -153,5 +139,6 @@ func TestParseSubscriptionIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/constants.go b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/constants.go index ff30f30c3a1b..32001a4a5e77 100644 --- a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/constants.go +++ b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/constants.go @@ -1,5 +1,7 @@ package privateendpointconnections +import "strings" + type CreatedByType string const ( @@ -9,6 +11,31 @@ const ( CreatedByTypeUser CreatedByType = "User" ) +func PossibleValuesForCreatedByType() []string { + return []string{ + string(CreatedByTypeApplication), + string(CreatedByTypeKey), + string(CreatedByTypeManagedIdentity), + string(CreatedByTypeUser), + } +} + +func parseCreatedByType(input string) (*CreatedByType, error) { + vals := map[string]CreatedByType{ + "application": CreatedByTypeApplication, + "key": CreatedByTypeKey, + "managedidentity": CreatedByTypeManagedIdentity, + "user": CreatedByTypeUser, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := CreatedByType(input) + return &out, nil +} + type PrivateEndpointConnectionProvisioningState string const ( @@ -18,6 +45,31 @@ const ( PrivateEndpointConnectionProvisioningStateSucceeded PrivateEndpointConnectionProvisioningState = "Succeeded" ) +func PossibleValuesForPrivateEndpointConnectionProvisioningState() []string { + return []string{ + string(PrivateEndpointConnectionProvisioningStateCreating), + string(PrivateEndpointConnectionProvisioningStateDeleting), + string(PrivateEndpointConnectionProvisioningStateFailed), + string(PrivateEndpointConnectionProvisioningStateSucceeded), + } +} + +func parsePrivateEndpointConnectionProvisioningState(input string) (*PrivateEndpointConnectionProvisioningState, error) { + vals := map[string]PrivateEndpointConnectionProvisioningState{ + "creating": PrivateEndpointConnectionProvisioningStateCreating, + "deleting": PrivateEndpointConnectionProvisioningStateDeleting, + "failed": PrivateEndpointConnectionProvisioningStateFailed, + "succeeded": PrivateEndpointConnectionProvisioningStateSucceeded, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := PrivateEndpointConnectionProvisioningState(input) + return &out, nil +} + type PrivateEndpointServiceConnectionStatus string const ( @@ -25,3 +77,26 @@ const ( PrivateEndpointServiceConnectionStatusPending PrivateEndpointServiceConnectionStatus = "Pending" PrivateEndpointServiceConnectionStatusRejected PrivateEndpointServiceConnectionStatus = "Rejected" ) + +func PossibleValuesForPrivateEndpointServiceConnectionStatus() []string { + return []string{ + string(PrivateEndpointServiceConnectionStatusApproved), + string(PrivateEndpointServiceConnectionStatusPending), + string(PrivateEndpointServiceConnectionStatusRejected), + } +} + +func parsePrivateEndpointServiceConnectionStatus(input string) (*PrivateEndpointServiceConnectionStatus, error) { + vals := map[string]PrivateEndpointServiceConnectionStatus{ + "approved": PrivateEndpointServiceConnectionStatusApproved, + "pending": PrivateEndpointServiceConnectionStatusPending, + "rejected": PrivateEndpointServiceConnectionStatusRejected, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := PrivateEndpointServiceConnectionStatus(input) + return &out, nil +} diff --git a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account.go b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account.go index 39aeef726922..ce1cb72aa46a 100644 --- a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account.go +++ b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account.go @@ -7,102 +7,118 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = AccountId{} + +// AccountId is a struct representing the Resource ID for a Account type AccountId struct { - SubscriptionId string - ResourceGroup string - Name string + SubscriptionId string + ResourceGroupName string + AccountName string } -func NewAccountID(subscriptionId, resourceGroup, name string) AccountId { +// NewAccountID returns a new AccountId struct +func NewAccountID(subscriptionId string, resourceGroupName string, accountName string) AccountId { return AccountId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, - Name: name, + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + AccountName: accountName, } } -func (id AccountId) String() string { - segments := []string{ - fmt.Sprintf("Name %q", id.Name), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Account", segmentsStr) -} - -func (id AccountId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.Name) -} - -// ParseAccountID parses a Account ID into an AccountId struct +// ParseAccountID parses 'input' into a AccountId func ParseAccountID(input string) (*AccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(AccountId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err - } - - resourceId := AccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } + var ok bool + id := AccountId{} - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.Name, err = id.PopSegment("accounts"); err != nil { - return nil, err + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - return &resourceId, nil + return &id, nil } -// ParseAccountIDInsensitively parses an Account ID into an AccountId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseAccountID method should be used instead for validation etc. +// ParseAccountIDInsensitively parses 'input' case-insensitively into a AccountId +// note: this method should only be used for API response data and not user input func ParseAccountIDInsensitively(input string) (*AccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(AccountId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := AccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + var ok bool + id := AccountId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - // find the correct casing for the 'accounts' segment - accountsKey := "accounts" - for key := range id.Path { - if strings.EqualFold(key, accountsKey) { - accountsKey = key - break - } + return &id, nil +} + +// ValidateAccountID checks that 'input' can be parsed as a Account ID +func ValidateAccountID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if resourceId.Name, err = id.PopSegment(accountsKey); err != nil { - return nil, err + + if _, err := ParseAccountID(v); err != nil { + errors = append(errors, err) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + return +} + +// ID returns the formatted Account ID +func (id AccountId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.AccountName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Account ID +func (id AccountId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("resourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("providers", "providers", "providers"), + resourceids.ResourceProviderSegment("microsoftCognitiveServices", "Microsoft.CognitiveServices", "Microsoft.CognitiveServices"), + resourceids.StaticSegment("accounts", "accounts", "accounts"), + resourceids.UserSpecifiedSegment("accountName", "accountValue"), } +} - return &resourceId, nil +// String returns a human-readable description of this Account ID +func (id AccountId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Account Name: %q", id.AccountName), + } + return fmt.Sprintf("Account (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account_test.go b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account_test.go index 1043d6610392..92510eac67b6 100644 --- a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_account_test.go @@ -6,13 +6,29 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = AccountId{} +var _ resourceids.ResourceId = AccountId{} -func TestAccountIDFormatter(t *testing.T) { - actual := NewAccountID("{subscriptionId}", "{resourceGroupName}", "{accountName}").ID() - expected := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}" +func TestNewAccountID(t *testing.T) { + id := NewAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.AccountName != "accountValue" { + t.Fatalf("Expected %q but got %q for Segment 'AccountName'", id.AccountName, "accountValue") + } +} + +func TestFormatAccountID(t *testing.T) { + actual := NewAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,66 +38,61 @@ func TestParseAccountID(t *testing.T) { Error bool Expected *AccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/RESOURCEGROUPS/{RESOURCEGROUPNAME}/PROVIDERS/MICROSOFT.COGNITIVESERVICES/ACCOUNTS/{ACCOUNTNAME}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -91,7 +102,7 @@ func TestParseAccountID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -100,12 +111,15 @@ func TestParseAccountID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } @@ -115,90 +129,110 @@ func TestParseAccountIDInsensitively(t *testing.T) { Error bool Expected *AccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", - Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", - Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/ACCOUNTS/{accountName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/AcCoUnTs/{accountName}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + AccountName: "aCcOuNtVaLuE", }, }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE/extra", + Error: true, + }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -208,7 +242,7 @@ func TestParseAccountIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -217,11 +251,14 @@ func TestParseAccountIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection.go b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection.go index afa991279fe0..e006a12de4cb 100644 --- a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection.go +++ b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection.go @@ -7,120 +7,131 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = PrivateEndpointConnectionId{} + +// PrivateEndpointConnectionId is a struct representing the Resource ID for a Private Endpoint Connection type PrivateEndpointConnectionId struct { - SubscriptionId string - ResourceGroup string - AccountName string - Name string + SubscriptionId string + ResourceGroupName string + AccountName string + PrivateEndpointConnectionName string } -func NewPrivateEndpointConnectionID(subscriptionId, resourceGroup, accountName, name string) PrivateEndpointConnectionId { +// NewPrivateEndpointConnectionID returns a new PrivateEndpointConnectionId struct +func NewPrivateEndpointConnectionID(subscriptionId string, resourceGroupName string, accountName string, privateEndpointConnectionName string) PrivateEndpointConnectionId { return PrivateEndpointConnectionId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, - AccountName: accountName, - Name: name, + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + AccountName: accountName, + PrivateEndpointConnectionName: privateEndpointConnectionName, } } -func (id PrivateEndpointConnectionId) String() string { - segments := []string{ - fmt.Sprintf("Name %q", id.Name), - fmt.Sprintf("Account Name %q", id.AccountName), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Private Endpoint Connection", segmentsStr) -} - -func (id PrivateEndpointConnectionId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s/privateEndpointConnections/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.AccountName, id.Name) -} - -// ParsePrivateEndpointConnectionID parses a PrivateEndpointConnection ID into an PrivateEndpointConnectionId struct +// ParsePrivateEndpointConnectionID parses 'input' into a PrivateEndpointConnectionId func ParsePrivateEndpointConnectionID(input string) (*PrivateEndpointConnectionId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(PrivateEndpointConnectionId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := PrivateEndpointConnectionId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, - } + var ok bool + id := PrivateEndpointConnectionId{} - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if resourceId.AccountName, err = id.PopSegment("accounts"); err != nil { - return nil, err - } - if resourceId.Name, err = id.PopSegment("privateEndpointConnections"); err != nil { - return nil, err + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if id.PrivateEndpointConnectionName, ok = parsed.Parsed["privateEndpointConnectionName"]; !ok { + return nil, fmt.Errorf("the segment 'privateEndpointConnectionName' was not found in the resource id %q", input) } - return &resourceId, nil + return &id, nil } -// ParsePrivateEndpointConnectionIDInsensitively parses an PrivateEndpointConnection ID into an PrivateEndpointConnectionId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParsePrivateEndpointConnectionID method should be used instead for validation etc. +// ParsePrivateEndpointConnectionIDInsensitively parses 'input' case-insensitively into a PrivateEndpointConnectionId +// note: this method should only be used for API response data and not user input func ParsePrivateEndpointConnectionIDInsensitively(input string) (*PrivateEndpointConnectionId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(PrivateEndpointConnectionId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := PrivateEndpointConnectionId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, - } + var ok bool + id := PrivateEndpointConnectionId{} - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - // find the correct casing for the 'accounts' segment - accountsKey := "accounts" - for key := range id.Path { - if strings.EqualFold(key, accountsKey) { - accountsKey = key - break - } + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - if resourceId.AccountName, err = id.PopSegment(accountsKey); err != nil { - return nil, err + + if id.PrivateEndpointConnectionName, ok = parsed.Parsed["privateEndpointConnectionName"]; !ok { + return nil, fmt.Errorf("the segment 'privateEndpointConnectionName' was not found in the resource id %q", input) } - // find the correct casing for the 'privateEndpointConnections' segment - privateEndpointConnectionsKey := "privateEndpointConnections" - for key := range id.Path { - if strings.EqualFold(key, privateEndpointConnectionsKey) { - privateEndpointConnectionsKey = key - break - } + return &id, nil +} + +// ValidatePrivateEndpointConnectionID checks that 'input' can be parsed as a Private Endpoint Connection ID +func ValidatePrivateEndpointConnectionID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if resourceId.Name, err = id.PopSegment(privateEndpointConnectionsKey); err != nil { - return nil, err + + if _, err := ParsePrivateEndpointConnectionID(v); err != nil { + errors = append(errors, err) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + return +} + +// ID returns the formatted Private Endpoint Connection ID +func (id PrivateEndpointConnectionId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s/privateEndpointConnections/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.AccountName, id.PrivateEndpointConnectionName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Private Endpoint Connection ID +func (id PrivateEndpointConnectionId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("resourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("providers", "providers", "providers"), + resourceids.ResourceProviderSegment("microsoftCognitiveServices", "Microsoft.CognitiveServices", "Microsoft.CognitiveServices"), + resourceids.StaticSegment("accounts", "accounts", "accounts"), + resourceids.UserSpecifiedSegment("accountName", "accountValue"), + resourceids.StaticSegment("privateEndpointConnections", "privateEndpointConnections", "privateEndpointConnections"), + resourceids.UserSpecifiedSegment("privateEndpointConnectionName", "privateEndpointConnectionValue"), } +} - return &resourceId, nil +// String returns a human-readable description of this Private Endpoint Connection ID +func (id PrivateEndpointConnectionId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Account Name: %q", id.AccountName), + fmt.Sprintf("Private Endpoint Connection Name: %q", id.PrivateEndpointConnectionName), + } + return fmt.Sprintf("Private Endpoint Connection (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection_test.go b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection_test.go index 52ed48096d1b..e93b9e4c382d 100644 --- a/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/privateendpointconnections/id_privateendpointconnection_test.go @@ -6,13 +6,33 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = PrivateEndpointConnectionId{} +var _ resourceids.ResourceId = PrivateEndpointConnectionId{} -func TestPrivateEndpointConnectionIDFormatter(t *testing.T) { - actual := NewPrivateEndpointConnectionID("{subscriptionId}", "{resourceGroupName}", "{accountName}", "{privateEndpointConnectionName}").ID() - expected := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/privateEndpointConnections/{privateEndpointConnectionName}" +func TestNewPrivateEndpointConnectionID(t *testing.T) { + id := NewPrivateEndpointConnectionID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue", "privateEndpointConnectionValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.AccountName != "accountValue" { + t.Fatalf("Expected %q but got %q for Segment 'AccountName'", id.AccountName, "accountValue") + } + + if id.PrivateEndpointConnectionName != "privateEndpointConnectionValue" { + t.Fatalf("Expected %q but got %q for Segment 'PrivateEndpointConnectionName'", id.PrivateEndpointConnectionName, "privateEndpointConnectionValue") + } +} + +func TestFormatPrivateEndpointConnectionID(t *testing.T) { + actual := NewPrivateEndpointConnectionID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue", "privateEndpointConnectionValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/privateEndpointConnections/privateEndpointConnectionValue" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,79 +42,72 @@ func TestParsePrivateEndpointConnectionID(t *testing.T) { Error bool Expected *PrivateEndpointConnectionId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", Error: true, }, - { - // missing AccountName - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", Error: true, }, - { - // missing value for AccountName - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/privateEndpointConnections/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/privateEndpointConnections", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/privateEndpointConnections/{privateEndpointConnectionName}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/privateEndpointConnections/privateEndpointConnectionValue", Expected: &PrivateEndpointConnectionId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - AccountName: "{accountName}", - Name: "{privateEndpointConnectionName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", + PrivateEndpointConnectionName: "privateEndpointConnectionValue", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/RESOURCEGROUPS/{RESOURCEGROUPNAME}/PROVIDERS/MICROSOFT.COGNITIVESERVICES/ACCOUNTS/{ACCOUNTNAME}/PRIVATEENDPOINTCONNECTIONS/{PRIVATEENDPOINTCONNECTIONNAME}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/privateEndpointConnections/privateEndpointConnectionValue/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -104,7 +117,7 @@ func TestParsePrivateEndpointConnectionID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -113,15 +126,19 @@ func TestParsePrivateEndpointConnectionID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } + if actual.AccountName != v.Expected.AccountName { t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.PrivateEndpointConnectionName != v.Expected.PrivateEndpointConnectionName { + t.Fatalf("Expected %q but got %q for PrivateEndpointConnectionName", v.Expected.PrivateEndpointConnectionName, actual.PrivateEndpointConnectionName) } + } } @@ -131,106 +148,132 @@ func TestParsePrivateEndpointConnectionIDInsensitively(t *testing.T) { Error bool Expected *PrivateEndpointConnectionId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing AccountName - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for AccountName - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/privateEndpointConnections/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/privateEndpointConnections/{privateEndpointConnectionName}", - Expected: &PrivateEndpointConnectionId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - AccountName: "{accountName}", - Name: "{privateEndpointConnectionName}", - }, + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/privateendpointconnections/{privateEndpointConnectionName}", - Expected: &PrivateEndpointConnectionId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - AccountName: "{accountName}", - Name: "{privateEndpointConnectionName}", - }, + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/ACCOUNTS/{accountName}/PRIVATEENDPOINTCONNECTIONS/{privateEndpointConnectionName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/privateEndpointConnections", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE/pRiVaTeEnDpOiNtCoNnEcTiOnS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/privateEndpointConnections/privateEndpointConnectionValue", Expected: &PrivateEndpointConnectionId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - AccountName: "{accountName}", - Name: "{privateEndpointConnectionName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", + PrivateEndpointConnectionName: "privateEndpointConnectionValue", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/AcCoUnTs/{accountName}/PrIvAtEeNdPoInTcOnNeCtIoNs/{privateEndpointConnectionName}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/privateEndpointConnections/privateEndpointConnectionValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE/pRiVaTeEnDpOiNtCoNnEcTiOnS/pRiVaTeEnDpOiNtCoNnEcTiOnVaLuE", Expected: &PrivateEndpointConnectionId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - AccountName: "{accountName}", - Name: "{privateEndpointConnectionName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + AccountName: "aCcOuNtVaLuE", + PrivateEndpointConnectionName: "pRiVaTeEnDpOiNtCoNnEcTiOnVaLuE", }, }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE/pRiVaTeEnDpOiNtCoNnEcTiOnS/pRiVaTeEnDpOiNtCoNnEcTiOnVaLuE/extra", + Error: true, + }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -240,7 +283,7 @@ func TestParsePrivateEndpointConnectionIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -249,14 +292,18 @@ func TestParsePrivateEndpointConnectionIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } + if actual.AccountName != v.Expected.AccountName { t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.PrivateEndpointConnectionName != v.Expected.PrivateEndpointConnectionName { + t.Fatalf("Expected %q but got %q for PrivateEndpointConnectionName", v.Expected.PrivateEndpointConnectionName, actual.PrivateEndpointConnectionName) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account.go b/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account.go index d981c17347f7..209a21ac0d21 100644 --- a/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account.go +++ b/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account.go @@ -7,102 +7,118 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = AccountId{} + +// AccountId is a struct representing the Resource ID for a Account type AccountId struct { - SubscriptionId string - ResourceGroup string - Name string + SubscriptionId string + ResourceGroupName string + AccountName string } -func NewAccountID(subscriptionId, resourceGroup, name string) AccountId { +// NewAccountID returns a new AccountId struct +func NewAccountID(subscriptionId string, resourceGroupName string, accountName string) AccountId { return AccountId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, - Name: name, + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + AccountName: accountName, } } -func (id AccountId) String() string { - segments := []string{ - fmt.Sprintf("Name %q", id.Name), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Account", segmentsStr) -} - -func (id AccountId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.Name) -} - -// ParseAccountID parses a Account ID into an AccountId struct +// ParseAccountID parses 'input' into a AccountId func ParseAccountID(input string) (*AccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(AccountId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err - } - - resourceId := AccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } + var ok bool + id := AccountId{} - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.Name, err = id.PopSegment("accounts"); err != nil { - return nil, err + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - return &resourceId, nil + return &id, nil } -// ParseAccountIDInsensitively parses an Account ID into an AccountId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseAccountID method should be used instead for validation etc. +// ParseAccountIDInsensitively parses 'input' case-insensitively into a AccountId +// note: this method should only be used for API response data and not user input func ParseAccountIDInsensitively(input string) (*AccountId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(AccountId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := AccountId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, + var ok bool + id := AccountId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) } - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + if id.AccountName, ok = parsed.Parsed["accountName"]; !ok { + return nil, fmt.Errorf("the segment 'accountName' was not found in the resource id %q", input) } - // find the correct casing for the 'accounts' segment - accountsKey := "accounts" - for key := range id.Path { - if strings.EqualFold(key, accountsKey) { - accountsKey = key - break - } + return &id, nil +} + +// ValidateAccountID checks that 'input' can be parsed as a Account ID +func ValidateAccountID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if resourceId.Name, err = id.PopSegment(accountsKey); err != nil { - return nil, err + + if _, err := ParseAccountID(v); err != nil { + errors = append(errors, err) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + return +} + +// ID returns the formatted Account ID +func (id AccountId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.CognitiveServices/accounts/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.AccountName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Account ID +func (id AccountId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("resourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("providers", "providers", "providers"), + resourceids.ResourceProviderSegment("microsoftCognitiveServices", "Microsoft.CognitiveServices", "Microsoft.CognitiveServices"), + resourceids.StaticSegment("accounts", "accounts", "accounts"), + resourceids.UserSpecifiedSegment("accountName", "accountValue"), } +} - return &resourceId, nil +// String returns a human-readable description of this Account ID +func (id AccountId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Account Name: %q", id.AccountName), + } + return fmt.Sprintf("Account (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account_test.go b/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account_test.go index dbbd275a51d3..711d49b0723a 100644 --- a/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/privatelinkresources/id_account_test.go @@ -6,13 +6,29 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = AccountId{} +var _ resourceids.ResourceId = AccountId{} -func TestAccountIDFormatter(t *testing.T) { - actual := NewAccountID("{subscriptionId}", "{resourceGroupName}", "{accountName}").ID() - expected := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}" +func TestNewAccountID(t *testing.T) { + id := NewAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.AccountName != "accountValue" { + t.Fatalf("Expected %q but got %q for Segment 'AccountName'", id.AccountName, "accountValue") + } +} + +func TestFormatAccountID(t *testing.T) { + actual := NewAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "accountValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,66 +38,61 @@ func TestParseAccountID(t *testing.T) { Error bool Expected *AccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}/RESOURCEGROUPS/{RESOURCEGROUPNAME}/PROVIDERS/MICROSOFT.COGNITIVESERVICES/ACCOUNTS/{ACCOUNTNAME}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -91,7 +102,7 @@ func TestParseAccountID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -100,12 +111,15 @@ func TestParseAccountID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } @@ -115,90 +129,110 @@ func TestParseAccountIDInsensitively(t *testing.T) { Error bool Expected *AccountId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // missing ResourceGroup - Input: "/subscriptions/{subscriptionId}/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing value for ResourceGroup - Input: "/subscriptions/{subscriptionId}/resourceGroups/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Error: true, }, - { - // missing Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", Error: true, }, - { - // missing value for Name - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", - Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}", - Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", - }, + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/ACCOUNTS/{accountName}", + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + AccountName: "accountValue", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/AcCoUnTs/{accountName}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.CognitiveServices/accounts/accountValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE", Expected: &AccountId{ - SubscriptionId: "{subscriptionId}", - ResourceGroup: "{resourceGroupName}", - Name: "{accountName}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + AccountName: "aCcOuNtVaLuE", }, }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOgNiTiVeSeRvIcEs/aCcOuNtS/aCcOuNtVaLuE/extra", + Error: true, + }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -208,7 +242,7 @@ func TestParseAccountIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -217,11 +251,14 @@ func TestParseAccountIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + + if actual.AccountName != v.Expected.AccountName { + t.Fatalf("Expected %q but got %q for AccountName", v.Expected.AccountName, actual.AccountName) } + } } diff --git a/internal/services/cognitive/sdk/2021-04-30/skus/constants.go b/internal/services/cognitive/sdk/2021-04-30/skus/constants.go index aae1c370ac3f..054306744526 100644 --- a/internal/services/cognitive/sdk/2021-04-30/skus/constants.go +++ b/internal/services/cognitive/sdk/2021-04-30/skus/constants.go @@ -1,5 +1,7 @@ package skus +import "strings" + type ResourceSkuRestrictionsReasonCode string const ( @@ -7,9 +9,51 @@ const ( ResourceSkuRestrictionsReasonCodeQuotaId ResourceSkuRestrictionsReasonCode = "QuotaId" ) +func PossibleValuesForResourceSkuRestrictionsReasonCode() []string { + return []string{ + string(ResourceSkuRestrictionsReasonCodeNotAvailableForSubscription), + string(ResourceSkuRestrictionsReasonCodeQuotaId), + } +} + +func parseResourceSkuRestrictionsReasonCode(input string) (*ResourceSkuRestrictionsReasonCode, error) { + vals := map[string]ResourceSkuRestrictionsReasonCode{ + "notavailableforsubscription": ResourceSkuRestrictionsReasonCodeNotAvailableForSubscription, + "quotaid": ResourceSkuRestrictionsReasonCodeQuotaId, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ResourceSkuRestrictionsReasonCode(input) + return &out, nil +} + type ResourceSkuRestrictionsType string const ( ResourceSkuRestrictionsTypeLocation ResourceSkuRestrictionsType = "Location" ResourceSkuRestrictionsTypeZone ResourceSkuRestrictionsType = "Zone" ) + +func PossibleValuesForResourceSkuRestrictionsType() []string { + return []string{ + string(ResourceSkuRestrictionsTypeLocation), + string(ResourceSkuRestrictionsTypeZone), + } +} + +func parseResourceSkuRestrictionsType(input string) (*ResourceSkuRestrictionsType, error) { + vals := map[string]ResourceSkuRestrictionsType{ + "location": ResourceSkuRestrictionsTypeLocation, + "zone": ResourceSkuRestrictionsTypeZone, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ResourceSkuRestrictionsType(input) + return &out, nil +} diff --git a/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription.go b/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription.go index cc9b8460e057..08c85415b21e 100644 --- a/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription.go +++ b/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription.go @@ -7,69 +7,90 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) +var _ resourceids.ResourceId = SubscriptionId{} + +// SubscriptionId is a struct representing the Resource ID for a Subscription type SubscriptionId struct { SubscriptionId string } +// NewSubscriptionID returns a new SubscriptionId struct func NewSubscriptionID(subscriptionId string) SubscriptionId { return SubscriptionId{ SubscriptionId: subscriptionId, } } -func (id SubscriptionId) String() string { - segments := []string{} - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Subscription", segmentsStr) -} - -func (id SubscriptionId) ID() string { - fmtString := "/subscriptions/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId) -} - -// ParseSubscriptionID parses a Subscription ID into an SubscriptionId struct +// ParseSubscriptionID parses 'input' into a SubscriptionId func ParseSubscriptionID(input string) (*SubscriptionId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(SubscriptionId{}) + parsed, err := parser.Parse(input, false) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := SubscriptionId{ - SubscriptionId: id.SubscriptionID, - } + var ok bool + id := SubscriptionId{} - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err - } - - return &resourceId, nil + return &id, nil } -// ParseSubscriptionIDInsensitively parses an Subscription ID into an SubscriptionId struct, insensitively -// This should only be used to parse an ID for rewriting to a consistent casing, -// the ParseSubscriptionID method should be used instead for validation etc. +// ParseSubscriptionIDInsensitively parses 'input' case-insensitively into a SubscriptionId +// note: this method should only be used for API response data and not user input func ParseSubscriptionIDInsensitively(input string) (*SubscriptionId, error) { - id, err := resourceids.ParseAzureResourceID(input) + parser := resourceids.NewParserFromResourceIdType(SubscriptionId{}) + parsed, err := parser.Parse(input, true) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing %q: %+v", input, err) } - resourceId := SubscriptionId{ - SubscriptionId: id.SubscriptionID, + var ok bool + id := SubscriptionId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) } - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + return &id, nil +} + +// ValidateSubscriptionID checks that 'input' can be parsed as a Subscription ID +func ValidateSubscriptionID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return } - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err + if _, err := ParseSubscriptionID(v); err != nil { + errors = append(errors, err) } - return &resourceId, nil + return +} + +// ID returns the formatted Subscription ID +func (id SubscriptionId) ID() string { + fmtString := "/subscriptions/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId) +} + +// Segments returns a slice of Resource ID Segments which comprise this Subscription ID +func (id SubscriptionId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("subscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + } +} + +// String returns a human-readable description of this Subscription ID +func (id SubscriptionId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + } + return fmt.Sprintf("Subscription (%s)", strings.Join(components, "\n")) } diff --git a/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription_test.go b/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription_test.go index 070e14575109..57ca9adc5efc 100644 --- a/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription_test.go +++ b/internal/services/cognitive/sdk/2021-04-30/skus/id_subscription_test.go @@ -6,13 +6,21 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" ) -var _ resourceids.Id = SubscriptionId{} +var _ resourceids.ResourceId = SubscriptionId{} -func TestSubscriptionIDFormatter(t *testing.T) { - actual := NewSubscriptionID("{subscriptionId}").ID() - expected := "/subscriptions/{subscriptionId}" +func TestNewSubscriptionID(t *testing.T) { + id := NewSubscriptionID("12345678-1234-9876-4563-123456789012") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } +} + +func TestFormatSubscriptionID(t *testing.T) { + actual := NewSubscriptionID("12345678-1234-9876-4563-123456789012").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012" if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) + t.Fatalf("Expected the Formatted ID to be %q but got %q", actual, expected) } } @@ -22,40 +30,29 @@ func TestParseSubscriptionID(t *testing.T) { Error bool Expected *SubscriptionId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/{subscriptionId}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", }, }, - { - // upper-cased - Input: "/SUBSCRIPTIONS/{SUBSCRIPTIONID}", + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/extra", Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -65,7 +62,7 @@ func TestParseSubscriptionID(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -74,6 +71,7 @@ func TestParseSubscriptionID(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } + } } @@ -83,58 +81,46 @@ func TestParseSubscriptionIDInsensitively(t *testing.T) { Error bool Expected *SubscriptionId }{ - { - // empty + // Incomplete URI Input: "", Error: true, }, - { - // missing SubscriptionId - Input: "/", + // Incomplete URI + Input: "/subscriptions", Error: true, }, - { - // missing value for SubscriptionId - Input: "/subscriptions/", + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", Error: true, }, - { - // valid - Input: "/subscriptions/{subscriptionId}", + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", }, }, - { - // lower-cased segment names - Input: "/subscriptions/{subscriptionId}", - Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", - }, + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/extra", + Error: true, }, - { - // upper-cased segment names - Input: "/subscriptions/{subscriptionId}", + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", + SubscriptionId: "12345678-1234-9876-4563-123456789012", }, }, - { - // mixed-cased segment names - Input: "/subscriptions/{subscriptionId}", - Expected: &SubscriptionId{ - SubscriptionId: "{subscriptionId}", - }, + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/extra", + Error: true, }, } - for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Input) @@ -144,7 +130,7 @@ func TestParseSubscriptionIDInsensitively(t *testing.T) { continue } - t.Fatalf("Expect a value but got an error: %s", err) + t.Fatalf("Expect a value but got an error: %+v", err) } if v.Error { t.Fatal("Expect an error but didn't get one") @@ -153,5 +139,6 @@ func TestParseSubscriptionIDInsensitively(t *testing.T) { if actual.SubscriptionId != v.Expected.SubscriptionId { t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) } + } }