From f3b731b34f7315f1928379f24a603937331c94d6 Mon Sep 17 00:00:00 2001 From: VaishnaviGopal Date: Mon, 30 Sep 2024 13:18:56 +0530 Subject: [PATCH] sch Agent resource updated to accommodate agent destroy resources --- .../resource_ibm_schematics_agent.go | 86 +++++++++++++++++-- website/docs/r/schematics_agent.html.markdown | 2 + 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/ibm/service/schematics/resource_ibm_schematics_agent.go b/ibm/service/schematics/resource_ibm_schematics_agent.go index 02843f1efd..5dd0150fe9 100644 --- a/ibm/service/schematics/resource_ibm_schematics_agent.go +++ b/ibm/service/schematics/resource_ibm_schematics_agent.go @@ -10,6 +10,7 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" @@ -26,9 +27,9 @@ func ResourceIbmSchematicsAgent() *schema.Resource { DeleteContext: resourceIbmSchematicsAgentDelete, Importer: &schema.ResourceImporter{}, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(10 * time.Minute), - Update: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(10 * time.Minute), + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), }, Schema: map[string]*schema.Schema{ @@ -267,6 +268,11 @@ func ResourceIbmSchematicsAgent() *schema.Resource { }, }, }, + "run_destroy_resources": { + Type: schema.TypeInt, + Optional: true, + Description: "Argument which helps to run destroy resources job. Increment the value to destroy resources associated with agent deployment.", + }, "user_state": &schema.Schema{ Type: schema.TypeList, MaxItems: 1, @@ -766,7 +772,35 @@ func resourceIbmSchematicsAgentRead(context context.Context, d *schema.ResourceD return nil } +func isWaitForAgentDestroyResources(context context.Context, schematicsClient *schematicsv1.SchematicsV1, id string, timeout time.Duration) (interface{}, error) { + log.Printf("Waiting for agent (%s) resources to be destroyed.", id) + stateConf := &resource.StateChangeConf{ + Pending: []string{"retry", agentProvisioningStatusCodeJobInProgress, agentProvisioningStatusCodeJobPending, agentProvisioningStatusCodeJobReadyToExecute, agentProvisioningStatusCodeJobStopInProgress}, + Target: []string{agentProvisioningStatusCodeJobFinished, agentProvisioningStatusCodeJobFailed, agentProvisioningStatusCodeJobCancelled, agentProvisioningStatusCodeJobStopped, ""}, + Refresh: agentDestroyRefreshFunc(schematicsClient, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 10 * time.Second, + } + return stateConf.WaitForStateContext(context) +} +func agentDestroyRefreshFunc(schematicsClient *schematicsv1.SchematicsV1, id string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + getAgentDataOptions := &schematicsv1.GetAgentDataOptions{ + AgentID: core.StringPtr(id), + Profile: core.StringPtr("detailed"), + } + agent, response, err := schematicsClient.GetAgentData(getAgentDataOptions) + if err != nil { + return nil, "", fmt.Errorf("[ERROR] Error Getting Agent: %s\n%s", err, response) + } + if agent.RecentDestroyJob.StatusCode != nil { + return agent, *agent.RecentDestroyJob.StatusCode, nil + } + return agent, agentProvisioningStatusCodeJobPending, nil + } +} func resourceIbmSchematicsAgentUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { schematicsClient, err := meta.(conns.ClientSession).SchematicsV1() if err != nil { @@ -778,8 +812,10 @@ func resourceIbmSchematicsAgentUpdate(context context.Context, d *schema.Resourc if err != nil { return diag.FromErr(err) } + iamAccessToken := session.Config.IAMAccessToken iamRefreshToken := session.Config.IAMRefreshToken ff := map[string]string{ + "Authorization": iamAccessToken, "refresh_token": iamRefreshToken, } updateAgentDataOptions.Headers = ff @@ -882,7 +918,23 @@ func resourceIbmSchematicsAgentUpdate(context context.Context, d *schema.Resourc updateAgentDataOptions.SetAgentMetadata(agentMetadata) hasChange = true } + if d.HasChange("run_destroy_resources") { + deleteAgentResourcesOptions := &schematicsv1.DeleteAgentResourcesOptions{} + deleteAgentResourcesOptions.Headers = ff + deleteAgentResourcesOptions.SetAgentID(d.Id()) + deleteAgentResourcesOptions.SetRefreshToken(iamRefreshToken) + + response, err := schematicsClient.DeleteAgentResourcesWithContext(context, deleteAgentResourcesOptions) + if err != nil { + log.Printf("[DEBUG] DeleteAgentResourcesWithContext failed %s\n%s", err, response) + } else { + _, err = isWaitForAgentDestroyResources(context, schematicsClient, *deleteAgentResourcesOptions.AgentID, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + log.Printf("[DEBUG] waiting for agent deploy resources to be destroyed has failed %s", err) + } + } + } if hasChange { _, response, err := schematicsClient.UpdateAgentDataWithContext(context, updateAgentDataOptions) if err != nil { @@ -907,18 +959,40 @@ func resourceIbmSchematicsAgentDelete(context context.Context, d *schema.Resourc if err != nil { return diag.FromErr(err) } + iamAccessToken := session.Config.IAMAccessToken iamRefreshToken := session.Config.IAMRefreshToken ff := map[string]string{ + "Authorization": iamAccessToken, "refresh_token": iamRefreshToken, } deleteAgentDataOptions.Headers = ff deleteAgentDataOptions.SetAgentID(d.Id()) - response, err := schematicsClient.DeleteAgentDataWithContext(context, deleteAgentDataOptions) + // first try destroying resources associated with agent deploy and then delete the agent + + deleteAgentResourcesOptions := &schematicsv1.DeleteAgentResourcesOptions{} + deleteAgentResourcesOptions.Headers = ff + + deleteAgentResourcesOptions.SetAgentID(d.Id()) + deleteAgentResourcesOptions.SetRefreshToken(iamRefreshToken) + + response, err := schematicsClient.DeleteAgentResourcesWithContext(context, deleteAgentResourcesOptions) + if err != nil { + log.Printf("[DEBUG] DeleteAgentResourcesWithContext failed %s\n%s", err, response) + } else { + _, err = isWaitForAgentDestroyResources(context, schematicsClient, *deleteAgentResourcesOptions.AgentID, d.Timeout(schema.TimeoutDelete)) + if err != nil { + log.Printf("[DEBUG] waiting for agent deploy resources to be destroyed has failed %s", err) + } + } + + // After deploy associated resources are destroyed, now attempt to delete the agent + + deleteresponse, err := schematicsClient.DeleteAgentDataWithContext(context, deleteAgentDataOptions) if err != nil { - log.Printf("[DEBUG] DeleteAgentDataWithContext failed %s\n%s", err, response) - return diag.FromErr(fmt.Errorf("DeleteAgentDataWithContext failed %s\n%s", err, response)) + log.Printf("[DEBUG] DeleteAgentDataWithContext failed %s\n%s", err, deleteresponse) + return diag.FromErr(fmt.Errorf("DeleteAgentDataWithContext failed %s\n%s", err, deleteresponse)) } d.SetId("") diff --git a/website/docs/r/schematics_agent.html.markdown b/website/docs/r/schematics_agent.html.markdown index 802bc9aa2d..c720f10b90 100644 --- a/website/docs/r/schematics_agent.html.markdown +++ b/website/docs/r/schematics_agent.html.markdown @@ -35,6 +35,7 @@ resource "ibm_schematics_agent" "schematics_agent_instance" { schematics_location = "us-south" tags = ["agent-MyDevAgent"] version = "1.0.0" + run_destroy_resources = 1 } ``` @@ -69,6 +70,7 @@ Nested scheme for **user_state**: * `state` - (Optional, String) User-defined states * `enable` Agent is enabled by the user. * `disable` Agent is disbaled by the user. * Constraints: Allowable values are: `enable`, `disable`. * `version` - (Required, String) Agent version. +* `run_destroy_resources` - (Optional, Int) Argument which helps to run destroy resources job. Increment the value to destroy resources associated with agent deployment. ## Attribute Reference