From 2251cc5f7bce2360f3347ecf1f9ca526d62adcf6 Mon Sep 17 00:00:00 2001
From: "Sk.Lv" <aiphalv0010@gmail.com>
Date: Thu, 22 Aug 2024 15:49:48 +0800
Subject: [PATCH 1/2] fix: kec change image with user_data

---
 ksyun/resource_ksyun_instance.go              |  7 ++--
 ksyun/service_ksyun_instance.go               | 36 ++++++++-----------
 ksyun/utils_ksyun_diff_suppress_funcs.go      |  3 ++
 website/docs/r/instance.html.markdown         |  2 +-
 website/docs/r/kce_cluster.html.markdown      |  4 +--
 .../r/kce_cluster_attachment.html.markdown    |  2 +-
 6 files changed, 24 insertions(+), 30 deletions(-)

diff --git a/ksyun/resource_ksyun_instance.go b/ksyun/resource_ksyun_instance.go
index a15da70b..69767f6e 100644
--- a/ksyun/resource_ksyun_instance.go
+++ b/ksyun/resource_ksyun_instance.go
@@ -52,7 +52,6 @@ import (
 )
 
 func instanceConfig() map[string]*schema.Schema {
-
 	return map[string]*schema.Schema{
 		"image_id": {
 			Type:        schema.TypeString,
@@ -299,9 +298,9 @@ func instanceConfig() map[string]*schema.Schema {
 			Description: "The hostname of the instance. only effective when image support cloud-init.",
 		},
 		"user_data": {
-			Type:             schema.TypeString,
-			Optional:         true,
-			ForceNew:         true,
+			Type:     schema.TypeString,
+			Optional: true,
+			// ForceNew:         true,
 			DiffSuppressFunc: kecImportDiffSuppress,
 			Description:      "The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.",
 		},
diff --git a/ksyun/service_ksyun_instance.go b/ksyun/service_ksyun_instance.go
index 940128ad..5c83162c 100644
--- a/ksyun/service_ksyun_instance.go
+++ b/ksyun/service_ksyun_instance.go
@@ -174,9 +174,7 @@ func (s *KecService) ReadAndSetKecInstances(d *schema.ResourceData, r *schema.Re
 }
 
 func (s *KecService) readKecNetworkInterface(networkInterfaceId string) (data map[string]interface{}, err error) {
-	var (
-		networkInterfaces []interface{}
-	)
+	var networkInterfaces []interface{}
 	vpcService := VpcService{s.client}
 	req := map[string]interface{}{
 		"NetworkInterfaceId.1": networkInterfaceId,
@@ -309,9 +307,7 @@ func readKecNetworkInterfaces(d *schema.ResourceData, meta interface{}, conditio
 }
 
 func (s *KecService) createKecInstance(d *schema.ResourceData, resource *schema.Resource) (err error) {
-	var (
-		callbacks []ApiCall
-	)
+	var callbacks []ApiCall
 	createCall, err := s.createKecInstanceCommon(d, resource)
 	if err != nil {
 		return err
@@ -333,9 +329,7 @@ func (s *KecService) createKecInstance(d *schema.ResourceData, resource *schema.
 }
 
 func (s *KecService) modifyKecInstance(d *schema.ResourceData, resource *schema.Resource) (err error) {
-	var (
-		callbacks []ApiCall
-	)
+	var callbacks []ApiCall
 	// project
 	projectCall, err := s.modifyKecInstanceProject(d, resource)
 	if err != nil {
@@ -466,7 +460,6 @@ func (s *KecService) modifyKecInstance(d *schema.ResourceData, resource *schema.
 }
 
 func transKecInstanceParams(d *schema.ResourceData, resource *schema.Resource) (map[string]interface{}, error) {
-
 	transform := map[string]SdkReqTransform{
 		"key_id": {
 			Type: TransformWithN,
@@ -543,9 +536,7 @@ func (s *KecService) createKecInstanceCommon(d *schema.ResourceData, r *schema.R
 		},
 		afterCall: func(d *schema.ResourceData, client *KsyunClient, resp *map[string]interface{}, call ApiCall) (err error) {
 			logger.Debug(logger.RespFormat, call.action, *(call.param), *resp)
-			var (
-				instanceId interface{}
-			)
+			var instanceId interface{}
 			if resp != nil {
 				instanceId, err = getSdkValue("InstancesSet.0.InstanceId", *resp)
 				if err != nil {
@@ -645,7 +636,6 @@ func (s *KecService) modifyKecInstanceType(d *schema.ResourceData, resource *sch
 					"active",
 					"resize_success_local", "migrating_success", "migrating_success_off_line", "cross_finish",
 				}, d.Timeout(schema.TimeoutUpdate))
-
 				if err != nil {
 					return err
 				}
@@ -655,6 +645,7 @@ func (s *KecService) modifyKecInstanceType(d *schema.ResourceData, resource *sch
 	}
 	return callback, err
 }
+
 func (s *KecService) modifyKecInstanceIamRole(d *schema.ResourceData) (callback ApiCall, err error) {
 	if d.HasChange("iam_role_name") {
 		_, nr := d.GetChange("iam_role_name")
@@ -986,6 +977,10 @@ func (s *KecService) modifyKecInstanceImage(d *schema.ResourceData, resource *sc
 	}
 	if _, ok := updateReq["ImageId"]; ok {
 		updateReq["InstanceId"] = d.Id()
+		if userData, uOk := d.GetOk("user_data"); uOk {
+			updateReq["UserData"] = userData
+		}
+
 		err = d.Set("has_modify_system_disk", true)
 		if err != nil {
 			return callback, err
@@ -1013,6 +1008,9 @@ func (s *KecService) modifyKecInstanceImage(d *schema.ResourceData, resource *sc
 				if err != nil {
 					return err
 				}
+				if userData, ok := updateReq["UserData"]; ok {
+					_ = d.Set("user_data", userData)
+				}
 				return err
 			},
 		}
@@ -1094,7 +1092,6 @@ func (s *KecService) rebootOrStartKecInstance(d *schema.ResourceData) (callback
 		param:  &updateReq,
 		action: "RebootOrStartInstances",
 		executeCall: func(d *schema.ResourceData, client *KsyunClient, call ApiCall) (resp *map[string]interface{}, err error) {
-
 			data, err := s.readKecInstance(d, "", false)
 			if err != nil {
 				return nil, err
@@ -1121,7 +1118,6 @@ func (s *KecService) rebootOrStartKecInstance(d *schema.ResourceData) (callback
 			}
 			// "active",
 			//	"resize_success_local", "migrating_success", "migrating_success_off_line", "cross_finish",
-
 		},
 		afterCall: func(d *schema.ResourceData, client *KsyunClient, resp *map[string]interface{}, call ApiCall) (err error) {
 			logger.Debug(logger.RespFormat, call.action, *(call.param), resp)
@@ -1300,9 +1296,7 @@ func (s *KecService) checkKecInstanceState(d *schema.ResourceData, instanceId st
 
 func (s *KecService) kecInstanceStateRefreshFunc(d *schema.ResourceData, instanceId string, failStates []string) resource.StateRefreshFunc {
 	return func() (interface{}, string, error) {
-		var (
-			err error
-		)
+		var err error
 		data, err := s.readKecInstance(d, instanceId, true)
 		if err != nil {
 			return nil, "", err
@@ -1578,9 +1572,7 @@ func (s *KecService) modifyNetworkInterface(d *schema.ResourceData, resource *sc
 	}
 	calls = append(calls, call)
 	if d.Get("instance_id") != "" {
-		var (
-			attrCall ApiCall
-		)
+		var attrCall ApiCall
 		attrCall, err = s.modifyNetworkInterfaceAttrCall(d, resource)
 		if err != nil {
 			return err
diff --git a/ksyun/utils_ksyun_diff_suppress_funcs.go b/ksyun/utils_ksyun_diff_suppress_funcs.go
index 37769c53..647803d1 100644
--- a/ksyun/utils_ksyun_diff_suppress_funcs.go
+++ b/ksyun/utils_ksyun_diff_suppress_funcs.go
@@ -57,6 +57,9 @@ func kecImportDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
 			return true
 		}
 		if k == "user_data" {
+			if d.HasChange("image_id") {
+				return false
+			}
 			return true
 		}
 		if k == "auto_create_ebs" {
diff --git a/website/docs/r/instance.html.markdown b/website/docs/r/instance.html.markdown
index 3e56c0da..a9b22477 100644
--- a/website/docs/r/instance.html.markdown
+++ b/website/docs/r/instance.html.markdown
@@ -72,7 +72,7 @@ The following arguments are supported:
 * `sriov_net_support` - (Optional, ForceNew) whether support networking enhancement.
 * `system_disk` - (Optional) System disk parameters.
 * `tags` - (Optional) the tags of the resource.
-* `user_data` - (Optional, ForceNew) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
+* `user_data` - (Optional) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
 
 The `data_disks` object supports the following:
 
diff --git a/website/docs/r/kce_cluster.html.markdown b/website/docs/r/kce_cluster.html.markdown
index a2393d1e..ef8243e7 100644
--- a/website/docs/r/kce_cluster.html.markdown
+++ b/website/docs/r/kce_cluster.html.markdown
@@ -275,7 +275,7 @@ The `master_config` object supports the following:
 * `sriov_net_support` - (Optional, ForceNew) whether support networking enhancement.
 * `system_disk` - (Optional) System disk parameters.
 * `tags` - (Optional) the tags of the resource.
-* `user_data` - (Optional, ForceNew) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
+* `user_data` - (Optional) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
 
 The `system_disk` object supports the following:
 
@@ -320,7 +320,7 @@ The `worker_config` object supports the following:
 * `sriov_net_support` - (Optional, ForceNew) whether support networking enhancement.
 * `system_disk` - (Optional) System disk parameters.
 * `tags` - (Optional) the tags of the resource.
-* `user_data` - (Optional, ForceNew) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
+* `user_data` - (Optional) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
 
 ## Attributes Reference
 
diff --git a/website/docs/r/kce_cluster_attachment.html.markdown b/website/docs/r/kce_cluster_attachment.html.markdown
index 68199e58..f158ab18 100644
--- a/website/docs/r/kce_cluster_attachment.html.markdown
+++ b/website/docs/r/kce_cluster_attachment.html.markdown
@@ -130,7 +130,7 @@ The `worker_config` object supports the following:
 * `sriov_net_support` - (Optional, ForceNew) whether support networking enhancement.
 * `system_disk` - (Optional) System disk parameters.
 * `tags` - (Optional) the tags of the resource.
-* `user_data` - (Optional, ForceNew) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
+* `user_data` - (Optional) The user data to be specified into this instance. Must be encrypted in base64 format and limited in 16 KB. only effective when image support cloud-init.
 
 ## Attributes Reference
 

From fb9dbe8115eaeb0293a8c036f6be0116c72c2f09 Mon Sep 17 00:00:00 2001
From: "Sk.Lv" <aiphalv0010@gmail.com>
Date: Thu, 22 Aug 2024 15:51:44 +0800
Subject: [PATCH 2/2] docs: changelog v1.16.3

---
 CHANGELOG.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a09346ea..cad5cd45 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.16.3 (Aug 22, 2024)
+
+BUGFIX:
+
+- `ksyun_instance`: 修复云主机变更镜像时`user_data`不生效
+
 ## 1.16.2 (Jul 30, 2024)
 
 FEATURES: