diff --git a/resourcemanager/commonids/shared_image_gallery.go b/resourcemanager/commonids/shared_image_gallery.go new file mode 100644 index 0000000..0c7cc58 --- /dev/null +++ b/resourcemanager/commonids/shared_image_gallery.go @@ -0,0 +1,127 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package commonids + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = SharedImageGalleryId{} + +// SharedImageGalleryId is a struct representing the Resource ID for a Shared Image Gallery +type SharedImageGalleryId struct { + SubscriptionId string + ResourceGroupName string + GalleryName string +} + +// NewSharedImageGalleryID returns a new sharedImageGalleryId struct +func NewSharedImageGalleryID(subscriptionId string, resourceGroupName string, galleryName string) SharedImageGalleryId { + return SharedImageGalleryId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + GalleryName: galleryName, + } +} + +// ParseSharedImageGalleryID parses 'input' into a sharedImageGalleryId +func ParseSharedImageGalleryID(input string) (*SharedImageGalleryId, error) { + parser := resourceids.NewParserFromResourceIdType(SharedImageGalleryId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := SharedImageGalleryId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) + } + + if id.GalleryName, ok = parsed.Parsed["galleryName"]; !ok { + return nil, resourceids.NewSegmentNotSpecifiedError(id, "galleryName", *parsed) + } + + return &id, nil +} + +// ParseSharedImageGalleryIDInsensitively parses 'input' case-insensitively into a sharedImageGalleryId +// note: this method should only be used for API response data and not user input +func ParseSharedImageGalleryIDInsensitively(input string) (*SharedImageGalleryId, error) { + parser := resourceids.NewParserFromResourceIdType(SharedImageGalleryId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := SharedImageGalleryId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) + } + + if id.GalleryName, ok = parsed.Parsed["galleryName"]; !ok { + return nil, resourceids.NewSegmentNotSpecifiedError(id, "galleryName", *parsed) + } + + return &id, nil +} + +// ValidateSharedImageGalleryID validates the ID of a Shared Image Gallery +func ValidateSharedImageGalleryID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected string, got %T", input)) + return + } + + if _, err := ParseSharedImageGalleryID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Shared Image Gallery ID +func (id SharedImageGalleryId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/galleries/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.GalleryName) +} + +// String returns a human-readable description of the Shared Image Gallery ID +func (id SharedImageGalleryId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Gallery Name: %q", id.GalleryName), + } + return fmt.Sprintf("Shared Image Gallery (%s)", strings.Join(components, "\n")) +} + +// Segments returns a slice of Resource ID Segments which comprise this Shared Image Gallery ID +func (id SharedImageGalleryId) 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("staticMicrosoftCompute", "Microsoft.Compute", "Microsoft.Compute"), + resourceids.StaticSegment("staticGalleries", "galleries", "galleries"), + resourceids.UserSpecifiedSegment("galleryName", "galleryValue"), + } +} diff --git a/resourcemanager/commonids/shared_image_gallery_test.go b/resourcemanager/commonids/shared_image_gallery_test.go new file mode 100644 index 0000000..09d3fd7 --- /dev/null +++ b/resourcemanager/commonids/shared_image_gallery_test.go @@ -0,0 +1,279 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package commonids + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = SharedImageGalleryId{} + +func TestNewSharedImageGalleryID(t *testing.T) { + id := NewSharedImageGalleryID("12345678-1234-9876-4563-123456789012", "example-resource-group", "galleryValue") + + 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.GalleryName != "galleryValue" { + t.Fatalf("Expected %q but got %q for Segment 'GalleryName'", id.GalleryName, "galleryValue") + } +} + +func TestFormatSharedImageGalleryID(t *testing.T) { + actual := NewSharedImageGalleryID("12345678-1234-9876-4563-123456789012", "example-resource-group", "galleryValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/galleries/galleryValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseSharedImageGalleryID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *SharedImageGalleryId + }{ + { + // 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.Compute", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/galleries", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/galleries/galleryValue", + Expected: &SharedImageGalleryId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + GalleryName: "galleryValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/galleries/galleryValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseSharedImageGalleryID(v.Input) + if err != nil { + if v.Error { + continue + } + t.Fatalf("Expected no error but got %q", err) + } + if v.Error { + t.Fatalf("Expected an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.GalleryName != v.Expected.GalleryName { + t.Fatalf("Expected %q but got %q for Segment 'GalleryName'", v.Expected.GalleryName, actual.GalleryName) + } + } +} + +func TestParseSharedImageGalleryIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *SharedImageGalleryId + }{ + { + // 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.Compute", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOmPuTe", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/galleries", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOmPuTe/gAlLeRiEs", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/galleries/galleryValue", + Expected: &SharedImageGalleryId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + GalleryName: "galleryValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Compute/galleries/galleryValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.cOmPuTe/gAlLeRiEs/gAlLeRyVaLuE", + Expected: &SharedImageGalleryId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + GalleryName: "gAlLeRyVaLuE", + }, + }, + { + // 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.cOmPuTe/gAlLeRiEs/gAlLeRyVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseSharedImageGalleryIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expected no error but got %q", err) + } + if v.Error { + t.Fatalf("Expected an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.GalleryName != v.Expected.GalleryName { + t.Fatalf("Expected %q but got %q for Segment 'GalleryName'", v.Expected.GalleryName, actual.GalleryName) + } + } +} + +func TestValidateSharedImageGalleryID(t *testing.T) { + segments := SharedImageGalleryId{}.Segments() + if len(segments) == 0 { + t.Fatalf("SharedImageGalleryId 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)) + } +}