func resourceAlibabacloudStackInstanceUpdate()

in alibabacloudstack/resource_apsarastack_ecs_instance.go [503:691]


func resourceAlibabacloudStackInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*connectivity.AlibabacloudStackClient)
	ecsService := EcsService{client}

	d.Partial(true)

	if !d.IsNewResource() {
		err := setTags(client, TagResourceInstance, d)
		if err != nil {
			return errmsgs.WrapError(err)
		}
	}
	if d.HasChange("security_groups") {
		if !d.IsNewResource() || d.Get("vswitch_id").(string) == "" {
			o, n := d.GetChange("security_groups")
			os := o.(*schema.Set)
			ns := n.(*schema.Set)

			rl := expandStringList(os.Difference(ns).List())
			al := expandStringList(ns.Difference(os).List())

			if len(al) > 0 {
				err := ecsService.JoinSecurityGroups(d.Id(), al)
				if err != nil {
					return errmsgs.WrapError(err)
				}
			}
			if len(rl) > 0 {
				err := ecsService.LeaveSecurityGroups(d.Id(), rl)
				if err != nil {
					return errmsgs.WrapError(err)
				}
			}
		}
	}

	run := false
	imageUpdate, err := modifyInstanceImage(d, meta, run)
	if err != nil {
		return errmsgs.WrapError(err)
	}

	vpcUpdate, err := modifyVpcAttribute(d, meta, run)
	if err != nil {
		return errmsgs.WrapError(err)
	}

	passwordUpdate, err := modifyInstanceAttribute(d, meta)
	if err != nil {
		return errmsgs.WrapError(err)
	}

	typeUpdate, err := modifyInstanceType(d, meta, run)
	if err != nil {
		return errmsgs.WrapError(err)
	}
	if imageUpdate || vpcUpdate || passwordUpdate || typeUpdate {
		run = true
		instance, errDesc := ecsService.DescribeInstance(d.Id())
		if errDesc != nil {
			return errmsgs.WrapError(errDesc)
		}
		if instance.Status == string(Running) {
			stopRequest := ecs.CreateStopInstanceRequest()
			client.InitRpcRequest(*stopRequest.RpcRequest)
			stopRequest.InstanceId = d.Id()
			stopRequest.ForceStop = requests.NewBoolean(false)
			raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
				return ecsClient.StopInstance(stopRequest)
			})
			if err != nil {
				errmsg := ""
				if bresponse, ok := raw.(*ecs.StopInstanceResponse); ok {
					errmsg = errmsgs.GetBaseResponseErrorMessage(bresponse.BaseResponse)
				}
				return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), stopRequest.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
			}
			addDebug(stopRequest.GetActionName(), raw)
		}

		stateConf := BuildStateConf([]string{"Pending", "Running", "Stopping"}, []string{"Stopped"}, d.Timeout(schema.TimeoutUpdate), 5*time.Second, ecsService.InstanceStateRefreshFunc(d.Id(), []string{}))

		if _, err = stateConf.WaitForState(); err != nil {
			return errmsgs.WrapErrorf(err, errmsgs.IdMsg, d.Id())
		}

		if _, err := modifyInstanceImage(d, meta, run); err != nil {
			return errmsgs.WrapError(err)
		}

		if _, err := modifyVpcAttribute(d, meta, run); err != nil {
			return errmsgs.WrapError(err)
		}

		if _, err := modifyInstanceType(d, meta, run); err != nil {
			return errmsgs.WrapError(err)
		}

		startRequest := ecs.CreateStartInstanceRequest()
		client.InitRpcRequest(*startRequest.RpcRequest)
		startRequest.InstanceId = d.Id()

		err := resource.Retry(5*time.Minute, func() *resource.RetryError {
			raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
				return ecsClient.StartInstance(startRequest)
			})
			if err != nil {
				if errmsgs.IsExpectedErrors(err, []string{"IncorrectInstanceStatus"}) {
					time.Sleep(time.Second)
					return resource.RetryableError(err)
				}
				errmsg := ""
				if bresponse, ok := raw.(*ecs.StartInstanceResponse); ok {
					errmsg = errmsgs.GetBaseResponseErrorMessage(bresponse.BaseResponse)
				}
				err = errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), startRequest.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
				return resource.NonRetryableError(err)
			}
			addDebug(startRequest.GetActionName(), raw)
			return nil
		})

		if err != nil {
			return err
		}

		stateConf = &resource.StateChangeConf{
			Pending:    []string{"Pending", "Starting", "Stopped"},
			Target:     []string{"Running"},
			Refresh:    ecsService.InstanceStateRefreshFunc(d.Id(), []string{}),
			Timeout:    d.Timeout(schema.TimeoutUpdate),
			Delay:      5 * time.Second,
			MinTimeout: 3 * time.Second,
		}

		if _, err = stateConf.WaitForState(); err != nil {
			return errmsgs.WrapErrorf(err, errmsgs.IdMsg, d.Id())
		}
	}

	if err := modifyInstanceNetworkSpec(d, meta); err != nil {
		return errmsgs.WrapError(err)
	}

	if d.HasChanges("system_disk_tags", "system_disk_id", "image_id", "tags") {
		var oraw, nraw map[string]interface{}
		system_disks, err := ecsService.DescribeInstanceDisksByType(d.Id(), client.ResourceGroup, "system")
		if err != nil {
			return errmsgs.WrapError(err)
		}
		system_disk_tags := getOnlySystemTags(d, system_disks[0].Tags.Tag)
		oraw = make(map[string]interface{})
		for k, v := range ecsService.tagsToMap(system_disk_tags) {
			oraw[k] = v
		}

		if v, ok := d.GetOk("system_disk_tags"); ok {
			nraw = v.(map[string]interface{})
		}

		err = updateTags(client, []string{system_disks[0].DiskId}, "disk", oraw, nraw)
		if err != nil {
			return errmsgs.WrapError(err)
		}
	}

	if data_disk_tags, ok := d.GetOk("data_disk_tags"); ok {
		disks, err := ecsService.DescribeInstanceDisksByType(d.Id(), client.ResourceGroup, "data")
		if err != nil {
			return errmsgs.WrapError(err)
		}
		if len(disks) > 0 {
			oraw := make(map[string]interface{})
			diskids := make([]string, 0, len(disks))
			datadisk_tags := ecsMergeTags(d, data_disk_tags.(map[string]interface{}))
			for _, disk := range disks {
				diskids = append(diskids, disk.DiskId)
			}
			err = updateTags(client, diskids, "disk", oraw, datadisk_tags)
			if err != nil {
				return errmsgs.WrapError(err)
			}
		}

	}

	d.Partial(false)
	return nil
}