diff --git a/docs/resources/rms_assignment_package.md b/docs/resources/rms_assignment_package.md index f2f8ff6c20..46015c1aea 100644 --- a/docs/resources/rms_assignment_package.md +++ b/docs/resources/rms_assignment_package.md @@ -32,9 +32,7 @@ resource "huaweicloud_rms_assignment_package" "test" { The following arguments are supported: -* `name` - (Required, String, ForceNew) Specifies the assignment package name. It contains 1 to 64 characters. - - Changing this parameter will create a new resource. +* `name` - (Required, String) Specifies the assignment package name. It contains 1 to 64 characters. * `agency_name` - (Optional, String, ForceNew) Specifies the agency name. The agency needs to authorize RFS to invoke the Config APIs for creating, updating, deleting an assignment. It contains 1 to 64 characters. @@ -58,10 +56,9 @@ The following arguments are supported: -> **NOTE:** Exactly one of `template_key`, `template_body`, `template_uri` should be specified. -* `vars_structure` - (Optional, List, ForceNew) Specifies the parameters of an assignment package. +* `vars_structure` - (Optional, List) Specifies the parameters of an assignment package. - Changing this parameter will create a new resource. -The [vars_structure](#AssignmentPackage_VarStructure) structure is documented below. + The [vars_structure](#AssignmentPackage_VarStructure) structure is documented below. The `vars_structure` block supports: diff --git a/huaweicloud/services/acceptance/rms/resource_huaweicloud_rms_assignment_package_test.go b/huaweicloud/services/acceptance/rms/resource_huaweicloud_rms_assignment_package_test.go index 254ebfd586..b0bcceab2f 100644 --- a/huaweicloud/services/acceptance/rms/resource_huaweicloud_rms_assignment_package_test.go +++ b/huaweicloud/services/acceptance/rms/resource_huaweicloud_rms_assignment_package_test.go @@ -79,6 +79,21 @@ func TestAccAssignmentPackage_basic(t *testing.T) { resource.TestCheckResourceAttrSet(rName, "status"), ), }, + { + Config: testAssignmentPackage_update(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", name+"-update"), + resource.TestCheckTypeSetElemNestedAttrs(rName, "vars_structure.*", map[string]string{ + "var_key": "lastBackupAgeValue", + "var_value": "25", + }), + resource.TestCheckResourceAttrSet(rName, "stack_id"), + resource.TestCheckResourceAttrSet(rName, "stack_name"), + resource.TestCheckResourceAttrSet(rName, "deployment_id"), + resource.TestCheckResourceAttrSet(rName, "status"), + ), + }, { ResourceName: rName, ImportState: true, @@ -102,10 +117,31 @@ resource "huaweicloud_rms_assignment_package" "test" { dynamic "vars_structure" { for_each = data.huaweicloud_rms_assignment_package_templates.test.templates.0.parameters content { - var_key = vars_structure.value["name"] + var_key = vars_structure.value["name"] var_value = vars_structure.value["default_value"] } } } `, name) } + +func testAssignmentPackage_update(name string) string { + return fmt.Sprintf(` +data "huaweicloud_rms_assignment_package_templates" "test" { + template_key = "Operational-Best-Practices-for-ECS.tf.json" +} + +resource "huaweicloud_rms_assignment_package" "test" { + name = "%s-update" + template_key = data.huaweicloud_rms_assignment_package_templates.test.templates.0.template_key + + dynamic "vars_structure" { + for_each = data.huaweicloud_rms_assignment_package_templates.test.templates.0.parameters + content { + var_key = vars_structure.value["name"] + var_value = vars_structure.value["name"] == "lastBackupAgeValue" ? 25 : vars_structure.value["default_value"] + } + } +} +`, name) +} diff --git a/huaweicloud/services/rms/resource_huaweicloud_rms_assignment_package.go b/huaweicloud/services/rms/resource_huaweicloud_rms_assignment_package.go index 4b80a9d24e..146db1ff5c 100644 --- a/huaweicloud/services/rms/resource_huaweicloud_rms_assignment_package.go +++ b/huaweicloud/services/rms/resource_huaweicloud_rms_assignment_package.go @@ -27,10 +27,12 @@ import ( // @API Config POST /v1/resource-manager/domains/{domain_id}/conformance-packs // @API Config DELETE /v1/resource-manager/domains/{domain_id}/conformance-packs/{id} // @API Config GET /v1/resource-manager/domains/{domain_id}/conformance-packs/{id} +// @API Config PUT /v1/resource-manager/domains/{domain_id}/conformance-packs/{id} func ResourceAssignmentPackage() *schema.Resource { return &schema.Resource{ CreateContext: resourceAssignmentPackageCreate, ReadContext: resourceAssignmentPackageRead, + UpdateContext: resourceAssignmentPackageUpdate, DeleteContext: resourceAssignmentPackageDelete, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -38,6 +40,7 @@ func ResourceAssignmentPackage() *schema.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), Delete: schema.DefaultTimeout(30 * time.Minute), }, @@ -45,7 +48,6 @@ func ResourceAssignmentPackage() *schema.Resource { "name": { Type: schema.TypeString, Required: true, - ForceNew: true, Description: `Specifies the assignment package name.`, }, "agency_name": { @@ -82,7 +84,6 @@ func ResourceAssignmentPackage() *schema.Resource { Elem: assignmentPackageParameterSchema(), Optional: true, Computed: true, - ForceNew: true, Description: `Specifies the parameters of an assignment package.`, }, "stack_id": { @@ -191,7 +192,7 @@ func resourceAssignmentPackageCreate(ctx context.Context, d *schema.ResourceData } func buildCreateAssignmentPackageBodyParams(d *schema.ResourceData) (map[string]interface{}, error) { - varsStructure, err := buildCreateAssignmentPackageRequestBodyParameter(d.Get("vars_structure")) + varsStructure, err := buildAssignmentPackageRequestBodyParameter(d.Get("vars_structure")) if err != nil { return nil, err } @@ -207,7 +208,7 @@ func buildCreateAssignmentPackageBodyParams(d *schema.ResourceData) (map[string] return bodyParams, err } -func buildCreateAssignmentPackageRequestBodyParameter(rawParams interface{}) ([]map[string]interface{}, error) { +func buildAssignmentPackageRequestBodyParameter(rawParams interface{}) ([]map[string]interface{}, error) { rawArray := rawParams.(*schema.Set).List() if len(rawArray) == 0 { return nil, nil @@ -279,6 +280,70 @@ func flattenGetAssignmentPackageResponseBodyParameter(resp interface{}) []interf return rst } +func resourceAssignmentPackageUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + cfg := meta.(*config.Config) + region := cfg.GetRegion(d) + assignmentPackageId := d.Id() + + // updateAssignmentPackage: Update an existing RMS assignment package + var ( + updateAssignmentPackageHttpUrl = "v1/resource-manager/domains/{domain_id}/conformance-packs/{id}" + updateAssignmentPackageProduct = "rms" + ) + updateAssignmentPackageClient, err := cfg.NewServiceClient(updateAssignmentPackageProduct, region) + if err != nil { + return diag.Errorf("error creating RMS client: %s", err) + } + + updateAssignmentPackagePath := updateAssignmentPackageClient.Endpoint + updateAssignmentPackageHttpUrl + updateAssignmentPackagePath = strings.ReplaceAll(updateAssignmentPackagePath, "{domain_id}", cfg.DomainID) + updateAssignmentPackagePath = strings.ReplaceAll(updateAssignmentPackagePath, "{id}", assignmentPackageId) + + updateAssignmentPackageOpt := golangsdk.RequestOpts{ + KeepResponseBody: true, + } + + updateOpts, err := buildUpdateAssignmentPackageBodyParams(d) + if err != nil { + return diag.FromErr(err) + } + + updateAssignmentPackageOpt.JSONBody = utils.RemoveNil(updateOpts) + log.Printf("[DEBUG] Update RMS assignment package options: %#v", updateAssignmentPackageOpt) + _, err = updateAssignmentPackageClient.Request("PUT", updateAssignmentPackagePath, &updateAssignmentPackageOpt) + if err != nil { + return diag.Errorf("error updating RMS assignment package: %s", err) + } + + stateConf := &resource.StateChangeConf{ + Target: []string{"UPDATE_SUCCESSFUL", "ROLLBACK_SUCCESSFUL"}, + Pending: []string{"UPDATE_IN_PROGRESS"}, + Refresh: rmsAssignmentPackageStateRefreshFunc(updateAssignmentPackageClient, cfg, assignmentPackageId), + Timeout: d.Timeout(schema.TimeoutUpdate), + Delay: 10 * time.Second, + PollInterval: 10 * time.Second, + } + + if _, err = stateConf.WaitForStateContext(ctx); err != nil { + return diag.Errorf("error waiting for RMS assignment Package (%s) to be updated: %s", assignmentPackageId, err) + } + + return resourceAssignmentPackageRead(ctx, d, meta) +} + +func buildUpdateAssignmentPackageBodyParams(d *schema.ResourceData) (map[string]interface{}, error) { + varsStructure, err := buildAssignmentPackageRequestBodyParameter(d.Get("vars_structure")) + if err != nil { + return nil, err + } + + bodyParams := map[string]interface{}{ + "name": d.Get("name"), + "vars_structure": varsStructure, + } + return bodyParams, err +} + func resourceAssignmentPackageDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { cfg := meta.(*config.Config) region := cfg.GetRegion(d)