diff --git a/alicloud/provider.go b/alicloud/provider.go index 3a7430f38256..7b5360141f75 100644 --- a/alicloud/provider.go +++ b/alicloud/provider.go @@ -1408,7 +1408,7 @@ func Provider() terraform.ResourceProvider { "alicloud_rds_parameter_group": resourceAlicloudRdsParameterGroup(), "alicloud_ecs_launch_template": resourceAliCloudEcsLaunchTemplate(), "alicloud_resource_manager_control_policy": resourceAlicloudResourceManagerControlPolicy(), - "alicloud_resource_manager_control_policy_attachment": resourceAlicloudResourceManagerControlPolicyAttachment(), + "alicloud_resource_manager_control_policy_attachment": resourceAliCloudResourceManagerControlPolicyAttachment(), "alicloud_rds_account": resourceAlicloudRdsAccount(), "alicloud_rds_db_node": resourceAlicloudRdsDBNode(), "alicloud_rds_db_instance_endpoint": resourceAlicloudRdsDBInstanceEndpoint(), diff --git a/alicloud/resource_alicloud_resource_manager_control_policy_attachment.go b/alicloud/resource_alicloud_resource_manager_control_policy_attachment.go index 491260d9cb7f..0dcfe609a900 100644 --- a/alicloud/resource_alicloud_resource_manager_control_policy_attachment.go +++ b/alicloud/resource_alicloud_resource_manager_control_policy_attachment.go @@ -11,14 +11,18 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) -func resourceAlicloudResourceManagerControlPolicyAttachment() *schema.Resource { +func resourceAliCloudResourceManagerControlPolicyAttachment() *schema.Resource { return &schema.Resource{ - Create: resourceAlicloudResourceManagerControlPolicyAttachmentCreate, - Read: resourceAlicloudResourceManagerControlPolicyAttachmentRead, - Delete: resourceAlicloudResourceManagerControlPolicyAttachmentDelete, + Create: resourceAliCloudResourceManagerControlPolicyAttachmentCreate, + Read: resourceAliCloudResourceManagerControlPolicyAttachmentRead, + Delete: resourceAliCloudResourceManagerControlPolicyAttachmentDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(5 * time.Minute), + Delete: schema.DefaultTimeout(5 * time.Minute), + }, Schema: map[string]*schema.Schema{ "policy_id": { Type: schema.TypeString, @@ -34,7 +38,7 @@ func resourceAlicloudResourceManagerControlPolicyAttachment() *schema.Resource { } } -func resourceAlicloudResourceManagerControlPolicyAttachmentCreate(d *schema.ResourceData, meta interface{}) error { +func resourceAliCloudResourceManagerControlPolicyAttachmentCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AliyunClient) var response map[string]interface{} action := "AttachControlPolicy" @@ -43,69 +47,84 @@ func resourceAlicloudResourceManagerControlPolicyAttachmentCreate(d *schema.Reso if err != nil { return WrapError(err) } + request["PolicyId"] = d.Get("policy_id") request["TargetId"] = d.Get("target_id") - wait := incrementalWait(3*time.Second, 3*time.Second) + + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 5*time.Second) err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2020-03-31"), StringPointer("AK"), nil, request, &util.RuntimeOptions{}) + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2020-03-31"), StringPointer("AK"), nil, request, &runtime) if err != nil { - if NeedRetry(err) { + if IsExpectedErrors(err, []string{"ConcurrentCallNotSupported"}) || NeedRetry(err) { wait() return resource.RetryableError(err) } return resource.NonRetryableError(err) } - addDebug(action, response, request) return nil }) + addDebug(action, response, request) + if err != nil { return WrapErrorf(err, DefaultErrorMsg, "alicloud_resource_manager_control_policy_attachment", action, AlibabaCloudSdkGoERROR) } - d.SetId(fmt.Sprint(request["PolicyId"], ":", request["TargetId"])) + d.SetId(fmt.Sprintf("%v:%v", request["PolicyId"], request["TargetId"])) - return resourceAlicloudResourceManagerControlPolicyAttachmentRead(d, meta) + return resourceAliCloudResourceManagerControlPolicyAttachmentRead(d, meta) } -func resourceAlicloudResourceManagerControlPolicyAttachmentRead(d *schema.ResourceData, meta interface{}) error { + +func resourceAliCloudResourceManagerControlPolicyAttachmentRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AliyunClient) resourcemanagerService := ResourcemanagerService{client} - _, err := resourcemanagerService.DescribeResourceManagerControlPolicyAttachment(d.Id()) + + object, err := resourcemanagerService.DescribeResourceManagerControlPolicyAttachment(d.Id()) if err != nil { - if NotFoundError(err) { + if !d.IsNewResource() && NotFoundError(err) { log.Printf("[DEBUG] Resource alicloud_resource_manager_control_policy_attachment resourcemanagerService.DescribeResourceManagerControlPolicyAttachment Failed!!! %s", err) d.SetId("") return nil } return WrapError(err) } + parts, err := ParseResourceId(d.Id(), 2) if err != nil { return WrapError(err) } - d.Set("policy_id", parts[0]) + + d.Set("policy_id", object["PolicyId"]) d.Set("target_id", parts[1]) + return nil } -func resourceAlicloudResourceManagerControlPolicyAttachmentDelete(d *schema.ResourceData, meta interface{}) error { + +func resourceAliCloudResourceManagerControlPolicyAttachmentDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AliyunClient) - parts, err := ParseResourceId(d.Id(), 2) - if err != nil { - return WrapError(err) - } action := "DetachControlPolicy" var response map[string]interface{} conn, err := client.NewResourcemanagerClient() if err != nil { return WrapError(err) } + + parts, err := ParseResourceId(d.Id(), 2) + if err != nil { + return WrapError(err) + } + request := map[string]interface{}{ "PolicyId": parts[0], "TargetId": parts[1], } - wait := incrementalWait(3*time.Second, 3*time.Second) + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 5*time.Second) err = resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { - response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2020-03-31"), StringPointer("AK"), nil, request, &util.RuntimeOptions{}) + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2020-03-31"), StringPointer("AK"), nil, request, &runtime) if err != nil { if NeedRetry(err) { wait() @@ -113,14 +132,16 @@ func resourceAlicloudResourceManagerControlPolicyAttachmentDelete(d *schema.Reso } return resource.NonRetryableError(err) } - addDebug(action, response, request) return nil }) + addDebug(action, response, request) + if err != nil { - if IsExpectedErrors(err, []string{"EntityNotExists.Target"}) { + if IsExpectedErrors(err, []string{"EntityNotExists.Target"}) || NotFoundError(err) { return nil } return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR) } + return nil } diff --git a/alicloud/resource_alicloud_resource_manager_control_policy_attachment_test.go b/alicloud/resource_alicloud_resource_manager_control_policy_attachment_test.go index 44a55c34f567..8b6300f1abf8 100644 --- a/alicloud/resource_alicloud_resource_manager_control_policy_attachment_test.go +++ b/alicloud/resource_alicloud_resource_manager_control_policy_attachment_test.go @@ -20,10 +20,10 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" ) -func TestAccAlicloudResourceManagerControlPolicyAttachment_basic(t *testing.T) { +func TestAccAliCloudResourceManagerControlPolicyAttachment_basic0(t *testing.T) { var v map[string]interface{} resourceId := "alicloud_resource_manager_control_policy_attachment.default" - ra := resourceAttrInit(resourceId, AlicloudResourceManagerControlPolicyAttachmentMap0) + ra := resourceAttrInit(resourceId, AliCloudResourceManagerControlPolicyAttachmentMap0) rc := resourceCheckInitWithDescribeMethod(resourceId, &v, func() interface{} { return &ResourcemanagerService{testAccProvider.Meta().(*connectivity.AliyunClient)} }, "DescribeResourceManagerControlPolicyAttachment") @@ -31,21 +31,19 @@ func TestAccAlicloudResourceManagerControlPolicyAttachment_basic(t *testing.T) { testAccCheck := rac.resourceAttrMapUpdateSet() rand := acctest.RandIntRange(10000, 99999) name := fmt.Sprintf("tf-testacc%srcontrolpolicy%d", defaultRegionToTest, rand) - testAccConfig := resourceTestAccConfigFunc(resourceId, name, AlicloudResourceManagerControlPolicyAttachmentBasicDependence0) + testAccConfig := resourceTestAccConfigFunc(resourceId, name, AliCloudResourceManagerControlPolicyAttachmentBasicDependence0) resource.Test(t, resource.TestCase{ PreCheck: func() { - testAccPreCheckEnterpriseAccountEnabled(t) testAccPreCheck(t) }, - IDRefreshName: resourceId, Providers: testAccProviders, CheckDestroy: rac.checkResourceDestroy(), Steps: []resource.TestStep{ { Config: testAccConfig(map[string]interface{}{ - "policy_id": "${alicloud_resource_manager_control_policy.example.id}", - "target_id": "${alicloud_resource_manager_folder.example.id}", + "policy_id": "${alicloud_resource_manager_control_policy.default.id}", + "target_id": "${alicloud_resource_manager_folder.default.id}", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ @@ -63,29 +61,28 @@ func TestAccAlicloudResourceManagerControlPolicyAttachment_basic(t *testing.T) { }) } -var AlicloudResourceManagerControlPolicyAttachmentMap0 = map[string]string{} +var AliCloudResourceManagerControlPolicyAttachmentMap0 = map[string]string{} -func AlicloudResourceManagerControlPolicyAttachmentBasicDependence0(name string) string { +func AliCloudResourceManagerControlPolicyAttachmentBasicDependence0(name string) string { return fmt.Sprintf(` -variable "name" { - default = "%s" - } - -resource "alicloud_resource_manager_folder" "example" { - folder_name = "tf-testAcc870912" -} + variable "name" { + default = "%s" + } -resource "alicloud_resource_manager_control_policy" "example" { - control_policy_name = var.name - description = var.name - effect_scope = "RAM" - policy_document = "{\"Version\":\"1\",\"Statement\":[{\"Effect\":\"Deny\",\"Action\":[\"ram:UpdateRole\",\"ram:DeleteRole\",\"ram:AttachPolicyToRole\",\"ram:DetachPolicyFromRole\"],\"Resource\":\"acs:ram:*:*:role/ResourceDirectoryAccountAccessRole\"}]}" -} + resource "alicloud_resource_manager_folder" "default" { + folder_name = var.name + } + resource "alicloud_resource_manager_control_policy" "default" { + control_policy_name = var.name + description = var.name + effect_scope = "RAM" + policy_document = "{\"Version\":\"1\",\"Statement\":[{\"Effect\":\"Deny\",\"Action\":[\"ram:UpdateRole\",\"ram:DeleteRole\",\"ram:AttachPolicyToRole\",\"ram:DetachPolicyFromRole\"],\"Resource\":\"acs:ram:*:*:role/ResourceDirectoryAccountAccessRole\"}]}" + } `, name) } -func TestUnitAlicloudResourceManagerControlPolicyAttachment(t *testing.T) { +func TestUnitAliCloudResourceManagerControlPolicyAttachment(t *testing.T) { p := Provider().(*schema.Provider).ResourcesMap dInit, _ := schema.InternalMap(p["alicloud_resource_manager_control_policy_attachment"].Schema).Data(nil, nil) dExisted, _ := schema.InternalMap(p["alicloud_resource_manager_control_policy_attachment"].Schema).Data(nil, nil) @@ -150,7 +147,7 @@ func TestUnitAlicloudResourceManagerControlPolicyAttachment(t *testing.T) { StatusCode: tea.Int(400), } }) - err = resourceAlicloudResourceManagerControlPolicyAttachmentCreate(dInit, rawClient) + err = resourceAliCloudResourceManagerControlPolicyAttachmentCreate(dInit, rawClient) patches.Reset() assert.NotNil(t, err) ReadMockResponseDiff := map[string]interface{}{ @@ -175,7 +172,7 @@ func TestUnitAlicloudResourceManagerControlPolicyAttachment(t *testing.T) { } return ReadMockResponse, nil }) - err := resourceAlicloudResourceManagerControlPolicyAttachmentCreate(dInit, rawClient) + err := resourceAliCloudResourceManagerControlPolicyAttachmentCreate(dInit, rawClient) patches.Reset() switch errorCode { case "NonRetryableError": @@ -220,7 +217,7 @@ func TestUnitAlicloudResourceManagerControlPolicyAttachment(t *testing.T) { } return ReadMockResponse, nil }) - err := resourceAlicloudResourceManagerControlPolicyAttachmentRead(dExisted, rawClient) + err := resourceAliCloudResourceManagerControlPolicyAttachmentRead(dExisted, rawClient) patches.Reset() switch errorCode { case "NonRetryableError": @@ -239,7 +236,7 @@ func TestUnitAlicloudResourceManagerControlPolicyAttachment(t *testing.T) { StatusCode: tea.Int(400), } }) - err = resourceAlicloudResourceManagerControlPolicyAttachmentDelete(dExisted, rawClient) + err = resourceAliCloudResourceManagerControlPolicyAttachmentDelete(dExisted, rawClient) patches.Reset() assert.NotNil(t, err) attributesDiff = map[string]interface{}{} @@ -267,7 +264,7 @@ func TestUnitAlicloudResourceManagerControlPolicyAttachment(t *testing.T) { } return ReadMockResponse, nil }) - err := resourceAlicloudResourceManagerControlPolicyAttachmentDelete(dExisted, rawClient) + err := resourceAliCloudResourceManagerControlPolicyAttachmentDelete(dExisted, rawClient) patches.Reset() switch errorCode { case "NonRetryableError": diff --git a/alicloud/service_alicloud_resourcemanager.go b/alicloud/service_alicloud_resourcemanager.go index b77f21ec660d..733f8cf3c729 100644 --- a/alicloud/service_alicloud_resourcemanager.go +++ b/alicloud/service_alicloud_resourcemanager.go @@ -508,49 +508,66 @@ func (s *ResourcemanagerService) DescribeResourceManagerControlPolicy(id string) func (s *ResourcemanagerService) DescribeResourceManagerControlPolicyAttachment(id string) (object map[string]interface{}, err error) { var response map[string]interface{} + action := "ListControlPolicyAttachmentsForTarget" + conn, err := s.client.NewResourcemanagerClient() if err != nil { return nil, WrapError(err) } - action := "ListControlPolicyAttachmentsForTarget" + parts, err := ParseResourceId(id, 2) if err != nil { - err = WrapError(err) - return + return nil, WrapError(err) } + request := map[string]interface{}{ - "RegionId": s.client.RegionId, "TargetId": parts[1], } + idExist := false runtime := util.RuntimeOptions{} runtime.SetAutoretry(true) - response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2020-03-31"), StringPointer("AK"), nil, request, &runtime) + wait := incrementalWait(3*time.Second, 5*time.Second) + err = resource.Retry(5*time.Minute, func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2020-03-31"), StringPointer("AK"), nil, request, &runtime) + if err != nil { + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + return nil + }) + addDebug(action, response, request) + if err != nil { if IsExpectedErrors(err, []string{"EntityNotExists.Target"}) { - err = WrapErrorf(Error(GetNotFoundMessage("ResourceManagerControlPolicyAttachment", id)), NotFoundMsg, ProviderERROR) - return object, err + return object, WrapErrorf(Error(GetNotFoundMessage("ResourceManager:ControlPolicyAttachment", id)), NotFoundWithResponse, response) } - err = WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR) - return object, err + return object, WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR) } - addDebug(action, response, request) - v, err := jsonpath.Get("$.ControlPolicyAttachments.ControlPolicyAttachment", response) + + resp, err := jsonpath.Get("$.ControlPolicyAttachments.ControlPolicyAttachment", response) if err != nil { return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ControlPolicyAttachments.ControlPolicyAttachment", response) } - if len(v.([]interface{})) < 1 { - return object, WrapErrorf(Error(GetNotFoundMessage("ResourceManager", id)), NotFoundWithResponse, response) + + if v, ok := resp.([]interface{}); !ok || len(v) < 1 { + return object, WrapErrorf(Error(GetNotFoundMessage("ResourceManager:ControlPolicyAttachment", id)), NotFoundWithResponse, response) } - for _, v := range v.([]interface{}) { - if v.(map[string]interface{})["PolicyId"].(string) == parts[0] { + + for _, v := range resp.([]interface{}) { + if fmt.Sprint(v.(map[string]interface{})["PolicyId"]) == parts[0] { idExist = true return v.(map[string]interface{}), nil } } + if !idExist { - return object, WrapErrorf(Error(GetNotFoundMessage("ResourceManager", id)), NotFoundWithResponse, response) + return object, WrapErrorf(Error(GetNotFoundMessage("ResourceManager:ControlPolicyAttachment", id)), NotFoundWithResponse, response) } + return object, nil } diff --git a/website/docs/r/resource_manager_control_policy_attachment.html.markdown b/website/docs/r/resource_manager_control_policy_attachment.html.markdown index e5ba79271001..0ef0edc523f8 100644 --- a/website/docs/r/resource_manager_control_policy_attachment.html.markdown +++ b/website/docs/r/resource_manager_control_policy_attachment.html.markdown @@ -11,7 +11,7 @@ description: |- Provides a Resource Manager Control Policy Attachment resource. -For information about Resource Manager Control Policy Attachment and how to use it, see [What is Control Policy Attachment](https://www.alibabacloud.com/help/en/resource-management/latest/api-resourcedirectorymaster-2022-04-19-attachcontrolpolicy). +For information about Resource Manager Control Policy Attachment and how to use it, see [What is Control Policy Attachment](https://www.alibabacloud.com/help/en/resource-management/resource-directory/developer-reference/api-resourcemanager-2020-03-31-attachcontrolpolicy). -> **NOTE:** Available since v1.120.0. @@ -27,7 +27,7 @@ Basic Usage ```terraform variable "name" { - default = "tf-example" + default = "terraform-example" } resource "random_integer" "default" { @@ -35,7 +35,7 @@ resource "random_integer" "default" { max = 99999 } -resource "alicloud_resource_manager_control_policy" "example" { +resource "alicloud_resource_manager_control_policy" "default" { control_policy_name = var.name description = var.name effect_scope = "RAM" @@ -58,13 +58,13 @@ resource "alicloud_resource_manager_control_policy" "example" { EOF } -resource "alicloud_resource_manager_folder" "example" { +resource "alicloud_resource_manager_folder" "default" { folder_name = "${var.name}-${random_integer.default.result}" } -resource "alicloud_resource_manager_control_policy_attachment" "example" { - policy_id = alicloud_resource_manager_control_policy.example.id - target_id = alicloud_resource_manager_folder.example.id +resource "alicloud_resource_manager_control_policy_attachment" "default" { + policy_id = alicloud_resource_manager_control_policy.default.id + target_id = alicloud_resource_manager_folder.default.id } ``` @@ -72,14 +72,23 @@ resource "alicloud_resource_manager_control_policy_attachment" "example" { The following arguments are supported: -* `policy_id` - (Required, ForceNew) The ID of control policy. -* `target_id` - (Required, ForceNew) The ID of target. +* `policy_id` - (Required, ForceNew) The ID of the access control policy. +* `target_id` - (Required, ForceNew) The ID of the object to which you want to attach the access control policy. ## Attributes Reference The following attributes are exported: -* `id` - The resource ID of Control Policy Attachment. The value is formatted `:`. +* `id` - The resource ID in terraform of Control Policy Attachment. It formats as `:`. + +## Timeouts + +-> **NOTE:** Available since v1.240.0. + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration-0-11/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 5 mins) Used when create the Control Policy Attachment. +* `delete` - (Defaults to 5 mins) Used when delete the Control Policy Attachment. ## Import