func resourceAlibabacloudStackKVStoreInstanceUpdate()

in alibabacloudstack/resource_apsarastack_kvstore_instance.go [352:623]


func resourceAlibabacloudStackKVStoreInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*connectivity.AlibabacloudStackClient)
	kvstoreService := KvstoreService{client}
	d.Partial(true)
	stateConf := BuildStateConf([]string{"DBInstanceClassChanging", "DBInstanceNetTypeChanging", "Changing"}, []string{"Normal"}, d.Timeout(schema.TimeoutUpdate), 1*time.Minute, kvstoreService.RdsKvstoreInstanceStateRefreshFunc(d.Id(), []string{"Deleting"}))

	if d.HasChange("parameters") {
		config := make(map[string]interface{})
		documented := d.Get("parameters").(*schema.Set).List()
		if len(documented) > 0 {
			for _, i := range documented {
				key := i.(map[string]interface{})["name"].(string)
				value := i.(map[string]interface{})["value"]
				config[key] = value
			}
			cfg, _ := json.Marshal(config)
			if err := kvstoreService.ModifyInstanceConfig(d.Id(), string(cfg)); err != nil {
				return errmsgs.WrapError(err)
			}
		}

		//d.SetPartial("parameters")
	}

	if d.HasChange("security_ips") {
		// wait instance status is Normal before modifying
		if _, err := stateConf.WaitForState(); err != nil {
			return errmsgs.WrapError(err)
		}
		request := r_kvstore.CreateModifySecurityIpsRequest()
		client.InitRpcRequest(*request.RpcRequest)
		request.SecurityIpGroupName = "default"
		request.InstanceId = d.Id()
		if len(d.Get("security_ips").(*schema.Set).List()) > 0 {
			request.SecurityIps = strings.Join(expandStringList(d.Get("security_ips").(*schema.Set).List())[:], COMMA_SEPARATED)
		} else {
			return errmsgs.WrapError(errmsgs.Error("Security ips cannot be empty"))
		}
		raw, err := client.WithRkvClient(func(rkvClient *r_kvstore.Client) (interface{}, error) {
			return rkvClient.ModifySecurityIps(request)
		})
		if err != nil {
			return err
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		//d.SetPartial("security_ips")
		// wait instance status is Normal after modifying
		if _, err := stateConf.WaitForState(); err != nil {
			return errmsgs.WrapError(err)
		}
	}

	if d.HasChange("vpc_auth_mode") {
		if vswitchId, ok := d.GetOk("vswitch_id"); ok && vswitchId.(string) != "" {
			// vpc_auth_mode works only if the network type is VPC
			instanceType := d.Get("instance_type").(string)
			if string(KVStoreRedis) == instanceType {
				// wait instance status is Normal before modifying
				if _, err := stateConf.WaitForState(); err != nil {
					return errmsgs.WrapError(err)
				}

				request := r_kvstore.CreateModifyInstanceVpcAuthModeRequest()
				client.InitRpcRequest(*request.RpcRequest)
				request.InstanceId = d.Id()
				request.VpcAuthMode = d.Get("vpc_auth_mode").(string)

				raw, err := client.WithRkvClient(func(rkvClient *r_kvstore.Client) (interface{}, error) {
					return rkvClient.ModifyInstanceVpcAuthMode(request)
				})
				if err != nil {
					errmsg := ""
					if raw != nil {
						baseResponse := &responses.BaseResponse{}
						err = json.Unmarshal([]byte(raw.(*r_kvstore.ModifyInstanceVpcAuthModeResponse).GetHttpContentString()), baseResponse)
						if err == nil {
							errmsg = errmsgs.GetBaseResponseErrorMessage(baseResponse)
						}
					}
					return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
				}
				addDebug(request.GetActionName(), raw, request.RpcRequest, request)
				//d.SetPartial("vpc_auth_mode")

				// The auth mode take some time to be effective, so wait to ensure the state !
				if _, err := stateConf.WaitForState(); err != nil {
					return errmsgs.WrapError(err)
				}
			}
		}
	}
	// 	configPayType := PayType(connectivity.GetResourceData(d, "payment_type", "instance_charge_type").(string))
	// 	if !d.IsNewResource() && (d.HasChanges("payment_type", "instance_charge_type")) && configPayType == PrePaid {
	// 		// for now we just support charge change from PostPaid to PrePaid
	// 		prePaidRequest := r_kvstore.CreateTransformToPrePaidRequest()
	// 		client.InitRpcRequest(*prePaidRequest.RpcRequest)
	// 		prePaidRequest.InstanceId = d.Id()
	// 		prePaidRequest.Period = requests.Integer(strconv.Itoa(d.Get("period").(int)))
	// 		prePaidRequest.AutoPay = requests.NewBoolean(true)
	// 		raw, err := client.WithRkvClient(func(rkvClient *r_kvstore.Client) (interface{}, error) {
	// 			return rkvClient.TransformToPrePaid(prePaidRequest)
	// 		})
	// 		if err != nil {
	// 			errmsg := ""
	// 			if raw != nil {
	// 				baseResponse := &responses.BaseResponse{}
	// 				err = json.Unmarshal([]byte(raw.(*r_kvstore.TransformToPrePaidResponse).GetHttpContentString()), baseResponse)
	// 				if err == nil {
	// 					errmsg = errmsgs.GetBaseResponseErrorMessage(baseResponse)
	// 				}
	// 			}
	// 			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), prePaidRequest.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
	// 		}
	// 		addDebug(prePaidRequest.GetActionName(), raw, prePaidRequest.RpcRequest, prePaidRequest)
	// 		// wait instance status is Normal after modifying
	// 		if _, err := stateConf.WaitForState(); err != nil {
	// 			return errmsgs.WrapError(err)
	// 		}
	// 		//d.SetPartial("instance_charge_type")
	// 		//d.SetPartial("period")
	// 	}

	if d.HasChanges("maintain_start_time", "maintain_end_time") {
		request := r_kvstore.CreateModifyInstanceMaintainTimeRequest()
		client.InitRpcRequest(*request.RpcRequest)
		request.InstanceId = d.Id()
		request.MaintainStartTime = d.Get("maintain_start_time").(string)
		request.MaintainEndTime = d.Get("maintain_end_time").(string)

		raw, err := client.WithRkvClient(func(client *r_kvstore.Client) (interface{}, error) {
			return client.ModifyInstanceMaintainTime(request)
		})
		if err != nil {
			errmsg := ""
			if raw != nil {
				baseResponse := &responses.BaseResponse{}
				err = json.Unmarshal([]byte(raw.(*r_kvstore.ModifyInstanceMaintainTimeResponse).GetHttpContentString()), baseResponse)
				if err == nil {
					errmsg = errmsgs.GetBaseResponseErrorMessage(baseResponse)
				}
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		//d.SetPartial("maintain_start_time")
		//d.SetPartial("maintain_end_time")
	}

	if d.IsNewResource() {
		d.Partial(false)
		return nil
	}

	if d.HasChange("instance_class") {
		// wait instance status is Normal before modifying
		if _, err := stateConf.WaitForState(); err != nil {
			return errmsgs.WrapError(err)
		}

		request := r_kvstore.CreateModifyInstanceSpecRequest()
		client.InitRpcRequest(*request.RpcRequest)
		request.InstanceId = d.Id()
		request.InstanceClass = d.Get("instance_class").(string)
		request.EffectiveTime = "Immediately"

		err := resource.Retry(5*time.Minute, func() *resource.RetryError {
			raw, err := client.WithRkvClient(func(rkvClient *r_kvstore.Client) (interface{}, error) {
				return rkvClient.ModifyInstanceSpec(request)
			})
			if err != nil {
				if errmsgs.IsExpectedErrors(err, []string{"MissingRedisUsedmemoryUnsupportPerfItem"}) {
					time.Sleep(time.Duration(5) * time.Second)
					return resource.RetryableError(err)
				}
				errmsg := ""
				if raw != nil {
					baseResponse := &responses.BaseResponse{}
					err = json.Unmarshal([]byte(raw.(*r_kvstore.ModifyInstanceSpecResponse).GetHttpContentString()), baseResponse)
					if err == nil {
						errmsg = errmsgs.GetBaseResponseErrorMessage(baseResponse)
					}
				}
				return resource.NonRetryableError(errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg))
			}
			addDebug(request.GetActionName(), raw, request.RpcRequest, request)
			return nil
		})
		if err != nil {
			return err
		}
		// wait instance status is Normal after modifying
		if _, err := stateConf.WaitForState(); err != nil {
			return errmsgs.WrapError(err)
		}
		// There needs more time to sync instance class update
		err = resource.Retry(1*time.Minute, func() *resource.RetryError {
			object, err := kvstoreService.DescribeKVstoreInstance(d.Id())
			if err != nil {
				return resource.NonRetryableError(err)
			}
			if object.InstanceClass != request.InstanceClass {
				return resource.RetryableError(errmsgs.Error("Waitting for instance class is changed timeout. Expect instance class %s, got %s.",
					object.InstanceClass, request.InstanceClass))
			}
			return nil
		})
		if err != nil {
			return errmsgs.WrapError(err)
		}

		//d.SetPartial("instance_class")
	}

	request := r_kvstore.CreateModifyInstanceAttributeRequest()
	client.InitRpcRequest(*request.RpcRequest)
	request.InstanceId = d.Id()
	update := false
	if d.HasChanges("tair_instance_name", "instance_name") {
		request.InstanceName = connectivity.GetResourceData(d, "tair_instance_name", "instance_name").(string)
		update = true
	}

	if d.HasChanges("password", "kms_encrypted_password") {
		if v := d.Get("password").(string); v != "" {
			//d.SetPartial("password")
			request.NewPassword = v
			update = true
		}
		if v := d.Get("kms_encrypted_password").(string); v != "" {
			kmsService := KmsService{meta.(*connectivity.AlibabacloudStackClient)}
			decryptResp, err := kmsService.Decrypt(v, d.Get("kms_encryption_context").(map[string]interface{}))
			if err != nil {
				return errmsgs.WrapError(err)
			}
			request.NewPassword = decryptResp.Plaintext
			//d.SetPartial("kms_encrypted_password")
			//d.SetPartial("kms_encryption_context")
			update = true
		}
	}

	if update {
		// wait instance status is Normal before modifying
		if _, err := stateConf.WaitForState(); err != nil {
			return errmsgs.WrapError(err)
		}
		raw, err := client.WithRkvClient(func(rkvClient *r_kvstore.Client) (interface{}, error) {
			return rkvClient.ModifyInstanceAttribute(request)
		})
		if err != nil {
			errmsg := ""
			if raw != nil {
				baseResponse := &responses.BaseResponse{}
				err = json.Unmarshal([]byte(raw.(*r_kvstore.ModifyInstanceAttributeResponse).GetHttpContentString()), baseResponse)
				if err == nil {
					errmsg = errmsgs.GetBaseResponseErrorMessage(baseResponse)
				}
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		// wait instance status is Normal after modifying
		if _, err := stateConf.WaitForState(); err != nil {
			return errmsgs.WrapError(err)
		}
		//d.SetPartial("instance_name")
		//d.SetPartial("password")
	}

	d.Partial(false)
	return nil
}