From b0922b7d21f4c8d21dbcff67af5f5b8f5a56039a Mon Sep 17 00:00:00 2001 From: teowa <104055472+teowa@users.noreply.github.com> Date: Thu, 6 Mar 2025 02:01:29 +0000 Subject: [PATCH] add cosmosdb commonid --- resourcemanager/commonids/cosmosdb_account.go | 122 ++++++++ .../commonids/cosmosdb_account_test.go | 279 ++++++++++++++++++ resourcemanager/commonids/ids.go | 2 +- 3 files changed, 402 insertions(+), 1 deletion(-) create mode 100644 resourcemanager/commonids/cosmosdb_account.go create mode 100644 resourcemanager/commonids/cosmosdb_account_test.go diff --git a/resourcemanager/commonids/cosmosdb_account.go b/resourcemanager/commonids/cosmosdb_account.go new file mode 100644 index 0000000..767aaea --- /dev/null +++ b/resourcemanager/commonids/cosmosdb_account.go @@ -0,0 +1,122 @@ +package commonids + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = &CosmosDBAccountId{} + +// CosmosDBAccountId is a struct representing the Resource ID for a CosmosDB Account +type CosmosDBAccountId struct { + SubscriptionId string + ResourceGroupName string + DatabaseAccountName string +} + +// NewCosmosDBAccountID returns a new CosmosDBAccountId struct +func NewCosmosDBAccountID(subscriptionId string, resourceGroupName string, databaseAccountName string) CosmosDBAccountId { + return CosmosDBAccountId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + DatabaseAccountName: databaseAccountName, + } +} + +// ParseCosmosDBAccountID parses 'input' into a CosmosDBAccountId +func ParseCosmosDBAccountID(input string) (*CosmosDBAccountId, error) { + parser := resourceids.NewParserFromResourceIdType(&CosmosDBAccountId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := CosmosDBAccountId{} + if err = id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseCosmosDBAccountIDInsensitively parses 'input' case-insensitively into a CosmosDBAccountId +// note: this method should only be used for API response data and not user input +func ParseCosmosDBAccountIDInsensitively(input string) (*CosmosDBAccountId, error) { + parser := resourceids.NewParserFromResourceIdType(&CosmosDBAccountId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := CosmosDBAccountId{} + if err = id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *CosmosDBAccountId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.SubscriptionId, ok = input.Parsed["subscriptionId"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", input) + } + + if id.ResourceGroupName, ok = input.Parsed["resourceGroupName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", input) + } + + if id.DatabaseAccountName, ok = input.Parsed["databaseAccountName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "databaseAccountName", input) + } + + return nil +} + +// ValidateCosmosDBAccountID checks that 'input' can be parsed as a Database Account ID +func ValidateCosmosDBAccountID(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 := ParseCosmosDBAccountID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Database Account ID +func (id CosmosDBAccountId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.DocumentDB/databaseAccounts/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.DatabaseAccountName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Database Account ID +func (id CosmosDBAccountId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftDocumentDB", "Microsoft.DocumentDB", "Microsoft.DocumentDB"), + resourceids.StaticSegment("staticDatabaseAccounts", "databaseAccounts", "databaseAccounts"), + resourceids.UserSpecifiedSegment("databaseAccountName", "databaseAccountName"), + } +} + +// String returns a human-readable description of this Database Account ID +func (id CosmosDBAccountId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("CosmosDB Account Name: %q", id.DatabaseAccountName), + } + return fmt.Sprintf("CosmosDB Account (%s)", strings.Join(components, "\n")) +} diff --git a/resourcemanager/commonids/cosmosdb_account_test.go b/resourcemanager/commonids/cosmosdb_account_test.go new file mode 100644 index 0000000..4000783 --- /dev/null +++ b/resourcemanager/commonids/cosmosdb_account_test.go @@ -0,0 +1,279 @@ +package commonids + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = &CosmosDBAccountId{} + +func TestNewCosmosDBAccountID(t *testing.T) { + id := NewCosmosDBAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "databaseAccountName") + + 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.DatabaseAccountName != "databaseAccountName" { + t.Fatalf("Expected %q but got %q for Segment 'DatabaseAccountName'", id.DatabaseAccountName, "databaseAccountName") + } +} + +func TestFormatCosmosDBAccountID(t *testing.T) { + actual := NewCosmosDBAccountID("12345678-1234-9876-4563-123456789012", "example-resource-group", "databaseAccountName").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB/databaseAccounts/databaseAccountName" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseCosmosDBAccountID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *CosmosDBAccountId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + 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 + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB/databaseAccounts", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB/databaseAccounts/databaseAccountName", + Expected: &CosmosDBAccountId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + DatabaseAccountName: "databaseAccountName", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB/databaseAccounts/databaseAccountName/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseCosmosDBAccountID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.DatabaseAccountName != v.Expected.DatabaseAccountName { + t.Fatalf("Expected %q but got %q for DatabaseAccountName", v.Expected.DatabaseAccountName, actual.DatabaseAccountName) + } + + } +} + +func TestParseCosmosDBAccountIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *CosmosDBAccountId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // 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.DocumentDB", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.dOcUmEnTdB", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB/databaseAccounts", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.dOcUmEnTdB/dAtAbAsEaCcOuNtS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB/databaseAccounts/databaseAccountName", + Expected: &CosmosDBAccountId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + DatabaseAccountName: "databaseAccountName", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.DocumentDB/databaseAccounts/databaseAccountName/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.dOcUmEnTdB/dAtAbAsEaCcOuNtS/dAtAbAsEaCcOuNtNaMe", + Expected: &CosmosDBAccountId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + DatabaseAccountName: "dAtAbAsEaCcOuNtNaMe", + }, + }, + { + // 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.dOcUmEnTdB/dAtAbAsEaCcOuNtS/dAtAbAsEaCcOuNtNaMe/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseCosmosDBAccountIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.DatabaseAccountName != v.Expected.DatabaseAccountName { + t.Fatalf("Expected %q but got %q for DatabaseAccountName", v.Expected.DatabaseAccountName, actual.DatabaseAccountName) + } + + } +} + +func TestSegmentsForCosmosDBAccountId(t *testing.T) { + segments := CosmosDBAccountId{}.Segments() + if len(segments) == 0 { + t.Fatalf("CosmosDBAccountId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/resourcemanager/commonids/ids.go b/resourcemanager/commonids/ids.go index f875bd4..bc2b366 100644 --- a/resourcemanager/commonids/ids.go +++ b/resourcemanager/commonids/ids.go @@ -8,7 +8,6 @@ import ( ) func CommonIds() []resourceids.ResourceId { - return []resourceids.ResourceId{ &AppServiceId{}, &AppServiceEnvironmentId{}, @@ -21,6 +20,7 @@ func CommonIds() []resourceids.ResourceId { &ChaosStudioTargetId{}, &CloudServicesIPConfigurationId{}, &CloudServicesPublicIPAddressId{}, + &CosmosDBAccountId{}, &DedicatedHostId{}, &DedicatedHostGroupId{}, &DevCenterId{},