diff --git a/alicloud/connectivity/client.go b/alicloud/connectivity/client.go index 444f14ad93e8..564b823db6d1 100644 --- a/alicloud/connectivity/client.go +++ b/alicloud/connectivity/client.go @@ -5402,3 +5402,27 @@ func (client *AliyunClient) NewDfsClient() (*rpc.Client, error) { } return conn, nil } +func (client *AliyunClient) NewAmqpClient() (*rpc.Client, error) { + productCode := "amqp-open" + endpoint := "" + if v, ok := client.config.Endpoints.Load(productCode); !ok || v.(string) == "" { + if err := client.loadEndpoint(productCode); err != nil { + endpoint = fmt.Sprintf("amqp-open.%s.aliyuncs.com", client.config.RegionId) + client.config.Endpoints.Store(productCode, endpoint) + log.Printf("[ERROR] loading %s endpoint got an error: %#v. Using the endpoint %s instead.", productCode, err, endpoint) + } + } + if v, ok := client.config.Endpoints.Load(productCode); ok && v.(string) != "" { + endpoint = v.(string) + } + if endpoint == "" { + return nil, fmt.Errorf("[ERROR] missing the product %s endpoint.", productCode) + } + sdkConfig := client.teaSdkConfig + sdkConfig.SetEndpoint(endpoint) + conn, err := rpc.NewClient(&sdkConfig) + if err != nil { + return nil, fmt.Errorf("unable to initialize the %s client: %#v", productCode, err) + } + return conn, nil +} diff --git a/alicloud/provider.go b/alicloud/provider.go index 37606821cecf..b92698aeb563 100644 --- a/alicloud/provider.go +++ b/alicloud/provider.go @@ -1310,7 +1310,7 @@ func Provider() terraform.ResourceProvider { "alicloud_amqp_exchange": resourceAlicloudAmqpExchange(), "alicloud_cassandra_backup_plan": resourceAlicloudCassandraBackupPlan(), "alicloud_cen_transit_router_peer_attachment": resourceAlicloudCenTransitRouterPeerAttachment(), - "alicloud_amqp_instance": resourceAlicloudAmqpInstance(), + "alicloud_amqp_instance": resourceAliCloudAmqpInstance(), "alicloud_hbr_vault": resourceAliCloudHbrVault(), "alicloud_ssl_certificates_service_certificate": resourceAliCloudSslCertificatesServiceCertificate(), "alicloud_arms_alert_contact": resourceAlicloudArmsAlertContact(), diff --git a/alicloud/resource_alicloud_amqp_instance.go b/alicloud/resource_alicloud_amqp_instance.go index e2c423165848..58e0bf831dd9 100644 --- a/alicloud/resource_alicloud_amqp_instance.go +++ b/alicloud/resource_alicloud_amqp_instance.go @@ -2,6 +2,7 @@ package alicloud import ( "fmt" + "github.com/PaesslerAG/jsonpath" "log" "time" @@ -9,40 +10,52 @@ import ( "github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ) -func resourceAlicloudAmqpInstance() *schema.Resource { +func resourceAliCloudAmqpInstance() *schema.Resource { return &schema.Resource{ - Create: resourceAlicloudAmqpInstanceCreate, - Read: resourceAlicloudAmqpInstanceRead, - Update: resourceAlicloudAmqpInstanceUpdate, - Delete: resourceAlicloudAmqpInstanceDelete, + Create: resourceAliCloudAmqpInstanceCreate, + Read: resourceAliCloudAmqpInstanceRead, + Update: resourceAliCloudAmqpInstanceUpdate, + Delete: resourceAliCloudAmqpInstanceDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(60 * time.Minute), + Create: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(5 * time.Minute), + Delete: schema.DefaultTimeout(5 * time.Minute), }, Schema: map[string]*schema.Schema{ + "auto_renew": { + Type: schema.TypeBool, + Optional: true, + }, + "create_time": { + Type: schema.TypeInt, + Computed: true, + }, "instance_name": { Type: schema.TypeString, - Computed: true, Optional: true, + Computed: true, }, "instance_type": { Type: schema.TypeString, - Required: true, + Optional: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"professional", "enterprise", "vip"}, false), + Computed: true, + ValidateFunc: StringInSlice([]string{"professional", "enterprise", "vip"}, true), }, - "logistics": { - Type: schema.TypeString, + "max_connections": { + Type: schema.TypeInt, Optional: true, + Computed: true, }, "max_eip_tps": { Type: schema.TypeString, Optional: true, + //Computed: true, DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { if v, ok := d.GetOkExists("support_eip"); ok && v.(bool) { return false @@ -52,37 +65,40 @@ func resourceAlicloudAmqpInstance() *schema.Resource { }, "max_tps": { Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, }, "modify_type": { Type: schema.TypeString, Optional: true, - ValidateFunc: validation.StringInSlice([]string{"Downgrade", "Upgrade"}, false), + ValidateFunc: StringInSlice([]string{"Upgrade", "Downgrade"}, true), }, "payment_type": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringInSlice([]string{"Subscription"}, false), + ForceNew: true, + ValidateFunc: StringInSlice([]string{"Subscription", "PayAsYouGo"}, true), }, "period": { Type: schema.TypeInt, Optional: true, - ValidateFunc: validation.IntInSlice([]int{1, 12, 2, 24, 3, 6}), - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - if v, ok := d.GetOk("payment_type"); ok && v.(string) == "Subscription" { - return false - } - return true - }, + ValidateFunc: IntInSlice([]int{0, 1, 2, 3, 6, 12, 24}), + }, + "period_cycle": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: StringInSlice([]string{"Month", "Year"}, true), }, "queue_capacity": { Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, }, "renewal_duration": { Type: schema.TypeInt, Optional: true, - ValidateFunc: validation.IntInSlice([]int{1, 12, 2, 3, 6}), + Computed: true, + ValidateFunc: IntInSlice([]int{0, 1, 2, 3, 6, 12}), DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { if v, ok := d.GetOk("payment_type"); ok && v.(string) == "Subscription" { if v, ok := d.GetOk("renewal_status"); ok && v.(string) == "AutoRenewal" { @@ -95,7 +111,8 @@ func resourceAlicloudAmqpInstance() *schema.Resource { "renewal_duration_unit": { Type: schema.TypeString, Optional: true, - ValidateFunc: validation.StringInSlice([]string{"Month", "Year"}, false), + Computed: true, + ValidateFunc: StringInSlice([]string{"Month", "Year"}, true), DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { if v, ok := d.GetOk("payment_type"); ok && v.(string) == "Subscription" { if v, ok := d.GetOk("renewal_status"); ok && v.(string) == "AutoRenewal" { @@ -109,7 +126,7 @@ func resourceAlicloudAmqpInstance() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - ValidateFunc: validation.StringInSlice([]string{"AutoRenewal", "ManualRenewal", "NotRenewal"}, false), + ValidateFunc: StringInSlice([]string{"AutoRenewal", "ManualRenewal", "NotRenewal"}, true), DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { if v, ok := d.GetOk("payment_type"); ok && v.(string) == "Subscription" { return false @@ -117,6 +134,10 @@ func resourceAlicloudAmqpInstance() *schema.Resource { return true }, }, + "serverless_charge_type": { + Type: schema.TypeString, + Optional: true, + }, "status": { Type: schema.TypeString, Computed: true, @@ -124,6 +145,7 @@ func resourceAlicloudAmqpInstance() *schema.Resource { "storage_size": { Type: schema.TypeString, Optional: true, + Computed: true, DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { if v, ok := d.GetOk("instance_type"); ok && v.(string) == "vip" { return false @@ -133,347 +155,466 @@ func resourceAlicloudAmqpInstance() *schema.Resource { }, "support_eip": { Type: schema.TypeBool, - Required: true, + Optional: true, + }, + "support_tracing": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "tracing_storage_time": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: IntInSlice([]int{-1, 0, 3, 7, 15}), }, }, } } -func resourceAlicloudAmqpInstanceCreate(d *schema.ResourceData, meta interface{}) error { +func resourceAliCloudAmqpInstanceCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) - var response map[string]interface{} + action := "CreateInstance" - request := make(map[string]interface{}) - parameterMapList := make([]map[string]interface{}, 0) - conn, err := client.NewBssopenapiClient() + var request map[string]interface{} + var response map[string]interface{} + query := make(map[string]interface{}) + conn, err := client.NewAmqpClient() if err != nil { return WrapError(err) } - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "InstanceType", - "Value": d.Get("instance_type"), - }) - if v, ok := d.GetOk("logistics"); ok { - request["Logistics"] = v + request = make(map[string]interface{}) + + request["ClientToken"] = buildClientToken(action) + + request["PaymentType"] = d.Get("payment_type") + if v, ok := d.GetOkExists("support_eip"); ok { + request["SupportEip"] = v + } + if v, ok := d.GetOk("instance_type"); ok { + request["InstanceType"] = v + } + if v, ok := d.GetOk("queue_capacity"); ok { + request["QueueCapacity"] = v } if v, ok := d.GetOk("max_eip_tps"); ok { - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "MaxEipTps", - "Value": v, - }) - } else if v, ok := d.GetOkExists("support_eip"); ok && v.(bool) { - return WrapError(fmt.Errorf("attribute '%s' is required when '%s' is %v ", "max_eip_tps", "support_eip", d.Get("support_eip"))) + request["MaxEipTps"] = v + } + if v, ok := d.GetOk("max_connections"); ok { + request["MaxConnections"] = v + } + if v, ok := d.GetOk("storage_size"); ok { + request["StorageSize"] = v + } + if v, ok := d.GetOkExists("support_tracing"); ok { + request["SupportTracing"] = v + } + if v, ok := d.GetOk("tracing_storage_time"); ok { + request["TracingStorageTime"] = v + } + if v, ok := d.GetOk("renewal_status"); ok { + request["RenewStatus"] = v + } + if v, ok := d.GetOk("renewal_duration"); ok { + request["AutoRenewPeriod"] = v + } + if v, ok := d.GetOk("renewal_duration_unit"); ok { + request["RenewalDurationUnit"] = v } - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "MaxTps", - "Value": d.Get("max_tps"), - }) - request["SubscriptionType"] = d.Get("payment_type") if v, ok := d.GetOk("period"); ok { request["Period"] = v } - request["ProductCode"] = "ons" - request["ProductType"] = "ons_onsproxy_pre" - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "QueueCapacity", - "Value": d.Get("queue_capacity"), - }) - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "Region", - "Value": client.RegionId, - }) - if v, ok := d.GetOk("renewal_duration"); ok { - request["RenewPeriod"] = v - } else if v, ok := d.GetOk("renewal_status"); ok && v.(string) == "AutoRenewal" { - return WrapError(fmt.Errorf("attribute '%s' is required when '%s' is %v ", "renewal_duration", "renewal_status", d.Get("renewal_status"))) + if v, ok := d.GetOk("period_cycle"); ok { + request["PeriodCycle"] = v } - if v, ok := d.GetOk("renewal_status"); ok { - request["RenewalStatus"] = v + if v, ok := d.GetOkExists("auto_renew"); ok { + request["AutoRenew"] = v } - if v, ok := d.GetOk("storage_size"); ok { - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "StorageSize", - "Value": v, - }) + if v, ok := d.GetOk("instance_name"); ok { + request["InstanceName"] = v + } + if v, ok := d.GetOk("serverless_charge_type"); ok { + request["ServerlessChargeType"] = v + } + if v, ok := d.GetOk("max_tps"); ok { + request["MaxPrivateTps"] = v } - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "SupportEip", - "Value": convertAmqpInstanceSupportEipRequest(d.Get("support_eip").(bool)), - }) - request["Parameter"] = parameterMapList - request["ClientToken"] = buildClientToken("CreateInstance") runtime := util.RuntimeOptions{} runtime.SetAutoretry(true) - wait := incrementalWait(3*time.Second, 3*time.Second) + 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("2017-12-14"), StringPointer("AK"), nil, request, &runtime) + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2019-12-12"), StringPointer("AK"), query, request, &runtime) + request["ClientToken"] = buildClientToken(action) + if err != nil { if NeedRetry(err) { wait() return resource.RetryableError(err) } - if IsExpectedErrors(err, []string{"NotApplicable"}) { - conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational) - request["ProductType"] = "ons_onsproxy_public_intl" - 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_amqp_instance", action, AlibabaCloudSdkGoERROR) } - if fmt.Sprint(response["Code"]) != "Success" { - return WrapError(fmt.Errorf("%s failed, response: %v", action, response)) + code, _ := jsonpath.Get("$.Code", response) + if fmt.Sprint(code) != "200" { + log.Printf("[DEBUG] Resource alicloud_amqp_instance CreateInstance Failed!!! %s", response) + return WrapErrorf(err, DefaultErrorMsg, "alicloud_amqp_instance", action, AlibabaCloudSdkGoERROR, response) } - responseData := response["Data"].(map[string]interface{}) - d.SetId(fmt.Sprint(responseData["InstanceId"])) - amqpOpenService := AmqpOpenService{client} - stateConf := BuildStateConf([]string{}, []string{"SERVING"}, d.Timeout(schema.TimeoutCreate), 10*time.Second, amqpOpenService.AmqpInstanceStateRefreshFunc(d.Id(), []string{"EXPIRED"})) + + d.SetId(fmt.Sprint(response["Data"])) + + amqpServiceV2 := AmqpServiceV2{client} + stateConf := BuildStateConf([]string{}, []string{"SERVING"}, d.Timeout(schema.TimeoutCreate), 1*time.Minute, amqpServiceV2.AmqpInstanceStateRefreshFunc(d.Id(), "Status", []string{})) if _, err := stateConf.WaitForState(); err != nil { return WrapErrorf(err, IdMsg, d.Id()) } - return resourceAlicloudAmqpInstanceUpdate(d, meta) + return resourceAliCloudAmqpInstanceRead(d, meta) } -func resourceAlicloudAmqpInstanceRead(d *schema.ResourceData, meta interface{}) error { + +func resourceAliCloudAmqpInstanceRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AliyunClient) - amqpOpenService := AmqpOpenService{client} - object, err := amqpOpenService.DescribeAmqpInstance(d.Id()) + amqpServiceV2 := AmqpServiceV2{client} + + objectRaw, err := amqpServiceV2.DescribeAmqpInstance(d.Id()) if err != nil { - if NotFoundError(err) { - log.Printf("[DEBUG] Resource alicloud_amqp_instance amqpOpenService.DescribeAmqpInstance Failed!!! %s", err) + if !d.IsNewResource() && NotFoundError(err) { + log.Printf("[DEBUG] Resource alicloud_amqp_instance DescribeAmqpInstance Failed!!! %s", err) d.SetId("") return nil } return WrapError(err) } - d.Set("instance_name", object["InstanceName"]) - d.Set("instance_type", convertAmqpInstanceInstanceTypeResponse(object["InstanceType"])) - d.Set("status", object["Status"]) - d.Set("support_eip", object["SupportEIP"]) - bssOpenApiService := BssOpenApiService{client} - queryAvailableInstancesObject, err := bssOpenApiService.QueryAvailableInstances(d.Id(), client.RegionId, "ons", "ons_onsproxy_pre", "ons", "ons_onsproxy_public_intl") + + d.Set("create_time", objectRaw["OrderCreateTime"]) + d.Set("instance_name", objectRaw["InstanceName"]) + d.Set("instance_type", convertAmqpInstanceDataInstanceTypeResponse(objectRaw["InstanceType"])) + d.Set("max_connections", objectRaw["MaxConnections"]) + d.Set("max_eip_tps", objectRaw["MaxEipTps"]) + d.Set("max_tps", objectRaw["MaxTps"]) + d.Set("queue_capacity", objectRaw["MaxQueue"]) + d.Set("status", objectRaw["Status"]) + d.Set("storage_size", objectRaw["StorageSize"]) + d.Set("support_eip", objectRaw["SupportEIP"]) + d.Set("support_tracing", objectRaw["SupportTracing"]) + d.Set("tracing_storage_time", objectRaw["TracingStorageTime"]) + + if convertAmqpInstanceDataInstanceTypeResponse(objectRaw["InstanceType"]) == "SERVERLESS" { + return nil + } + + objectRaw, err = amqpServiceV2.DescribeQueryAvailableInstances(d.Id()) if err != nil { return WrapError(err) } - d.Set("payment_type", queryAvailableInstancesObject["SubscriptionType"]) - if v, ok := queryAvailableInstancesObject["RenewalDuration"]; ok && fmt.Sprint(v) != "0" { - d.Set("renewal_duration", formatInt(v)) - } - d.Set("renewal_duration_unit", convertAmqpInstanceRenewalDurationUnitResponse(object["RenewalDurationUnit"])) - d.Set("renewal_status", queryAvailableInstancesObject["RenewStatus"]) + + d.Set("create_time", objectRaw["CreateTime"]) + d.Set("payment_type", objectRaw["SubscriptionType"]) + d.Set("renewal_duration", objectRaw["RenewalDuration"]) + d.Set("renewal_duration_unit", convertAmqpInstanceDataInstanceListRenewalDurationUnitResponse(objectRaw["RenewalDurationUnit"])) + d.Set("renewal_status", objectRaw["RenewStatus"]) + return nil } -func resourceAlicloudAmqpInstanceUpdate(d *schema.ResourceData, meta interface{}) error { + +func resourceAliCloudAmqpInstanceUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AliyunClient) + var request map[string]interface{} + var response map[string]interface{} + var query map[string]interface{} + update := false + d.Partial(true) + action := "SetRenewal" conn, err := client.NewBssopenapiClient() if err != nil { return WrapError(err) } - var response map[string]interface{} - d.Partial(true) + request = make(map[string]interface{}) + query = make(map[string]interface{}) + query["InstanceIDs"] = d.Id() + if d.HasChange("payment_type") { + update = true + } + request["SubscriptionType"] = d.Get("payment_type") + if d.HasChange("renewal_duration_unit") { + update = true + } + if v, ok := d.GetOk("renewal_duration_unit"); ok { + request["RenewalPeriodUnit"] = convertAmqpInstanceRenewalPeriodUnitRequest(fmt.Sprint(v)) + } - update := false - request := map[string]interface{}{ - "InstanceId": d.Id(), + if d.HasChange("renewal_duration") { + update = true } - if d.HasChange("instance_name") { + if v, ok := d.GetOk("renewal_duration"); ok { + request["RenewalPeriod"] = v + } + + if d.HasChange("renewal_status") { update = true } - if v, ok := d.GetOk("instance_name"); ok { - request["InstanceName"] = v + if v, ok := d.GetOk("renewal_status"); ok { + request["RenewalStatus"] = v } + + request["ProductCode"] = "ons" if update { - action := "UpdateInstanceName" - conn, err := client.NewOnsproxyClient() - if err != nil { - return WrapError(err) - } - 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.TimeoutUpdate), func() *resource.RetryError { - response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2019-12-12"), StringPointer("AK"), nil, request, &util.RuntimeOptions{}) + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-12-14"), StringPointer("AK"), query, request, &runtime) + if err != nil { + if IsExpectedErrors(err, []string{"NotApplicable"}) { + conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational) + request["ProductType"] = "ons_onsproxy_public_intl" + return resource.RetryableError(err) + } if 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, d.Id(), action, AlibabaCloudSdkGoERROR) } - if fmt.Sprint(response["Success"]) == "false" { - return WrapError(fmt.Errorf("%s failed, response: %v", action, response)) - } - d.SetPartial("instance_name") + d.SetPartial("renewal_duration_unit") + d.SetPartial("renewal_duration") + d.SetPartial("renewal_status") } update = false - setRenewalReq := map[string]interface{}{ - "InstanceIDs": d.Id(), - } - - if !d.IsNewResource() && d.HasChange("renewal_status") { - update = true - } - if v, ok := d.GetOk("renewal_status"); ok { - setRenewalReq["RenewalStatus"] = v + action = "UpdateInstanceName" + conn, err = client.NewAmqpClient() + if err != nil { + return WrapError(err) } - if !d.IsNewResource() && d.HasChange("renewal_duration") { + request = make(map[string]interface{}) + query = make(map[string]interface{}) + query["InstanceId"] = d.Id() + if d.HasChange("instance_name") { update = true - } - if v, ok := d.GetOk("renewal_duration"); ok { - setRenewalReq["RenewalPeriod"] = v + request["InstanceName"] = d.Get("instance_name") } - if !d.IsNewResource() && d.HasChange("payment_type") { - update = true - setRenewalReq["SubscriptionType"] = d.Get("payment_type") - } - setRenewalReq["ProductCode"] = "ons" - setRenewalReq["ProductType"] = "ons_onsproxy_pre" - if d.HasChange("renewal_duration_unit") { - update = true - if v, ok := d.GetOk("renewal_duration_unit"); ok { - setRenewalReq["RenewalPeriodUnit"] = convertAmqpInstanceRenewalDurationUnitRequest(v.(string)) - } else if v, ok := d.GetOk("renewal_status"); ok && v.(string) == "AutoRenewal" { - return WrapError(fmt.Errorf("attribute '%s' is required when '%s' is %v ", "renewal_duration_unit", "renewal_status", d.Get("renewal_status"))) - } - setRenewalReq["RenewalStatus"] = d.Get("renewal_status") - } if update { - action := "SetRenewal" - 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.TimeoutUpdate), func() *resource.RetryError { - response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-12-14"), StringPointer("AK"), nil, setRenewalReq, &util.RuntimeOptions{}) + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2019-12-12"), StringPointer("AK"), query, request, &runtime) + if err != nil { if NeedRetry(err) { wait() return resource.RetryableError(err) } - if IsExpectedErrors(err, []string{"NotApplicable"}) { - conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational) - setRenewalReq["ProductType"] = "ons_onsproxy_public_intl" - return resource.RetryableError(err) - } return resource.NonRetryableError(err) } + addDebug(action, response, request) return nil }) - addDebug(action, response, setRenewalReq) if err != nil { return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR) } - if fmt.Sprint(response["Code"]) != "Success" { - return WrapError(fmt.Errorf("%s failed, response: %v", action, response)) - } - d.SetPartial("renewal_status") - d.SetPartial("payment_type") - d.SetPartial("renewal_duration") - d.SetPartial("renewal_duration_unit") + d.SetPartial("instance_name") } update = false - modifyInstanceReq := map[string]interface{}{ - "InstanceId": d.Id(), + action = "UpdateInstance" + conn, err = client.NewAmqpClient() + if err != nil { + return WrapError(err) } - parameterMapList := make([]map[string]interface{}, 0) - if !d.IsNewResource() && d.HasChange("max_tps") { + request = make(map[string]interface{}) + query = make(map[string]interface{}) + query["InstanceId"] = d.Id() + request["ClientToken"] = buildClientToken(action) + if v, ok := d.GetOk("modify_type"); ok { + request["ModifyType"] = convertAmqpInstanceModifyTypeRequest(v.(string)) + } + if d.HasChange("instance_type") { update = true } - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "MaxTps", - "Value": d.Get("max_tps"), - }) + if v, ok := d.GetOk("instance_type"); ok && fmt.Sprint(v) != "SERVERLESS" { + request["InstanceType"] = v + } - modifyInstanceReq["SubscriptionType"] = d.Get("payment_type") - modifyInstanceReq["ProductCode"] = "ons" - if !d.IsNewResource() && d.HasChange("queue_capacity") { + if v, ok := d.GetOk("serverless_charge_type"); ok { + request["ServerlessChargeType"] = v + } + if d.HasChange("support_eip") { update = true } - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "QueueCapacity", - "Value": d.Get("queue_capacity"), - }) - if !d.IsNewResource() && d.HasChange("support_eip") { + if v, ok := d.GetOkExists("support_eip"); ok { + request["SupportEip"] = v + } + + if d.HasChange("max_eip_tps") { update = true } - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "SupportEip", - "Value": convertAmqpInstanceSupportEipRequest(d.Get("support_eip").(bool)), - }) - if !d.IsNewResource() && d.HasChange("max_eip_tps") { + if v, ok := d.GetOk("max_eip_tps"); ok && fmt.Sprint(v) != "-1" && d.Get("support_eip").(bool) { + request["MaxEipTps"] = v + } + + if d.HasChange("queue_capacity") { update = true } - if v, ok := d.GetOk("max_eip_tps"); ok { - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "MaxEipTps", - "Value": v, - }) - } else if v, ok := d.GetOkExists("support_eip"); ok && v.(bool) { - return WrapError(fmt.Errorf("attribute '%s' is required when '%s' is %v ", "max_eip_tps", "support_eip", d.Get("support_eip"))) + if v, ok := d.GetOk("queue_capacity"); ok && fmt.Sprint(v) != "-1" { + request["QueueCapacity"] = v } - modifyInstanceReq["ProductType"] = "ons_onsproxy_pre" - if !d.IsNewResource() && d.HasChange("storage_size") { + + if d.HasChange("max_connections") { update = true } - if v, ok := d.GetOk("storage_size"); ok { - parameterMapList = append(parameterMapList, map[string]interface{}{ - "Code": "StorageSize", - "Value": v, - }) + if v, ok := d.GetOk("max_connections"); ok && fmt.Sprint(v) != "-1" { + request["MaxConnections"] = v + } + + if d.HasChange("storage_size") { + update = true + } + if v, ok := d.GetOk("storage_size"); ok && fmt.Sprint(v) != "-1" { + request["StorageSize"] = v + } + + if d.HasChange("support_tracing") { + update = true + } + if v, ok := d.GetOk("support_tracing"); ok && fmt.Sprint(v) != "-1" { + request["SupportTracing"] = v } - modifyInstanceReq["Parameter"] = parameterMapList + + if d.HasChange("tracing_storage_time") { + update = true + } + if v, ok := d.GetOk("tracing_storage_time"); ok && fmt.Sprint(v) != "-1" { + request["TracingStorageTime"] = v + } + + if d.HasChange("max_tps") { + update = true + } + if v, ok := d.GetOk("max_tps"); ok && fmt.Sprint(v) != "-1" { + request["MaxPrivateTps"] = v + } + if update { - if v, ok := d.GetOk("modify_type"); ok { - modifyInstanceReq["ModifyType"] = v - } - action := "ModifyInstance" - request["ClientToken"] = buildClientToken("ModifyInstance") runtime := util.RuntimeOptions{} runtime.SetAutoretry(true) - wait := incrementalWait(3*time.Second, 3*time.Second) + wait := incrementalWait(3*time.Second, 5*time.Second) err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError { - response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-12-14"), StringPointer("AK"), nil, modifyInstanceReq, &runtime) + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2019-12-12"), StringPointer("AK"), query, request, &runtime) + request["ClientToken"] = buildClientToken(action) + if err != nil { if NeedRetry(err) { wait() return resource.RetryableError(err) } - if IsExpectedErrors(err, []string{"NotApplicable"}) { - conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational) - modifyInstanceReq["ProductType"] = "ons_onsproxy_public_intl" - return resource.RetryableError(err) - } return resource.NonRetryableError(err) } + addDebug(action, response, request) return nil }) - addDebug(action, response, modifyInstanceReq) if err != nil { return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR) } - if fmt.Sprint(response["Code"]) != "Success" { - return WrapError(fmt.Errorf("%s failed, response: %v", action, response)) + code, _ := jsonpath.Get("$.Code", response) + if fmt.Sprint(code) != "200" { + log.Printf("[DEBUG] Resource alicloud_amqp_instance UpdateInstance Failed!!! %s", response) + return WrapErrorf(err, DefaultErrorMsg, "alicloud_amqp_instance", action, AlibabaCloudSdkGoERROR, response) } - d.SetPartial("max_tps") - d.SetPartial("payment_type") - d.SetPartial("queue_capacity") + amqpServiceV2 := AmqpServiceV2{client} + stateConf := BuildStateConf([]string{}, []string{"SERVING"}, d.Timeout(schema.TimeoutUpdate), 1*time.Minute, amqpServiceV2.AmqpInstanceStateRefreshFunc(d.Id(), "Status", []string{})) + if _, err := stateConf.WaitForState(); err != nil { + return WrapErrorf(err, IdMsg, d.Id()) + } + d.SetPartial("instance_type") d.SetPartial("support_eip") d.SetPartial("max_eip_tps") + d.SetPartial("queue_capacity") + d.SetPartial("max_connections") d.SetPartial("storage_size") + d.SetPartial("support_tracing") + d.SetPartial("tracing_storage_time") + d.SetPartial("max_tps") } + d.Partial(false) - return resourceAlicloudAmqpInstanceRead(d, meta) + return resourceAliCloudAmqpInstanceRead(d, meta) } -func resourceAlicloudAmqpInstanceDelete(d *schema.ResourceData, meta interface{}) error { - log.Printf("[WARN] Cannot destroy resourceAlicloudAmqpInstance. Terraform will remove this resource from the state file, however resources may remain.") + +func resourceAliCloudAmqpInstanceDelete(d *schema.ResourceData, meta interface{}) error { + + if v, ok := d.GetOk("payment_type"); ok { + if v == "PayAsYouGo" { + log.Printf("[WARN] Cannot destroy resource alicloud_amqp_instance which payment_type valued PayAsYouGo. Terraform will remove this resource from the state file, however resources may remain.") + return nil + } + } + + client := meta.(*connectivity.AliyunClient) + action := "RefundInstance" + var request map[string]interface{} + var response map[string]interface{} + query := make(map[string]interface{}) + conn, err := client.NewBssopenapiClient() + if err != nil { + return WrapError(err) + } + request = make(map[string]interface{}) + query["InstanceId"] = d.Id() + + request["ClientToken"] = buildClientToken(action) + + request["ImmediatelyRelease"] = "1" + request["ProductCode"] = "ons" + request["ProductType"] = "ons_onsproxy_pre" + 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("2017-12-14"), StringPointer("AK"), query, request, &runtime) + request["ClientToken"] = buildClientToken(action) + + if err != nil { + if IsExpectedErrors(err, []string{"NotApplicable"}) { + conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational) + request["ProductType"] = "ons_onsproxy_public_intl" + return resource.RetryableError(err) + } + 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) + } + + amqpServiceV2 := AmqpServiceV2{client} + stateConf := BuildStateConf([]string{}, []string{"RELEASED"}, d.Timeout(schema.TimeoutDelete), 1*time.Minute, amqpServiceV2.AmqpInstanceStateRefreshFunc(d.Id(), "Status", []string{})) + if _, err := stateConf.WaitForState(); err != nil { + return WrapErrorf(err, IdMsg, d.Id()) + } return nil } + func convertAmqpInstanceSupportEipRequest(source interface{}) interface{} { switch source { case false: @@ -512,3 +653,42 @@ func convertAmqpInstanceRenewalDurationUnitRequest(source interface{}) interface } return source } + +func convertAmqpInstanceDataInstanceTypeResponse(source interface{}) interface{} { + switch source { + case "PROFESSIONAL": + return "professional" + case "VIP": + return "vip" + case "ENTERPRISE": + return "enterprise" + } + return source +} +func convertAmqpInstanceDataInstanceListRenewalDurationUnitResponse(source interface{}) interface{} { + switch source { + case "M": + return "Month" + case "Y": + return "Year" + } + return source +} +func convertAmqpInstanceRenewalPeriodUnitRequest(source interface{}) interface{} { + switch source { + case "Month": + return "M" + case "Year": + return "Y" + } + return source +} +func convertAmqpInstanceModifyTypeRequest(source interface{}) interface{} { + switch source { + case "Downgrade": + return "DOWNGRADE" + case "Upgrade": + return "UPGRADE" + } + return source +} diff --git a/alicloud/resource_alicloud_amqp_instance_test.go b/alicloud/resource_alicloud_amqp_instance_test.go index 62cd535c36a9..e9def79c0eac 100644 --- a/alicloud/resource_alicloud_amqp_instance_test.go +++ b/alicloud/resource_alicloud_amqp_instance_test.go @@ -20,7 +20,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" ) -func TestAccAlicloudAmqpInstance_professional(t *testing.T) { +func TestAccAliCloudAmqpInstance_professional(t *testing.T) { var v map[string]interface{} resourceId := "alicloud_amqp_instance.default" @@ -44,7 +44,7 @@ func TestAccAlicloudAmqpInstance_professional(t *testing.T) { // module name IDRefreshName: resourceId, Providers: testAccProviders, - CheckDestroy: nil, + //CheckDestroy: nil, Steps: []resource.TestStep{ { Config: testAccConfig(map[string]interface{}{ @@ -55,6 +55,8 @@ func TestAccAlicloudAmqpInstance_professional(t *testing.T) { "period": "1", "queue_capacity": "50", "support_eip": "false", + "auto_renew": "true", + "period_cycle": "Year", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ @@ -64,12 +66,22 @@ func TestAccAlicloudAmqpInstance_professional(t *testing.T) { "payment_type": "Subscription", "queue_capacity": "50", "support_eip": "false", - "renewal_status": "ManualRenewal", - "renewal_duration_unit": "", + "renewal_status": "AutoRenewal", + "renewal_duration_unit": "Month", "status": "SERVING", }), ), }, + { + Config: testAccConfig(map[string]interface{}{ + "auto_renew": "false", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "auto_renew": "false", + }), + ), + }, { Config: testAccConfig(map[string]interface{}{ "instance_name": name + "-update", @@ -82,52 +94,86 @@ func TestAccAlicloudAmqpInstance_professional(t *testing.T) { }, { Config: testAccConfig(map[string]interface{}{ - "modify_type": "Upgrade", - "max_tps": "1500", + "modify_type": "Upgrade", + "max_tps": "1500", + "max_eip_tps": "256", + "max_connections": "1500", + "queue_capacity": "150", + // "tracing_storage_time": "3", + "support_eip": "true", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ - "max_tps": "1500", + "max_tps": "1500", + "max_eip_tps": "256", + "support_eip": "true", + "queue_capacity": "150", }), ), }, { Config: testAccConfig(map[string]interface{}{ - "queue_capacity": "55", + "queue_capacity": "200", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ - "queue_capacity": "55", + "queue_capacity": "200", }), ), }, { Config: testAccConfig(map[string]interface{}{ + "modify_type": "Downgrade", "support_eip": "false", - //"max_eip_tps": "128", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ + "modify_type": "Downgrade", "support_eip": "false", - //"max_eip_tps": "128", + "max_eip_tps": "-1", + }), + ), + }, + { + Config: testAccConfig(map[string]interface{}{ + "renewal_duration": "1", + "renewal_duration_unit": "Year", + "renewal_status": "AutoRenewal", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "renewal_duration": "1", + "renewal_duration_unit": "Year", + "renewal_status": "AutoRenewal", + }), + ), + }, + { + Config: testAccConfig(map[string]interface{}{ + "renewal_duration": "2", + "renewal_duration_unit": "Month", + "renewal_status": "AutoRenewal", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "renewal_duration": "2", + "renewal_duration_unit": "Month", + "renewal_status": "AutoRenewal", + }), + ), + }, + { + Config: testAccConfig(map[string]interface{}{ + "renewal_status": "ManualRenewal", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "renewal_duration": CHECKSET, + "renewal_duration_unit": CHECKSET, + "renewal_status": "ManualRenewal", }), ), }, - // There is an OpenAPI bug that the api return renewal_duration_unit is "" - //{ - // Config: testAccConfig(map[string]interface{}{ - // "renewal_duration": "1", - // "renewal_duration_unit": "Month", - // "renewal_status": "AutoRenewal", - // }), - // Check: resource.ComposeTestCheckFunc( - // testAccCheck(map[string]string{ - // "renewal_duration": "1", - // "renewal_duration_unit": "Month", - // "renewal_status": "AutoRenewal", - // }), - // ), - //}, { Config: testAccConfig(map[string]interface{}{ "instance_name": name, @@ -144,8 +190,9 @@ func TestAccAlicloudAmqpInstance_professional(t *testing.T) { "queue_capacity": "50", "support_eip": "false", "renewal_status": "NotRenewal", - "renewal_duration": NOSET, - "renewal_duration_unit": "", + "renewal_duration": CHECKSET, + "renewal_duration_unit": "Month", + "max_eip_tps": "-1", }), ), }, @@ -154,13 +201,13 @@ func TestAccAlicloudAmqpInstance_professional(t *testing.T) { ResourceName: resourceId, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"modify_type", "period", "max_tps", "max_eip_tps", "queue_capacity"}, + ImportStateVerifyIgnore: []string{"modify_type", "period", "max_tps", "max_eip_tps", "queue_capacity", "auto_renew"}, }, }, }) } -func TestAccAlicloudAmqpInstance_enterprise(t *testing.T) { +func TestAccAliCloudAmqpInstance_enterprise(t *testing.T) { var v map[string]interface{} resourceId := "alicloud_amqp_instance.default" @@ -179,7 +226,7 @@ func TestAccAlicloudAmqpInstance_enterprise(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) - testAccPreCheckWithTime(t, []int{1}) + //testAccPreCheckWithTime(t, []int{1}) }, // module name IDRefreshName: resourceId, @@ -205,7 +252,7 @@ func TestAccAlicloudAmqpInstance_enterprise(t *testing.T) { "queue_capacity": "200", "support_eip": "false", "renewal_status": "ManualRenewal", - "renewal_duration_unit": "", + "renewal_duration_unit": "Month", "status": "SERVING", }), ), @@ -222,8 +269,9 @@ func TestAccAlicloudAmqpInstance_enterprise(t *testing.T) { }, { Config: testAccConfig(map[string]interface{}{ - "modify_type": "Upgrade", - "max_tps": "5000", + "modify_type": "Upgrade", + "max_tps": "5000", + "max_connections": "2000", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ @@ -255,12 +303,25 @@ func TestAccAlicloudAmqpInstance_enterprise(t *testing.T) { }, { Config: testAccConfig(map[string]interface{}{ - "instance_name": name, - "modify_type": "Downgrade", - "max_tps": "3000", - "queue_capacity": "200", - "support_eip": "false", - "renewal_status": "NotRenewal", + "support_tracing": "true", + "tracing_storage_time": "15", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "support_tracing": "true", + "tracing_storage_time": "15", + }), + ), + }, + { + Config: testAccConfig(map[string]interface{}{ + "instance_name": name, + "modify_type": "Downgrade", + "max_tps": "3000", + "queue_capacity": "200", + "support_eip": "false", + "renewal_status": "NotRenewal", + "support_tracing": "false", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ @@ -269,8 +330,10 @@ func TestAccAlicloudAmqpInstance_enterprise(t *testing.T) { "queue_capacity": "200", "support_eip": "false", "renewal_status": "NotRenewal", - "renewal_duration": NOSET, - "renewal_duration_unit": "", + "renewal_duration": CHECKSET, + "renewal_duration_unit": "Month", + "max_eip_tps": "-1", + "support_tracing": "false", }), ), }, @@ -286,7 +349,7 @@ func TestAccAlicloudAmqpInstance_enterprise(t *testing.T) { } // Currently, the test account does not support the vip -func SkipTestAccAlicloudAmqpInstance_vip(t *testing.T) { +func TestAccAliCloudAmqpInstance_vip(t *testing.T) { var v map[string]interface{} resourceId := "alicloud_amqp_instance.default" @@ -314,109 +377,32 @@ func SkipTestAccAlicloudAmqpInstance_vip(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccConfig(map[string]interface{}{ - "instance_type": "vip", - "max_tps": "5000", - "payment_type": "Subscription", - "period": "1", - "queue_capacity": "50", - "storage_size": "700", - "support_eip": "false", + "instance_type": "vip", + "max_tps": "8000", + "max_eip_tps": "128", + "max_connections": "50000", + "payment_type": "Subscription", + "period": "1", + "queue_capacity": "10000", + "storage_size": "700", + "support_eip": "true", + "support_tracing": "true", + "tracing_storage_time": "15", }), Check: resource.ComposeTestCheckFunc( testAccCheck(map[string]string{ "instance_type": "vip", - "max_tps": "5000", + "max_tps": "8000", "payment_type": "Subscription", - "queue_capacity": "50", + "queue_capacity": "10000", "storage_size": "700", - "support_eip": "false", + "support_eip": "true", "renewal_status": "ManualRenewal", - "renewal_duration": "0", - "renewal_duration_unit": "", + "renewal_duration_unit": "Month", "status": "SERVING", }), ), }, - { - Config: testAccConfig(map[string]interface{}{ - "modify_type": "Upgrade", - "max_tps": "10000", - }), - Check: resource.ComposeTestCheckFunc( - testAccCheck(map[string]string{ - "max_tps": "10000", - }), - ), - }, - { - Config: testAccConfig(map[string]interface{}{ - "queue_capacity": "55", - }), - Check: resource.ComposeTestCheckFunc( - testAccCheck(map[string]string{ - "queue_capacity": "55", - }), - ), - }, - { - Config: testAccConfig(map[string]interface{}{ - "storage_size": "800", - }), - Check: resource.ComposeTestCheckFunc( - testAccCheck(map[string]string{ - "storage_size": "800", - }), - ), - }, - { - Config: testAccConfig(map[string]interface{}{ - "support_eip": "true", - "max_eip_tps": "128", - }), - Check: resource.ComposeTestCheckFunc( - testAccCheck(map[string]string{ - "support_eip": "true", - "max_eip_tps": "128", - }), - ), - }, - // There is an OpenAPI bug that the api return renewal_duration_unit is "" - //{ - // Config: testAccConfig(map[string]interface{}{ - // "renewal_duration": "1", - // "renewal_duration_unit": "Month", - // "renewal_status": "AutoRenewal", - // }), - // Check: resource.ComposeTestCheckFunc( - // testAccCheck(map[string]string{ - // "renewal_duration": "1", - // "renewal_duration_unit": "Month", - // "renewal_status": "AutoRenewal", - // }), - // ), - //}, - { - Config: testAccConfig(map[string]interface{}{ - "modify_type": "Downgrade", - "max_tps": "5000", - "queue_capacity": "50", - "storage_size": "700", - "support_eip": "false", - "renewal_status": "NotRenewal", - }), - Check: resource.ComposeTestCheckFunc( - testAccCheck(map[string]string{ - "max_tps": "5000", - "queue_capacity": "50", - "storage_size": "700", - "support_eip": "false", - "renewal_status": "NotRenewal", - "renewal_duration": "0", - "renewal_duration_unit": "", - }), - ), - }, - { ResourceName: resourceId, ImportState: true, @@ -592,7 +578,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { StatusCode: tea.Int(400), } }) - err := resourceAlicloudAmqpInstanceCreate(d, rawClient) + err := resourceAliCloudAmqpInstanceCreate(d, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -609,7 +595,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["CreateNormal"]("") }) - err := resourceAlicloudAmqpInstanceCreate(d, rawClient) + err := resourceAliCloudAmqpInstanceCreate(d, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -626,7 +612,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["CreateNormal"]("") }) - err := resourceAlicloudAmqpInstanceCreate(dCreate, rawClient) + err := resourceAliCloudAmqpInstanceCreate(dCreate, rawClient) patches.Reset() assert.Nil(t, err) }) @@ -644,7 +630,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["CreateNormal"]("") }) - err := resourceAlicloudAmqpInstanceCreate(d, rawClient) + err := resourceAliCloudAmqpInstanceCreate(d, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -662,7 +648,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["CreateNormal"]("") }) - err := resourceAlicloudAmqpInstanceCreate(dCreateMock, rawClient) + err := resourceAliCloudAmqpInstanceCreate(dCreateMock, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -680,7 +666,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["CreateNormal"]("") }) - err := resourceAlicloudAmqpInstanceCreate(dCreateRenewalStatus, rawClient) + err := resourceAliCloudAmqpInstanceCreate(dCreateRenewalStatus, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -698,7 +684,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["CreateResponseCode"]("") }) - err := resourceAlicloudAmqpInstanceCreate(dCreate, rawClient) + err := resourceAliCloudAmqpInstanceCreate(dCreate, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -716,7 +702,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } }) - err := resourceAlicloudAmqpInstanceUpdate(d, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(d, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -751,7 +737,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -786,7 +772,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.Nil(t, err) }) @@ -821,7 +807,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateResponse"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -856,7 +842,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -891,7 +877,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -927,7 +913,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.Nil(t, err) }) @@ -963,7 +949,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateResponse"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -1001,7 +987,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -1036,7 +1022,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.Nil(t, err) }) @@ -1074,7 +1060,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateResponse"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -1112,7 +1098,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) @@ -1134,14 +1120,14 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["UpdateNormal"]("") }) - err := resourceAlicloudAmqpInstanceUpdate(resourceData1, rawClient) + err := resourceAliCloudAmqpInstanceUpdate(resourceData1, rawClient) patches.Reset() assert.NotNil(t, err) }) // Delete t.Run("DeleteNormal", func(t *testing.T) { - err := resourceAlicloudAmqpInstanceDelete(d, rawClient) + err := resourceAliCloudAmqpInstanceDelete(d, rawClient) assert.Nil(t, err) }) @@ -1157,7 +1143,7 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["ReadNormal"]("") }) - err := resourceAlicloudAmqpInstanceRead(d, rawClient) + err := resourceAliCloudAmqpInstanceRead(d, rawClient) patcheDorequest.Reset() assert.Nil(t, err) }) @@ -1173,8 +1159,88 @@ func TestUnitAlicloudAmqpInstance(t *testing.T) { } return responseMock["ReadNormal"]("") }) - err := resourceAlicloudAmqpInstanceRead(d, rawClient) + err := resourceAliCloudAmqpInstanceRead(d, rawClient) patcheDorequest.Reset() assert.NotNil(t, err) }) } + +// Case 创建serverless实例 6128 +func TestAccAliCloudAmqpInstance_basic6128(t *testing.T) { + var v map[string]interface{} + resourceId := "alicloud_amqp_instance.default" + ra := resourceAttrInit(resourceId, AlicloudAmqpInstanceMap6128) + rc := resourceCheckInitWithDescribeMethod(resourceId, &v, func() interface{} { + return &AmqpServiceV2{testAccProvider.Meta().(*connectivity.AliyunClient)} + }, "DescribeAmqpInstance") + rac := resourceAttrCheckInit(rc, ra) + testAccCheck := rac.resourceAttrMapUpdateSet() + rand := acctest.RandIntRange(10000, 99999) + name := fmt.Sprintf("tf-testacc%samqpinstance%d", defaultRegionToTest, rand) + testAccConfig := resourceTestAccConfigFunc(resourceId, name, AlicloudAmqpInstanceBasicDependence6128) + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + IDRefreshName: resourceId, + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccConfig(map[string]interface{}{ + "payment_type": "PayAsYouGo", + "serverless_charge_type": "onDemand", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "payment_type": "PayAsYouGo", + }), + ), + }, + { + Config: testAccConfig(map[string]interface{}{ + "support_eip": "true", + "support_tracing": "true", + "serverless_charge_type": "onDemand", + "payment_type": "PayAsYouGo", + "max_eip_tps": "128", + "tracing_storage_time": "15", + "modify_type": "Upgrade", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "support_eip": "true", + "support_tracing": "true", + "serverless_charge_type": "onDemand", + "payment_type": "PayAsYouGo", + "max_eip_tps": "128", + "tracing_storage_time": "15", + }), + ), + }, + { + ResourceName: resourceId, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"auto_renew", "modify_type", "period", "period_cycle", "serverless_charge_type", "renewal_duration", "renewal_duration_unit", "renewal_status", "payment_type"}, + }, + }, + }) +} + +var AlicloudAmqpInstanceMap6128 = map[string]string{ + "support_tracing": "false", + "status": CHECKSET, + "create_time": CHECKSET, + "instance_name": CHECKSET, +} + +func AlicloudAmqpInstanceBasicDependence6128(name string) string { + return fmt.Sprintf(` +variable "name" { + default = "%s" +} + + +`, name) +} diff --git a/alicloud/service_alicloud_amqp_v2.go b/alicloud/service_alicloud_amqp_v2.go new file mode 100644 index 000000000000..99468b88f31f --- /dev/null +++ b/alicloud/service_alicloud_amqp_v2.go @@ -0,0 +1,143 @@ +package alicloud + +import ( + "fmt" + "time" + + "github.com/PaesslerAG/jsonpath" + util "github.com/alibabacloud-go/tea-utils/service" + "github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +type AmqpServiceV2 struct { + client *connectivity.AliyunClient +} + +// DescribeAmqpInstance <<< Encapsulated get interface for Amqp Instance. + +func (s *AmqpServiceV2) DescribeAmqpInstance(id string) (object map[string]interface{}, err error) { + client := s.client + var request map[string]interface{} + var response map[string]interface{} + var query map[string]interface{} + action := "GetInstance" + conn, err := client.NewAmqpClient() + if err != nil { + return object, WrapError(err) + } + request = make(map[string]interface{}) + query = make(map[string]interface{}) + query["InstanceId"] = id + + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 5*time.Second) + err = resource.Retry(1*time.Minute, func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("GET"), StringPointer("2019-12-12"), StringPointer("AK"), query, request, &runtime) + + if err != nil { + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + addDebug(action, response, request) + return nil + }) + + if err != nil { + addDebug(action, response, request) + return object, WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR) + } + + v, err := jsonpath.Get("$.Data", response) + if err != nil { + return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.Data", response) + } + + currentStatus := v.(map[string]interface{})["Status"] + if currentStatus == "" { + return object, WrapErrorf(Error(GetNotFoundMessage("Instance", id)), NotFoundMsg, response) + } + + return v.(map[string]interface{}), nil +} +func (s *AmqpServiceV2) DescribeQueryAvailableInstances(id string) (object map[string]interface{}, err error) { + client := s.client + var request map[string]interface{} + var response map[string]interface{} + var query map[string]interface{} + action := "QueryAvailableInstances" + conn, err := client.NewBssopenapiClient() + if err != nil { + return object, WrapError(err) + } + request = make(map[string]interface{}) + query = make(map[string]interface{}) + query["InstanceIDs"] = id + + request["ProductCode"] = "ons" + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 5*time.Second) + err = resource.Retry(1*time.Minute, func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-12-14"), StringPointer("AK"), query, request, &runtime) + + if err != nil { + if IsExpectedErrors(err, []string{"NotApplicable"}) { + conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational) + request["ProductType"] = "ons_onsproxy_public_intl" + return resource.RetryableError(err) + } + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + addDebug(action, response, request) + return nil + }) + + if err != nil { + addDebug(action, response, request) + return object, WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR) + } + + v, err := jsonpath.Get("$.Data.InstanceList[*]", response) + if err != nil { + return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.Data.InstanceList[*]", response) + } + + if len(v.([]interface{})) == 0 { + return object, WrapErrorf(Error(GetNotFoundMessage("Instance", id)), NotFoundMsg, response) + } + + return v.([]interface{})[0].(map[string]interface{}), nil +} + +func (s *AmqpServiceV2) AmqpInstanceStateRefreshFunc(id string, field string, failStates []string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + object, err := s.DescribeAmqpInstance(id) + if err != nil { + if NotFoundError(err) { + return object, "", nil + } + return nil, "", WrapError(err) + } + + v, err := jsonpath.Get(field, object) + currentStatus := fmt.Sprint(v) + + for _, failState := range failStates { + if currentStatus == failState { + return object, currentStatus, WrapError(Error(FailedToReachTargetStatus, currentStatus)) + } + } + return object, currentStatus, nil + } +} + +// DescribeAmqpInstance >>> Encapsulated. diff --git a/website/docs/r/amqp_instance.html.markdown b/website/docs/r/amqp_instance.html.markdown index 86b59145c0c9..63e55fa48a79 100644 --- a/website/docs/r/amqp_instance.html.markdown +++ b/website/docs/r/amqp_instance.html.markdown @@ -2,14 +2,13 @@ subcategory: "RabbitMQ (AMQP)" layout: "alicloud" page_title: "Alicloud: alicloud_amqp_instance" -sidebar_current: "docs-alicloud-resource-amqp-instance" description: |- - Provides a Alicloud RabbitMQ (AMQP) Instance resource. + Provides a Alicloud Amqp Instance resource. --- # alicloud_amqp_instance -Provides a RabbitMQ (AMQP) Instance resource. +Provides a Amqp Instance resource. The instance of Amqp. For information about RabbitMQ (AMQP) Instance and how to use it, see [What is Instance](https://www.alibabacloud.com/help/en/message-queue-for-rabbitmq/latest/createinstance). @@ -20,74 +19,77 @@ For information about RabbitMQ (AMQP) Instance and how to use it, see [What is I Basic Usage ```terraform -resource "alicloud_amqp_instance" "professional" { - instance_type = "professional" - max_tps = 1000 - queue_capacity = 50 - support_eip = true - max_eip_tps = 128 - payment_type = "Subscription" - period = 1 +variable "name" { + default = "terraform-example" } -resource "alicloud_amqp_instance" "enterprise" { - instance_type = "enterprise" - max_tps = 3000 - queue_capacity = 200 - storage_size = 700 - support_eip = false - max_eip_tps = 128 +provider "alicloud" { + region = "cn-hangzhou" +} + + +resource "alicloud_amqp_instance" "default" { + instance_name = var.name + instance_type = "professional" + max_tps = "1000" + queue_capacity = "50" + period_cycle = "Year" + support_eip = "false" + period = "1" + auto_renew = "true" payment_type = "Subscription" - period = 1 } ``` ### Deleting `alicloud_amqp_instance` or removing it from your configuration -The `alicloud_amqp_instance` resource allows you to manage `payment_type = "Subscription"` amqp instance, but Terraform cannot destroy it. -Deleting the subscription resource or removing it from your configuration will remove it from your state file and management, but will not destroy the amqp Instance. -You can resume managing the subscription db instance via the AlibabaCloud Console. +The `alicloud_amqp_instance` resource allows you to manage `payment_type = "PayAsYouGo"` instance, but Terraform cannot destroy it. +Deleting the subscription resource or removing it from your configuration will remove it from your state file and management, but will not destroy the Instance. +You can resume managing the subscription instance via the AlibabaCloud Console. ## Argument Reference The following arguments are supported: - -* `instance_name` - (Optional, Available in v1.131.0+) The instance name. -* `instance_type` - (Required, ForceNew) The Instance Type. Valid values: `professional`, `enterprise`, `vip`. -* `max_eip_tps` - (Optional) The max eip tps. It is valid when `support_eip` is true. The valid value is [128, 45000] with the step size 128. -* `max_tps` - (Required) The peak TPS traffic. The smallest valid value is 1000 and the largest value is 100,000. -* `modify_type` - (Optional) The modify type. Valid values: `Downgrade`, `Upgrade`. It is required when updating other attributes. -* `payment_type` - (Required) The payment type. Valid values: `Subscription`. -* `period` - (Optional) The period. Valid values: `1`, `12`, `2`, `24`, `3`, `6`. -* `queue_capacity` - (Required) The queue capacity. The smallest value is 50 and the step size 5. -* `renewal_duration` - (Optional) RenewalDuration. Valid values: `1`, `12`, `2`, `3`, `6`. -* `renewal_duration_unit` - (Optional) Auto-Renewal Cycle Unit Values Include: Month: Month. Year: Years. Valid values: `Month`, `Year`. -* `renewal_status` - (Optional) Whether to renew an instance automatically or not. Default to "ManualRenewal". - - `AutoRenewal`: Auto renewal. - - `ManualRenewal`: Manual renewal. - - `NotRenewal`: No renewal any longer. After you specify this value, Alibaba Cloud stop sending notification of instance expiry, and only gives a brief reminder on the third day before the instance expiry. - -* `storage_size` - (Optional) The storage size. It is valid when `instance_type` is vip. -* `support_eip` - (Required) Whether to support EIP. -* `logistics` - (Optional) The logistic information This parameter is not required when you create a ApsaraMQ for RabbitMQ instance. You do not need to specify this parameter. +* `auto_renew` - (Optional, Available since v1.129.0) Renewal method. Automatic renewal: true; Manual renewal: false. When RenewalStatus has a value, the value of RenewalStatus shall prevail. +* `instance_name` - (Optional, Computed) The instance name. +* `instance_type` - (Optional, Computed, ForceNew, ForceNew) Instance type. Valid values are as follows: professional: professional Edition enterprise: enterprise Edition vip: Platinum Edition. +* `max_connections` - (Optional, Computed, Available since v1.129.0) The maximum number of connections, according to the value given on the purchase page of the cloud message queue RabbitMQ version console. +* `max_eip_tps` - (Optional) Peak TPS traffic of the public network, which must be a multiple of 128, unit: times per second. +* `max_tps` - (Optional, Computed) Configure the private network TPS traffic peak, please set the value according to the cloud message queue RabbitMQ version of the console purchase page given. +* `modify_type` - (Optional) Type of instance lifting and lowering: + - Upgrade: Upgrade + - Downgrade: Downgrading. +* `payment_type` - (Required, ForceNew) The Payment type. Valid value: Subscription: prepaid. PayAsYouGo: Post-paid. +* `period` - (Optional) Prepayment cycle, unit: periodCycle. This parameter is valid when PaymentType is set to Subscription. +* `period_cycle` - (Optional, Available since v1.129.0) Prepaid cycle units. Value: Month. Year: Year. +* `queue_capacity` - (Optional, Computed) Configure the maximum number of queues. The value range is as follows: Professional version:[50,1000], minimum modification step size is 5 Enterprise Edition:[200,6000], minimum modification step size is 100 Platinum version:[10000,80000], minimum modification step size is 100. +* `renewal_duration` - (Optional, Computed) The number of automatic renewal cycles. +* `renewal_duration_unit` - (Optional, Computed) Auto-Renewal Cycle Unit Values Include: Month: Month. Year: Years. +* `renewal_status` - (Optional, Computed) The renewal status. Value: AutoRenewal: automatic renewal. ManualRenewal: manual renewal. NotRenewal: no renewal. +* `serverless_charge_type` - (Optional, Available since v1.129.0) The billing type of the serverless instance. Value: onDemand. +* `storage_size` - (Optional, Computed) Configure the message storage space. Unit: GB. The value is as follows: Professional Edition and Enterprise Edition: Fixed to 0. Description A value of 0 indicates that the Professional Edition and Enterprise Edition instances do not charge storage fees, but do not have storage space. Platinum version example: m × 100, where the value range of m is [7,28]. +* `support_eip` - (Optional) Whether to support public network. +* `support_tracing` - (Optional, Computed) Whether to activate the message trace function. The values are as follows: true: Enable message trace function false: message trace function is not enabled Description The Platinum Edition instance provides the 15-day message trace function free of charge. The trace function can only be enabled and the trace storage duration can only be set to 15 days. For instances of other specifications, you can enable or disable the trace function. +* `tracing_storage_time` - (Optional, Computed) Configure the storage duration of message traces. Unit: Days. The value is as follows: 3:3 days 7:7 days 15:15 days This parameter is valid when SupportTracing is true. ## Attributes Reference The following attributes are exported: - -* `id` - The resource ID in terraform of Instance. +* `id` - The ID of the resource supplied above. +* `create_time` - OrderCreateTime. * `status` - The status of the resource. ## Timeouts 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 60 min) Used when create the Instance. +* `create` - (Defaults to 5 mins) Used when create the Instance. +* `delete` - (Defaults to 5 mins) Used when delete the Instance. +* `update` - (Defaults to 5 mins) Used when update the Instance. ## Import -RabbitMQ (AMQP) Instance can be imported using the id, e.g. +Amqp Instance can be imported using the id, e.g. ```shell $ terraform import alicloud_amqp_instance.example -``` +``` \ No newline at end of file