func resourceAliCloudMongoDBInstanceUpdate()

in alicloud/resource_alicloud_mongodb_instance.go [692:1215]


func resourceAliCloudMongoDBInstanceUpdate(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").(string)

	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.RdsMongodbDBInstanceStateRefreshFunc(d.Id(), []string{}))
		if _, err := stateConf.WaitForState(); err != nil {
			return WrapError(err)
		}

		d.SetPartial("engine_version")
	}

	update = false
	modifyDBInstanceSpecReq := map[string]interface{}{
		"DBInstanceId": d.Id(),
	}

	if !d.IsNewResource() && d.HasChange("db_instance_class") {
		update = true
	}
	modifyDBInstanceSpecReq["DBInstanceClass"] = d.Get("db_instance_class").(string)

	if !d.IsNewResource() && d.HasChange("db_instance_storage") {
		update = true
	}
	modifyDBInstanceSpecReq["DBInstanceStorage"] = strconv.Itoa(d.Get("db_instance_storage").(int))

	if !d.IsNewResource() && d.HasChange("replication_factor") {
		update = true
	}
	if v, ok := d.GetOkExists("replication_factor"); ok {
		modifyDBInstanceSpecReq["ReplicationFactor"] = strconv.Itoa(v.(int))
	}

	if !d.IsNewResource() && d.HasChange("readonly_replicas") {
		update = true
	}
	if v, ok := d.GetOkExists("readonly_replicas"); ok {
		modifyDBInstanceSpecReq["ReadonlyReplicas"] = strconv.Itoa(v.(int))
	}

	if v, ok := d.GetOk("effective_time"); ok {
		modifyDBInstanceSpecReq["EffectiveTime"] = v
	}

	if v, ok := d.GetOk("order_type"); ok {
		modifyDBInstanceSpecReq["OrderType"] = v.(string)
	}

	if update {
		action := "ModifyDBInstanceSpec"
		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, modifyDBInstanceSpecReq, true)
			if err != nil {
				if IsExpectedErrors(err, []string{"Task.Conflict", "OperationDenied.DBInstanceStatus"}) || NeedRetry(err) {
					wait()
					return resource.RetryableError(err)
				}
				return resource.NonRetryableError(err)
			}
			return nil
		})
		addDebug(action, response, modifyDBInstanceSpecReq)

		if err != nil {
			return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
		}

		stateConf := BuildStateConf([]string{"order_wait_for_produce"}, []string{"all_completed"}, d.Timeout(schema.TimeoutUpdate), 1*time.Minute, ddsService.RdsMongodbDBInstanceOrderStateRefreshFunc(d.Id(), []string{""}))
		if _, err := stateConf.WaitForState(); err != nil {
			return WrapError(err)
		}

		stateConf = BuildStateConf([]string{"DBInstanceClassChanging", "DBInstanceNetTypeChanging", "NodeCreating"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 1*time.Minute, ddsService.RdsMongodbDBInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
		if _, err := stateConf.WaitForState(); err != nil {
			return WrapError(err)
		}

		d.SetPartial("db_instance_class")
		d.SetPartial("db_instance_storage")
		d.SetPartial("replication_factor")
		d.SetPartial("readonly_replicas")
	}

	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.RdsMongodbDBInstanceStateRefreshFunc(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 {
		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", "OperationDenied.DBInstanceStatus"}) || 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")
	}

	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.RdsMongodbDBInstanceStateRefreshFunc(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.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.RdsMongodbDBInstanceStateRefreshFunc(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, "instance")
		if err != nil {
			return WrapError(err)
		}
	}

	if d.HasChange("backup_time") || d.HasChange("backup_period") || d.HasChange("backup_retention_period") || d.HasChange("backup_retention_policy_on_cluster_deletion") || d.HasChange("enable_backup_log") || d.HasChange("log_backup_retention_period") || d.HasChange("snapshot_backup_type") || d.HasChange("backup_interval") {
		if err := ddsService.ModifyMongoDBBackupPolicy(d); err != nil {
			return WrapError(err)
		}

		d.SetPartial("backup_time")
		d.SetPartial("backup_period")
		d.SetPartial("backup_retention_period")
		d.SetPartial("backup_retention_policy_on_cluster_deletion")
		d.SetPartial("enable_backup_log")
		d.SetPartial("log_backup_retention_period")
		d.SetPartial("snapshot_backup_type")
		d.SetPartial("backup_interval")
	}

	if d.HasChange("ssl_action") {
		action := "ModifyDBInstanceSSL"

		modifyDBInstanceSSLReq := map[string]interface{}{
			"DBInstanceId": d.Id(),
		}

		if v, ok := d.GetOk("ssl_action"); ok {
			modifyDBInstanceSSLReq["SSLAction"] = 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, modifyDBInstanceSSLReq, true)
			if err != nil {
				if NeedRetry(err) {
					wait()
					return resource.RetryableError(err)
				}
				return resource.NonRetryableError(err)
			}
			return nil
		})
		addDebug(action, response, modifyDBInstanceSSLReq)

		if err != nil {
			return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
		}

		stateConf := BuildStateConf([]string{"SSLModifying"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 0, ddsService.RdsMongodbDBInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
		if _, err := stateConf.WaitForState(); err != nil {
			return WrapError(err)
		}

		d.SetPartial("ssl_action")
	}

	if d.HasChange("maintain_start_time") || d.HasChange("maintain_end_time") {
		action := "ModifyDBInstanceMaintainTime"

		modifyDBInstanceMaintainTimeReq := map[string]interface{}{
			"DBInstanceId": d.Id(),
		}

		if v, ok := d.GetOk("maintain_start_time"); ok {
			modifyDBInstanceMaintainTimeReq["MaintainStartTime"] = v
		}

		if v, ok := d.GetOk("maintain_end_time"); ok {
			modifyDBInstanceMaintainTimeReq["MaintainEndTime"] = 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, modifyDBInstanceMaintainTimeReq, true)
			if err != nil {
				if NeedRetry(err) {
					wait()
					return resource.RetryableError(err)
				}
				return resource.NonRetryableError(err)
			}
			return nil
		})
		addDebug(action, response, modifyDBInstanceMaintainTimeReq)

		if err != nil {
			return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
		}

		d.SetPartial("maintain_start_time")
		d.SetPartial("maintain_end_time")
	}

	if d.HasChange("tde_status") || d.HasChange("encryptor_name") || d.HasChange("encryption_key") {
		action := "ModifyDBInstanceTDE"

		modifyDBInstanceTDEReq := map[string]interface{}{
			"DBInstanceId": d.Id(),
		}

		if d.HasChange("tde_status") {

			if v, ok := d.GetOk("tde_status"); ok {
				modifyDBInstanceTDEReq["TDEStatus"] = v
			}
		}

		if d.HasChange("encryptor_name") {

			if v, ok := d.GetOk("encryptor_name"); ok {
				modifyDBInstanceTDEReq["EncryptorName"] = v
			}
		}

		if d.HasChange("encryption_key") {

			if v, ok := d.GetOk("encryption_key"); ok {
				modifyDBInstanceTDEReq["EncryptionKey"] = v
			}
		}

		if d.HasChange("role_arn") {

			if v, ok := d.GetOk("role_arn"); ok {
				modifyDBInstanceTDEReq["RoleARN"] = 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.RdsMongodbDBInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))
		if _, err := stateConf.WaitForState(); err != nil {
			return WrapError(err)
		}

		d.SetPartial("tde_status")
		d.SetPartial("encryptor_name")
		d.SetPartial("encryption_key")
	}

	if err := ddsService.setInstanceTags(d); err != nil {
		return WrapError(err)
	}

	if d.HasChange("parameters") {
		if err := ddsService.ModifyParameters(d, "parameters"); err != nil {
			return WrapError(err)
		}
	}

	d.Partial(false)

	return resourceAliCloudMongoDBInstanceRead(d, meta)
}