Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 105 additions & 21 deletions internal/services/automation/automation_module_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (

func resourceAutomationModule() *pluginsdk.Resource {
return &pluginsdk.Resource{
Create: resourceAutomationModuleCreateUpdate,
Create: resourceAutomationModuleCreate,
Read: resourceAutomationModuleRead,
Update: resourceAutomationModuleCreateUpdate,
Update: resourceAutomationModuleUpdate,
Delete: resourceAutomationModuleDelete,

Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
Expand Down Expand Up @@ -91,29 +91,27 @@ func resourceAutomationModule() *pluginsdk.Resource {
}
}

func resourceAutomationModuleCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
func resourceAutomationModuleCreate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Automation.Module
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

log.Printf("[INFO] preparing arguments for AzureRM Automation Module creation.")

id := module.NewModuleID(subscriptionId, d.Get("resource_group_name").(string), d.Get("automation_account_name").(string), d.Get("name").(string))

if d.IsNewResource() {
existing, err := client.Get(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for presence of existing %s: %s", id, err)
}
existing, err := client.Get(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for presence of existing %s: %s", id, err)
}
}

// for existing global module do update instead of raising ImportAsExistsError
isGlobal := existing.Model != nil && existing.Model.Properties != nil && existing.Model.Properties.IsGlobal != nil && *existing.Model.Properties.IsGlobal
if !response.WasNotFound(existing.HttpResponse) && !isGlobal {
return tf.ImportAsExistsError("azurerm_automation_module", id.ID())
}
// for existing global module do update instead of raising ImportAsExistsError
isGlobal := existing.Model != nil && existing.Model.Properties != nil && existing.Model.Properties.IsGlobal != nil && *existing.Model.Properties.IsGlobal
if !response.WasNotFound(existing.HttpResponse) && !isGlobal {
return tf.ImportAsExistsError("azurerm_automation_module", id.ID())
}

parameters := module.ModuleCreateOrUpdateParameters{
Expand All @@ -123,7 +121,7 @@ func resourceAutomationModuleCreateUpdate(d *pluginsdk.ResourceData, meta interf
}

if _, err := client.CreateOrUpdate(ctx, id, parameters); err != nil {
return err
return fmt.Errorf("creating %s: %+v", id, err)
}

// the API returns 'done' but it's not actually finished provisioning yet
Expand All @@ -148,6 +146,7 @@ func resourceAutomationModuleCreateUpdate(d *pluginsdk.ResourceData, meta interf
string(module.ModuleProvisioningStateSucceeded),
},
MinTimeout: 30 * time.Second,
Timeout: d.Timeout(pluginsdk.TimeoutCreate),
Refresh: func() (interface{}, string, error) {
resp, err2 := client.Get(ctx, id)
if err2 != nil {
Expand All @@ -169,11 +168,6 @@ func resourceAutomationModuleCreateUpdate(d *pluginsdk.ResourceData, meta interf
return resp, provisioningState, nil
},
}
if d.IsNewResource() {
stateConf.Timeout = d.Timeout(pluginsdk.TimeoutCreate)
} else {
stateConf.Timeout = d.Timeout(pluginsdk.TimeoutUpdate)
}

if _, err := stateConf.WaitForStateContext(ctx); err != nil {
return fmt.Errorf("waiting for %s to finish provisioning: %+v", id, err)
Expand All @@ -184,6 +178,96 @@ func resourceAutomationModuleCreateUpdate(d *pluginsdk.ResourceData, meta interf
return resourceAutomationModuleRead(d, meta)
}

func resourceAutomationModuleUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Automation.Module
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := module.ParseModuleID(d.Id())
if err != nil {
return err
}

existing, err := client.Get(ctx, *id)
if err != nil {
return fmt.Errorf("retrieving existing %s: %+v", *id, err)
}

// Start from the existing content link so that fields managed via
// ignore_changes retain their server-side value.
var contentLink *module.ContentLink
if existing.Model != nil && existing.Model.Properties != nil {
contentLink = existing.Model.Properties.ContentLink
}

if d.HasChange("module_link") {
expanded := expandModuleLink(d)
contentLink = &expanded
}

parameters := module.ModuleUpdateParameters{
Name: &id.ModuleName,
Properties: &module.ModuleUpdateProperties{
ContentLink: contentLink,
},
}

if _, err := client.Update(ctx, *id, parameters); err != nil {
return fmt.Errorf("updating %s: %+v", *id, err)
}

// the API returns 'done' but it's not actually finished provisioning yet
// tracking issue: https://github.com/Azure/azure-rest-api-specs/pull/25435
stateConf := &pluginsdk.StateChangeConf{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put this block and the create block of this code into a function since it looks to be mostly copy paste outside of the timeout

Pending: []string{
string(module.ModuleProvisioningStateActivitiesStored),
string(module.ModuleProvisioningStateConnectionTypeImported),
string(module.ModuleProvisioningStateContentDownloaded),
string(module.ModuleProvisioningStateContentRetrieved),
string(module.ModuleProvisioningStateContentStored),
string(module.ModuleProvisioningStateContentValidated),
string(module.ModuleProvisioningStateCreated),
string(module.ModuleProvisioningStateCreating),
string(module.ModuleProvisioningStateModuleDataStored),
string(module.ModuleProvisioningStateModuleImportRunbookComplete),
string(module.ModuleProvisioningStateRunningImportModuleRunbook),
string(module.ModuleProvisioningStateStartingImportModuleRunbook),
string(module.ModuleProvisioningStateUpdating),
},
Target: []string{
string(module.ModuleProvisioningStateSucceeded),
},
MinTimeout: 30 * time.Second,
Timeout: d.Timeout(pluginsdk.TimeoutUpdate),
Refresh: func() (interface{}, string, error) {
resp, err2 := client.Get(ctx, *id)
if err2 != nil {
return resp, "Error", fmt.Errorf("retrieving %s: %+v", *id, err2)
}

provisioningState := "Unknown"
if model := resp.Model; model != nil {
if props := model.Properties; props != nil {
if props.ProvisioningState != nil {
provisioningState = string(*props.ProvisioningState)
}
if props.Error != nil && props.Error.Message != nil && *props.Error.Message != "" {
return resp, provisioningState, errors.New(*props.Error.Message)
}
return resp, provisioningState, nil
}
}
return resp, provisioningState, nil
},
}

if _, err := stateConf.WaitForStateContext(ctx); err != nil {
return fmt.Errorf("waiting for %s to finish provisioning: %+v", *id, err)
}

return resourceAutomationModuleRead(d, meta)
}

func resourceAutomationModuleRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Automation.Module
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
Expand Down
Loading