alicloud/resource_alicloud_mongodb_sharding_instance.go (909 lines of code) (raw):
package alicloud
import (
"fmt"
"log"
"strconv"
"strings"
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"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 resourceAliCloudMongoDBShardingInstance() *schema.Resource {
return &schema.Resource{
Create: resourceAliCloudMongoDBShardingInstanceCreate,
Read: resourceAliCloudMongoDBShardingInstanceRead,
Update: resourceAliCloudMongoDBShardingInstanceUpdate,
Delete: resourceAliCloudMongoDBShardingInstanceDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Update: schema.DefaultTimeout(30 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},
Schema: map[string]*schema.Schema{
"engine_version": {
Type: schema.TypeString,
Required: true,
},
"storage_engine": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ValidateFunc: StringInSlice([]string{"WiredTiger", "RocksDB"}, false),
},
"storage_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: StringInSlice([]string{"cloud_essd1", "cloud_essd2", "cloud_essd3", "cloud_auto", "local_ssd"}, false),
},
"provisioned_iops": {
Type: schema.TypeInt,
Optional: true,
},
"protocol_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ValidateFunc: StringInSlice([]string{"mongodb", "dynamodb"}, false),
},
"vpc_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"vswitch_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"zone_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"security_group_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"network_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ValidateFunc: StringInSlice([]string{"Classic", "VPC"}, false),
},
"name": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: StringLenBetween(2, 256),
},
"instance_charge_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: StringInSlice([]string{string(PrePaid), string(PostPaid)}, false),
},
"period": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ValidateFunc: IntInSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 24, 36}),
DiffSuppressFunc: PostPaidDiffSuppressFunc,
},
"security_ip_list": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"account_password": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
},
"kms_encrypted_password": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: kmsDiffSuppressFunc,
},
"kms_encryption_context": {
Type: schema.TypeMap,
Optional: true,
Elem: schema.TypeString,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return d.Get("kms_encrypted_password").(string) == ""
},
},
"resource_group_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"auto_renew": {
Type: schema.TypeBool,
Optional: true,
},
"backup_time": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: StringInSlice(BACKUP_TIME, false),
},
"backup_period": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"backup_retention_policy_on_cluster_deletion": {
Type: schema.TypeInt,
Optional: true,
},
"tde_status": {
Type: schema.TypeString,
Optional: true,
Computed: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return d.Get("engine_version").(string) < "4.0"
},
},
"mongo_list": {
Type: schema.TypeList,
Required: true,
MinItems: 2,
MaxItems: 32,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"node_class": {
Type: schema.TypeString,
Required: true,
},
"node_id": {
Type: schema.TypeString,
Computed: true,
},
"connect_string": {
Type: schema.TypeString,
Computed: true,
},
"port": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"shard_list": {
Type: schema.TypeList,
Required: true,
MinItems: 2,
MaxItems: 32,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"node_class": {
Type: schema.TypeString,
Required: true,
},
"node_storage": {
Type: schema.TypeInt,
Required: true,
},
"readonly_replicas": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ValidateFunc: IntBetween(0, 5),
},
"node_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"config_server_list": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"node_class": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"node_storage": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
Computed: true,
},
"node_id": {
Type: schema.TypeString,
Computed: true,
},
"connect_string": {
Type: schema.TypeString,
Computed: true,
},
"port": {
Type: schema.TypeInt,
Computed: true,
},
"max_connections": {
Type: schema.TypeInt,
Computed: true,
},
"max_iops": {
Type: schema.TypeInt,
Computed: true,
},
"node_description": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"tags": tagsSchema(),
"retention_period": {
Type: schema.TypeInt,
Computed: true,
},
"order_type": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: StringInSlice([]string{"UPGRADE", "DOWNGRADE"}, false),
},
},
}
}
func resourceAliCloudMongoDBShardingInstanceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ddsService := MongoDBService{client}
var response map[string]interface{}
action := "CreateShardingDBInstance"
request := make(map[string]interface{})
var err error
request["RegionId"] = client.RegionId
request["ClientToken"] = buildClientToken(action)
request["Engine"] = "MongoDB"
request["EngineVersion"] = d.Get("engine_version")
if v, ok := d.GetOk("storage_engine"); ok {
request["StorageEngine"] = v
}
if v, ok := d.GetOk("storage_type"); ok {
request["StorageType"] = v
}
if v, ok := d.GetOkExists("provisioned_iops"); ok {
request["ProvisionedIops"] = v
}
if v, ok := d.GetOk("protocol_type"); ok {
request["ProtocolType"] = v
}
if v, ok := d.GetOk("vpc_id"); ok {
request["VpcId"] = v
}
if v, ok := d.GetOk("vswitch_id"); ok {
request["VSwitchId"] = v
}
if v, ok := d.GetOk("zone_id"); ok {
request["ZoneId"] = v
}
if (request["ZoneId"] == nil || request["VpcId"] == nil) && request["VSwitchId"] != nil {
// check vswitchId in zone
vpcService := VpcService{client}
vsw, err := vpcService.DescribeVSwitch(request["VSwitchId"].(string))
if err != nil {
return WrapError(err)
}
if request["ZoneId"] == nil {
request["ZoneId"] = vsw.ZoneId
} else if strings.Contains(request["ZoneId"].(string), MULTI_IZ_SYMBOL) {
zoneStr := strings.Split(strings.SplitAfter(request["ZoneId"].(string), "(")[1], ")")[0]
if !strings.Contains(zoneStr, string([]byte(vsw.ZoneId)[len(vsw.ZoneId)-1])) {
return WrapError(Error("The specified vswitch %s isn't in multi the zone %s", vsw.VSwitchId, request["ZoneId"].(string)))
}
} else if request["ZoneId"].(string) != vsw.ZoneId {
return WrapError(Error("The specified vswitch %s isn't in the zone %s", vsw.VSwitchId, request["ZoneId"].(string)))
}
if request["VpcId"] == nil {
request["VpcId"] = vsw.VpcId
}
}
if v, ok := d.GetOk("network_type"); ok {
request["NetworkType"] = v
}
if request["NetworkType"] == nil && request["VSwitchId"] != nil {
request["NetworkType"] = "VPC"
}
if v, ok := d.GetOk("name"); ok {
request["DBInstanceDescription"] = v
}
if v, ok := d.GetOk("instance_charge_type"); ok {
request["ChargeType"] = v
if period, ok := d.GetOk("period"); ok && PayType(v.(string)) == PrePaid {
request["Period"] = period
}
}
request["SecurityIPList"] = LOCAL_HOST_IP
if v, ok := d.GetOk("security_ip_list"); ok {
request["SecurityIPList"] = strings.Join(expandStringList(v.(*schema.Set).List()), COMMA_SEPARATED)
}
if v, ok := d.GetOk("account_password"); ok {
request["AccountPassword"] = v
} else if v, ok := d.GetOk("kms_encrypted_password"); ok {
kmsService := KmsService{client}
decryptResp, err := kmsService.Decrypt(v.(string), d.Get("kms_encryption_context").(map[string]interface{}))
if err != nil {
return WrapError(err)
}
request["AccountPassword"] = decryptResp
}
if v, ok := d.GetOk("resource_group_id"); ok {
request["ResourceGroupId"] = v
}
if v, ok := d.GetOkExists("auto_renew"); ok {
request["AutoRenew"] = strconv.FormatBool(v.(bool))
}
mongoList := d.Get("mongo_list")
mongoListMaps := make([]map[string]interface{}, 0)
for _, mongoLists := range mongoList.([]interface{}) {
mongoListMap := map[string]interface{}{}
mongoListArg := mongoLists.(map[string]interface{})
mongoListMap["Class"] = mongoListArg["node_class"]
mongoListMaps = append(mongoListMaps, mongoListMap)
}
request["Mongos"] = mongoListMaps
shardList := d.Get("shard_list")
shardListMaps := make([]map[string]interface{}, 0)
for _, shardLists := range shardList.([]interface{}) {
shardListMap := map[string]interface{}{}
shardListArg := shardLists.(map[string]interface{})
shardListMap["Class"] = shardListArg["node_class"]
shardListMap["Storage"] = shardListArg["node_storage"]
if readonlyReplicas, ok := shardListArg["readonly_replicas"]; ok {
shardListMap["ReadonlyReplicas"] = readonlyReplicas
}
shardListMaps = append(shardListMaps, shardListMap)
}
request["ReplicaSet"] = shardListMaps
if v, ok := d.GetOk("config_server_list"); ok {
configServerListMaps := make([]map[string]interface{}, 0)
for _, configServerList := range v.([]interface{}) {
configServerListMap := map[string]interface{}{}
configServerListArg := configServerList.(map[string]interface{})
if class, ok := configServerListArg["node_class"]; ok {
configServerListMap["Class"] = class
}
if storage, ok := configServerListArg["node_storage"]; ok {
configServerListMap["Storage"] = storage
}
configServerListMaps = append(configServerListMaps, configServerListMap)
}
request["ConfigServer"] = configServerListMaps
} else {
request["ConfigServer"] = []map[string]interface{}{{"Class": "dds.cs.mid", "Storage": 20}}
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutCreate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, request, true)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, request)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, "alicloud_mongodb_sharding_instance", action, AlibabaCloudSdkGoERROR)
}
d.SetId(fmt.Sprint(response["DBInstanceId"]))
stateConf := BuildStateConf([]string{"Creating"}, []string{"Running"}, d.Timeout(schema.TimeoutCreate), 5*time.Minute, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapError(err)
}
return resourceAliCloudMongoDBShardingInstanceUpdate(d, meta)
}
func resourceAliCloudMongoDBShardingInstanceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ddsService := MongoDBService{client}
object, err := ddsService.DescribeMongoDBShardingInstance(d.Id())
if err != nil {
if !d.IsNewResource() && NotFoundError(err) {
d.SetId("")
return nil
}
return WrapError(err)
}
d.Set("engine_version", object["EngineVersion"])
d.Set("storage_engine", object["StorageEngine"])
d.Set("storage_type", object["StorageType"])
d.Set("provisioned_iops", formatInt(object["ProvisionedIops"]))
d.Set("protocol_type", object["ProtocolType"])
d.Set("vpc_id", object["VPCId"])
d.Set("vswitch_id", object["VSwitchId"])
d.Set("zone_id", object["ZoneId"])
d.Set("network_type", object["NetworkType"])
d.Set("name", object["DBInstanceDescription"])
d.Set("instance_charge_type", object["ChargeType"])
d.Set("resource_group_id", object["ResourceGroupId"])
groupIp, err := ddsService.DescribeMongoDBShardingSecurityGroupId(d.Id())
if err != nil {
return WrapError(err)
}
if len(groupIp) > 0 {
if groupIpItem, ok := groupIp[0].(map[string]interface{}); ok {
d.Set("security_group_id", groupIpItem["SecurityGroupId"])
}
}
if fmt.Sprint(object["ChargeType"]) == "PrePaid" {
period, err := computePeriodByUnit(object["CreationTime"], object["ExpireTime"], d.Get("period").(int), "Month")
if err != nil {
return WrapError(err)
}
d.Set("period", period)
}
securityIpList, err := ddsService.DescribeMongoDBShardingSecurityIps(d.Id())
if err != nil {
return WrapError(err)
}
d.Set("security_ip_list", securityIpList)
backupPolicy, err := ddsService.DescribeMongoDBShardingBackupPolicy(d.Id())
if err != nil {
return WrapError(err)
}
d.Set("backup_time", backupPolicy["PreferredBackupTime"])
d.Set("backup_period", strings.Split(backupPolicy["PreferredBackupPeriod"].(string), ","))
d.Set("retention_period", formatInt(backupPolicy["BackupRetentionPeriod"]))
d.Set("backup_retention_policy_on_cluster_deletion", formatInt(backupPolicy["BackupRetentionPolicyOnClusterDeletion"]))
tdeInfo, err := ddsService.DescribeMongoDBShardingTDEInfo(d.Id())
if err != nil {
return WrapError(err)
}
d.Set("tde_status", tdeInfo["TDEStatus"])
if v, ok := object["Tags"].(map[string]interface{}); ok {
d.Set("tags", tagsToMap(v["Tag"]))
}
if MongosListMap, ok := object["MongosList"].(map[string]interface{}); ok && MongosListMap != nil {
if MongosList, ok := MongosListMap["MongosAttribute"]; ok && MongosList != nil {
MongosListMaps := make([]map[string]interface{}, 0)
for _, MongosLists := range MongosList.([]interface{}) {
MongosListItemMap := make(map[string]interface{})
MongosListArg := MongosLists.(map[string]interface{})
if nodeClass, ok := MongosListArg["NodeClass"]; ok {
MongosListItemMap["node_class"] = nodeClass
}
if nodeId, ok := MongosListArg["NodeId"]; ok {
MongosListItemMap["node_id"] = nodeId
}
if connectSting, ok := MongosListArg["ConnectSting"]; ok {
MongosListItemMap["connect_string"] = connectSting
}
if port, ok := MongosListArg["Port"]; ok {
MongosListItemMap["port"] = formatInt(port)
}
MongosListMaps = append(MongosListMaps, MongosListItemMap)
}
d.Set("mongo_list", MongosListMaps)
}
}
if shardListMap, ok := object["ShardList"].(map[string]interface{}); ok && shardListMap != nil {
if shardList, ok := shardListMap["ShardAttribute"]; ok && shardList != nil {
shardListMaps := make([]map[string]interface{}, 0)
for _, shardLists := range shardList.([]interface{}) {
shardListItemMap := make(map[string]interface{})
shardListArg := shardLists.(map[string]interface{})
if nodeClass, ok := shardListArg["NodeClass"]; ok {
shardListItemMap["node_class"] = nodeClass
}
if nodeStorage, ok := shardListArg["NodeStorage"]; ok {
shardListItemMap["node_storage"] = formatInt(nodeStorage)
}
if readonlyReplicas, ok := shardListArg["ReadonlyReplicas"]; ok {
shardListItemMap["readonly_replicas"] = formatInt(readonlyReplicas)
}
if nodeId, ok := shardListArg["NodeId"]; ok {
shardListItemMap["node_id"] = nodeId
}
shardListMaps = append(shardListMaps, shardListItemMap)
}
d.Set("shard_list", shardListMaps)
}
}
if configServerListMap, ok := object["ConfigserverList"].(map[string]interface{}); ok && configServerListMap != nil {
if configServerList, ok := configServerListMap["ConfigserverAttribute"]; ok && configServerList != nil {
configServerListMaps := make([]map[string]interface{}, 0)
for _, configServerLists := range configServerList.([]interface{}) {
configServerListItemMap := make(map[string]interface{})
configServerListArg := configServerLists.(map[string]interface{})
if nodeClass, ok := configServerListArg["NodeClass"]; ok {
configServerListItemMap["node_class"] = nodeClass
}
if nodeStorage, ok := configServerListArg["NodeStorage"]; ok {
configServerListItemMap["node_storage"] = nodeStorage
}
if nodeId, ok := configServerListArg["NodeId"]; ok {
configServerListItemMap["node_id"] = nodeId
}
if connectString, ok := configServerListArg["ConnectString"]; ok {
configServerListItemMap["connect_string"] = connectString
}
if port, ok := configServerListArg["Port"]; ok {
configServerListItemMap["port"] = formatInt(port)
}
if maxConnections, ok := configServerListArg["MaxConnections"]; ok {
configServerListItemMap["max_connections"] = maxConnections
}
if maxIOPS, ok := configServerListArg["MaxIOPS"]; ok {
configServerListItemMap["max_iops"] = maxIOPS
}
if nodeDescription, ok := configServerListArg["NodeDescription"]; ok {
configServerListItemMap["node_description"] = nodeDescription
}
configServerListMaps = append(configServerListMaps, configServerListItemMap)
}
d.Set("config_server_list", configServerListMaps)
}
}
return nil
}
func resourceAliCloudMongoDBShardingInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ddsService := MongoDBService{client}
var response map[string]interface{}
var err error
d.Partial(true)
update := false
upgradeDBInstanceEngineVersionReq := map[string]interface{}{
"DBInstanceId": d.Id(),
}
if !d.IsNewResource() && d.HasChange("engine_version") {
update = true
}
upgradeDBInstanceEngineVersionReq["EngineVersion"] = d.Get("engine_version")
if update {
action := "UpgradeDBInstanceEngineVersion"
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, upgradeDBInstanceEngineVersionReq, true)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, upgradeDBInstanceEngineVersionReq)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
stateConf := BuildStateConf([]string{}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 1*time.Minute, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapError(err)
}
d.SetPartial("engine_version")
}
update = false
modifyDBInstanceDiskTypeReq := map[string]interface{}{
"DBInstanceId": d.Id(),
}
if !d.IsNewResource() && d.HasChange("storage_type") {
update = true
}
if v, ok := d.GetOk("storage_type"); ok {
modifyDBInstanceDiskTypeReq["DbInstanceStorageType"] = v
}
if !d.IsNewResource() && d.HasChange("provisioned_iops") {
update = true
if v, ok := d.GetOkExists("provisioned_iops"); ok {
modifyDBInstanceDiskTypeReq["ProvisionedIops"] = v
}
}
if update {
action := "ModifyDBInstanceDiskType"
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, modifyDBInstanceDiskTypeReq, true)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, modifyDBInstanceDiskTypeReq)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
stateConf := BuildStateConf([]string{}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 1*time.Minute, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapError(err)
}
d.SetPartial("storage_type")
d.SetPartial("provisioned_iops")
}
update = false
modifySecurityGroupConfigurationReq := map[string]interface{}{
"DBInstanceId": d.Id(),
}
if d.HasChange("security_group_id") {
update = true
}
if v, ok := d.GetOk("security_group_id"); ok {
modifySecurityGroupConfigurationReq["SecurityGroupId"] = v.(string)
}
if update {
stateConf := BuildStateConf([]string{}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 5*time.Minute, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapError(err)
}
action := "ModifySecurityGroupConfiguration"
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, modifySecurityGroupConfigurationReq, true)
if err != nil {
if IsExpectedErrors(err, []string{"InstanceStatusInvalid"}) || NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, modifySecurityGroupConfigurationReq)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
d.SetPartial("security_group_id")
}
update = false
modifyDBInstanceDescriptionReq := map[string]interface{}{
"DBInstanceId": d.Id(),
}
if !d.IsNewResource() && d.HasChange("name") {
update = true
}
if v, ok := d.GetOk("name"); ok {
modifyDBInstanceDescriptionReq["DBInstanceDescription"] = v
}
if update {
action := "ModifyDBInstanceDescription"
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, modifyDBInstanceDescriptionReq, true)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, modifyDBInstanceDescriptionReq)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
d.SetPartial("name")
}
if !d.IsNewResource() && (d.HasChange("instance_charge_type") && d.Get("instance_charge_type").(string) == "PrePaid") {
action := "TransformToPrePaid"
transformToPrePaidReq := map[string]interface{}{
"InstanceId": d.Id(),
}
transformToPrePaidReq["AutoPay"] = requests.NewBoolean(true)
transformToPrePaidReq["Period"] = requests.NewInteger(d.Get("period").(int))
if v, ok := d.GetOkExists("auto_renew"); ok {
transformToPrePaidReq["AutoRenew"] = strconv.FormatBool(v.(bool))
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, transformToPrePaidReq, true)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, transformToPrePaidReq)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
// wait instance status is running after modifying
stateConf := BuildStateConf([]string{"DBInstanceClassChanging", "DBInstanceNetTypeChanging"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 0, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapError(err)
}
d.SetPartial("instance_charge_type")
d.SetPartial("period")
}
if !d.IsNewResource() && d.HasChange("security_ip_list") {
ipList := expandStringList(d.Get("security_ip_list").(*schema.Set).List())
ipstr := strings.Join(ipList[:], COMMA_SEPARATED)
// default disable connect from outside
if ipstr == "" {
ipstr = LOCAL_HOST_IP
}
if err := ddsService.ModifyMongoDBSecurityIps(d, ipstr); err != nil {
return WrapError(err)
}
d.SetPartial("security_ip_list")
}
if !d.IsNewResource() && (d.HasChange("account_password") || d.HasChange("kms_encrypted_password")) {
var accountPassword string
if accountPassword = d.Get("account_password").(string); accountPassword != "" {
d.SetPartial("account_password")
} else if kmsPassword := d.Get("kms_encrypted_password").(string); kmsPassword != "" {
kmsService := KmsService{meta.(*connectivity.AliyunClient)}
decryptResp, err := kmsService.Decrypt(kmsPassword, d.Get("kms_encryption_context").(map[string]interface{}))
if err != nil {
return WrapError(err)
}
accountPassword = decryptResp
d.SetPartial("kms_encrypted_password")
d.SetPartial("kms_encryption_context")
}
err := ddsService.ResetAccountPassword(d, accountPassword, "shardingInstance")
if err != nil {
return WrapError(err)
}
}
update = false
modifyResourceGroupReq := map[string]interface{}{
"RegionId": client.RegionId,
"DBInstanceId": d.Id(),
}
if !d.IsNewResource() && d.HasChange("resource_group_id") {
update = true
}
if v, ok := d.GetOk("resource_group_id"); ok {
modifyResourceGroupReq["ResourceGroupId"] = v
}
if update {
stateConf := BuildStateConf([]string{}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 5*time.Minute, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapError(err)
}
action := "ModifyResourceGroup"
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, modifyResourceGroupReq, true)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, modifyResourceGroupReq)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
d.SetPartial("resource_group_id")
}
if d.HasChange("backup_time") || d.HasChange("backup_period") || d.HasChange("backup_retention_policy_on_cluster_deletion") {
if err := ddsService.ModifyMongoDBBackupPolicy(d); err != nil {
return WrapError(err)
}
d.SetPartial("backup_time")
d.SetPartial("backup_period")
d.SetPartial("backup_retention_policy_on_cluster_deletion")
}
if d.HasChange("tde_status") {
action := "ModifyDBInstanceTDE"
modifyDBInstanceTDEReq := map[string]interface{}{
"DBInstanceId": d.Id(),
}
if v, ok := d.GetOk("tde_status"); ok {
modifyDBInstanceTDEReq["TDEStatus"] = v
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, modifyDBInstanceTDEReq, true)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, modifyDBInstanceTDEReq)
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
stateConf := BuildStateConf([]string{}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 5*time.Minute, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapError(err)
}
d.SetPartial("tde_status")
}
if err := ddsService.setInstanceTags(d); err != nil {
return WrapError(err)
}
if !d.IsNewResource() && d.HasChange("mongo_list") {
state, diff := d.GetChange("mongo_list")
err := ddsService.ModifyMongodbShardingInstanceNode(d, MongoDBShardingNodeMongos, state.([]interface{}), diff.([]interface{}))
if err != nil {
return WrapError(err)
}
d.SetPartial("mongo_list")
}
if !d.IsNewResource() && d.HasChange("shard_list") {
state, diff := d.GetChange("shard_list")
err := ddsService.ModifyMongodbShardingInstanceNode(d, MongoDBShardingNodeShard, state.([]interface{}), diff.([]interface{}))
if err != nil {
return WrapError(err)
}
d.SetPartial("shard_list")
}
d.Partial(false)
return resourceAliCloudMongoDBShardingInstanceRead(d, meta)
}
func resourceAliCloudMongoDBShardingInstanceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ddsService := MongoDBService{client}
action := "DeleteDBInstance"
var response map[string]interface{}
var err error
object, err := ddsService.DescribeMongoDBShardingInstance(d.Id())
if err != nil {
return WrapError(err)
}
if fmt.Sprint(object["ChargeType"]) == "PrePaid" {
log.Printf("[WARN] Cannot destroy resourceAliCloudMongoDBShardingInstance. Terraform will remove this resource from the state file, however resources may remain.")
return nil
}
request := map[string]interface{}{
"DBInstanceId": d.Id(),
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutDelete)), func() *resource.RetryError {
response, err = client.RpcPost("Dds", "2015-12-01", action, nil, request, true)
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{"InvalidDBInstanceId.NotFound"}) || NotFoundError(err) {
return nil
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
stateConf := BuildStateConf([]string{"Creating", "Deleting"}, []string{}, d.Timeout(schema.TimeoutDelete), 1*time.Minute, ddsService.RdsMongodbDBShardingInstanceStateRefreshFunc(d.Id(), []string{}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
return nil
}