diff --git a/resourcemanager/commonids/chaos_studio_capability.go b/resourcemanager/commonids/chaos_studio_capability.go new file mode 100644 index 0000000..145edb2 --- /dev/null +++ b/resourcemanager/commonids/chaos_studio_capability.go @@ -0,0 +1,124 @@ +// 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 = ChaosStudioCapabilityId{} + +// ChaosStudioCapabilityId is a struct representing the Resource ID for an App Service Plan +type ChaosStudioCapabilityId struct { + Scope string + TargetName string + CapabilityName string +} + +// NewChaosStudioCapabilityID returns a new ChaosStudioCapabilityId struct +func NewChaosStudioCapabilityID(scope string, targetName string, capabilityName string) ChaosStudioCapabilityId { + return ChaosStudioCapabilityId{ + Scope: scope, + TargetName: targetName, + CapabilityName: capabilityName, + } +} + +// ParseChaosStudioCapabilityID parses 'input' into a ChaosStudioCapabilityId +func ParseChaosStudioCapabilityID(input string) (*ChaosStudioCapabilityId, error) { + parser := resourceids.NewParserFromResourceIdType(ChaosStudioCapabilityId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ChaosStudioCapabilityId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseChaosStudioCapabilityIDInsensitively parses 'input' case-insensitively into a ChaosStudioCapabilityId +// note: this method should only be used for API response data and not user input +func ParseChaosStudioCapabilityIDInsensitively(input string) (*ChaosStudioCapabilityId, error) { + parser := resourceids.NewParserFromResourceIdType(ChaosStudioCapabilityId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ChaosStudioCapabilityId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *ChaosStudioCapabilityId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.Scope, ok = input.Parsed["scope"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "scope", input) + } + + if id.TargetName, ok = input.Parsed["targetName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "targetName", input) + } + + if id.CapabilityName, ok = input.Parsed["capabilityName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "capabilityName", input) + } + + return nil +} + +// ValidateChaosStudioCapabilityID checks that 'input' can be parsed as an App Service Plan ID +func ValidateChaosStudioCapabilityID(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 := ParseChaosStudioCapabilityID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted App Service Plan ID +func (id ChaosStudioCapabilityId) ID() string { + fmtString := "%s/providers/Microsoft.Chaos/targets/%s/capabilities/%s" + return fmt.Sprintf(fmtString, id.Scope, id.TargetName, id.CapabilityName) +} + +// Segments returns a slice of Resource ID Segments which comprise this App Service Plan ID +func (id ChaosStudioCapabilityId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.ScopeSegment("scope", "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftWeb", "Microsoft.Chaos", "Microsoft.Chaos"), + resourceids.StaticSegment("staticTargets", "targets", "targets"), + resourceids.UserSpecifiedSegment("targetName", "targetName"), + resourceids.StaticSegment("staticCapabilities", "capabilities", "capabilities"), + resourceids.UserSpecifiedSegment("capabilityName", "capabilityName"), + } +} + +// String returns a human-readable description of this App Service Plan ID +func (id ChaosStudioCapabilityId) String() string { + components := []string{ + fmt.Sprintf("Scope: %q", id.Scope), + fmt.Sprintf("Target Name: %q", id.TargetName), + fmt.Sprintf("Capability Name: %q", id.TargetName), + } + return fmt.Sprintf("Chaos Studio Capability (%s)", strings.Join(components, "\n")) +} diff --git a/resourcemanager/commonids/chaos_studio_capability_test.go b/resourcemanager/commonids/chaos_studio_capability_test.go new file mode 100644 index 0000000..4b387d9 --- /dev/null +++ b/resourcemanager/commonids/chaos_studio_capability_test.go @@ -0,0 +1,162 @@ +// 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 = ChaosStudioCapabilityId{} + +func TestNewChaosStudioCapabilityId(t *testing.T) { + id := NewChaosStudioCapabilityID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "targetName", "capabilityName") + + if id.Scope != "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'Scope'", id.Scope, "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group") + } + + if id.TargetName != "targetName" { + t.Fatalf("Expected %q but got %q for Segment 'Target Name'", id.TargetName, "targetName") + } + + if id.CapabilityName != "capabilityName" { + t.Fatalf("Expected %q but got %q for Segment 'Capability Name'", id.CapabilityName, "capabilityName") + } +} + +func TestFormatChaosStudioCapabilityId(t *testing.T) { + actual := NewChaosStudioCapabilityID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "targetName", "capabilityName").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group/providers/Microsoft.Chaos/targets/targetName/capabilities/capabilityName" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseChaosStudioCapabilityId(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *ChaosStudioCapabilityId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group/providers/Microsoft.Chaos/targets/targetName/capabilities/capabilityName", + Expected: &ChaosStudioCapabilityId{ + Scope: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", + TargetName: "targetName", + CapabilityName: "capabilityName", + }, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseChaosStudioCapabilityID(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.Scope != v.Expected.Scope { + t.Fatalf("Expected %q but got %q for Scope", v.Expected.Scope, actual.Scope) + } + + if actual.TargetName != v.Expected.TargetName { + t.Fatalf("Expected %q but got %q for Target Name", v.Expected.TargetName, actual.TargetName) + } + + if actual.CapabilityName != v.Expected.CapabilityName { + t.Fatalf("Expected %q but got %q for Capability Name", v.Expected.CapabilityName, actual.CapabilityName) + } + + } +} + +func TestParseChaosStudioCapabilityIdInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *ChaosStudioCapabilityId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group/providers/Microsoft.Chaos/targets/targetName/capabilities/capabilityName", + Expected: &ChaosStudioCapabilityId{ + Scope: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", + TargetName: "targetName", + CapabilityName: "capabilityName", + }, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/sOmE-ReSoUrCe-gRoUp/providers/Microsoft.Chaos/TaRgEtS/targetName/CaPaBiLitIeS/capabilityName", + Expected: &ChaosStudioCapabilityId{ + Scope: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/sOmE-ReSoUrCe-gRoUp", + TargetName: "targetName", + CapabilityName: "capabilityName", + }, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseChaosStudioCapabilityIDInsensitively(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.Scope != v.Expected.Scope { + t.Fatalf("Expected %q but got %q for Scope", v.Expected.Scope, actual.Scope) + } + + if actual.TargetName != v.Expected.TargetName { + t.Fatalf("Expected %q but got %q for Scope", v.Expected.TargetName, actual.TargetName) + } + + if actual.CapabilityName != v.Expected.CapabilityName { + t.Fatalf("Expected %q but got %q for Capability Name", v.Expected.CapabilityName, actual.CapabilityName) + } + + } +} + +func TestSegmentsForChaosStudioCapabilityId(t *testing.T) { + segments := ChaosStudioCapabilityId{}.Segments() + if len(segments) == 0 { + t.Fatalf("ChaosStudioTargetId 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/chaos_studio_target.go b/resourcemanager/commonids/chaos_studio_target.go new file mode 100644 index 0000000..b6d09fe --- /dev/null +++ b/resourcemanager/commonids/chaos_studio_target.go @@ -0,0 +1,115 @@ +// 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 = ChaosStudioTargetId{} + +// ChaosStudioTargetId is a struct representing the Resource ID for an App Service Plan +type ChaosStudioTargetId struct { + Scope string + TargetName string +} + +// NewChaosStudioTargetID returns a new ChaosStudioTargetId struct +func NewChaosStudioTargetID(scope string, targetName string) ChaosStudioTargetId { + return ChaosStudioTargetId{ + Scope: scope, + TargetName: targetName, + } +} + +// ParseChaosStudioTargetID parses 'input' into a ChaosStudioTargetId +func ParseChaosStudioTargetID(input string) (*ChaosStudioTargetId, error) { + parser := resourceids.NewParserFromResourceIdType(ChaosStudioTargetId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ChaosStudioTargetId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseChaosStudioTargetIDInsensitively parses 'input' case-insensitively into a ChaosStudioTargetId +// note: this method should only be used for API response data and not user input +func ParseChaosStudioTargetIDInsensitively(input string) (*ChaosStudioTargetId, error) { + parser := resourceids.NewParserFromResourceIdType(ChaosStudioTargetId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := ChaosStudioTargetId{} + if err := id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *ChaosStudioTargetId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.Scope, ok = input.Parsed["scope"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "scope", input) + } + + if id.TargetName, ok = input.Parsed["targetName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "targetName", input) + } + + return nil +} + +// ValidateChaosStudioTargetID checks that 'input' can be parsed as an App Service Plan ID +func ValidateChaosStudioTargetID(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 := ParseChaosStudioTargetID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted App Service Plan ID +func (id ChaosStudioTargetId) ID() string { + fmtString := "%s/providers/Microsoft.Chaos/targets/%s" + return fmt.Sprintf(fmtString, id.Scope, id.TargetName) +} + +// Segments returns a slice of Resource ID Segments which comprise this App Service Plan ID +func (id ChaosStudioTargetId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.ScopeSegment("scope", "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftWeb", "Microsoft.Chaos", "Microsoft.Chaos"), + resourceids.StaticSegment("staticTargets", "targets", "targets"), + resourceids.UserSpecifiedSegment("targetName", "targetName"), + } +} + +// String returns a human-readable description of this App Service Plan ID +func (id ChaosStudioTargetId) String() string { + components := []string{ + fmt.Sprintf("Scope: %q", id.Scope), + fmt.Sprintf("Target Name: %q", id.TargetName), + } + return fmt.Sprintf("Chaos Studio Target (%s)", strings.Join(components, "\n")) +} diff --git a/resourcemanager/commonids/chaos_studio_target_test.go b/resourcemanager/commonids/chaos_studio_target_test.go new file mode 100644 index 0000000..20f4d9f --- /dev/null +++ b/resourcemanager/commonids/chaos_studio_target_test.go @@ -0,0 +1,147 @@ +// 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 = ChaosStudioTargetId{} + +func TestNewChaosStudioTargetId(t *testing.T) { + id := NewChaosStudioTargetID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "targetName") + + if id.Scope != "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'Scope'", id.Scope, "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group") + } + + if id.TargetName != "targetName" { + t.Fatalf("Expected %q but got %q for Segment 'Target Name'", id.TargetName, "targetName") + } +} + +func TestFormatChaosStudioTargetId(t *testing.T) { + actual := NewChaosStudioTargetID("/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", "targetName").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group/providers/Microsoft.Chaos/targets/targetName" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseChaosStudioTargetId(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *ChaosStudioTargetId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group/providers/Microsoft.Chaos/targets/targetName", + Expected: &ChaosStudioTargetId{ + Scope: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", + TargetName: "targetName", + }, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseChaosStudioTargetID(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.Scope != v.Expected.Scope { + t.Fatalf("Expected %q but got %q for Scope", v.Expected.Scope, actual.Scope) + } + + if actual.TargetName != v.Expected.TargetName { + t.Fatalf("Expected %q but got %q for Target Name", v.Expected.TargetName, actual.TargetName) + } + + } +} + +func TestParseChaosStudioTargetIdInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *ChaosStudioTargetId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group/providers/Microsoft.Chaos/targets/targetName", + Expected: &ChaosStudioTargetId{ + Scope: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/some-resource-group", + TargetName: "targetName", + }, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/sOmE-ReSoUrCe-gRoUp/providers/Microsoft.Chaos/TaRgEtS/targetName", + Expected: &ChaosStudioTargetId{ + Scope: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/sOmE-ReSoUrCe-gRoUp", + TargetName: "targetName", + }, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseChaosStudioTargetIDInsensitively(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.Scope != v.Expected.Scope { + t.Fatalf("Expected %q but got %q for Scope", v.Expected.Scope, actual.Scope) + } + + if actual.TargetName != v.Expected.TargetName { + t.Fatalf("Expected %q but got %q for Scope", v.Expected.TargetName, actual.TargetName) + } + + } +} + +func TestSegmentsForChaosStudioTargetId(t *testing.T) { + segments := ChaosStudioTargetId{}.Segments() + if len(segments) == 0 { + t.Fatalf("ChaosStudioTargetId 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)) + } +}