Skip to content

Commit

Permalink
azurerm_automation_webhook/azurerm_automation_source_control - a …
Browse files Browse the repository at this point in the history
…state migration to work around the previously incorrect id casing (#19506)
  • Loading branch information
mbfrahry authored Dec 2, 2022
1 parent d9860ae commit 82597ef
Show file tree
Hide file tree
Showing 13 changed files with 607 additions and 18 deletions.
10 changes: 10 additions & 0 deletions internal/services/automation/automation_source_control.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/Azure/azure-sdk-for-go/services/preview/automation/mgmt/2020-01-13-preview/automation"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/migration"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
Expand Down Expand Up @@ -37,6 +38,15 @@ type SourceControlResource struct{}

var _ sdk.Resource = (*SourceControlResource)(nil)

func (r SourceControlResource) StateUpgraders() sdk.StateUpgradeData {
return sdk.StateUpgradeData{
SchemaVersion: 1,
Upgraders: map[int]pluginsdk.StateUpgrade{
0: migration.AutomationSourceControlV0ToV1{},
},
}
}

func (m SourceControlResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"automation_account_id": {
Expand Down
6 changes: 6 additions & 0 deletions internal/services/automation/automation_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/migration"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
Expand All @@ -32,6 +33,11 @@ func resourceAutomationWebhook() *pluginsdk.Resource {
return err
}),

SchemaVersion: 1,
StateUpgraders: pluginsdk.StateUpgrades(map[int]pluginsdk.StateUpgrade{
0: migration.AutomationWebhookV0ToV1{},
}),

Timeouts: &pluginsdk.ResourceTimeout{
Create: pluginsdk.DefaultTimeout(30 * time.Minute),
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package migration

import (
"context"
"log"

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

type AutomationSourceControlV0ToV1 struct{}

func (s AutomationSourceControlV0ToV1) Schema() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"automation_account_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
},

"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
},

"repository_url": {
Type: pluginsdk.TypeString,
Required: true,
},

"branch": {
Type: pluginsdk.TypeString,
Optional: true,
},

"folder_path": {
Type: pluginsdk.TypeString,
Required: true,
},

"automatic_sync": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: false,
},

"publish_runbook_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: true,
},

"source_control_type": {
Type: pluginsdk.TypeString,
Required: true,
},

"description": {
Type: pluginsdk.TypeString,
Optional: true,
},

"security": {
Type: pluginsdk.TypeList,
Required: true,
MaxItems: 1,
MinItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"token": {
Type: pluginsdk.TypeString,
Required: true,
},

"refresh_token": {
Type: pluginsdk.TypeString,
Optional: true,
},

"token_type": {
Type: pluginsdk.TypeString,
Required: true,
},
},
},
},
}
}

func (s AutomationSourceControlV0ToV1) UpgradeFunc() pluginsdk.StateUpgraderFunc {
return func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
oldId := rawState["id"].(string)
newId, err := parse.SourceControlIDInsensitively(oldId)
if err != nil {
return nil, err
}

log.Printf("[DEBUG] Updating ID from %q to %q", oldId, newId)

rawState["id"] = newId.ID()
return rawState, nil
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package migration

import (
"context"
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

type AutomationWebhookV0ToV1 struct{}

func (s AutomationWebhookV0ToV1) Schema() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
},

"automation_account_name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
},

"expiry_time": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
},

"enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: true,
},

"runbook_name": {
Type: pluginsdk.TypeString,
Required: true,
},
"run_on_worker_group": {
Type: pluginsdk.TypeString,
Optional: true,
},
"parameters": {
Type: pluginsdk.TypeMap,
Optional: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
"uri": {
Type: pluginsdk.TypeString,
ConfigMode: schema.SchemaConfigModeAttr,
Optional: true,
ForceNew: true,
Computed: true,
Sensitive: true,
},
}
}

func (s AutomationWebhookV0ToV1) UpgradeFunc() pluginsdk.StateUpgraderFunc {
return func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
oldId := rawState["id"].(string)
newId, err := parse.WebhookIDInsensitively(oldId)
if err != nil {
return nil, err
}

log.Printf("[DEBUG] Updating ID from %q to %q", oldId, newId)

rawState["id"] = newId.ID()
return rawState, nil
}
}
60 changes: 58 additions & 2 deletions internal/services/automation/parse/source_control.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (id SourceControlId) String() string {
}

func (id SourceControlId) ID() string {
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Automation/automationAccounts/%s/sourcecontrols/%s"
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Automation/automationAccounts/%s/sourceControls/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.AutomationAccountName, id.Name)
}

Expand All @@ -63,7 +63,63 @@ func SourceControlID(input string) (*SourceControlId, error) {
if resourceId.AutomationAccountName, err = id.PopSegment("automationAccounts"); err != nil {
return nil, err
}
if resourceId.Name, err = id.PopSegment("sourcecontrols"); err != nil {
if resourceId.Name, err = id.PopSegment("sourceControls"); err != nil {
return nil, err
}

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

return &resourceId, nil
}

// SourceControlIDInsensitively parses an SourceControl ID into an SourceControlId struct, insensitively
// This should only be used to parse an ID for rewriting, the SourceControlID
// 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 SourceControlIDInsensitively(input string) (*SourceControlId, error) {
id, err := resourceids.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := SourceControlId{
SubscriptionId: id.SubscriptionID,
ResourceGroup: id.ResourceGroup,
}

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

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

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

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

Expand Down
Loading

0 comments on commit 82597ef

Please sign in to comment.