diff --git a/alicloud/provider.go b/alicloud/provider.go index def528831f46..5821bf9c26c2 100644 --- a/alicloud/provider.go +++ b/alicloud/provider.go @@ -1941,6 +1941,7 @@ func Provider() terraform.ResourceProvider { "alicloud_api_gateway_model": resourceAlicloudApiGatewayModel(), "alicloud_cen_transit_router_grant_attachment": resourceAlicloudCenTransitRouterGrantAttachment(), "alicloud_api_gateway_plugin": resourceAliCloudApiGatewayPlugin(), + "alicloud_api_gateway_group_plugin_attachment": resourceAlicloudApiGatewayGroupPluginAttachment(), "alicloud_api_gateway_plugin_attachment": resourceAlicloudApiGatewayPluginAttachment(), "alicloud_message_service_queue": resourceAliCloudMessageServiceQueue(), "alicloud_message_service_topic": resourceAliCloudMessageServiceTopic(), diff --git a/alicloud/resource_alicloud_api_gateway_group_plugin_attachment.go b/alicloud/resource_alicloud_api_gateway_group_plugin_attachment.go new file mode 100644 index 000000000000..4e10b2eb68dc --- /dev/null +++ b/alicloud/resource_alicloud_api_gateway_group_plugin_attachment.go @@ -0,0 +1,138 @@ +package alicloud + +import ( + "fmt" + "time" + + "github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func resourceAlicloudApiGatewayGroupPluginAttachment() *schema.Resource { + return &schema.Resource{ + Create: resourceAlicloudApiGatewayGroupPluginAttachmentCreate, + Read: resourceAlicloudApiGatewayGroupPluginAttachmentRead, + Delete: resourceAlicloudApiGatewayGroupPluginAttachmentDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "group_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "plugin_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "stage_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func resourceAlicloudApiGatewayGroupPluginAttachmentCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + var response map[string]interface{} + action := "AttachGroupPlugin" + request := make(map[string]interface{}) + var err error + request["GroupId"] = d.Get("group_id") + request["PluginId"] = d.Get("plugin_id") + request["StageName"] = d.Get("stage_name") + wait := incrementalWait(3*time.Second, 3*time.Second) + err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutCreate)), func() *resource.RetryError { + response, err = client.RpcPost("CloudAPI", "2016-07-14", action, nil, request, false) + if err != nil { + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + addDebug(action, response, request) + return nil + }) + + if err != nil { + return WrapErrorf(err, DefaultErrorMsg, "alicloud_api_gateway_group_plugin_attachment", action, AlibabaCloudSdkGoERROR) + } + + d.SetId(fmt.Sprint(request["GroupId"], ":", request["PluginId"], ":", request["StageName"])) + + return resourceAlicloudApiGatewayGroupPluginAttachmentRead(d, meta) +} + +func resourceAlicloudApiGatewayGroupPluginAttachmentRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + apiGatewayServiceV2 := ApiGatewayServiceV2{client} + + objectRaw, err := apiGatewayServiceV2.DescribeApiGatewayGroupPluginAttachment(d.Id()) + + if err != nil { + if !d.IsNewResource() && NotFoundError(err) { + d.SetId("") + return nil + } + return WrapError(err) + } + + err = d.Set("group_id", objectRaw["GroupId"].(string)) + if err != nil { + return WrapError(err) + } + err = d.Set("stage_name", objectRaw["StageName"].(string)) + if err != nil { + return WrapError(err) + } + err = d.Set("plugin_id", objectRaw["PluginId"].(string)) + if err != nil { + return WrapError(err) + } + return nil + +} + +func resourceAlicloudApiGatewayGroupPluginAttachmentDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + parts, err := ParseResourceId(d.Id(), 3) + if err != nil { + return WrapError(err) + } + var response map[string]interface{} + request := make(map[string]interface{}) + action := "DetachGroupPlugin" + request["RegionId"] = client.RegionId + request["GroupId"] = parts[0] + request["PluginId"] = parts[1] + request["StageName"] = parts[2] + + wait := incrementalWait(3*time.Second, 3*time.Second) + err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutCreate)), func() *resource.RetryError { + response, err = client.RpcPost("CloudAPI", "2016-07-14", action, nil, request, false) + if err != nil { + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + addDebug(action, response, request) + return nil + }) + + if err != nil { + return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR) + } + + return nil +} diff --git a/alicloud/resource_alicloud_api_gateway_group_plugin_attachment_test.go b/alicloud/resource_alicloud_api_gateway_group_plugin_attachment_test.go new file mode 100644 index 000000000000..c03996fd2ad7 --- /dev/null +++ b/alicloud/resource_alicloud_api_gateway_group_plugin_attachment_test.go @@ -0,0 +1,86 @@ +package alicloud + +import ( + "fmt" + "testing" + + "github.com/aliyun/alibaba-cloud-sdk-go/services/cloudapi" + "github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity" + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccAliCloudApiGatewayGroupPluginAttachment(t *testing.T) { + var v *cloudapi.PluginAttribute + + resourceId := "alicloud_api_gateway_group_plugin_attachment.default" + ra := resourceAttrInit(resourceId, apiGatewayGroupPluginAttachmentBasicMap) + rc := resourceCheckInitWithDescribeMethod(resourceId, &v, func() interface{} { + return &ApiGatewayServiceV2{testAccProvider.Meta().(*connectivity.AliyunClient)} + }, "DescribeApiGatewayGroupPluginAttachment") + + rac := resourceAttrCheckInit(rc, ra) + + testAccCheck := rac.resourceAttrMapUpdateSet() + rand := acctest.RandIntRange(1000000, 9999999) + name := fmt.Sprintf("tf_testAccGroupPlugin_%d", rand) + testAccConfig := resourceTestAccConfigFunc(resourceId, name, resourceApiGatewayGroupPluginAttachmentConfigDependence) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + // module name + IDRefreshName: resourceId, + Providers: testAccProviders, + CheckDestroy: rac.checkResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testAccConfig(map[string]interface{}{ + "group_id": "${alicloud_api_gateway_group.default.id}", + "plugin_id": "${alicloud_api_gateway_plugin.default.id}", + "stage_name": "RELEASE", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "group_id": CHECKSET, + "plugin_id": CHECKSET, + "stage_name": "RELEASE", + }), + ), + }, + { + ResourceName: resourceId, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{}, + }, + }, + }) +} + +func resourceApiGatewayGroupPluginAttachmentConfigDependence(name string) string { + return fmt.Sprintf(` +variable "name" { + default = "%s" +} +resource "alicloud_api_gateway_group" "default" { + name = "${var.name}" + description = "tf_testAccApiGroup Description" +} + +resource "alicloud_api_gateway_plugin" "default" { + plugin_name = "${var.name}" + plugin_data = jsonencode({"allowOrigins": "api.foo.com","allowMethods": "GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH","allowHeaders": "Authorization,Accept,Accept-Ranges,Cache-Control,Range,Date,Content-Type,Content-Length,Content-MD5,User-Agent,X-Ca-Signature,X-Ca-Signature-Headers,X-Ca-Signature-Method,X-Ca-Key,X-Ca-Timestamp,X-Ca-Nonce,X-Ca-Stage,X-Ca-Request-Mode,x-ca-deviceid","exposeHeaders": "Content-MD5,Server,Date,Latency,X-Ca-Request-Id,X-Ca-Error-Code,X-Ca-Error-Message","maxAge": 172800,"allowCredentials": true}) + plugin_type = "cors" + description = "tf_testAccApiPlugin Description" +} + + `, name) +} + +var apiGatewayGroupPluginAttachmentBasicMap = map[string]string{ + "group_id": CHECKSET, + "plugin_id": CHECKSET, + "stage_name": "RELEASE", +} diff --git a/alicloud/service_alicloud_api_gateway_v2.go b/alicloud/service_alicloud_api_gateway_v2.go index c3dd0b3c55ff..1c1233e84273 100644 --- a/alicloud/service_alicloud_api_gateway_v2.go +++ b/alicloud/service_alicloud_api_gateway_v2.go @@ -320,6 +320,73 @@ func (s *ApiGatewayServiceV2) DescribeApiGatewayAclEntryAttachmentAttribute(id s return object, WrapErrorf(NotFoundErr("AclEntryAttachment", id), NotFoundWithResponse, response) } +func (s *ApiGatewayServiceV2) DescribeApiGatewayGroupPluginAttachment(id string) (object map[string]interface{}, err error) { + parts, err2 := ParseResourceId(id, 3) + if err2 != nil { + return object, WrapError(err2) + } + + client := s.client + var response map[string]interface{} + + action := "DescribePluginsByGroup" + request := make(map[string]interface{}) + request["GroupId"] = parts[0] + request["StageName"] = parts[2] + request["PageSize"] = 100 + wait := incrementalWait(3*time.Second, 3*time.Second) + err = resource.Retry(client.GetRetryTimeout(1*time.Minute), func() *resource.RetryError { + response, err = client.RpcPost("CloudAPI", "2016-07-14", action, nil, request, false) + if err != nil { + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + addDebug(action, response, request) + return nil + }) + + if err != nil { + if IsExpectedErrors(err, []string{"InvokeDescribePluginsByGroupApiFail"}) { + return object, WrapErrorf(NotFoundErr("GroupPluginAttachment", id), NotFoundMsg, response) + } + addDebug(action, response, request) + return object, WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR) + } + + v, err := jsonpath.Get("$.Plugins.PluginAttribute[*]", response) + if err != nil { + return object, WrapErrorf(err, DefaultErrorMsg, "$.Plugins.PluginAttribute[*]", response) + } + + if len(v.([]interface{})) == 0 { + return object, WrapErrorf(NotFoundErr("GroupPluginAttachment", id), NotFoundMsg, response) + } + + plugins := v.([]interface{}) + pluginId := parts[1] + + var foundPlugin map[string]interface{} + + for _, plugin := range plugins { + pluginMap := plugin.(map[string]interface{}) + if pluginMap["PluginId"].(string) == pluginId { + foundPlugin = pluginMap + foundPlugin["GroupId"] = parts[0] + foundPlugin["StageName"] = parts[2] + break + } + } + + if foundPlugin == nil { + return object, WrapErrorf(NotFoundErr("GroupPluginAttachment", id), NotFoundMsg, response) + } + + return foundPlugin, nil +} + func (s *ApiGatewayServiceV2) DescribeApiGatewayInstanceAclAttachmentAttribute(id string) (object map[string]interface{}, err error) { parts, err := ParseResourceIds(id) if err != nil { diff --git a/go.mod b/go.mod index 759d01c9dba3..e807aaca156f 100644 --- a/go.mod +++ b/go.mod @@ -43,6 +43,9 @@ require ( github.com/alibabacloud-go/sts-20150401/v2 v2.0.2 github.com/alibabacloud-go/tea-utils/v2 v2.0.7 github.com/blues/jsonata-go v1.5.4 + github.com/hashicorp/errwrap v1.1.0 + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757 github.com/samber/lo v1.49.1 github.com/tidwall/sjson v1.2.5 golang.org/x/tools v0.38.0 @@ -108,7 +111,6 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v23.5.26+incompatible // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.6.0 // indirect @@ -118,9 +120,7 @@ require ( github.com/googleapis/gax-go/v2 v2.12.3 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/grafana/regexp v0.0.0-20221005093135-b4c2bcb0a4b6 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter v1.7.3 // indirect github.com/hashicorp/go-hclog v1.6.2 // indirect github.com/hashicorp/go-multierror v1.0.0 // indirect @@ -141,7 +141,6 @@ require ( github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757 // indirect github.com/klauspost/compress v1.17.8 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/website/docs/r/api_gateway_group_plugin_attachment.html.markdown b/website/docs/r/api_gateway_group_plugin_attachment.html.markdown new file mode 100644 index 000000000000..7496ee702e36 --- /dev/null +++ b/website/docs/r/api_gateway_group_plugin_attachment.html.markdown @@ -0,0 +1,70 @@ +--- +subcategory: "Api Gateway" +layout: "alicloud" +page_title: "Alicloud: alicloud_api_gateway_group_plugin_attachment" +sidebar_current: "docs-alicloud-resource-api-gateway_group-plugin-attachment" +description: |- + Provides a Alicloud Api Gateway Group Plugin Attachment Resource. +--- + +# alicloud_api_gateway_group_plugin_attachment + +Provides a plugin attachment resource.It is used for attaching a specific plugin to an api group. + +For information about Api Gateway Plugin attachment and how to use it, see [Attach Plugin to specified API GROUP](https://www.alibabacloud.com/help/en/api-gateway/traditional-api-gateway/developer-reference/api-cloudapi-2016-07-14-attachgroupplugin) + +-> **NOTE:** Available since v1.273.0 +-> **NOTE:** Terraform will auto build plugin attachment while it uses `alicloud_api_gateway_group_plugin_attachment` to build. + +## Example Usage + +Basic Usage + + +```terraform +provider "alicloud" { + region = "cn-beijing" +} + +variable "name" { + default = "terraform_example" +} +resource "alicloud_api_gateway_group" "example" { + name = var.name + description = var.name +} + +resource "alicloud_api_gateway_plugin" "example" { + description = "tf_example" + plugin_name = "tf_example" + plugin_data = jsonencode({ "allowOrigins" : "api.foo.com", "allowMethods" : "GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH", "allowHeaders" : "Authorization,Accept,Accept-Ranges,Cache-Control,Range,Date,Content-Type,Content-Length,Content-MD5,User-Agent,X-Ca-Signature,X-Ca-Signature-Headers,X-Ca-Signature-Method,X-Ca-Key,X-Ca-Timestamp,X-Ca-Nonce,X-Ca-Stage,X-Ca-Request-Mode,x-ca-deviceid", "exposeHeaders" : "Content-MD5,Server,Date,Latency,X-Ca-Request-Id,X-Ca-Error-Code,X-Ca-Error-Message", "maxAge" : 172800, "allowCredentials" : true }) + plugin_type = "cors" +} + +resource "alicloud_api_gateway_group_plugin_attachment" "example" { + group_id = alicloud_api_gateway_group.example.id + plugin_id = alicloud_api_gateway_plugin.example.id + stage_name = "RELEASE" +} +``` + +📚 Need more examples? [VIEW MORE EXAMPLES](https://api.aliyun.com/terraform?activeTab=sample&source=Sample&sourcePath=OfficialSample:alicloud_api_gateway_plugin_attachment&spm=docs.r.api_gateway_plugin_attachment.example&intl_lang=EN_US) + +## Argument Reference + +The following arguments are supported: +* `group_id` - (Required, ForceNew) The group that plugin attaches to. +* `plugin_id` - (Required, ForceNew) The plugin that attaches to the group. +* `stage_name` - (Required, ForceNew) Stage that the plugin attaches to. + +## Attributes Reference + +The following attributes are exported: +* `id` - The resource ID of the group plugin attachment. The value formats as `::`. + +## Import +Api Gateway group plugin attachment a can be imported using the id, e.g. + +```shell +$ terraform import alicloud_api_gateway_group_plugin_attachment.example :: +```