Skip to content

Commit

Permalink
r/security_center_auto_provisioning: adding an import validator
Browse files Browse the repository at this point in the history
  • Loading branch information
tombuildsstuff committed Mar 23, 2022
1 parent 86f952b commit ddd2d05
Show file tree
Hide file tree
Showing 8 changed files with 472 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package migration

import (
"context"
"fmt"
"log"

"github.com/hashicorp/terraform-provider-azurerm/internal/services/securitycenter/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

type AutoProvisioningV0ToV1 struct{}

func (a AutoProvisioningV0ToV1) Schema() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"auto_provision": {
Type: pluginsdk.TypeString,
Required: true,
},
}
}

func (a AutoProvisioningV0ToV1) UpgradeFunc() pluginsdk.StateUpgraderFunc {
return func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
oldId := rawState["id"].(string)

parsed, err := parse.AutoProvisioningSettingIDInsensitively(oldId)
if err != nil {
return nil, fmt.Errorf("parsing old ID %q: %+v", oldId, err)
}

// potentially overkill, but the name is fixed (we can't guarantee the casing, however)
parsed.Name = "default"

newId := parsed.ID()
log.Printf("[DEBUG] Updating the ID from %q to %q..", oldId, newId)
rawState["id"] = newId
log.Printf("[DEBUG] Updated the ID from %q to %q.", oldId, newId)

return rawState, nil
}
}
100 changes: 100 additions & 0 deletions internal/services/securitycenter/parse/auto_provisioning_setting.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"fmt"
"strings"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

type AutoProvisioningSettingId struct {
SubscriptionId string
Name string
}

func NewAutoProvisioningSettingID(subscriptionId, name string) AutoProvisioningSettingId {
return AutoProvisioningSettingId{
SubscriptionId: subscriptionId,
Name: name,
}
}

func (id AutoProvisioningSettingId) String() string {
segments := []string{
fmt.Sprintf("Name %q", id.Name),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Auto Provisioning Setting", segmentsStr)
}

func (id AutoProvisioningSettingId) ID() string {
fmtString := "/subscriptions/%s/providers/Microsoft.Security/autoProvisioningSettings/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.Name)
}

// AutoProvisioningSettingID parses a AutoProvisioningSetting ID into an AutoProvisioningSettingId struct
func AutoProvisioningSettingID(input string) (*AutoProvisioningSettingId, error) {
id, err := resourceids.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := AutoProvisioningSettingId{
SubscriptionId: id.SubscriptionID,
}

if resourceId.SubscriptionId == "" {
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
}

if resourceId.Name, err = id.PopSegment("autoProvisioningSettings"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}

// AutoProvisioningSettingIDInsensitively parses an AutoProvisioningSetting ID into an AutoProvisioningSettingId struct, insensitively
// This should only be used to parse an ID for rewriting, the AutoProvisioningSettingID
// method should be used instead for validation etc.
//
// Whilst this may seem strange, this enables Terraform have consistent casing
// which works around issues in Core, whilst handling broken API responses.
func AutoProvisioningSettingIDInsensitively(input string) (*AutoProvisioningSettingId, error) {
id, err := resourceids.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := AutoProvisioningSettingId{
SubscriptionId: id.SubscriptionID,
}

if resourceId.SubscriptionId == "" {
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
}

// find the correct casing for the 'autoProvisioningSettings' segment
autoProvisioningSettingsKey := "autoProvisioningSettings"
for key := range id.Path {
if strings.EqualFold(key, autoProvisioningSettingsKey) {
autoProvisioningSettingsKey = key
break
}
}
if resourceId.Name, err = id.PopSegment(autoProvisioningSettingsKey); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"testing"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

var _ resourceids.Id = AutoProvisioningSettingId{}

func TestAutoProvisioningSettingIDFormatter(t *testing.T) {
actual := NewAutoProvisioningSettingID("12345678-1234-9876-4563-123456789012", "default").ID()
expected := "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/autoProvisioningSettings/default"
if actual != expected {
t.Fatalf("Expected %q but got %q", expected, actual)
}
}

func TestAutoProvisioningSettingID(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *AutoProvisioningSettingId
}{

{
// empty
Input: "",
Error: true,
},

{
// missing SubscriptionId
Input: "/",
Error: true,
},

{
// missing value for SubscriptionId
Input: "/subscriptions/",
Error: true,
},

{
// missing Name
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/",
Error: true,
},

{
// missing value for Name
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/autoProvisioningSettings/",
Error: true,
},

{
// valid
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/autoProvisioningSettings/default",
Expected: &AutoProvisioningSettingId{
SubscriptionId: "12345678-1234-9876-4563-123456789012",
Name: "default",
},
},

{
// upper-cased
Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/PROVIDERS/MICROSOFT.SECURITY/AUTOPROVISIONINGSETTINGS/DEFAULT",
Error: true,
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := AutoProvisioningSettingID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expect a value but got an error: %s", 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.Name != v.Expected.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
}
}
}

func TestAutoProvisioningSettingIDInsensitively(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *AutoProvisioningSettingId
}{

{
// empty
Input: "",
Error: true,
},

{
// missing SubscriptionId
Input: "/",
Error: true,
},

{
// missing value for SubscriptionId
Input: "/subscriptions/",
Error: true,
},

{
// missing Name
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/",
Error: true,
},

{
// missing value for Name
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/autoProvisioningSettings/",
Error: true,
},

{
// valid
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/autoProvisioningSettings/default",
Expected: &AutoProvisioningSettingId{
SubscriptionId: "12345678-1234-9876-4563-123456789012",
Name: "default",
},
},

{
// lower-cased segment names
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/autoprovisioningsettings/default",
Expected: &AutoProvisioningSettingId{
SubscriptionId: "12345678-1234-9876-4563-123456789012",
Name: "default",
},
},

{
// upper-cased segment names
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/AUTOPROVISIONINGSETTINGS/default",
Expected: &AutoProvisioningSettingId{
SubscriptionId: "12345678-1234-9876-4563-123456789012",
Name: "default",
},
},

{
// mixed-cased segment names
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/AuToPrOvIsIoNiNgSeTtInGs/default",
Expected: &AutoProvisioningSettingId{
SubscriptionId: "12345678-1234-9876-4563-123456789012",
Name: "default",
},
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := AutoProvisioningSettingIDInsensitively(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expect a value but got an error: %s", 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.Name != v.Expected.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
}
}
}
1 change: 1 addition & 0 deletions internal/services/securitycenter/resourceids.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ package securitycenter
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Workspace -id=/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/workspaceSettings/workspace1

//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=AssessmentMetadata -id=/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/assessmentMetadata/metadata1
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=AutoProvisioningSetting -id=/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Security/autoProvisioningSettings/default -rewrite=true
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=IotSecuritySolution -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Security/IoTSecuritySolutions/solution1
Loading

0 comments on commit ddd2d05

Please sign in to comment.