diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index a4ca59f97d..1a801f2140 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -1119,10 +1119,10 @@ func Provider() *schema.Provider { "tencentcloud_kubernetes_auth_attachment": tke.ResourceTencentCloudTKEAuthAttachment(), "tencentcloud_kubernetes_as_scaling_group": tke.ResourceTencentCloudKubernetesAsScalingGroup(), "tencentcloud_kubernetes_scale_worker": tke.ResourceTencentCloudTkeScaleWorker(), - "tencentcloud_kubernetes_cluster_attachment": tke.ResourceTencentCloudTkeClusterAttachment(), + "tencentcloud_kubernetes_cluster_attachment": tke.ResourceTencentCloudKubernetesClusterAttachment(), "tencentcloud_kubernetes_node_pool": tke.ResourceTencentCloudKubernetesNodePool(), "tencentcloud_kubernetes_serverless_node_pool": tke.ResourceTencentCloudTkeServerLessNodePool(), - "tencentcloud_kubernetes_backup_storage_location": tke.ResourceTencentCloudTkeBackupStorageLocation(), + "tencentcloud_kubernetes_backup_storage_location": tke.ResourceTencentCloudKubernetesBackupStorageLocation(), "tencentcloud_kubernetes_encryption_protection": tke.ResourceTencentCloudKubernetesEncryptionProtection(), "tencentcloud_mysql_backup_policy": cdb.ResourceTencentCloudMysqlBackupPolicy(), "tencentcloud_mysql_account": cdb.ResourceTencentCloudMysqlAccount(), diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_backup_storage_location.go b/tencentcloud/services/tke/resource_tc_kubernetes_backup_storage_location.go index 655d02d50d..0a28fbf17c 100644 --- a/tencentcloud/services/tke/resource_tc_kubernetes_backup_storage_location.go +++ b/tencentcloud/services/tke/resource_tc_kubernetes_backup_storage_location.go @@ -1,26 +1,26 @@ +// Code generated by iacg; DO NOT EDIT. package tke import ( "context" - "fmt" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "log" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) -func ResourceTencentCloudTkeBackupStorageLocation() *schema.Resource { +func ResourceTencentCloudKubernetesBackupStorageLocation() *schema.Resource { return &schema.Resource{ + Create: resourceTencentCloudKubernetesBackupStorageLocationCreate, + Read: resourceTencentCloudKubernetesBackupStorageLocationRead, + Delete: resourceTencentCloudKubernetesBackupStorageLocationDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, - Create: resourceTencentCloudTkeBackupStorageLocationCreate, - Read: resourceTencentCloudTkeBackupStorageLocationRead, - Delete: resourceTencentCloudTkeBackupStorageLocationDelete, Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -28,29 +28,34 @@ func ResourceTencentCloudTkeBackupStorageLocation() *schema.Resource { ForceNew: true, Description: "Name of the backup storage location.", }, + "storage_region": { Type: schema.TypeString, Required: true, ForceNew: true, Description: "Region of the storage.", }, + "bucket": { Type: schema.TypeString, Required: true, ForceNew: true, Description: "Name of the bucket.", }, + "path": { Type: schema.TypeString, Optional: true, ForceNew: true, Description: "Prefix of the bucket.", }, + "state": { Type: schema.TypeString, Computed: true, Description: "State of the backup storage location.", }, + "message": { Type: schema.TypeString, Computed: true, @@ -60,117 +65,154 @@ func ResourceTencentCloudTkeBackupStorageLocation() *schema.Resource { } } -func resourceTencentCloudTkeBackupStorageLocationCreate(d *schema.ResourceData, meta interface{}) error { +func resourceTencentCloudKubernetesBackupStorageLocationCreate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_backup_storage_location.create")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - service := TkeService{client: client} - request := genCreateBackupStorageLocationRequest(d) - err := service.createBackupStorageLocation(ctx, request) - if err != nil { - return err + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + var ( + name string + ) + var ( + request = tke.NewCreateBackupStorageLocationRequest() + response = tke.NewCreateBackupStorageLocationResponse() + ) + + if v, ok := d.GetOk("name"); ok { + name = v.(string) } - // wait for status ok - err = resource.Retry(3*tccommon.ReadRetryTimeout, func() *resource.RetryError { - locations, errRet := service.DescribeBackupStorageLocations(ctx, []string{d.Get("name").(string)}) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if len(locations) != 1 { - resource.RetryableError(fmt.Errorf("more than 1 location returnen in api response, expected 1 but got %d", len(locations))) - } - if locations[0].State == nil { - return resource.RetryableError(fmt.Errorf("location %s is still in state nil", d.Get("name").(string))) - } - if len(locations) == 1 && *locations[0].State == backupStorageLocationStateAvailable { - return nil + if v, ok := d.GetOk("name"); ok { + request.Name = helper.String(v.(string)) + } + + if v, ok := d.GetOk("storage_region"); ok { + request.StorageRegion = helper.String(v.(string)) + } + + if v, ok := d.GetOk("bucket"); ok { + request.Bucket = helper.String(v.(string)) + } + + if v, ok := d.GetOk("path"); ok { + request.Path = helper.String(v.(string)) + } + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().CreateBackupStorageLocationWithContext(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 resource.RetryableError(fmt.Errorf("location %s is still in state %s", d.Get("name").(string), *locations[0].State)) + response = result + return nil }) if err != nil { + log.Printf("[CRITAL]%s create kubernetes backup storage location failed, reason:%+v", logId, err) return err } - d.SetId(d.Get("name").(string)) - return resourceTencentCloudTkeBackupStorageLocationRead(d, meta) + _ = response + + if err := resourceTencentCloudKubernetesBackupStorageLocationCreatePostHandleResponse0(ctx, response); err != nil { + return err + } + + d.SetId(name) + + return resourceTencentCloudKubernetesBackupStorageLocationRead(d, meta) } -func resourceTencentCloudTkeBackupStorageLocationRead(d *schema.ResourceData, meta interface{}) error { +func resourceTencentCloudKubernetesBackupStorageLocationRead(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_backup_storage_location.read")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - service := TkeService{client: client} - locations, err := service.DescribeBackupStorageLocations(ctx, []string{d.Id()}) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + name := d.Id() + + _ = d.Set("name", name) + + respData, err := service.DescribeKubernetesBackupStorageLocationById(ctx, name) if err != nil { return err } - for _, location := range locations { - if *location.Name == d.Id() { - _ = d.Set("name", location.Name) - _ = d.Set("storage_region", location.StorageRegion) - _ = d.Set("bucket", location.Bucket) - _ = d.Set("path", location.Path) - _ = d.Set("state", location.State) - _ = d.Set("message", location.Message) - return nil - } + + if respData == nil { + d.SetId("") + log.Printf("[WARN]%s resource `kubernetes_backup_storage_location` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil + } + if respData.Name != nil { + _ = d.Set("name", respData.Name) + } + + if respData.StorageRegion != nil { + _ = d.Set("storage_region", respData.StorageRegion) + } + + if respData.Bucket != nil { + _ = d.Set("bucket", respData.Bucket) + } + + if respData.Path != nil { + _ = d.Set("path", respData.Path) + } + + if respData.State != nil { + _ = d.Set("state", respData.State) + } + + if respData.Message != nil { + _ = d.Set("message", respData.Message) } - d.SetId("") return nil } -func resourceTencentCloudTkeBackupStorageLocationDelete(d *schema.ResourceData, meta interface{}) error { +func resourceTencentCloudKubernetesBackupStorageLocationDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_backup_storage_location.delete")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - service := TkeService{client: client} + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - err := service.DeleteBackupStorageLocation(ctx, d.Id()) - if err != nil { - return err - } + name := d.Id() - // wait until location is deleted - err = resource.Retry(3*tccommon.ReadRetryTimeout, func() *resource.RetryError { - locations, errRet := service.DescribeBackupStorageLocations(ctx, []string{d.Id()}) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if len(locations) == 0 { - return nil + var ( + request = tke.NewDeleteBackupStorageLocationRequest() + response = tke.NewDeleteBackupStorageLocationResponse() + ) + + request.Name = helper.String(name) + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().DeleteBackupStorageLocationWithContext(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 resource.RetryableError(fmt.Errorf("location %s is still not deleted", d.Id())) + response = result + return nil }) if err != nil { + log.Printf("[CRITAL]%s delete kubernetes backup storage location failed, reason:%+v", logId, err) return err } - return nil -} - -func genCreateBackupStorageLocationRequest(d *schema.ResourceData) (request *tke.CreateBackupStorageLocationRequest) { - request = tke.NewCreateBackupStorageLocationRequest() - if v, ok := d.GetOk("name"); ok { - request.Name = helper.String(v.(string)) - } - if v, ok := d.GetOk("storage_region"); ok { - request.StorageRegion = helper.String(v.(string)) - } - if v, ok := d.GetOk("bucket"); ok { - request.Bucket = helper.String(v.(string)) - } - if v, ok := d.GetOk("path"); ok { - request.Path = helper.String(v.(string)) + _ = response + if err := resourceTencentCloudKubernetesBackupStorageLocationDeletePostHandleResponse0(ctx, response); err != nil { + return err } - return request + + return nil } diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_backup_storage_location_extension.go b/tencentcloud/services/tke/resource_tc_kubernetes_backup_storage_location_extension.go new file mode 100644 index 0000000000..de31a9bd5f --- /dev/null +++ b/tencentcloud/services/tke/resource_tc_kubernetes_backup_storage_location_extension.go @@ -0,0 +1,66 @@ +package tke + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" +) + +func resourceTencentCloudKubernetesBackupStorageLocationCreatePostHandleResponse0(ctx context.Context, resp *tke.CreateBackupStorageLocationResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + if d == nil { + return fmt.Errorf("resource data can not be nil") + } + + meta := tccommon.ProviderMetaFromContext(ctx) + if meta == nil { + return fmt.Errorf("provider meta can not be nil") + } + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + // wait for status ok + return resource.Retry(3*tccommon.ReadRetryTimeout, func() *resource.RetryError { + locations, errRet := service.DescribeBackupStorageLocations(ctx, []string{d.Get("name").(string)}) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if len(locations) != 1 { + resource.RetryableError(fmt.Errorf("more than 1 location returnen in api response, expected 1 but got %d", len(locations))) + } + if locations[0].State == nil { + return resource.RetryableError(fmt.Errorf("location %s is still in state nil", d.Get("name").(string))) + } + if len(locations) == 1 && *locations[0].State == backupStorageLocationStateAvailable { + return nil + } + return resource.RetryableError(fmt.Errorf("location %s is still in state %s", d.Get("name").(string), *locations[0].State)) + }) +} + +func resourceTencentCloudKubernetesBackupStorageLocationDeletePostHandleResponse0(ctx context.Context, resp *tke.DeleteBackupStorageLocationResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + if d == nil { + return fmt.Errorf("resource data can not be nil") + } + meta := tccommon.ProviderMetaFromContext(ctx) + if meta == nil { + return fmt.Errorf("provider meta can not be nil") + } + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + // wait until location is deleted + return resource.Retry(3*tccommon.ReadRetryTimeout, func() *resource.RetryError { + locations, errRet := service.DescribeBackupStorageLocations(ctx, []string{d.Id()}) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if len(locations) == 0 { + return nil + } + return resource.RetryableError(fmt.Errorf("location %s is still not deleted", d.Id())) + }) +} diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_cluster_attachment.go b/tencentcloud/services/tke/resource_tc_kubernetes_cluster_attachment.go index b705b1072b..6f547479c5 100644 --- a/tencentcloud/services/tke/resource_tc_kubernetes_cluster_attachment.go +++ b/tencentcloud/services/tke/resource_tc_kubernetes_cluster_attachment.go @@ -1,684 +1,718 @@ +// Code generated by iacg; DO NOT EDIT. package tke import ( - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - svcas "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/as" - svccvm "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/cvm" - "context" "fmt" + "log" "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" - cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/ratelimit" + svcas "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/as" ) -func TKEGpuArgsSetting() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "mig_enable": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Whether to enable MIG.", - }, - "driver": { - Type: schema.TypeMap, - Optional: true, - ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, - Description: "GPU driver version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", - }, - "cuda": { - Type: schema.TypeMap, - Optional: true, - ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, - Description: "CUDA version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", - }, - "cudnn": { - Type: schema.TypeMap, - Optional: true, - ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, - Description: "cuDNN version. Format like: `{ version: String, name: String, doc_name: String, dev_name: String }`." + - " `version`: cuDNN version; `name`: cuDNN name; `doc_name`: Doc name of cuDNN; `dev_name`: Dev name of cuDNN.", - }, - "custom_driver": { - Type: schema.TypeMap, - Optional: true, - Description: "Custom GPU driver. Format like: `{address: String}`. `address`: URL of custom GPU driver address.", - }, - } -} +func ResourceTencentCloudKubernetesClusterAttachment() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudKubernetesClusterAttachmentCreate, + Read: resourceTencentCloudKubernetesClusterAttachmentRead, + Delete: resourceTencentCloudKubernetesClusterAttachmentDelete, + Schema: map[string]*schema.Schema{ + "cluster_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "ID of the cluster.", + }, -func TkeInstanceAdvancedSetting() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "mount_target": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "Mount target. Default is not mounting.", - }, - "docker_graph_path": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: "/var/lib/docker", - Description: "Docker graph path. Default is `/var/lib/docker`.", - }, - "data_disk": { - Type: schema.TypeList, - ForceNew: true, - Optional: true, - MaxItems: 11, - Description: "Configurations of data disk.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "disk_type": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Default: svcas.SYSTEM_DISK_TYPE_CLOUD_PREMIUM, - ValidateFunc: tccommon.ValidateAllowedStringValue(svcas.SYSTEM_DISK_ALLOW_TYPE), - Description: "Types of disk. Valid value: `LOCAL_BASIC`, `LOCAL_SSD`, `CLOUD_BASIC`, `CLOUD_PREMIUM`, `CLOUD_SSD`, `CLOUD_HSSD`, `CLOUD_TSSD` and `CLOUD_BSSD`.", - }, - "disk_size": { - Type: schema.TypeInt, - ForceNew: true, - Optional: true, - Default: 0, - Description: "Volume of disk in GB. Default is `0`.", - }, - "file_system": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Default: "", - Description: "File system, e.g. `ext3/ext4/xfs`.", - }, - "auto_format_and_mount": { - Type: schema.TypeBool, - Optional: true, - ForceNew: true, - Default: false, - Description: "Indicate whether to auto format and mount or not. Default is `false`.", - }, - "mount_target": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: "", - Description: "Mount target.", + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "ID of the CVM instance, this cvm will reinstall the system.", + }, + + "password": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Sensitive: true, + Description: "Password to access, should be set if `key_ids` not set.", + ValidateFunc: tccommon.ValidateAsConfigPassword, + }, + + "key_ids": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "The key pair to use for the instance, it looks like skey-16jig7tx, it should be set if `password` not set.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "hostname": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The host name of the attached instance. Dot (.) and dash (-) cannot be used as the first and last characters of HostName and cannot be used consecutively. Windows example: The length of the name character is [2, 15], letters (capitalization is not restricted), numbers and dashes (-) are allowed, dots (.) are not supported, and not all numbers are allowed. Examples of other types (Linux, etc.): The character length is [2, 60], and multiple dots are allowed. There is a segment between the dots. Each segment allows letters (with no limitation on capitalization), numbers and dashes (-).", + }, + + "worker_config": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "Deploy the machine configuration information of the 'WORKER', commonly used to attach existing instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Mount target. Default is not mounting.", + }, + "docker_graph_path": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "/var/lib/docker", + Description: "Docker graph path. Default is `/var/lib/docker`.", + }, + "data_disk": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 11, + Description: "Configurations of data disk.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "CLOUD_PREMIUM", + Description: "Types of disk. Valid value: `LOCAL_BASIC`, `LOCAL_SSD`, `CLOUD_BASIC`, `CLOUD_PREMIUM`, `CLOUD_SSD`, `CLOUD_HSSD`, `CLOUD_TSSD` and `CLOUD_BSSD`.", + ValidateFunc: tccommon.ValidateAllowedStringValue(svcas.SYSTEM_DISK_ALLOW_TYPE), + }, + "disk_size": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 0, + Description: "Volume of disk in GB. Default is `0`.", + }, + "file_system": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "", + Description: "File system, e.g. `ext3/ext4/xfs`.", + }, + "auto_format_and_mount": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: false, + Description: "Indicate whether to auto format and mount or not. Default is `false`.", + }, + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "", + Description: "Mount target.", + }, + "disk_partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name of the device or partition to mount. NOTE: this argument doesn't support setting in node pool, or will leads to mount error.", + }, + }, + }, + }, + "extra_args": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: "Custom parameter information related to the node. This is a white-list parameter.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "user_data": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Base64-encoded User Data text, the length limit is 16KB.", + }, + "pre_start_user_script": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Base64-encoded user script, executed before initializing the node, currently only effective for adding existing nodes.", + }, + "is_schedule": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: true, + Description: "Indicate to schedule the adding node or not. Default is true.", + }, + "desired_pod_num": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: "Indicate to set desired pod number in node. valid when the cluster is podCIDR.", + }, + "gpu_args": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "GPU driver parameters.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mig_enable": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to enable MIG.", + }, + "driver": { + Type: schema.TypeMap, + Optional: true, + Description: "GPU driver version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + }, + "cuda": { + Type: schema.TypeMap, + Optional: true, + Description: "CUDA version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + }, + "cudnn": { + Type: schema.TypeMap, + Optional: true, + Description: "cuDNN version. Format like: `{ version: String, name: String, doc_name: String, dev_name: String }`. `version`: cuDNN version; `name`: cuDNN name; `doc_name`: Doc name of cuDNN; `dev_name`: Dev name of cuDNN.", + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + }, + "custom_driver": { + Type: schema.TypeMap, + Optional: true, + Description: "Custom GPU driver. Format like: `{address: String}`. `address`: URL of custom GPU driver address.", + }, + }, + }, + }, }, - "disk_partition": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Description: "The name of the device or partition to mount. NOTE: this argument doesn't support setting in node pool, or will leads to mount error.", + }, + }, + + "worker_config_overrides": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "Override variable worker_config, commonly used to attach existing instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Mount target. Default is not mounting.", + }, + "docker_graph_path": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "/var/lib/docker", + Description: "Docker graph path. Default is `/var/lib/docker`.", + }, + "data_disk": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 11, + Description: "Configurations of data disk.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "CLOUD_PREMIUM", + Description: "Types of disk. Valid value: `LOCAL_BASIC`, `LOCAL_SSD`, `CLOUD_BASIC`, `CLOUD_PREMIUM`, `CLOUD_SSD`, `CLOUD_HSSD`, `CLOUD_TSSD` and `CLOUD_BSSD`.", + ValidateFunc: tccommon.ValidateAllowedStringValue(svcas.SYSTEM_DISK_ALLOW_TYPE), + }, + "disk_size": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 0, + Description: "Volume of disk in GB. Default is `0`.", + }, + "file_system": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "", + Description: "File system, e.g. `ext3/ext4/xfs`.", + }, + "auto_format_and_mount": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: false, + Description: "Indicate whether to auto format and mount or not. Default is `false`.", + }, + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "", + Description: "Mount target.", + }, + "disk_partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name of the device or partition to mount. NOTE: this argument doesn't support setting in node pool, or will leads to mount error.", + }, + }, + }, + }, + "extra_args": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: "Custom parameter information related to the node. This is a white-list parameter.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "user_data": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Base64-encoded User Data text, the length limit is 16KB.", + }, + "pre_start_user_script": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Base64-encoded user script, executed before initializing the node, currently only effective for adding existing nodes.", + }, + "is_schedule": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: true, + Description: "Indicate to schedule the adding node or not. Default is true.", + }, + "desired_pod_num": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: "Indicate to set desired pod number in node. valid when the cluster is podCIDR.", + }, + "gpu_args": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "GPU driver parameters.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mig_enable": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to enable MIG.", + }, + "driver": { + Type: schema.TypeMap, + Optional: true, + Description: "GPU driver version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + }, + "cuda": { + Type: schema.TypeMap, + Optional: true, + Description: "CUDA version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + }, + "cudnn": { + Type: schema.TypeMap, + Optional: true, + Description: "cuDNN version. Format like: `{ version: String, name: String, doc_name: String, dev_name: String }`. `version`: cuDNN version; `name`: cuDNN name; `doc_name`: Doc name of cuDNN; `dev_name`: Dev name of cuDNN.", + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + }, + "custom_driver": { + Type: schema.TypeMap, + Optional: true, + Description: "Custom GPU driver. Format like: `{address: String}`. `address`: URL of custom GPU driver address.", + }, + }, + }, + }, }, }, }, - }, - "extra_args": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "Custom parameter information related to the node. This is a white-list parameter.", - }, - "user_data": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Description: "Base64-encoded User Data text, the length limit is 16KB.", - }, - "pre_start_user_script": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Description: "Base64-encoded user script, executed before initializing the node, currently only effective for adding existing nodes.", - }, - "is_schedule": { - Type: schema.TypeBool, - ForceNew: true, - Optional: true, - Default: true, - Description: "Indicate to schedule the adding node or not. Default is true.", - }, - "desired_pod_num": { - Type: schema.TypeInt, - ForceNew: true, - Optional: true, - Description: "Indicate to set desired pod number in node. valid when the cluster is podCIDR.", - }, - "gpu_args": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: TKEGpuArgsSetting(), + + "labels": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + Description: "Labels of tke attachment exits CVM.", }, - Description: "GPU driver parameters.", - }, - } -} -func ResourceTencentCloudTkeClusterAttachment() *schema.Resource { - schemaBody := map[string]*schema.Schema{ - "cluster_id": { - Type: schema.TypeString, - ForceNew: true, - Required: true, - Description: "ID of the cluster.", - }, - "instance_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: "ID of the CVM instance, this cvm will reinstall the system.", - }, - "password": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Sensitive: true, - ValidateFunc: tccommon.ValidateAsConfigPassword, - Description: "Password to access, should be set if `key_ids` not set.", - }, - "key_ids": { - MaxItems: 1, - Type: schema.TypeList, - ForceNew: true, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "The key pair to use for the instance, it looks like skey-16jig7tx, it should be set if `password` not set.", - }, - "hostname": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Description: "The host name of the attached instance. " + - "Dot (.) and dash (-) cannot be used as the first and last characters of HostName and cannot be used consecutively. " + - "Windows example: The length of the name character is [2, 15], letters (capitalization is not restricted), numbers and dashes (-) are allowed, dots (.) are not supported, and not all numbers are allowed. " + - "Examples of other types (Linux, etc.): The character length is [2, 60], and multiple dots are allowed. There is a segment between the dots. Each segment allows letters (with no limitation on capitalization), numbers and dashes (-).", - }, - "worker_config": { - Type: schema.TypeList, - ForceNew: true, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: TkeInstanceAdvancedSetting(), + "unschedulable": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 0, + Description: "Sets whether the joining node participates in the schedule. Default is '0'. Participate in scheduling.", }, - Description: "Deploy the machine configuration information of the 'WORKER', commonly used to attach existing instances.", - }, - "worker_config_overrides": { - Type: schema.TypeList, - ForceNew: true, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: TkeInstanceAdvancedSetting(), + + "security_groups": { + Type: schema.TypeSet, + Computed: true, + Description: "A list of security group IDs after attach to cluster.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - Description: "Override variable worker_config, commonly used to attach existing instances.", - }, - "labels": { - Type: schema.TypeMap, - Optional: true, - ForceNew: true, - Description: "Labels of tke attachment exits CVM.", - }, - "unschedulable": { - Type: schema.TypeInt, - Optional: true, - ForceNew: true, - Default: 0, - Description: "Sets whether the joining node participates in the schedule. Default is '0'. Participate in scheduling.", - }, - //compute - "security_groups": { - Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, - Computed: true, - Description: "A list of security group IDs after attach to cluster.", - }, - "state": { - Type: schema.TypeString, - Computed: true, - Description: "State of the node.", - }, - } - return &schema.Resource{ - Create: resourceTencentCloudTkeClusterAttachmentCreate, - Read: resourceTencentCloudTkeClusterAttachmentRead, - Delete: resourceTencentCloudTkeClusterAttachmentDelete, - Schema: schemaBody, + "state": { + Type: schema.TypeString, + Computed: true, + Description: "State of the node.", + }, + }, } } -func tkeGetInstanceAdvancedPara(dMap map[string]interface{}, meta interface{}) (setting tke.InstanceAdvancedSettings) { - setting = tke.InstanceAdvancedSettings{} - if v, ok := dMap["mount_target"]; ok { - setting.MountTarget = helper.String(v.(string)) - } +func resourceTencentCloudKubernetesClusterAttachmentCreate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_cluster_attachment.create")() + defer tccommon.InconsistentCheck(d, meta)() - if v, ok := dMap["data_disk"]; ok { - dataDisks := v.([]interface{}) - setting.DataDisks = make([]*tke.DataDisk, len(dataDisks)) - for i, d := range dataDisks { - value := d.(map[string]interface{}) - var diskType, fileSystem, mountTarget, diskPartition string - if v, ok := value["disk_type"].(string); ok { - diskType = v - } - if v, ok := value["file_system"].(string); ok { - fileSystem = v - } - if v, ok := value["mount_target"].(string); ok { - mountTarget = v - } - if v, ok := value["disk_partition"].(string); ok { - diskPartition = v - } + logId := tccommon.GetLogId(tccommon.ContextNil) - diskSize := int64(value["disk_size"].(int)) - autoFormatAndMount := value["auto_format_and_mount"].(bool) - dataDisk := &tke.DataDisk{ - DiskType: &diskType, - FileSystem: &fileSystem, - AutoFormatAndMount: &autoFormatAndMount, - MountTarget: &mountTarget, - DiskPartition: &diskPartition, - } - if diskSize > 0 { - dataDisk.DiskSize = &diskSize - } - setting.DataDisks[i] = dataDisk - } - } - if v, ok := dMap["is_schedule"]; ok { - setting.Unschedulable = helper.BoolToInt64Ptr(!v.(bool)) - } + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - if v, ok := dMap["user_data"]; ok { - setting.UserScript = helper.String(v.(string)) - } + var ( + instanceId string + clusterId string + ) + var ( + request = tke.NewAddExistedInstancesRequest() + response = tke.NewAddExistedInstancesResponse() + ) - if v, ok := dMap["pre_start_user_script"]; ok { - setting.PreStartUserScript = helper.String(v.(string)) + if v, ok := d.GetOk("instance_id"); ok { + instanceId = v.(string) } - - if v, ok := dMap["docker_graph_path"]; ok { - setting.DockerGraphPath = helper.String(v.(string)) + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) } - if v, ok := dMap["desired_pod_num"]; ok { - setting.DesiredPodNumber = helper.Int64(int64(v.(int))) + if v, ok := d.GetOk("cluster_id"); ok { + request.ClusterId = helper.String(v.(string)) } - if temp, ok := dMap["extra_args"]; ok { - extraArgs := helper.InterfacesStrings(temp.([]interface{})) - clusterExtraArgs := tke.InstanceExtraArgs{} - clusterExtraArgs.Kubelet = make([]*string, 0) - for i := range extraArgs { - clusterExtraArgs.Kubelet = append(clusterExtraArgs.Kubelet, &extraArgs[i]) - } - setting.ExtraArgs = &clusterExtraArgs + request.InstanceIds = []*string{helper.String(instanceId)} + + loginSettings := tke.LoginSettings{} + if v, ok := d.GetOk("password"); ok { + loginSettings.Password = helper.String(v.(string)) } + request.LoginSettings = &loginSettings - // get gpu_args - if v, ok := dMap["gpu_args"]; ok && len(v.([]interface{})) > 0 { - gpuArgs := v.([]interface{})[0].(map[string]interface{}) - - var ( - migEnable = gpuArgs["mig_enable"].(bool) - driver = gpuArgs["driver"].(map[string]interface{}) - cuda = gpuArgs["cuda"].(map[string]interface{}) - cudnn = gpuArgs["cudnn"].(map[string]interface{}) - customDriver = gpuArgs["custom_driver"].(map[string]interface{}) - ) - tkeGpuArgs := tke.GPUArgs{} - tkeGpuArgs.MIGEnable = &migEnable - if len(driver) > 0 { - tkeGpuArgs.Driver = &tke.DriverVersion{ - Version: helper.String(driver["version"].(string)), - Name: helper.String(driver["name"].(string)), - } + if instanceAdvancedSettingsMap, ok := helper.InterfacesHeadMap(d, "worker_config"); ok { + instanceAdvancedSettings := tke.InstanceAdvancedSettings{} + if v, ok := instanceAdvancedSettingsMap["mount_target"]; ok { + instanceAdvancedSettings.MountTarget = helper.String(v.(string)) } - if len(cuda) > 0 { - tkeGpuArgs.CUDA = &tke.DriverVersion{ - Version: helper.String(cuda["version"].(string)), - Name: helper.String(cuda["name"].(string)), + if v, ok := instanceAdvancedSettingsMap["data_disk"]; ok { + for _, item := range v.([]interface{}) { + dataDisksMap := item.(map[string]interface{}) + dataDisk := tke.DataDisk{} + if v, ok := dataDisksMap["disk_type"]; ok { + dataDisk.DiskType = helper.String(v.(string)) + } + if v, ok := dataDisksMap["file_system"]; ok { + dataDisk.FileSystem = helper.String(v.(string)) + } + if v, ok := dataDisksMap["auto_format_and_mount"]; ok { + dataDisk.AutoFormatAndMount = helper.Bool(v.(bool)) + } + if v, ok := dataDisksMap["mount_target"]; ok { + dataDisk.MountTarget = helper.String(v.(string)) + } + if v, ok := dataDisksMap["disk_partition"]; ok { + dataDisk.DiskPartition = helper.String(v.(string)) + } + if v, ok := dataDisksMap["disk_size"]; ok { + dataDisk.DiskSize = helper.IntInt64(v.(int)) + } + instanceAdvancedSettings.DataDisks = append(instanceAdvancedSettings.DataDisks, &dataDisk) } } - if len(cudnn) > 0 { - tkeGpuArgs.CUDNN = &tke.CUDNN{ - Version: helper.String(cudnn["version"].(string)), - Name: helper.String(cudnn["name"].(string)), - } - if cudnn["doc_name"] != nil { - tkeGpuArgs.CUDNN.DocName = helper.String(cudnn["doc_name"].(string)) - } - if cudnn["dev_name"] != nil { - tkeGpuArgs.CUDNN.DevName = helper.String(cudnn["dev_name"].(string)) - } + if v, ok := instanceAdvancedSettingsMap["user_data"]; ok { + instanceAdvancedSettings.UserScript = helper.String(v.(string)) + } + if v, ok := instanceAdvancedSettingsMap["pre_start_user_script"]; ok { + instanceAdvancedSettings.PreStartUserScript = helper.String(v.(string)) + } + if v, ok := instanceAdvancedSettingsMap["docker_graph_path"]; ok { + instanceAdvancedSettings.DockerGraphPath = helper.String(v.(string)) + } + if v, ok := instanceAdvancedSettingsMap["desired_pod_num"]; ok { + instanceAdvancedSettings.DesiredPodNumber = helper.IntInt64(v.(int)) } - if len(customDriver) > 0 { - tkeGpuArgs.CustomDriver = &tke.CustomDriver{ - Address: helper.String(customDriver["address"].(string)), + if gPUArgsMap, ok := helper.ConvertInterfacesHeadToMap(instanceAdvancedSettingsMap["gpu_args"]); ok { + gPUArgs := tke.GPUArgs{} + if v, ok := gPUArgsMap["mig_enable"]; ok { + gPUArgs.MIGEnable = helper.Bool(v.(bool)) } + instanceAdvancedSettings.GPUArgs = &gPUArgs } - setting.GPUArgs = &tkeGpuArgs + if v, ok := d.GetOkExists("unschedulable"); ok { + instanceAdvancedSettings.Unschedulable = helper.IntInt64(v.(int)) + } + request.InstanceAdvancedSettings = &instanceAdvancedSettings } - return setting -} -func resourceTencentCloudTkeClusterAttachmentRead(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_cluster_attachment.read")() - defer tccommon.InconsistentCheck(d, meta)() - - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - - tkeService := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - cvmService := svccvm.NewCvmService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) - instanceId, clusterId := "", "" - - if items := strings.Split(d.Id(), "_"); len(items) != 2 { - return fmt.Errorf("the resource id is corrupted") - } else { - instanceId, clusterId = items[0], items[1] + if v, ok := d.GetOk("hostname"); ok { + request.HostName = helper.String(v.(string)) } - /*tke has been deleted*/ - _, has, err := tkeService.DescribeCluster(ctx, clusterId) - if err != nil { - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, has, err = tkeService.DescribeCluster(ctx, clusterId) - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) + if v, ok := d.GetOk("worker_config_overrides"); ok { + for _, item := range v.([]interface{}) { + instanceAdvancedSettingsOverridesMap := item.(map[string]interface{}) + instanceAdvancedSettings := tke.InstanceAdvancedSettings{} + if v, ok := instanceAdvancedSettingsOverridesMap["mount_target"]; ok { + instanceAdvancedSettings.MountTarget = helper.String(v.(string)) } - return nil - }) - } - if err != nil { - return nil - } - if !has { - d.SetId("") - return nil + if v, ok := instanceAdvancedSettingsOverridesMap["data_disk"]; ok { + for _, item := range v.([]interface{}) { + dataDisksMap := item.(map[string]interface{}) + dataDisk := tke.DataDisk{} + if v, ok := dataDisksMap["disk_type"]; ok { + dataDisk.DiskType = helper.String(v.(string)) + } + if v, ok := dataDisksMap["file_system"]; ok { + dataDisk.FileSystem = helper.String(v.(string)) + } + if v, ok := dataDisksMap["auto_format_and_mount"]; ok { + dataDisk.AutoFormatAndMount = helper.Bool(v.(bool)) + } + if v, ok := dataDisksMap["mount_target"]; ok { + dataDisk.MountTarget = helper.String(v.(string)) + } + if v, ok := dataDisksMap["disk_partition"]; ok { + dataDisk.DiskPartition = helper.String(v.(string)) + } + if v, ok := dataDisksMap["disk_size"]; ok { + dataDisk.DiskSize = helper.IntInt64(v.(int)) + } + instanceAdvancedSettings.DataDisks = append(instanceAdvancedSettings.DataDisks, &dataDisk) + } + } + if v, ok := instanceAdvancedSettingsOverridesMap["user_data"]; ok { + instanceAdvancedSettings.UserScript = helper.String(v.(string)) + } + if v, ok := instanceAdvancedSettingsOverridesMap["pre_start_user_script"]; ok { + instanceAdvancedSettings.PreStartUserScript = helper.String(v.(string)) + } + if v, ok := instanceAdvancedSettingsOverridesMap["docker_graph_path"]; ok { + instanceAdvancedSettings.DockerGraphPath = helper.String(v.(string)) + } + if v, ok := instanceAdvancedSettingsOverridesMap["desired_pod_num"]; ok { + instanceAdvancedSettings.DesiredPodNumber = helper.IntInt64(v.(int)) + } + if gPUArgsMap, ok := helper.ConvertInterfacesHeadToMap(instanceAdvancedSettingsOverridesMap["gpu_args"]); ok { + gPUArgs2 := tke.GPUArgs{} + if v, ok := gPUArgsMap["mig_enable"]; ok { + gPUArgs2.MIGEnable = helper.Bool(v.(bool)) + } + instanceAdvancedSettings.GPUArgs = &gPUArgs2 + } + if v, ok := d.GetOkExists("unschedulable"); ok { + instanceAdvancedSettings.Unschedulable = helper.IntInt64(v.(int)) + } + request.InstanceAdvancedSettingsOverrides = append(request.InstanceAdvancedSettingsOverrides, &instanceAdvancedSettings) + } } - /*cvm has been deleted*/ - var instance *cvm.Instance - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, err = cvmService.DescribeInstanceById(ctx, instanceId) - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) - } - return nil - }) - if err != nil { + if err := resourceTencentCloudKubernetesClusterAttachmentCreatePostFillRequest0(ctx, request); err != nil { return err } - if instance == nil { - d.SetId("") - return nil - } - - instanceState := "" - has = false - /*attachment has been deleted*/ - - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, workers, err := tkeService.DescribeClusterInstances(ctx, clusterId) - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) - } - for _, worker := range workers { - if worker.InstanceId == instanceId { - has = true - instanceState = worker.InstanceState - if worker.InstanceState == "failed" { - return resource.NonRetryableError(fmt.Errorf("cvm instance %s attach to cluster %s fail,reason:%s", - worker.InstanceId, clusterId, worker.FailedReason)) - } - if worker.InstanceState != "running" { - return resource.RetryableError(fmt.Errorf("cvm instance %s in tke status is %s, retry...", - worker.InstanceId, worker.InstanceState)) - } - _ = d.Set("unschedulable", worker.InstanceAdvancedSettings.Unschedulable) - } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().AddExistedInstancesWithContext(ctx, request) + if e != nil { + return resourceTencentCloudKubernetesClusterAttachmentCreateRequestOnError0(ctx, request, e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) } - + response = result return nil }) - if err != nil { + log.Printf("[CRITAL]%s create kubernetes cluster attachment failed, reason:%+v", logId, err) return err } - if !has { - d.SetId("") - return nil - } + _ = response - if len(instance.LoginSettings.KeyIds) > 0 { - _ = d.Set("key_ids", instance.LoginSettings.KeyIds) + if err := resourceTencentCloudKubernetesClusterAttachmentCreatePostHandleResponse0(ctx, response); err != nil { + return err } - _ = d.Set("security_groups", helper.StringsInterfaces(instance.SecurityGroupIds)) - _ = d.Set("state", instanceState) - return nil + d.SetId(strings.Join([]string{instanceId, clusterId}, "_")) + + return resourceTencentCloudKubernetesClusterAttachmentRead(d, meta) } -func resourceTencentCloudTkeClusterAttachmentCreate(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_cluster_attachment.create")() +func resourceTencentCloudKubernetesClusterAttachmentRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_cluster_attachment.read")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - - tkeService := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - cvmService := svccvm.NewCvmService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) - - request := tke.NewAddExistedInstancesRequest() - instanceId := helper.String(d.Get("instance_id").(string)) - request.ClusterId = helper.String(d.Get("cluster_id").(string)) - request.InstanceIds = []*string{instanceId} - request.LoginSettings = &tke.LoginSettings{} - - var loginSettingsNumbers = 0 - - if v, ok := d.GetOk("key_ids"); ok { - request.LoginSettings.KeyIds = helper.Strings(helper.InterfacesStrings(v.([]interface{}))) - loginSettingsNumbers++ - } + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - if v, ok := d.GetOk("password"); ok { - request.LoginSettings.Password = helper.String(v.(string)) - loginSettingsNumbers++ - } + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - if loginSettingsNumbers != 1 { - return fmt.Errorf("parameters `key_ids` and `password` must set and only set one") + idSplit := strings.Split(d.Id(), "_") + if len(idSplit) != 2 { + return fmt.Errorf("id is broken,%s", d.Id()) } + instanceId := idSplit[0] + clusterId := idSplit[1] - request.InstanceAdvancedSettings = &tke.InstanceAdvancedSettings{} - if workConfig, ok := d.GetOk("worker_config"); ok { - workConfigList := workConfig.([]interface{}) - if len(workConfigList) == 1 { - workConfigPara := workConfigList[0].(map[string]interface{}) - setting := tkeGetInstanceAdvancedPara(workConfigPara, meta) - request.InstanceAdvancedSettings = &setting - } - } + _ = d.Set("instance_id", instanceId) - request.InstanceAdvancedSettings.Labels = GetTkeLabels(d, "labels") - if hostName, ok := d.GetOk("hostname"); ok { - hostNameStr := hostName.(string) - request.HostName = &hostNameStr - } + _ = d.Set("cluster_id", clusterId) - if v, ok := d.GetOk("unschedulable"); ok { - request.InstanceAdvancedSettings.Unschedulable = helper.Int64(v.(int64)) + respData, err := service.DescribeKubernetesClusterAttachmentById(ctx, clusterId) + if err != nil { + return err } - if workConfigOverrides, ok := d.GetOk("worker_config_overrides"); ok { - workConfigOverrideList := workConfigOverrides.([]interface{}) - request.InstanceAdvancedSettingsOverrides = make([]*tke.InstanceAdvancedSettings, 0, len(workConfigOverrideList)) - for _, conf := range workConfigOverrideList { - workConfigPara := conf.(map[string]interface{}) - setting := tkeGetInstanceAdvancedPara(workConfigPara, meta) - request.InstanceAdvancedSettingsOverrides = append(request.InstanceAdvancedSettingsOverrides, &setting) - } + if respData == nil { + d.SetId("") + log.Printf("[WARN]%s resource `kubernetes_cluster_attachment` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil } - /*cvm has been attached*/ - var err error - _, workers, err := tkeService.DescribeClusterInstances(ctx, *request.ClusterId) - if err != nil { - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, workers, err = tkeService.DescribeClusterInstances(ctx, *request.ClusterId) - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) - } - return nil - }) - } + respData1, err := service.DescribeKubernetesClusterAttachmentById1(ctx, instanceId) if err != nil { return err } - has := false - for _, worker := range workers { - if worker.InstanceId == *instanceId { - has = true - } - } - if has { - return fmt.Errorf("instance %s has been attached to cluster %s,can not attach again", *instanceId, *request.ClusterId) - } - - var response *tke.AddExistedInstancesResponse - - if err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - ratelimit.Check(request.GetAction()) - response, err = tkeService.client.UseTkeClient().AddExistedInstances(request) - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) - } + if respData1 == nil { + d.SetId("") + log.Printf("[WARN]%s resource `kubernetes_cluster_attachment` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil - }); err != nil { - return fmt.Errorf("add existed instance %s to cluster %s error,reason %v", *instanceId, *request.ClusterId, err) } - var success = false - for _, v := range response.Response.SuccInstanceIds { - if *v == *instanceId { - d.SetId(*instanceId + "_" + *request.ClusterId) - success = true + if respData1.LoginSettings != nil { + if respData1.LoginSettings.KeyIds != nil { + _ = d.Set("key_ids", respData1.LoginSettings.KeyIds) } + } - if !success { - return fmt.Errorf("add existed instance %s to cluster %s error, instance not in success instanceIds", *instanceId, *request.ClusterId) + if respData1.SecurityGroupIds != nil { + _ = d.Set("security_groups", respData1.SecurityGroupIds) } - /*wait for cvm status*/ - if err = resource.Retry(7*tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, *instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) + var respData2 *tke.Instance + reqErr2 := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeKubernetesClusterAttachmentById2(ctx, instanceId, clusterId) + if e != nil { + return resourceTencentCloudKubernetesClusterAttachmentReadRequestOnError2(ctx, result, e) } - if instance != nil && *instance.InstanceState == svccvm.CVM_STATUS_RUNNING { - return nil + if err := resourceTencentCloudKubernetesClusterAttachmentReadRequestOnSuccess2(ctx, result); err != nil { + return err } - return resource.RetryableError(fmt.Errorf("cvm instance %s status is %s, retry...", *instanceId, *instance.InstanceState)) - }); err != nil { - return err + respData2 = result + return nil + }) + if reqErr2 != nil { + log.Printf("[CRITAL]%s read kubernetes cluster attachment failed, reason:%+v", logId, reqErr2) + return reqErr2 } - /*wait for tke init ok */ - err = resource.Retry(7*tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, workers, err = tkeService.DescribeClusterInstances(ctx, *request.ClusterId) - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) + if respData2 == nil { + d.SetId("") + log.Printf("[WARN]%s resource `kubernetes_cluster_attachment` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil + } + if respData2.InstanceAdvancedSettings != nil { + if respData2.InstanceAdvancedSettings.Unschedulable != nil { + _ = d.Set("unschedulable", respData2.InstanceAdvancedSettings.Unschedulable) } - has := false - for _, worker := range workers { - if worker.InstanceId == *instanceId { - has = true - if worker.InstanceState == "failed" { - return resource.NonRetryableError(fmt.Errorf("cvm instance %s attach to cluster %s fail,reason:%s", - *instanceId, *request.ClusterId, worker.FailedReason)) - } - - if worker.InstanceState != "running" { - return resource.RetryableError(fmt.Errorf("cvm instance %s in tke status is %s, retry...", - *instanceId, worker.InstanceState)) - } - } - } - if !has { - return resource.NonRetryableError(fmt.Errorf("cvm instance %s not exist in tke instance list", *instanceId)) - } - return nil - }) + } - if err != nil { - return err + if respData2.InstanceState != nil { + _ = d.Set("state", respData2.InstanceState) } - return resourceTencentCloudTkeClusterAttachmentRead(d, meta) + return nil } -func resourceTencentCloudTkeClusterAttachmentDelete(d *schema.ResourceData, meta interface{}) error { +func resourceTencentCloudKubernetesClusterAttachmentDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_cluster_attachment.delete")() + defer tccommon.InconsistentCheck(d, meta)() - tkeService := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - instanceId, clusterId := "", "" + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - if items := strings.Split(d.Id(), "_"); len(items) != 2 { - return fmt.Errorf("the resource id is corrupted") - } else { - instanceId, clusterId = items[0], items[1] + idSplit := strings.Split(d.Id(), "_") + if len(idSplit) != 2 { + return fmt.Errorf("id is broken,%s", d.Id()) } + instanceId := idSplit[0] + clusterId := idSplit[1] - request := tke.NewDeleteClusterInstancesRequest() + var ( + request = tke.NewDeleteClusterInstancesRequest() + response = tke.NewDeleteClusterInstancesResponse() + ) - request.ClusterId = &clusterId - request.InstanceIds = []*string{ - &instanceId, - } - request.InstanceDeleteMode = helper.String("retain") + request.ClusterId = helper.String(clusterId) - var err error + request.InstanceIds = []*string{helper.String(instanceId)} - if err = resource.Retry(4*tccommon.WriteRetryTimeout, func() *resource.RetryError { - _, err := tkeService.client.UseTkeClient().DeleteClusterInstances(request) - if e, ok := err.(*errors.TencentCloudSDKError); ok { - if e.GetCode() == "InternalError.ClusterNotFound" { - return nil - } - if e.GetCode() == "InternalError.Param" && - strings.Contains(e.GetMessage(), `PARAM_ERROR[some instances []is not in right state`) { - return nil - } - } + instanceDeleteMode := "retain" + request.InstanceDeleteMode = &instanceDeleteMode - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().DeleteClusterInstancesWithContext(ctx, request) + if e != nil { + return resourceTencentCloudKubernetesClusterAttachmentDeleteRequestOnError0(ctx, e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) } + response = result return nil - }); err != nil { + }) + if err != nil { + log.Printf("[CRITAL]%s delete kubernetes cluster attachment failed, reason:%+v", logId, err) return err } + + _ = response return nil } diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_cluster_attachment_extension.go b/tencentcloud/services/tke/resource_tc_kubernetes_cluster_attachment_extension.go new file mode 100644 index 0000000000..f47a78920f --- /dev/null +++ b/tencentcloud/services/tke/resource_tc_kubernetes_cluster_attachment_extension.go @@ -0,0 +1,555 @@ +package tke + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" + tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + svcas "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/as" + svccvm "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/cvm" +) + +func resourceTencentCloudKubernetesClusterAttachmentCreatePostFillRequest0(ctx context.Context, req *tke.AddExistedInstancesRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + if d == nil { + return fmt.Errorf("resource data can not be nil") + } + + var instanceId string + if v, ok := d.GetOk("instance_id"); ok { + instanceId = v.(string) + } + + // key_ids + var loginSettingsNumbers = 0 + if v, ok := d.GetOk("key_ids"); ok { + req.LoginSettings.KeyIds = helper.Strings(helper.InterfacesStrings(v.([]interface{}))) + loginSettingsNumbers++ + } + // password + if req.LoginSettings.Password != nil { + loginSettingsNumbers++ + } + if loginSettingsNumbers != 1 { + return fmt.Errorf("parameters `key_ids` and `password` must set and only set one") + } + + // labels + req.InstanceAdvancedSettings.Labels = GetTkeLabels(d, "labels") + + if dMap, ok := helper.InterfacesHeadMap(d, "worker_config"); ok { + completeInstanceAdvancedSettings(dMap, req.InstanceAdvancedSettings) + } + if v, ok := d.GetOk("worker_config_overrides"); ok { + for i, item := range v.([]interface{}) { + dMap := item.(map[string]interface{}) + completeInstanceAdvancedSettings(dMap, req.InstanceAdvancedSettingsOverrides[i]) + } + } + + // 检查是否已经绑定 + if hasAttached, err := nodeHasAttachedToCluster(ctx, instanceId, *req.ClusterId); err != nil { + return err + } else if hasAttached { + return fmt.Errorf("instance %s has been attached to cluster %s,can not attach again", instanceId, *req.ClusterId) + } + + return nil +} + +func resourceTencentCloudKubernetesClusterAttachmentCreateRequestOnError0(ctx context.Context, req *tke.AddExistedInstancesRequest, e error) *resource.RetryError { + return tccommon.RetryError(e, tccommon.InternalError) +} + +func resourceTencentCloudKubernetesClusterAttachmentCreatePostHandleResponse0(ctx context.Context, resp *tke.AddExistedInstancesResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + if d == nil { + return fmt.Errorf("resource data can not be nil") + } + + var instanceId string + if v, ok := d.GetOk("instance_id"); ok { + instanceId = v.(string) + } + var clusterId string + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) + } + + meta := tccommon.ProviderMetaFromContext(ctx) + if meta == nil { + return fmt.Errorf("provider meta can not be nil") + } + tkeService := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + cvmService := svccvm.NewCvmService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + + // 检查响应 + var success = false + for _, v := range resp.Response.SuccInstanceIds { + if *v == instanceId { + success = true + } + } + if !success { + return fmt.Errorf("add existed instance %s to cluster %s error, instance not in success instanceIds", instanceId, clusterId) + } + + /*wait for cvm status*/ + if err := resource.Retry(7*tccommon.ReadRetryTimeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance != nil && *instance.InstanceState == svccvm.CVM_STATUS_RUNNING { + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance %s status is %s, retry...", instanceId, *instance.InstanceState)) + }); err != nil { + return err + } + + /*wait for tke init ok */ + return resource.Retry(7*tccommon.ReadRetryTimeout, func() *resource.RetryError { + _, workers, err := tkeService.DescribeClusterInstances(ctx, clusterId) + if err != nil { + return tccommon.RetryError(err, tccommon.InternalError) + } + has := false + for _, worker := range workers { + if worker.InstanceId == instanceId { + has = true + if worker.InstanceState == "failed" { + return resource.NonRetryableError(fmt.Errorf("cvm instance %s attach to cluster %s fail,reason:%s", + instanceId, clusterId, worker.FailedReason)) + } + + if worker.InstanceState != "running" { + return resource.RetryableError(fmt.Errorf("cvm instance %s in tke status is %s, retry...", + instanceId, worker.InstanceState)) + } + + } + } + if !has { + return resource.NonRetryableError(fmt.Errorf("cvm instance %s not exist in tke instance list", instanceId)) + } + return nil + }) +} + +func resourceTencentCloudKubernetesClusterAttachmentDeleteRequestOnError0(ctx context.Context, e error) *resource.RetryError { + if sdkErr, ok := e.(*errors.TencentCloudSDKError); ok { + if sdkErr.GetCode() == "InternalError.ClusterNotFound" { + return nil + } + if sdkErr.GetCode() == "InternalError.Param" && + strings.Contains(sdkErr.GetMessage(), `PARAM_ERROR[some instances []is not in right state`) { + return nil + } + } + return tccommon.RetryError(e, tccommon.InternalError) +} + +func resourceTencentCloudKubernetesClusterAttachmentReadRequestOnError2(ctx context.Context, resp *tke.Instance, e error) *resource.RetryError { + return tccommon.RetryError(e, tccommon.InternalError) +} + +func resourceTencentCloudKubernetesClusterAttachmentReadRequestOnSuccess2(ctx context.Context, resp *tke.Instance) *resource.RetryError { + if resp == nil { + return nil + } + var insID string + if resp.InstanceId != nil { + insID = *resp.InstanceId + } + var insState string + if resp.InstanceState != nil { + insState = *resp.InstanceState + } + + if insState == "failed" { + return resource.NonRetryableError(fmt.Errorf( + "cvm instance %s attach to cluster fail, reason: %s", + insID, insState, + )) + } + + if insState != "running" { + return resource.RetryableError(fmt.Errorf( + "cvm instance %s in tke status is %s, retry...", + insID, insState, + )) + } + + return nil +} + +// nodeHasAttachedToCluster 判断节点是否已经绑定集群 +func nodeHasAttachedToCluster(ctx context.Context, insID, clsID string) (bool, error) { + meta := tccommon.ProviderMetaFromContext(ctx) + if meta == nil { + return false, fmt.Errorf("provider meta can not be nil") + } + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + var err error + _, workers, err := service.DescribeClusterInstances(ctx, clsID) + if err != nil { + err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + _, workers, err = service.DescribeClusterInstances(ctx, clsID) + if err != nil { + return tccommon.RetryError(err, tccommon.InternalError) + } + return nil + }) + } + if err != nil { + return false, err + } + + for _, worker := range workers { + if worker.InstanceId == insID { + return true, nil + } + } + return false, nil +} + +func completeInstanceAdvancedSettings(dMap map[string]interface{}, setting *tke.InstanceAdvancedSettings) { + // 去除不合法的磁盘大小 + for i, disk := range setting.DataDisks { + if disk.DiskSize != nil && *disk.DiskSize <= 0 { + setting.DataDisks[i].DiskSize = nil + } + } + + // is_schedule + if v, ok := dMap["is_schedule"]; ok { + setting.Unschedulable = helper.BoolToInt64Ptr(!v.(bool)) + } + + // extra_args + if temp, ok := dMap["extra_args"]; ok { + extraArgs := helper.InterfacesStrings(temp.([]interface{})) + clusterExtraArgs := tke.InstanceExtraArgs{} + clusterExtraArgs.Kubelet = make([]*string, 0) + for i := range extraArgs { + clusterExtraArgs.Kubelet = append(clusterExtraArgs.Kubelet, &extraArgs[i]) + } + setting.ExtraArgs = &clusterExtraArgs + } + + if v, ok := dMap["gpu_args"]; ok && len(v.([]interface{})) > 0 { + gpuArgs := v.([]interface{})[0].(map[string]interface{}) + + driver := gpuArgs["driver"].(map[string]interface{}) + if len(driver) > 0 { + setting.GPUArgs.Driver = &tke.DriverVersion{ + Version: helper.String(driver["version"].(string)), + Name: helper.String(driver["name"].(string)), + } + } + + cuda := gpuArgs["cuda"].(map[string]interface{}) + if len(cuda) > 0 { + setting.GPUArgs.CUDA = &tke.DriverVersion{ + Version: helper.String(cuda["version"].(string)), + Name: helper.String(cuda["name"].(string)), + } + } + + cudnn := gpuArgs["cudnn"].(map[string]interface{}) + if len(cudnn) > 0 { + setting.GPUArgs.CUDNN = &tke.CUDNN{ + Version: helper.String(cudnn["version"].(string)), + Name: helper.String(cudnn["name"].(string)), + } + if cudnn["doc_name"] != nil { + setting.GPUArgs.CUDNN.DocName = helper.String(cudnn["doc_name"].(string)) + } + if cudnn["dev_name"] != nil { + setting.GPUArgs.CUDNN.DevName = helper.String(cudnn["dev_name"].(string)) + } + } + + customDriver := gpuArgs["custom_driver"].(map[string]interface{}) + if len(customDriver) > 0 { + setting.GPUArgs.CustomDriver = &tke.CustomDriver{ + Address: helper.String(customDriver["address"].(string)), + } + } + } +} + +func TKEGpuArgsSetting() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "mig_enable": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to enable MIG.", + }, + "driver": { + Type: schema.TypeMap, + Optional: true, + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + Description: "GPU driver version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", + }, + "cuda": { + Type: schema.TypeMap, + Optional: true, + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + Description: "CUDA version. Format like: `{ version: String, name: String }`. `version`: Version of GPU driver or CUDA; `name`: Name of GPU driver or CUDA.", + }, + "cudnn": { + Type: schema.TypeMap, + Optional: true, + ValidateFunc: tccommon.ValidateTkeGpuDriverVersion, + Description: "cuDNN version. Format like: `{ version: String, name: String, doc_name: String, dev_name: String }`." + + " `version`: cuDNN version; `name`: cuDNN name; `doc_name`: Doc name of cuDNN; `dev_name`: Dev name of cuDNN.", + }, + "custom_driver": { + Type: schema.TypeMap, + Optional: true, + Description: "Custom GPU driver. Format like: `{address: String}`. `address`: URL of custom GPU driver address.", + }, + } +} + +func TkeInstanceAdvancedSetting() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Mount target. Default is not mounting.", + }, + "docker_graph_path": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "/var/lib/docker", + Description: "Docker graph path. Default is `/var/lib/docker`.", + }, + "data_disk": { + Type: schema.TypeList, + ForceNew: true, + Optional: true, + MaxItems: 11, + Description: "Configurations of data disk.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disk_type": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Default: svcas.SYSTEM_DISK_TYPE_CLOUD_PREMIUM, + ValidateFunc: tccommon.ValidateAllowedStringValue(svcas.SYSTEM_DISK_ALLOW_TYPE), + Description: "Types of disk. Valid value: `LOCAL_BASIC`, `LOCAL_SSD`, `CLOUD_BASIC`, `CLOUD_PREMIUM`, `CLOUD_SSD`, `CLOUD_HSSD`, `CLOUD_TSSD` and `CLOUD_BSSD`.", + }, + "disk_size": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Default: 0, + Description: "Volume of disk in GB. Default is `0`.", + }, + "file_system": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Default: "", + Description: "File system, e.g. `ext3/ext4/xfs`.", + }, + "auto_format_and_mount": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: false, + Description: "Indicate whether to auto format and mount or not. Default is `false`.", + }, + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "", + Description: "Mount target.", + }, + "disk_partition": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: "The name of the device or partition to mount. NOTE: this argument doesn't support setting in node pool, or will leads to mount error.", + }, + }, + }, + }, + "extra_args": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Custom parameter information related to the node. This is a white-list parameter.", + }, + "user_data": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: "Base64-encoded User Data text, the length limit is 16KB.", + }, + "pre_start_user_script": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: "Base64-encoded user script, executed before initializing the node, currently only effective for adding existing nodes.", + }, + "is_schedule": { + Type: schema.TypeBool, + ForceNew: true, + Optional: true, + Default: true, + Description: "Indicate to schedule the adding node or not. Default is true.", + }, + "desired_pod_num": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Description: "Indicate to set desired pod number in node. valid when the cluster is podCIDR.", + }, + "gpu_args": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: TKEGpuArgsSetting(), + }, + Description: "GPU driver parameters.", + }, + } +} + +func tkeGetInstanceAdvancedPara(dMap map[string]interface{}, meta interface{}) (setting tke.InstanceAdvancedSettings) { + setting = tke.InstanceAdvancedSettings{} + if v, ok := dMap["mount_target"]; ok { + setting.MountTarget = helper.String(v.(string)) + } + + if v, ok := dMap["data_disk"]; ok { + dataDisks := v.([]interface{}) + setting.DataDisks = make([]*tke.DataDisk, len(dataDisks)) + for i, d := range dataDisks { + value := d.(map[string]interface{}) + var diskType, fileSystem, mountTarget, diskPartition string + if v, ok := value["disk_type"].(string); ok { + diskType = v + } + if v, ok := value["file_system"].(string); ok { + fileSystem = v + } + if v, ok := value["mount_target"].(string); ok { + mountTarget = v + } + if v, ok := value["disk_partition"].(string); ok { + diskPartition = v + } + + diskSize := int64(value["disk_size"].(int)) + autoFormatAndMount := value["auto_format_and_mount"].(bool) + dataDisk := &tke.DataDisk{ + DiskType: &diskType, + FileSystem: &fileSystem, + AutoFormatAndMount: &autoFormatAndMount, + MountTarget: &mountTarget, + DiskPartition: &diskPartition, + } + if diskSize > 0 { + dataDisk.DiskSize = &diskSize + } + setting.DataDisks[i] = dataDisk + } + } + if v, ok := dMap["is_schedule"]; ok { + setting.Unschedulable = helper.BoolToInt64Ptr(!v.(bool)) + } + + if v, ok := dMap["user_data"]; ok { + setting.UserScript = helper.String(v.(string)) + } + + if v, ok := dMap["pre_start_user_script"]; ok { + setting.PreStartUserScript = helper.String(v.(string)) + } + + if v, ok := dMap["docker_graph_path"]; ok { + setting.DockerGraphPath = helper.String(v.(string)) + } + + if v, ok := dMap["desired_pod_num"]; ok { + setting.DesiredPodNumber = helper.Int64(int64(v.(int))) + } + + if temp, ok := dMap["extra_args"]; ok { + extraArgs := helper.InterfacesStrings(temp.([]interface{})) + clusterExtraArgs := tke.InstanceExtraArgs{} + clusterExtraArgs.Kubelet = make([]*string, 0) + for i := range extraArgs { + clusterExtraArgs.Kubelet = append(clusterExtraArgs.Kubelet, &extraArgs[i]) + } + setting.ExtraArgs = &clusterExtraArgs + } + + // get gpu_args + if v, ok := dMap["gpu_args"]; ok && len(v.([]interface{})) > 0 { + gpuArgs := v.([]interface{})[0].(map[string]interface{}) + + var ( + migEnable = gpuArgs["mig_enable"].(bool) + driver = gpuArgs["driver"].(map[string]interface{}) + cuda = gpuArgs["cuda"].(map[string]interface{}) + cudnn = gpuArgs["cudnn"].(map[string]interface{}) + customDriver = gpuArgs["custom_driver"].(map[string]interface{}) + ) + tkeGpuArgs := tke.GPUArgs{} + tkeGpuArgs.MIGEnable = &migEnable + if len(driver) > 0 { + tkeGpuArgs.Driver = &tke.DriverVersion{ + Version: helper.String(driver["version"].(string)), + Name: helper.String(driver["name"].(string)), + } + } + if len(cuda) > 0 { + tkeGpuArgs.CUDA = &tke.DriverVersion{ + Version: helper.String(cuda["version"].(string)), + Name: helper.String(cuda["name"].(string)), + } + } + if len(cudnn) > 0 { + tkeGpuArgs.CUDNN = &tke.CUDNN{ + Version: helper.String(cudnn["version"].(string)), + Name: helper.String(cudnn["name"].(string)), + } + if cudnn["doc_name"] != nil { + tkeGpuArgs.CUDNN.DocName = helper.String(cudnn["doc_name"].(string)) + } + if cudnn["dev_name"] != nil { + tkeGpuArgs.CUDNN.DevName = helper.String(cudnn["dev_name"].(string)) + } + } + if len(customDriver) > 0 { + tkeGpuArgs.CustomDriver = &tke.CustomDriver{ + Address: helper.String(customDriver["address"].(string)), + } + } + setting.GPUArgs = &tkeGpuArgs + } + + return setting +} diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_encryption_protection.go b/tencentcloud/services/tke/resource_tc_kubernetes_encryption_protection.go index 63dc866645..1526479a0f 100644 --- a/tencentcloud/services/tke/resource_tc_kubernetes_encryption_protection.go +++ b/tencentcloud/services/tke/resource_tc_kubernetes_encryption_protection.go @@ -1,16 +1,15 @@ +// Code generated by iacg; DO NOT EDIT. package tke import ( "context" "log" - "time" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -21,16 +20,16 @@ func ResourceTencentCloudKubernetesEncryptionProtection() *schema.Resource { Delete: resourceTencentCloudKubernetesEncryptionProtectionDelete, Schema: map[string]*schema.Schema{ "cluster_id": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "cluster id.", }, "kms_configuration": { + Type: schema.TypeList, Required: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "kms encryption configuration.", Elem: &schema.Resource{ @@ -48,9 +47,10 @@ func ResourceTencentCloudKubernetesEncryptionProtection() *schema.Resource { }, }, }, + "status": { - Computed: true, Type: schema.TypeString, + Computed: true, Description: "kms encryption status.", }, }, @@ -58,106 +58,131 @@ func ResourceTencentCloudKubernetesEncryptionProtection() *schema.Resource { } func resourceTencentCloudKubernetesEncryptionProtectionCreate(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_tke_encryption_protection.create")() + defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_encryption_protection.create")() defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + var ( - request = tke.NewEnableEncryptionProtectionRequest() clusterId string ) + var ( + request = tke.NewEnableEncryptionProtectionRequest() + response = tke.NewEnableEncryptionProtectionResponse() + ) + if v, ok := d.GetOk("cluster_id"); ok { - request.ClusterId = helper.String(v.(string)) clusterId = v.(string) } - if dMap, ok := helper.InterfacesHeadMap(d, "kms_configuration"); ok { + if v, ok := d.GetOk("cluster_id"); ok { + request.ClusterId = helper.String(v.(string)) + } + + if kMSConfigurationMap, ok := helper.InterfacesHeadMap(d, "kms_configuration"); ok { kMSConfiguration := tke.KMSConfiguration{} - if v, ok := dMap["key_id"]; ok { + if v, ok := kMSConfigurationMap["key_id"]; ok { kMSConfiguration.KeyId = helper.String(v.(string)) } - if v, ok := dMap["kms_region"]; ok { + if v, ok := kMSConfigurationMap["kms_region"]; ok { kMSConfiguration.KmsRegion = helper.String(v.(string)) } request.KMSConfiguration = &kMSConfiguration } err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().EnableEncryptionProtection(request) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().EnableEncryptionProtectionWithContext(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()) } + response = result return nil }) if err != nil { - log.Printf("[CRITAL]%s create tke encryptionProtection failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s create kubernetes encryption protection failed, reason:%+v", logId, err) return err } - d.SetId(clusterId) - - service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - - conf := tccommon.BuildStateChangeConf([]string{}, []string{"Opened"}, 3*tccommon.ReadRetryTimeout, time.Second, service.TkeEncryptionProtectionStateRefreshFunc(d.Id(), []string{})) + _ = response - if _, e := conf.WaitForState(); e != nil { - return e + if err := resourceTencentCloudKubernetesEncryptionProtectionCreatePostHandleResponse0(ctx, response); err != nil { + return err } + d.SetId(clusterId) + return resourceTencentCloudKubernetesEncryptionProtectionRead(d, meta) } func resourceTencentCloudKubernetesEncryptionProtectionRead(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_tke_encryption_protection.read")() + defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_encryption_protection.read")() defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - encryptionProtectionId := d.Id() + clusterId := d.Id() + + _ = d.Set("cluster_id", clusterId) - encryptionProtection, err := service.DescribeTkeEncryptionProtectionById(ctx, encryptionProtectionId) + respData, err := service.DescribeKubernetesEncryptionProtectionById(ctx, clusterId) if err != nil { return err } - if encryptionProtection == nil { + if respData == nil { d.SetId("") - log.Printf("[WARN]%s resource `TkeEncryptionProtection` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + log.Printf("[WARN]%s resource `kubernetes_encryption_protection` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } - - if encryptionProtection.Status != nil { - _ = d.Set("status", encryptionProtection.Status) + if respData.Status != nil { + _ = d.Set("status", respData.Status) } return nil } func resourceTencentCloudKubernetesEncryptionProtectionDelete(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_tke_encryption_protection.delete")() + defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_encryption_protection.delete")() defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - encryptionProtectionId := d.Id() + clusterId := d.Id() + + var ( + request = tke.NewDisableEncryptionProtectionRequest() + response = tke.NewDisableEncryptionProtectionResponse() + ) + + request.ClusterId = helper.String(clusterId) - if err := service.DeleteTkeEncryptionProtectionById(ctx, encryptionProtectionId); err != nil { + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().DisableEncryptionProtectionWithContext(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()) + } + response = result + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s delete kubernetes encryption protection failed, reason:%+v", logId, err) return err } - conf := tccommon.BuildStateChangeConf([]string{}, []string{"Closed"}, 3*tccommon.ReadRetryTimeout, time.Second, service.TkeEncryptionProtectionStateRefreshFunc(d.Id(), []string{})) - - if _, e := conf.WaitForState(); e != nil { - return e + _ = response + if err := resourceTencentCloudKubernetesEncryptionProtectionDeletePostHandleResponse0(ctx, response); err != nil { + return err } return nil diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_encryption_protection_extension.go b/tencentcloud/services/tke/resource_tc_kubernetes_encryption_protection_extension.go new file mode 100644 index 0000000000..e88c011263 --- /dev/null +++ b/tencentcloud/services/tke/resource_tc_kubernetes_encryption_protection_extension.go @@ -0,0 +1,67 @@ +package tke + +import ( + "context" + "fmt" + "time" + + tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" +) + +func resourceTencentCloudKubernetesEncryptionProtectionCreatePostHandleResponse0(ctx context.Context, resp *tke.EnableEncryptionProtectionResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + if d == nil { + return fmt.Errorf("resource data can not be nil") + } + + var clusterId string + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) + } + + meta := tccommon.ProviderMetaFromContext(ctx) + if meta == nil { + return fmt.Errorf("provider meta can not be nil") + } + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + conf := tccommon.BuildStateChangeConf( + []string{}, + []string{"Opened"}, + 3*tccommon.ReadRetryTimeout, + time.Second, + service.TkeEncryptionProtectionStateRefreshFunc(clusterId, []string{}), + ) + + if _, e := conf.WaitForState(); e != nil { + return e + } + return nil +} + +func resourceTencentCloudKubernetesEncryptionProtectionDeletePostHandleResponse0(ctx context.Context, resp *tke.DisableEncryptionProtectionResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + if d == nil { + return fmt.Errorf("resource data can not be nil") + } + meta := tccommon.ProviderMetaFromContext(ctx) + if meta == nil { + return fmt.Errorf("provider meta can not be nil") + } + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + conf := tccommon.BuildStateChangeConf( + []string{}, + []string{"Closed"}, + 3*tccommon.ReadRetryTimeout, + time.Second, + service.TkeEncryptionProtectionStateRefreshFunc(d.Id(), []string{}), + ) + + if _, e := conf.WaitForState(); e != nil { + return e + } + return nil +} diff --git a/tencentcloud/services/tke/service_tencentcloud_tke.go b/tencentcloud/services/tke/service_tencentcloud_tke.go index 2169fe08de..263b989e51 100644 --- a/tencentcloud/services/tke/service_tencentcloud_tke.go +++ b/tencentcloud/services/tke/service_tencentcloud_tke.go @@ -10,6 +10,7 @@ import ( svccvm "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/cvm" sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" cwp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cwp/v20180228" tat "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tat/v20201028" @@ -2998,3 +2999,155 @@ func (me *TkeService) DescribeKubernetesChartsByFilter(ctx context.Context, para ret = response.Response.AppCharts return } + +func (me *TkeService) DescribeKubernetesEncryptionProtectionById(ctx context.Context, clusterId string) (ret *tke.DescribeEncryptionStatusResponseParams, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := tke.NewDescribeEncryptionStatusRequest() + request.ClusterId = helper.String(clusterId) + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseTkeClient().DescribeEncryptionStatus(request) + if err != nil { + errRet = err + return + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + ret = response.Response + return +} + +func (me *TkeService) DescribeKubernetesClusterAttachmentById(ctx context.Context, clusterId string) (ret *tke.Cluster, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := tke.NewDescribeClustersRequest() + request.ClusterIds = []*string{helper.String(clusterId)} + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseTkeClient().DescribeClusters(request) + if err != nil { + errRet = err + return + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if len(response.Response.Clusters) < 1 { + return + } + + ret = response.Response.Clusters[0] + return +} + +func (me *TkeService) DescribeKubernetesClusterAttachmentById1(ctx context.Context, instanceId string) (ret *cvm.Instance, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := cvm.NewDescribeInstancesRequest() + request.InstanceIds = []*string{helper.String(instanceId)} + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseCvmClient().DescribeInstances(request) + if err != nil { + errRet = err + return + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if len(response.Response.InstanceSet) < 1 { + return + } + + ret = response.Response.InstanceSet[0] + return +} + +func (me *TkeService) DescribeKubernetesClusterAttachmentById2(ctx context.Context, instanceId string, clusterId string) (ret *tke.Instance, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := tke.NewDescribeClusterInstancesRequest() + request.ClusterId = helper.String(clusterId) + request.InstanceIds = []*string{helper.String(instanceId)} + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseTkeClient().DescribeClusterInstances(request) + if err != nil { + errRet = err + return + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if len(response.Response.InstanceSet) < 1 { + return + } + + for _, info := range response.Response.InstanceSet { + if info.InstanceId != nil && *info.InstanceId == instanceId { + ret = info + break + } + } + return +} + +func (me *TkeService) DescribeKubernetesBackupStorageLocationById(ctx context.Context, name string) (ret *tke.BackupStorageLocation, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := tke.NewDescribeBackupStorageLocationsRequest() + request.Names = []*string{helper.String(name)} + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseTkeClient().DescribeBackupStorageLocations(request) + if err != nil { + errRet = err + return + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if len(response.Response.BackupStorageLocationSet) < 1 { + return + } + + for _, info := range response.Response.BackupStorageLocationSet { + if info.Name != nil && *info.Name == name { + ret = info + break + } + } + return +}