diff --git a/.changelog/2837.txt b/.changelog/2837.txt new file mode 100644 index 0000000000..7887962eeb --- /dev/null +++ b/.changelog/2837.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/tencentcloud_kubernetes_node_pool: support delete `taints` and `labels` params +``` diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_node_pool.go b/tencentcloud/services/tke/resource_tc_kubernetes_node_pool.go index 7812b1d5e1..2aca906f9e 100644 --- a/tencentcloud/services/tke/resource_tc_kubernetes_node_pool.go +++ b/tencentcloud/services/tke/resource_tc_kubernetes_node_pool.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "strings" + "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -897,23 +898,6 @@ func resourceTencentCloudKubernetesNodePoolUpdate(d *schema.ResourceData, meta i request.MinNodesNum = helper.IntInt64(v.(int)) } - if v, ok := d.GetOk("taints"); ok { - for _, item := range v.([]interface{}) { - taintsMap := item.(map[string]interface{}) - taint := tkev20180525.Taint{} - if v, ok := taintsMap["key"]; ok { - taint.Key = helper.String(v.(string)) - } - if v, ok := taintsMap["value"]; ok { - taint.Value = helper.String(v.(string)) - } - if v, ok := taintsMap["effect"]; ok { - taint.Effect = helper.String(v.(string)) - } - request.Taints = append(request.Taints, &taint) - } - } - if v, ok := d.GetOkExists("enable_auto_scale"); ok { request.EnableAutoscale = helper.Bool(v.(bool)) } @@ -935,6 +919,16 @@ func resourceTencentCloudKubernetesNodePoolUpdate(d *schema.ResourceData, meta i log.Printf("[CRITAL]%s update kubernetes node pool failed, reason:%+v", logId, err) return err } + if _, err := (&resource.StateChangeConf{ + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + Pending: []string{}, + Refresh: resourceKubernetesNodePoolUpdateStateRefreshFunc_0_0(ctx, clusterId, nodePoolId), + Target: []string{"normal"}, + Timeout: 600 * time.Second, + }).WaitForStateContext(ctx); err != nil { + return err + } } if err := resourceTencentCloudKubernetesNodePoolUpdateOnExit(ctx); err != nil { @@ -1000,3 +994,34 @@ func resourceTencentCloudKubernetesNodePoolDelete(d *schema.ResourceData, meta i return nil } + +func resourceKubernetesNodePoolUpdateStateRefreshFunc_0_0(ctx context.Context, clusterId string, nodePoolId string) resource.StateRefreshFunc { + var req *tkev20180525.DescribeClusterNodePoolDetailRequest + return func() (interface{}, string, error) { + meta := tccommon.ProviderMetaFromContext(ctx) + if meta == nil { + return nil, "", fmt.Errorf("resource data can not be nil") + } + if req == nil { + d := tccommon.ResourceDataFromContext(ctx) + if d == nil { + return nil, "", fmt.Errorf("resource data can not be nil") + } + _ = d + req = tkev20180525.NewDescribeClusterNodePoolDetailRequest() + req.ClusterId = helper.String(clusterId) + + req.NodePoolId = helper.String(nodePoolId) + + } + resp, err := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeV20180525Client().DescribeClusterNodePoolDetailWithContext(ctx, req) + if err != nil { + return nil, "", err + } + if resp == nil || resp.Response == nil { + return nil, "", nil + } + state := fmt.Sprintf("%v", *resp.Response.NodePool.LifeState) + return resp.Response, state, nil + } +} diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_node_pool_extension.go b/tencentcloud/services/tke/resource_tc_kubernetes_node_pool_extension.go index fed9b7504e..aa32faada0 100644 --- a/tencentcloud/services/tke/resource_tc_kubernetes_node_pool_extension.go +++ b/tencentcloud/services/tke/resource_tc_kubernetes_node_pool_extension.go @@ -6,6 +6,8 @@ import ( "log" "strings" + tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http" + as "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as/v20180419" sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" @@ -616,45 +618,49 @@ func resourceTencentCloudKubernetesNodePoolUpdateOnStart(ctx context.Context) er "labels", "tags", ) { - request := tke.NewModifyClusterNodePoolRequest() - request.ClusterId = &clusterId - request.NodePoolId = &nodePoolId + var body map[string]interface{} + nodeOs := d.Get("node_os").(string) + nodeOsType := d.Get("node_os_type").(string) + //自定镜像不能指定节点操作系统类型 + if strings.Contains(nodeOs, "img-") { + nodeOsType = "" + } labels := GetTkeLabels(d, "labels") - tags := helper.GetTags(d, "tags") - if len(labels) > 0 { - request.Labels = labels + body = map[string]interface{}{ + "ClusterId": clusterId, + "NodePoolId": nodePoolId, + "OsName": nodeOs, + "OsCustomizeType": nodeOsType, + "Labels": labels, } + + tags := helper.GetTags(d, "tags") if len(tags) > 0 { + var tmpTags []*tke.Tag for k, v := range tags { key := k val := v - request.Tags = append(request.Tags, &tke.Tag{ + tmpTags = append(tmpTags, &tke.Tag{ Key: &key, Value: &val, }) } + + body["Tags"] = tmpTags } - nodeOs := d.Get("node_os").(string) - nodeOsType := d.Get("node_os_type").(string) - //自定镜像不能指定节点操作系统类型 - if strings.Contains(nodeOs, "img-") { - nodeOsType = "" + client := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseOmitNilClient("tke") + request := tchttp.NewCommonRequest("tke", "2018-05-25", "ModifyClusterNodePool") + err := request.SetActionParameters(body) + if err != nil { + return err } - request.OsName = &nodeOs - request.OsCustomizeType = &nodeOsType - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().ModifyClusterNodePool(request) - if e != nil { - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) - } - return nil - }) + + response := tchttp.NewCommonResponse() + err = client.Send(request, response) if err != nil { - log.Printf("[CRITAL]%s update kubernetes node pool failed, reason:%+v", logId, err) + fmt.Printf("update kubernetes node pool taints failed: %v \n", err) return err } @@ -707,6 +713,11 @@ func resourceTencentCloudKubernetesNodePoolUpdateOnExit(ctx context.Context) err clusterId := items[0] nodePoolId := items[1] + err := resourceTencentCloudKubernetesNodePoolUpdateTaints(ctx, clusterId, nodePoolId) + if err != nil { + return err + } + // ModifyScalingGroup if d.HasChange("scaling_group_name") || d.HasChange("zones") || @@ -1243,3 +1254,95 @@ func desiredCapacityOutRange(d *schema.ResourceData) bool { maxSize := d.Get("max_size").(int) return capacity > maxSize || capacity < minSize } + +func resourceTencentCloudKubernetesNodePoolUpdateTaints(ctx context.Context, clusterId string, nodePoolId string) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + logId := tccommon.GetLogId(tccommon.ContextNil) + + if d.HasChange("taints") { + _, n := d.GetChange("taints") + + // clean taints + if len(n.([]interface{})) == 0 { + body := map[string]interface{}{ + "ClusterId": clusterId, + "NodePoolId": nodePoolId, + "Taints": []interface{}{}, + } + + client := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseOmitNilClient("tke") + request := tchttp.NewCommonRequest("tke", "2018-05-25", "ModifyClusterNodePool") + err := request.SetActionParameters(body) + if err != nil { + return err + } + + response := tchttp.NewCommonResponse() + err = client.Send(request, response) + if err != nil { + fmt.Printf("update kubernetes node pool taints failed: %v \n", err) + return err + } + } else { + request := tke.NewModifyClusterNodePoolRequest() + request.ClusterId = helper.String(clusterId) + request.NodePoolId = helper.String(nodePoolId) + + if v, ok := d.GetOk("taints"); ok { + for _, item := range v.([]interface{}) { + taintsMap := item.(map[string]interface{}) + taint := tke.Taint{} + if v, ok := taintsMap["key"]; ok { + taint.Key = helper.String(v.(string)) + } + + if v, ok := taintsMap["value"]; ok { + taint.Value = helper.String(v.(string)) + } + + if v, ok := taintsMap["effect"]; ok { + taint.Effect = helper.String(v.(string)) + } + + request.Taints = append(request.Taints, &taint) + } + } + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeV20180525Client().ModifyClusterNodePoolWithContext(ctx, request) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + + return nil + }) + + if err != nil { + log.Printf("[CRITAL]%s update kubernetes node pool taints failed, reason:%+v", logId, err) + return err + } + } + + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + err := resource.Retry(5*tccommon.ReadRetryTimeout, func() *resource.RetryError { + nodePool, _, errRet := service.DescribeNodePool(ctx, clusterId, nodePoolId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if nodePool != nil && *nodePool.LifeState == "normal" { + return nil + } + return resource.RetryableError(fmt.Errorf("node pool status is %s, retry...", *nodePool.LifeState)) + }) + + if err != nil { + return err + } + + return nil + } + return nil +}