diff --git a/.changelog/2581.txt b/.changelog/2581.txt new file mode 100644 index 0000000000..5ba9a67bdf --- /dev/null +++ b/.changelog/2581.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +tencentcloud_tse_cngw_network_access_control +``` \ No newline at end of file diff --git a/.changelog/2582.txt b/.changelog/2582.txt new file mode 100644 index 0000000000..4b169ef416 --- /dev/null +++ b/.changelog/2582.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/tencentcloud_vod_adaptive_dynamic_streaming_template: add param `segment_type` +``` + +```release-note:enhancement +resource/tencentcloud_vod_procedure_template: update param `adaptive_dynamic_streaming_task_list` and `review_audio_video_task` +``` \ No newline at end of file diff --git a/.changelog/2583.txt b/.changelog/2583.txt new file mode 100644 index 0000000000..e43e2ecc56 --- /dev/null +++ b/.changelog/2583.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +datasource/tencentcloud_mariadb_db_instances: Support `vip`, `vport`, `internet_domain`, `internet_ip`, `internet_port` field +``` diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ccc9d9c26..6a8ddb13ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## 1.81.87 (April 7, 2024) + +FEATURES: + +* **New Resource:** `tencentcloud_tse_cngw_network_access_control` ([#2581](https://github.com/tencentcloudstack/terraform-provider-tencentcloud/pull/2581)) + +ENHANCEMENTS: + +* datasource/tencentcloud_mariadb_db_instances: Support `vip`, `vport`, `internet_domain`, `internet_ip`, `internet_port` field ([#2583](https://github.com/tencentcloudstack/terraform-provider-tencentcloud/pull/2583)) +* resource/tencentcloud_kubernetes_cluster: Field `cluster_subnet_id` supports ForceNew ([#2578](https://github.com/tencentcloudstack/terraform-provider-tencentcloud/pull/2578)) +* resource/tencentcloud_vod_adaptive_dynamic_streaming_template: add param `segment_type` ([#2582](https://github.com/tencentcloudstack/terraform-provider-tencentcloud/pull/2582)) +* resource/tencentcloud_vod_procedure_template: update param `adaptive_dynamic_streaming_task_list` and `review_audio_video_task` ([#2582](https://github.com/tencentcloudstack/terraform-provider-tencentcloud/pull/2582)) + ## 1.81.86 (March 28, 2024) FEATURES: diff --git a/tencentcloud/acctest/basic.go b/tencentcloud/acctest/basic.go index c6b72d6799..90f716a68a 100644 --- a/tencentcloud/acctest/basic.go +++ b/tencentcloud/acctest/basic.go @@ -940,8 +940,8 @@ const ( DefaultMariadbVpcId = "vpc-k1t8ickr" DefaultMariadbSecurityGroupId = "sg-7kpsbxdb" - DefaultMariadbInstanceSubnetId = "subnet-4w4twlf4" - DefaultMariadbInstanceVpcId = "vpc-9m66acml" + DefaultMariadbInstanceSubnetId = "subnet-8fpt571a" + DefaultMariadbInstanceVpcId = "vpc-axrsmmrv" ) // End of MARIADB diff --git a/tencentcloud/common/context.go b/tencentcloud/common/context.go new file mode 100644 index 0000000000..e5458aa9b2 --- /dev/null +++ b/tencentcloud/common/context.go @@ -0,0 +1,39 @@ +package common + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +type ctxResourceDataKey struct{} +type ctxProviderMetaKey struct{} + +// NewResourceLifeCycleHandleFuncContext 创建一个资源生命周期处理方法上下文 +func NewResourceLifeCycleHandleFuncContext( + parent context.Context, + logID string, + d *schema.ResourceData, + meta interface{}, +) context.Context { + ctx := context.WithValue(parent, LogIdKey, logID) + ctx = context.WithValue(ctx, ctxResourceDataKey{}, d) + ctx = context.WithValue(ctx, ctxProviderMetaKey{}, meta) + return ctx +} + +// ResourceDataFromContext 从上下文获取资源数据 +func ResourceDataFromContext(ctx context.Context) *schema.ResourceData { + if d, ok := ctx.Value(ctxResourceDataKey{}).(*schema.ResourceData); ok { + return d + } + return nil +} + +// ProviderMetaFromContext 从上下文获取 provider meta +func ProviderMetaFromContext(ctx context.Context) interface{} { + if meta, ok := ctx.Value(ctxProviderMetaKey{}).(ProviderMeta); ok { + return meta + } + return nil +} diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 1e6aa3265f..6014591792 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -1117,7 +1117,7 @@ func Provider() *schema.Provider { "tencentcloud_kubernetes_addon_attachment": tke.ResourceTencentCloudTkeAddonAttachment(), "tencentcloud_kubernetes_auth_attachment": tke.ResourceTencentCloudTKEAuthAttachment(), "tencentcloud_kubernetes_as_scaling_group": tke.ResourceTencentCloudKubernetesAsScalingGroup(), - "tencentcloud_kubernetes_scale_worker": tke.ResourceTencentCloudTkeScaleWorker(), + "tencentcloud_kubernetes_scale_worker": tke.ResourceTencentCloudKubernetesScaleWorker(), "tencentcloud_kubernetes_cluster_attachment": tke.ResourceTencentCloudTkeClusterAttachment(), "tencentcloud_kubernetes_node_pool": tke.ResourceTencentCloudKubernetesNodePool(), "tencentcloud_kubernetes_serverless_node_pool": tke.ResourceTencentCloudTkeServerLessNodePool(), @@ -1850,6 +1850,7 @@ func Provider() *schema.Provider { "tencentcloud_tse_waf_protection": tse.ResourceTencentCloudTseWafProtection(), "tencentcloud_tse_waf_domains": tse.ResourceTencentCloudTseWafDomains(), "tencentcloud_tse_cngw_network": tse.ResourceTencentCloudTseCngwNetwork(), + "tencentcloud_tse_cngw_network_access_control": tse.ResourceTencentCloudTseCngwNetworkAccessControl(), "tencentcloud_tse_cngw_strategy": tse.ResourceTencentCloudTseCngwStrategy(), "tencentcloud_tse_cngw_strategy_bind_group": tse.ResourceTencentCloudTseCngwStrategyBindGroup(), "tencentcloud_clickhouse_instance": cdwch.ResourceTencentCloudClickhouseInstance(), diff --git a/tencentcloud/provider.md b/tencentcloud/provider.md index 3da5667232..dc3f36b513 100644 --- a/tencentcloud/provider.md +++ b/tencentcloud/provider.md @@ -1117,7 +1117,6 @@ Video on Demand(VOD) tencentcloud_vod_procedure_template tencentcloud_vod_snapshot_by_time_offset_template tencentcloud_vod_image_sprite_template - tencentcloud_vod_super_player_config tencentcloud_vod_sub_application tencentcloud_vod_sample_snapshot_template tencentcloud_vod_transcode_template @@ -1930,6 +1929,7 @@ Tencent Cloud Service Engine(TSE) tencentcloud_tse_cngw_network tencentcloud_tse_cngw_strategy tencentcloud_tse_cngw_strategy_bind_group + tencentcloud_tse_cngw_network_access_control ClickHouse(CDWCH) Data Source diff --git a/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances.go b/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances.go index 6697031159..6dd4c41834 100644 --- a/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances.go +++ b/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances.go @@ -110,6 +110,31 @@ func DataSourceTencentCloudMariadbDbInstances() *schema.Resource { Computed: true, Description: "db version id.", }, + "vip": { + Type: schema.TypeString, + Computed: true, + Description: "Intranet IP address.", + }, + "vport": { + Type: schema.TypeInt, + Computed: true, + Description: "Intranet port.", + }, + "internet_domain": { + Type: schema.TypeString, + Computed: true, + Description: "Public network access domain name.", + }, + "internet_ip": { + Type: schema.TypeString, + Computed: true, + Description: "Public IP address.", + }, + "internet_port": { + Type: schema.TypeInt, + Computed: true, + Description: "Public network port.", + }, "resource_tags": { Type: schema.TypeList, Computed: true, @@ -231,6 +256,21 @@ func dataSourceTencentCloudMariadbDbInstancesRead(d *schema.ResourceData, meta i if instance.DbVersionId != nil { instanceMap["db_version_id"] = instance.DbVersionId } + if instance.Vip != nil { + instanceMap["vip"] = instance.Vip + } + if instance.Vport != nil { + instanceMap["vport"] = instance.Vport + } + if instance.WanDomain != nil { + instanceMap["internet_domain"] = instance.WanDomain + } + if instance.WanVip != nil { + instanceMap["internet_ip"] = instance.WanVip + } + if instance.WanPort != nil { + instanceMap["internet_port"] = instance.WanPort + } if instance.ResourceTags != nil { resourceTagsList := []interface{}{} for _, resourceTags := range instance.ResourceTags { diff --git a/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances_test.go b/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances_test.go index d6faae65b2..cbe8cd48a2 100644 --- a/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances_test.go +++ b/tencentcloud/services/mariadb/data_source_tc_mariadb_db_instances_test.go @@ -20,14 +20,29 @@ func TestAccTencentCloudMariadbDbInstancesDataSource(t *testing.T) { Config: testAccDataSourceMariadbDbInstances, Check: resource.ComposeTestCheckFunc( tcacctest.AccCheckTencentCloudDataSourceID("data.tencentcloud_mariadb_db_instances.db_instances"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.#"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.instance_id"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.instance_name"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.project_id"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.region"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.zone"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.memory"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.storage"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.vpc_id"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.subnet_id"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.db_version_id"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.vip"), + resource.TestCheckResourceAttrSet("data.tencentcloud_mariadb_db_instances.db_instances", "instances.0.vport"), ), }, }, }) } -const testAccDataSourceMariadbDbInstances = ` +const testAccDataSourceMariadbDbInstances = testAccMariadbInstance + ` -data "tencentcloud_mariadb_db_instances" "db_instances" {} +data "tencentcloud_mariadb_db_instances" "db_instances" { + depends_on = [ tencentcloud_mariadb_instance.instance ] +} ` diff --git a/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions.go b/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions.go index 3394999395..77c676c451 100644 --- a/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions.go +++ b/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions.go @@ -77,82 +77,67 @@ func dataSourceTencentCloudKubernetesAvailableClusterVersionsRead(d *schema.Reso defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - - var ( - versions []*string - clusters []*tke.ClusterVersion - id *string - ids []string - ) + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} paramMap := make(map[string]interface{}) if v, ok := d.GetOk("cluster_id"); ok { - id = helper.String(v.(string)) - paramMap["cluster_id"] = id + paramMap["ClusterId"] = helper.String(v.(string)) } if v, ok := d.GetOk("cluster_ids"); ok { + clusterIdsList := []*string{} clusterIdsSet := v.(*schema.Set).List() - ids = helper.InterfacesStrings(clusterIdsSet) - paramMap["cluster_ids"] = helper.InterfacesStringsPoint(clusterIdsSet) + for i := range clusterIdsSet { + clusterIds := clusterIdsSet[i].(string) + clusterIdsList = append(clusterIdsList, helper.String(clusterIds)) + } + paramMap["ClusterIds"] = clusterIdsList } - service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - + var respData *tke.DescribeAvailableClusterVersionResponseParams err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { result, e := service.DescribeKubernetesAvailableClusterVersionsByFilter(ctx, paramMap) if e != nil { return tccommon.RetryError(e) } - if result != nil { - versions = result.Versions - clusters = result.Clusters - } + respData = result return nil }) if err != nil { return err } - if versions != nil { - _ = d.Set("versions", versions) + if respData.Versions != nil { + _ = d.Set("versions", respData.Versions) } - tmpList := make([]map[string]interface{}, 0, len(clusters)) - - if clusters != nil { - for _, clusterVersion := range clusters { - clusterVersionMap := map[string]interface{}{} + clustersList := make([]map[string]interface{}, 0, len(respData.Clusters)) + if respData.Clusters != nil { + for _, clusters := range respData.Clusters { + clustersMap := map[string]interface{}{} - if clusterVersion.ClusterId != nil { - clusterVersionMap["cluster_id"] = clusterVersion.ClusterId + if clusters.ClusterId != nil { + clustersMap["cluster_id"] = clusters.ClusterId } - if clusterVersion.Versions != nil { - clusterVersionMap["versions"] = clusterVersion.Versions + if clusters.Versions != nil { + clustersMap["versions"] = clusters.Versions } - tmpList = append(tmpList, clusterVersionMap) + clustersList = append(clustersList, clustersMap) } - _ = d.Set("clusters", tmpList) + _ = d.Set("clusters", clustersList) } - var clusterIds []string - if id != nil { - clusterIds = []string{*id} - } else { - clusterIds = ids - } - - d.SetId(helper.DataResourceIdsHash(clusterIds)) output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if e := tccommon.WriteToFile(output.(string), tmpList); e != nil { + if e := tccommon.WriteToFile(output.(string), dataSourceTencentCloudKubernetesAvailableClusterVersionsReadOutputContent(ctx)); e != nil { return e } } + return nil } diff --git a/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions_extension.go b/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions_extension.go new file mode 100644 index 0000000000..973f66932e --- /dev/null +++ b/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions_extension.go @@ -0,0 +1,41 @@ +package tke + +import ( + "context" + "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 dataSourceTencentCloudKubernetesAvailableClusterVersionsReadPostRequest0(ctx context.Context, req *tke.DescribeAvailableClusterVersionRequest, resp *tke.DescribeAvailableClusterVersionResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + + var ( + clusterIds []string + id *string + ids []string + ) + + if v, ok := d.GetOk("cluster_id"); ok { + id = helper.String(v.(string)) + } + + if v, ok := d.GetOk("cluster_ids"); ok { + clusterIdsSet := v.(*schema.Set).List() + ids = helper.InterfacesStrings(clusterIdsSet) + } + + if id != nil { + clusterIds = []string{*id} + } else { + clusterIds = ids + } + + d.SetId(helper.DataResourceIdsHash(clusterIds)) + return nil +} + +func dataSourceTencentCloudKubernetesAvailableClusterVersionsReadOutputContent(ctx context.Context) interface{} { + return "clustersList" +} diff --git a/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions_test.go b/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions_test.go index cb3582a9b0..952c80f98a 100644 --- a/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions_test.go +++ b/tencentcloud/services/tke/data_source_tc_kubernetes_available_cluster_versions_test.go @@ -1,7 +1,6 @@ package tke_test import ( - "fmt" "testing" tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" @@ -9,6 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) +// go test -i; go test -test.run TestAccTencentCloudKubernetesAvailableClusterVersionsDataSource_basic -v func TestAccTencentCloudKubernetesAvailableClusterVersionsDataSource_basic(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -18,7 +18,7 @@ func TestAccTencentCloudKubernetesAvailableClusterVersionsDataSource_basic(t *te Providers: tcacctest.AccProviders, Steps: []resource.TestStep{ { - Config: fmt.Sprintf(testAccKubernetesAvailableClusterVersionsDataSource_basic, tcacctest.DefaultTkeClusterId), + Config: testAccKubernetesAvailableClusterVersionsDataSource_basic, Check: resource.ComposeTestCheckFunc( tcacctest.AccCheckTencentCloudDataSourceID("data.tencentcloud_kubernetes_available_cluster_versions.id"), resource.TestCheckResourceAttrSet("data.tencentcloud_kubernetes_available_cluster_versions.id", "versions.#"), @@ -26,11 +26,11 @@ func TestAccTencentCloudKubernetesAvailableClusterVersionsDataSource_basic(t *te ), }, { - Config: fmt.Sprintf(testAccKubernetesAvailableClusterVersionsDataSource_multiple, tcacctest.DefaultTkeClusterId), + Config: testAccKubernetesAvailableClusterVersionsDataSource_multiple, Check: resource.ComposeTestCheckFunc( tcacctest.AccCheckTencentCloudDataSourceID("data.tencentcloud_kubernetes_available_cluster_versions.ids"), resource.TestCheckResourceAttrSet("data.tencentcloud_kubernetes_available_cluster_versions.ids", "clusters.#"), - resource.TestCheckResourceAttr("data.tencentcloud_kubernetes_available_cluster_versions.ids", "clusters.0.cluster_id", tcacctest.DefaultTkeClusterId), + resource.TestCheckResourceAttr("data.tencentcloud_kubernetes_available_cluster_versions.ids", "clusters.0.cluster_id", "cls-r8gqwjw6"), ), }, }, @@ -38,21 +38,13 @@ func TestAccTencentCloudKubernetesAvailableClusterVersionsDataSource_basic(t *te } const testAccKubernetesAvailableClusterVersionsDataSource_basic = ` - data "tencentcloud_kubernetes_available_cluster_versions" "id" { - cluster_id = "%s" -} - -output "versions"{ - value = data.tencentcloud_kubernetes_available_cluster_versions.id.versions + cluster_id = "cls-r8gqwjw6" } - ` const testAccKubernetesAvailableClusterVersionsDataSource_multiple = ` - data "tencentcloud_kubernetes_available_cluster_versions" "ids" { - cluster_ids = ["%s"] + cluster_ids = ["cls-r8gqwjw6"] } - ` diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker.go b/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker.go index 91a4200c9c..ec5da4cc08 100644 --- a/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker.go +++ b/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker.go @@ -1,652 +1,711 @@ 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" - "time" - "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" - - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "log" + "strings" ) -func ResourceTencentCloudTkeScaleWorker() *schema.Resource { +func ResourceTencentCloudKubernetesScaleWorker() *schema.Resource { return &schema.Resource{ - Create: resourceTencentCloudTkeScaleWorkerCreate, - Read: resourceTencentCloudTkeScaleWorkerRead, - Delete: resourceTencentCloudTkeScaleWorkerDelete, + Create: resourceTencentCloudKubernetesScaleWorkerCreate, + Read: resourceTencentCloudKubernetesScaleWorkerRead, + Delete: resourceTencentCloudKubernetesScaleWorkerDelete, Importer: &schema.ResourceImporter{ - StateContext: func(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { - importFlag = true - err := resourceTencentCloudTkeScaleWorkerRead(d, m) - if err != nil { - return nil, fmt.Errorf("failed to import resource") - } - - return []*schema.ResourceData{d}, nil - }, + StateContext: customResourceImporter, }, Schema: map[string]*schema.Schema{ "cluster_id": { Type: schema.TypeString, - ForceNew: true, Required: true, + ForceNew: true, Description: "ID of the cluster.", }, - "worker_config": { - Type: schema.TypeList, - ForceNew: true, - MaxItems: 1, - MinItems: 1, - Required: true, + + "data_disk": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 11, + Description: "Configurations of data disk.", Elem: &schema.Resource{ - Schema: TkeCvmCreateInfo(), + Schema: map[string]*schema.Schema{ + "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`.", + }, + "disk_size": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 0, + Description: "Volume of disk in GB. Default is `0`.", + }, + "disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "CLOUD_PREMIUM", + Description: "Types of disk, available values: `CLOUD_PREMIUM` and `CLOUD_SSD` and `CLOUD_HSSD` and `CLOUD_TSSD`.", + }, + "file_system": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "", + Description: "File system, e.g. `ext3/ext4/xfs`.", + }, + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "", + Description: "Mount target.", + }, + }, }, - Description: "Deploy the machine configuration information of the 'WORK' service, and create <=20 units for common users.", }, - //advanced instance settings - "labels": { - Type: schema.TypeMap, + + "desired_pod_num": { + Type: schema.TypeInt, Optional: true, ForceNew: true, - Description: "Labels of kubernetes scale worker created nodes.", + Description: "Indicate to set desired pod number in current node. Valid when the cluster enable customized pod cidr.", }, + + "docker_graph_path": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Docker graph path. Default is `/var/lib/docker`.", + }, + "extra_args": { Type: schema.TypeList, Optional: true, ForceNew: true, - Elem: &schema.Schema{Type: schema.TypeString}, Description: "Custom parameter information related to the node.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, + "gpu_args": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "GPU driver parameters.", Elem: &schema.Resource{ - Schema: TKEGpuArgsSetting(), + Schema: map[string]*schema.Schema{ + "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.", + }, + "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.", + }, + "custom_driver": { + Type: schema.TypeMap, + Optional: true, + Description: "Custom GPU driver. Format like: `{address: String}`. `address`: URL of custom GPU driver address.", + }, + "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.", + }, + "mig_enable": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to enable MIG.", + }, + }, }, - Description: "GPU driver parameters.", }, - "unschedulable": { - Type: schema.TypeInt, + + "labels": { + Type: schema.TypeMap, Optional: true, ForceNew: true, - Default: 0, - Description: "Sets whether the joining node participates in the schedule. Default is '0'. Participate in scheduling.", - }, - "desired_pod_num": { - Type: schema.TypeInt, - ForceNew: true, - Optional: true, - Description: "Indicate to set desired pod number in current node. Valid when the cluster enable customized pod cidr.", + Description: "Labels of kubernetes scale worker created nodes.", }, - "docker_graph_path": { + + "mount_target": { Type: schema.TypeString, Optional: true, ForceNew: true, - Description: "Docker graph path. Default is `/var/lib/docker`.", + Description: "Mount target. Default is not mounting.", }, - "mount_target": { - Type: schema.TypeString, + + "unschedulable": { + Type: schema.TypeInt, Optional: true, ForceNew: true, - Description: "Mount target. Default is not mounting.", + Default: 0, + Description: "Sets whether the joining node participates in the schedule. Default is '0'. Participate in scheduling.", }, - "data_disk": { + + "worker_config": { Type: schema.TypeList, + Required: true, ForceNew: true, - Optional: true, - MaxItems: 11, - Description: "Configurations of data disk.", + MaxItems: 1, + MinItems: 1, + Description: "Deploy the machine configuration information of the 'WORK' service, and create <=20 units for common users.", 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, available values: `CLOUD_PREMIUM` and `CLOUD_SSD` and `CLOUD_HSSD` and `CLOUD_TSSD`.", + "availability_zone": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Indicates which availability zone will be used.", }, - "disk_size": { + "bandwidth_package_id": { + Type: schema.TypeString, + Optional: true, + Description: "bandwidth package id. if user is standard user, then the bandwidth_package_id is needed, or default has bandwidth_package_id.", + }, + "cam_role_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "CAM role name authorized to access.", + }, + "count": { Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 1, + Description: "Number of cvm.", + }, + "data_disk": { + Type: schema.TypeList, + Optional: true, ForceNew: true, + MaxItems: 11, + Description: "Configurations of data disk.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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`.", + }, + "disk_partition": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name of the device or partition to mount.", + }, + "disk_size": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 0, + Description: "Volume of disk in GB. Default is `0`.", + }, + "disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "CLOUD_PREMIUM", + Description: "Types of disk, available values: `CLOUD_PREMIUM` and `CLOUD_SSD` and `CLOUD_HSSD` and `CLOUD_TSSD`.", + }, + "encrypt": { + Type: schema.TypeBool, + Optional: true, + Description: "Indicates whether to encrypt data disk, default `false`.", + }, + "file_system": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "File system, e.g. `ext3/ext4/xfs`.", + }, + "kms_key_id": { + Type: schema.TypeString, + Optional: true, + Description: "ID of the custom CMK in the format of UUID or `kms-abcd1234`. This parameter is used to encrypt cloud disks.", + }, + "mount_target": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Mount target.", + }, + "snapshot_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Data disk snapshot ID.", + }, + }, + }, + }, + "desired_pod_num": { + Type: schema.TypeInt, Optional: true, + ForceNew: true, Default: 0, - Description: "Volume of disk in GB. Default is `0`.", + Description: "Indicate to set desired pod number in node. valid when enable_customized_pod_cidr=true, and it override `[globe_]desired_pod_num` for current node. Either all the fields `desired_pod_num` or none.", }, - "file_system": { + "disaster_recover_group_ids": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "Disaster recover groups to which a CVM instance belongs. Only support maximum 1.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "enhanced_monitor_service": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: true, + Description: "To specify whether to enable cloud monitor service. Default is TRUE.", + }, + "enhanced_security_service": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: true, + Description: "To specify whether to enable cloud security service. Default is TRUE.", + }, + "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 (-).", + }, + "hpc_cluster_id": { + Type: schema.TypeString, Optional: true, - Default: "", - Description: "File system, e.g. `ext3/ext4/xfs`.", + Description: "Id of cvm hpc cluster.", }, - "auto_format_and_mount": { + "img_id": { + Type: schema.TypeString, + Optional: true, + Description: "The valid image id, format of img-xxx.", + }, + "instance_charge_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "POSTPAID_BY_HOUR", + Description: "The charge type of instance. Valid values are `PREPAID` and `POSTPAID_BY_HOUR`. The default is `POSTPAID_BY_HOUR`. Note: TencentCloud International only supports `POSTPAID_BY_HOUR`, `PREPAID` instance will not terminated after cluster deleted, and may not allow to delete before expired.", + }, + "instance_charge_type_prepaid_period": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 1, + Description: "The tenancy (time unit is month) of the prepaid instance. NOTE: it only works when instance_charge_type is set to `PREPAID`. Valid values are `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `24`, `36`.", + }, + "instance_charge_type_prepaid_renew_flag": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "Auto renewal flag. Valid values: `NOTIFY_AND_AUTO_RENEW`: notify upon expiration and renew automatically, `NOTIFY_AND_MANUAL_RENEW`: notify upon expiration but do not renew automatically, `DISABLE_NOTIFY_AND_MANUAL_RENEW`: neither notify upon expiration nor renew automatically. Default value: `NOTIFY_AND_MANUAL_RENEW`. If this parameter is specified as `NOTIFY_AND_AUTO_RENEW`, the instance will be automatically renewed on a monthly basis if the account balance is sufficient. NOTE: it only works when instance_charge_type is set to `PREPAID`.", + }, + "instance_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "sub machine of tke", + Description: "Name of the CVMs.", + }, + "instance_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Specified types of CVM instance.", + }, + "internet_charge_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "TRAFFIC_POSTPAID_BY_HOUR", + Description: "Charge types for network traffic. Available values include `TRAFFIC_POSTPAID_BY_HOUR`.", + }, + "internet_max_bandwidth_out": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Max bandwidth of Internet access in Mbps. Default is 0.", + }, + "key_ids": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Description: "ID list of keys, should be set if `password` not set.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "password": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Sensitive: true, + Description: "Password to access, should be set if `key_ids` not set.", + }, + "public_ip_assigned": { Type: schema.TypeBool, Optional: true, ForceNew: true, - Default: false, - Description: "Indicate whether to auto format and mount or not. Default is `false`.", + Description: "Specify whether to assign an Internet IP address.", }, - "mount_target": { + "security_group_ids": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: "Security groups to which a CVM instance belongs.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "subnet_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Private network ID.", + }, + "system_disk_size": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 50, + Description: "Volume of system disk in GB. Default is `50`.", + }, + "system_disk_type": { Type: schema.TypeString, Optional: true, ForceNew: true, - Default: "", - Description: "Mount target.", + Default: "CLOUD_PREMIUM", + Description: "System disk type. For more information on limits of system disk types, see [Storage Overview](https://intl.cloud.tencent.com/document/product/213/4952). Valid values: `LOCAL_BASIC`: local disk, `LOCAL_SSD`: local SSD disk, `CLOUD_SSD`: SSD, `CLOUD_PREMIUM`: Premium Cloud Storage. NOTE: `CLOUD_BASIC`, `LOCAL_BASIC` and `LOCAL_SSD` are deprecated.", + }, + "user_data": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "ase64-encoded User Data text, the length limit is 16KB.", }, }, }, }, - // Computed values + "worker_instances_list": { - Type: schema.TypeList, - Computed: true, + Type: schema.TypeList, + Computed: true, + Description: "An information list of kubernetes cluster 'WORKER'. Each element contains the following attributes:", Elem: &schema.Resource{ - Schema: tkeCvmState(), + Schema: map[string]*schema.Schema{ + "failed_reason": { + Type: schema.TypeString, + Computed: true, + Description: "Information of the cvm when it is failed.", + }, + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of the cvm.", + }, + "instance_role": { + Type: schema.TypeString, + Computed: true, + Description: "Role of the cvm.", + }, + "instance_state": { + Type: schema.TypeString, + Computed: true, + Description: "State of the cvm.", + }, + "lan_ip": { + Type: schema.TypeString, + Computed: true, + Description: "LAN IP of the cvm.", + }, + }, }, - Description: "An information list of kubernetes cluster 'WORKER'. Each element contains the following attributes:", }, }, } } -func resourceTencentCloudTkeScaleWorkerCreate(d *schema.ResourceData, meta interface{}) error { +func resourceTencentCloudKubernetesScaleWorkerCreate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_scale_worker.create")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - var cvms RunInstancesForNode - var iAdvanced tke.InstanceAdvancedSettings - cvms.Work = []string{} + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + var ( + clusterId string + instanceIdSet []string + ) + var ( + request = tke.NewDescribeClustersRequest() + response = tke.NewDescribeClustersResponse() + ) - clusterId := d.Get("cluster_id").(string) - if clusterId == "" { - return fmt.Errorf("`cluster_id` is empty.") + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) } - info, has, err := service.DescribeCluster(ctx, clusterId) - if err != nil { - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - info, has, err = service.DescribeCluster(ctx, clusterId) - if err != nil { - return tccommon.RetryError(err) - } - return nil - }) - } + request.ClusterIds = []*string{&clusterId} - if err != nil { + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().DescribeClustersWithContext(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()) + } + if err := resourceTencentCloudKubernetesScaleWorkerCreatePostRequest0(ctx, request, result); err != nil { + return resource.NonRetryableError(err) + } + + response = result return nil + }) + if err != nil { + log.Printf("[CRITAL]%s create kubernetes scale worker failed, reason:%+v", logId, err) + return err } - if !has { - return fmt.Errorf("cluster [%s] is not exist.", clusterId) - } + _ = response - dMap := make(map[string]interface{}, 5) - //mount_target, docker_graph_path, data_disk, extra_args, desired_pod_num - iAdvancedParas := []string{"mount_target", "docker_graph_path", "extra_args", "data_disk", "desired_pod_num", "gpu_args"} - for _, k := range iAdvancedParas { - if v, ok := d.GetOk(k); ok { - dMap[k] = v - } - } - iAdvanced = tkeGetInstanceAdvancedPara(dMap, meta) + var ( + request1 = tke.NewCreateClusterInstancesRequest() + response1 = tke.NewCreateClusterInstancesResponse() + ) - iAdvanced.Labels = GetTkeLabels(d, "labels") - if temp, ok := d.GetOk("unschedulable"); ok { - iAdvanced.Unschedulable = helper.Int64(int64(temp.(int))) + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) } - if workers, ok := d.GetOk("worker_config"); ok { - workerList := workers.([]interface{}) - for index := range workerList { - worker := workerList[index].(map[string]interface{}) - paraJson, _, err := tkeGetCvmRunInstancesPara(worker, meta, info.VpcId, info.ProjectId) - if err != nil { - return err - } - cvms.Work = append(cvms.Work, paraJson) - } - } - if len(cvms.Work) != 1 { - return fmt.Errorf("only one additional configuration of virtual machines is now supported now, " + - "so len(cvms.Work) should be 1") - } + request1.ClusterId = &clusterId - instanceIds, err := service.CreateClusterInstances(ctx, clusterId, cvms.Work[0], iAdvanced) - if err != nil { + if err = resourceTencentCloudKubernetesScaleWorkerCreatePostFillRequest1(ctx, request1); err != nil { return err } - workerInstancesList := make([]map[string]interface{}, 0, len(instanceIds)) - for _, v := range instanceIds { - if v == "" { - return fmt.Errorf("CreateClusterInstances return one instanceId is empty") + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().CreateClusterInstancesWithContext(ctx, request1) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request1.GetAction(), request1.ToJsonString(), result.ToJsonString()) } - infoMap := make(map[string]interface{}) - infoMap["instance_id"] = v - infoMap["instance_role"] = TKE_ROLE_WORKER - workerInstancesList = append(workerInstancesList, infoMap) - } - if err = d.Set("worker_instances_list", workerInstancesList); err != nil { + if instanceIdSet, err = resourceTencentCloudKubernetesScaleWorkerCreatePostRequest1(ctx, request1, result); err != nil { + return resource.NonRetryableError(err) + } + + response1 = result + return nil + }) + + if err != nil { + log.Printf("[CRITAL]%s create kubernetes scale worker failed, reason:%+v", logId, err) return err } - //修改id设置,不符合id规则 - id := clusterId + tccommon.FILED_SP + strings.Join(instanceIds, tccommon.FILED_SP) + _ = response1 + + id := clusterId + tccommon.FILED_SP + strings.Join(instanceIdSet, tccommon.FILED_SP) d.SetId(id) - //wait for LANIP - time.Sleep(tccommon.ReadRetryTimeout) - return resourceTencentCloudTkeScaleWorkerRead(d, meta) + return resourceTencentCloudKubernetesScaleWorkerRead(d, meta) } -func resourceTencentCloudTkeScaleWorkerRead(d *schema.ResourceData, meta interface{}) error { - +func resourceTencentCloudKubernetesScaleWorkerRead(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_scale_worker.read")() defer tccommon.InconsistentCheck(d, meta)() - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, tccommon.GetLogId(tccommon.ContextNil)) - service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - cvmService := svccvm.NewCvmService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + logId := tccommon.GetLogId(tccommon.ContextNil) - var ( - items = strings.Split(d.Id(), tccommon.FILED_SP) - oldWorkerInstancesList = d.Get("worker_instances_list").([]interface{}) - instanceMap = make(map[string]bool) - clusterId = "" - ) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - if importFlag { - clusterId = items[0] - if len(items[1:]) >= 2 { - return fmt.Errorf("only one additional configuration of virtual machines is now supported now, " + - "so should be 1") - } - infoMap := map[string]interface{}{ - "instance_id": items[1], - } - oldWorkerInstancesList = append(oldWorkerInstancesList, infoMap) - } else { - clusterId = d.Get("cluster_id").(string) - } + service := TkeService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - if clusterId == "" { - return fmt.Errorf("tke.`cluster_id` is empty.") + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) != 2 { + return fmt.Errorf("id is broken,%s", d.Id()) } + clusterId := idSplit[0] + instanceIdSet := idSplit[1] - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, has, err := service.DescribeCluster(ctx, clusterId) - if err != nil { - return tccommon.RetryError(err) - } + _ = d.Set("cluster_id", clusterId) - if !has { - d.SetId("") - return nil - } - return nil - }) + respData, err := service.DescribeKubernetesScaleWorkerById(ctx, clusterId) if err != nil { return err } - for _, v := range oldWorkerInstancesList { - infoMap, ok := v.(map[string]interface{}) - if !ok || infoMap["instance_id"] == nil { - return fmt.Errorf("worker_instances_list is broken.") - } - instanceId, ok := infoMap["instance_id"].(string) - if !ok || instanceId == "" { - return fmt.Errorf("worker_instances_list.instance_id is broken.") - } - if instanceMap[instanceId] { - continue - } - instanceMap[instanceId] = true - } - - _, workers, err := service.DescribeClusterInstances(ctx, clusterId) - if err != nil { - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, workers, err = service.DescribeClusterInstances(ctx, clusterId) - if e, ok := err.(*errors.TencentCloudSDKError); ok { - if e.GetCode() == "InternalError.ClusterNotFound" { - return nil - } - } - if err != nil { - return resource.RetryableError(err) - } - return nil - }) + if respData == nil { + d.SetId("") + log.Printf("[WARN]%s resource `kubernetes_scale_worker` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil } + respData1, err := service.DescribeKubernetesScaleWorkerById1(ctx, clusterId) if err != nil { return err } - newWorkerInstancesList := make([]map[string]interface{}, 0, len(workers)) - labelsMap := make(map[string]string) - instanceIds := make([]*string, 0) - for sub, cvm := range workers { - if _, ok := instanceMap[cvm.InstanceId]; !ok { - continue - } - instanceIds = append(instanceIds, &workers[sub].InstanceId) - tempMap := make(map[string]interface{}) - tempMap["instance_id"] = cvm.InstanceId - tempMap["instance_role"] = cvm.InstanceRole - tempMap["instance_state"] = cvm.InstanceState - tempMap["failed_reason"] = cvm.FailedReason - tempMap["lan_ip"] = cvm.LanIp - - newWorkerInstancesList = append(newWorkerInstancesList, tempMap) - if cvm.InstanceAdvancedSettings != nil { - if cvm.InstanceAdvancedSettings.Labels != nil { - for _, v := range cvm.InstanceAdvancedSettings.Labels { - labelsMap[helper.PString(v.Name)] = helper.PString(v.Value) - } - } - - _ = d.Set("unschedulable", helper.PInt64(cvm.InstanceAdvancedSettings.Unschedulable)) - - if importFlag { - _ = d.Set("docker_graph_path", helper.PString(cvm.InstanceAdvancedSettings.DockerGraphPath)) - _ = d.Set("desired_pod_num", helper.PInt64(cvm.InstanceAdvancedSettings.DesiredPodNumber)) - _ = d.Set("mount_target", helper.PString(cvm.InstanceAdvancedSettings.MountTarget)) - } - - if cvm.InstanceAdvancedSettings.DataDisks != nil && len(cvm.InstanceAdvancedSettings.DataDisks) > 0 { - dataDisks := make([]interface{}, 0, len(cvm.InstanceAdvancedSettings.DataDisks)) - for i := range cvm.InstanceAdvancedSettings.DataDisks { - item := cvm.InstanceAdvancedSettings.DataDisks[i] - disk := make(map[string]interface{}) - disk["disk_type"] = helper.PString(item.DiskType) - disk["disk_size"] = helper.PInt64(item.DiskSize) - disk["file_system"] = helper.PString(item.FileSystem) - disk["auto_format_and_mount"] = helper.PBool(item.AutoFormatAndMount) - disk["mount_target"] = helper.PString(item.MountTarget) - disk["disk_partition"] = helper.PString(item.MountTarget) - dataDisks = append(dataDisks, disk) - } - if importFlag { - _ = d.Set("data_disk", dataDisks) - } - } - - if cvm.InstanceAdvancedSettings.GPUArgs != nil { - setting := cvm.InstanceAdvancedSettings.GPUArgs - - var driverEmptyFlag, cudaEmptyFlag, cudnnEmptyFlag, customDriverEmptyFlag bool - gpuArgs := map[string]interface{}{ - "mig_enable": helper.PBool(setting.MIGEnable), - } - - if !isDriverEmpty(setting.Driver) { - driverEmptyFlag = true - driver := map[string]interface{}{ - "version": helper.PString(setting.Driver.Version), - "name": helper.PString(setting.Driver.Name), - } - gpuArgs["driver"] = driver - } - - if !isCUDAEmpty(setting.CUDA) { - cudaEmptyFlag = true - cuda := map[string]interface{}{ - "version": helper.PString(setting.CUDA.Version), - "name": helper.PString(setting.CUDA.Name), - } - gpuArgs["cuda"] = cuda - } - - if !isCUDNNEmpty(setting.CUDNN) { - cudnnEmptyFlag = true - cudnn := map[string]interface{}{ - "version": helper.PString(setting.CUDNN.Version), - "name": helper.PString(setting.CUDNN.Name), - "doc_name": helper.PString(setting.CUDNN.DocName), - "dev_name": helper.PString(setting.CUDNN.DevName), - } - gpuArgs["cudnn"] = cudnn - } - - if !isCustomDriverEmpty(setting.CustomDriver) { - customDriverEmptyFlag = true - customDriver := map[string]interface{}{ - "address": helper.PString(setting.CustomDriver.Address), - } - gpuArgs["custom_driver"] = customDriver - } - - if importFlag { - if driverEmptyFlag || cudaEmptyFlag || cudnnEmptyFlag || customDriverEmptyFlag { - _ = d.Set("gpu_args", []interface{}{gpuArgs}) - } - - } - } - } + if respData1 == nil { + d.SetId("") + log.Printf("[WARN]%s resource `kubernetes_scale_worker` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil } - //worker_config - var instances []*cvm.Instance - var errRet error - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - instances, errRet = cvmService.DescribeInstanceByFilter(ctx, instanceIds, nil) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - return nil - }) + respData2, err := service.DescribeKubernetesScaleWorkerById2(ctx) if err != nil { return err } - instanceList := make([]interface{}, 0, len(instances)) - for _, instance := range instances { - mapping := map[string]interface{}{ - "count": 1, - "instance_charge_type_prepaid_period": 1, - "instance_type": helper.PString(instance.InstanceType), - "subnet_id": helper.PString(instance.VirtualPrivateCloud.SubnetId), - "availability_zone": helper.PString(instance.Placement.Zone), - "instance_name": helper.PString(instance.InstanceName), - "instance_charge_type": helper.PString(instance.InstanceChargeType), - "system_disk_type": helper.PString(instance.SystemDisk.DiskType), - "system_disk_size": helper.PInt64(instance.SystemDisk.DiskSize), - "internet_charge_type": helper.PString(instance.InternetAccessible.InternetChargeType), - "bandwidth_package_id": helper.PString(instance.InternetAccessible.BandwidthPackageId), - "internet_max_bandwidth_out": helper.PInt64(instance.InternetAccessible.InternetMaxBandwidthOut), - "security_group_ids": helper.StringsInterfaces(instance.SecurityGroupIds), - "img_id": helper.PString(instance.ImageId), - } - - if instance.RenewFlag != nil && helper.PString(instance.InstanceChargeType) == "PREPAID" { - mapping["instance_charge_type_prepaid_renew_flag"] = helper.PString(instance.RenewFlag) - } else { - mapping["instance_charge_type_prepaid_renew_flag"] = "" - } - if helper.PInt64(instance.InternetAccessible.InternetMaxBandwidthOut) > 0 { - mapping["public_ip_assigned"] = true - } - - if instance.CamRoleName != nil { - mapping["cam_role_name"] = instance.CamRoleName - } - if instance.LoginSettings != nil { - if instance.LoginSettings.KeyIds != nil && len(instance.LoginSettings.KeyIds) > 0 { - mapping["key_ids"] = helper.StringsInterfaces(instance.LoginSettings.KeyIds) - } - if instance.LoginSettings.Password != nil { - mapping["password"] = helper.PString(instance.LoginSettings.Password) - } - } - if instance.DisasterRecoverGroupId != nil && helper.PString(instance.DisasterRecoverGroupId) != "" { - mapping["disaster_recover_group_ids"] = []string{helper.PString(instance.DisasterRecoverGroupId)} - } - if instance.HpcClusterId != nil { - mapping["hpc_cluster_id"] = helper.PString(instance.HpcClusterId) - } - - dataDisks := make([]interface{}, 0, len(instance.DataDisks)) - for _, v := range instance.DataDisks { - dataDisk := map[string]interface{}{ - "disk_type": helper.PString(v.DiskType), - "disk_size": helper.PInt64(v.DiskSize), - "snapshot_id": helper.PString(v.DiskId), - "encrypt": helper.PBool(v.Encrypt), - "kms_key_id": helper.PString(v.KmsKeyId), - } - dataDisks = append(dataDisks, dataDisk) - } - - mapping["data_disk"] = dataDisks - instanceList = append(instanceList, mapping) - } - if importFlag { - _ = d.Set("worker_config", instanceList) - } - - // The machines I generated was deleted by others. - if len(newWorkerInstancesList) == 0 { + if respData2 == nil { d.SetId("") + log.Printf("[WARN]%s resource `kubernetes_scale_worker` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } - - _ = d.Set("cluster_id", clusterId) - _ = d.Set("labels", labelsMap) - _ = d.Set("worker_instances_list", newWorkerInstancesList) - + _ = instanceIdSet return nil } -func resourceTencentCloudTkeScaleWorkerDelete(d *schema.ResourceData, meta interface{}) error { +func resourceTencentCloudKubernetesScaleWorkerDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_kubernetes_scale_worker.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()} + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) != 2 { + return fmt.Errorf("id is broken,%s", d.Id()) + } + clusterId := idSplit[0] + instanceIdSet := idSplit[1] - clusterId := d.Get("cluster_id").(string) + var ( + request = tke.NewDescribeClustersRequest() + response = tke.NewDescribeClustersResponse() + ) - if clusterId == "" { - return fmt.Errorf("`cluster_id` is empty.") + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) } - _, has, err := service.DescribeCluster(ctx, clusterId) - if err != nil { - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, has, err = service.DescribeCluster(ctx, clusterId) - if err != nil { - return tccommon.RetryError(err) - } - return nil - }) - } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().DescribeClustersWithContext(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()) + } - if err != nil { - return nil - } - // The cluster has been deleted - if !has { + if err := resourceTencentCloudKubernetesScaleWorkerDeletePostRequest0(ctx, request, result); err != nil { + return resource.NonRetryableError(err) + } + + response = result return nil + }) + + if err != nil { + log.Printf("[CRITAL]%s create kubernetes scale worker failed, reason:%+v", logId, err) + return err } - workerInstancesList := d.Get("worker_instances_list").([]interface{}) - instanceMap := make(map[string]bool) + _ = response - for _, v := range workerInstancesList { + var ( + request1 = tke.NewDescribeClusterInstancesRequest() + response1 = tke.NewDescribeClusterInstancesResponse() + workers []InstanceInfo + ) - infoMap, ok := v.(map[string]interface{}) + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) + } - if !ok || infoMap["instance_id"] == nil { - return fmt.Errorf("worker_instances_list is broken.") - } - instanceId, ok := infoMap["instance_id"].(string) - if !ok || instanceId == "" { - return fmt.Errorf("worker_instances_list.instance_id is broken.") + request1.ClusterId = &clusterId + + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().DescribeClusterInstancesWithContext(ctx, request1) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request1.GetAction(), request1.ToJsonString(), result.ToJsonString()) } - if instanceMap[instanceId] { - log.Printf("[WARN]The same instance id exists in the list") + if workers, err = resourceTencentCloudKubernetesScaleWorkerDeletePostRequest1(ctx, request1, result); err != nil { + return resource.NonRetryableError(err) } - instanceMap[instanceId] = true + response1 = result + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s create kubernetes scale worker failed, reason:%+v", logId, err) + return err } - _, workers, err := service.DescribeClusterInstances(ctx, clusterId) - if err != nil { - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, workers, err = service.DescribeClusterInstances(ctx, clusterId) - - if e, ok := err.(*errors.TencentCloudSDKError); ok { - if e.GetCode() == "InternalError.ClusterNotFound" { - return nil - } - } - - if err != nil { - return resource.RetryableError(err) - } - return nil - }) + _ = response1 + + var ( + request2 = tke.NewDeleteClusterInstancesRequest() + response2 = tke.NewDeleteClusterInstancesResponse() + ) + + if v, ok := d.GetOk("cluster_id"); ok { + clusterId = v.(string) } - if err != nil { + request2.ClusterId = &clusterId + + if err = resourceTencentCloudKubernetesScaleWorkerDeletePostFillRequest2(ctx, request2, workers); err != nil { return err } - needDeletes := []string{} - for _, cvm := range workers { - if _, ok := instanceMap[cvm.InstanceId]; ok { - needDeletes = append(needDeletes, cvm.InstanceId) + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTkeClient().DeleteClusterInstancesWithContext(ctx, request2) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request2.GetAction(), request2.ToJsonString(), result.ToJsonString()) } - } - // The machines I generated was deleted by others. - if len(needDeletes) == 0 { + response2 = result return nil - } + }) - err = service.DeleteClusterInstances(ctx, clusterId, needDeletes) if err != nil { - err = resource.Retry(3*tccommon.WriteRetryTimeout, func() *resource.RetryError { - err = service.DeleteClusterInstances(ctx, clusterId, needDeletes) - - 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 - } - } - - if err != nil { - return tccommon.RetryError(err, tccommon.InternalError) - } - return nil - }) + log.Printf("[CRITAL]%s create kubernetes scale worker failed, reason:%+v", logId, err) + return err } - return err + + _ = response2 + _ = instanceIdSet + return nil } diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker_extension.go b/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker_extension.go new file mode 100644 index 0000000000..7bd9655e56 --- /dev/null +++ b/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker_extension.go @@ -0,0 +1,504 @@ +package tke + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + 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" + "log" + "strings" + "time" +) + +var importFlag1 = false + +var GlobalClusterId string +var CreateClusterInstancesVpcId string +var CreateClusterInstancesProjectId int64 +var WorkersInstanceIds []*string +var WorkersNewWorkerInstancesList []map[string]interface{} +var WorkersLabelsMap map[string]string + +func init() { + +} + +func customResourceImporter(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + importFlag1 = true + err := resourceTencentCloudKubernetesScaleWorkerRead(d, m) + if err != nil { + return nil, fmt.Errorf("failed to import resource") + } + + return []*schema.ResourceData{d}, nil +} + +func resourceTencentCloudKubernetesScaleWorkerCreatePostRequest1(ctx context.Context, req *tke.CreateClusterInstancesRequest, resp *tke.CreateClusterInstancesResponse) (instanceIdSet []string, err error) { + d := tccommon.ResourceDataFromContext(ctx) + + instanceIdSet = make([]string, 0) + workerInstancesList := make([]map[string]interface{}, 0, len(resp.Response.InstanceIdSet)) + for _, v := range resp.Response.InstanceIdSet { + if *v == "" { + return nil, fmt.Errorf("CreateClusterInstances return one instanceId is empty") + } + infoMap := make(map[string]interface{}) + infoMap["instance_id"] = v + infoMap["instance_role"] = TKE_ROLE_WORKER + workerInstancesList = append(workerInstancesList, infoMap) + instanceIdSet = append(instanceIdSet, *v) + } + + if err := d.Set("worker_instances_list", workerInstancesList); err != nil { + return nil, err + } + + //wait for LANIP + time.Sleep(tccommon.ReadRetryTimeout) + return instanceIdSet, nil +} + +func resourceTencentCloudKubernetesScaleWorkerReadPostRequest1(ctx context.Context, req *tke.DescribeClusterInstancesRequest, resp *tke.DescribeClusterInstancesResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + var has = map[string]bool{} + + workerInstancesList := d.Get("worker_instances_list").([]interface{}) + instanceMap := make(map[string]bool) + for _, v := range workerInstancesList { + infoMap, ok := v.(map[string]interface{}) + if !ok || infoMap["instance_id"] == nil { + return fmt.Errorf("worker_instances_list is broken.") + } + + instanceId, ok := infoMap["instance_id"].(string) + if !ok || instanceId == "" { + return fmt.Errorf("worker_instances_list.instance_id is broken.") + } + + if instanceMap[instanceId] { + log.Printf("[WARN]The same instance id exists in the list") + } + + instanceMap[instanceId] = true + } + workers := make([]InstanceInfo, 0, 100) + for _, item := range resp.Response.InstanceSet { + if has[*item.InstanceId] { + return fmt.Errorf("get repeated instance_id[%s] when doing DescribeClusterInstances", *item.InstanceId) + } + has[*item.InstanceId] = true + instanceInfo := InstanceInfo{ + InstanceId: *item.InstanceId, + InstanceRole: *item.InstanceRole, + InstanceState: *item.InstanceState, + FailedReason: *item.FailedReason, + InstanceAdvancedSettings: item.InstanceAdvancedSettings, + } + if item.CreatedTime != nil { + instanceInfo.CreatedTime = *item.CreatedTime + } + if item.NodePoolId != nil { + instanceInfo.NodePoolId = *item.NodePoolId + } + if item.LanIP != nil { + instanceInfo.LanIp = *item.LanIP + } + if instanceInfo.InstanceRole == TKE_ROLE_WORKER { + workers = append(workers, instanceInfo) + } + } + + WorkersNewWorkerInstancesList = make([]map[string]interface{}, 0, len(workers)) + WorkersLabelsMap = make(map[string]string) + WorkersInstanceIds = make([]*string, 0) + for sub, cvmInfo := range workers { + if _, ok := instanceMap[cvmInfo.InstanceId]; !ok { + continue + } + WorkersInstanceIds = append(WorkersInstanceIds, &workers[sub].InstanceId) + tempMap := make(map[string]interface{}) + tempMap["instance_id"] = cvmInfo.InstanceId + tempMap["instance_role"] = cvmInfo.InstanceRole + tempMap["instance_state"] = cvmInfo.InstanceState + tempMap["failed_reason"] = cvmInfo.FailedReason + tempMap["lan_ip"] = cvmInfo.LanIp + + WorkersNewWorkerInstancesList = append(WorkersNewWorkerInstancesList, tempMap) + if cvmInfo.InstanceAdvancedSettings != nil { + if cvmInfo.InstanceAdvancedSettings.Labels != nil { + for _, v := range cvmInfo.InstanceAdvancedSettings.Labels { + WorkersLabelsMap[helper.PString(v.Name)] = helper.PString(v.Value) + } + } + + _ = d.Set("unschedulable", helper.PInt64(cvmInfo.InstanceAdvancedSettings.Unschedulable)) + + if importFlag1 { + _ = d.Set("docker_graph_path", helper.PString(cvmInfo.InstanceAdvancedSettings.DockerGraphPath)) + _ = d.Set("desired_pod_num", helper.PInt64(cvmInfo.InstanceAdvancedSettings.DesiredPodNumber)) + _ = d.Set("mount_target", helper.PString(cvmInfo.InstanceAdvancedSettings.MountTarget)) + } + + if cvmInfo.InstanceAdvancedSettings.DataDisks != nil && len(cvmInfo.InstanceAdvancedSettings.DataDisks) > 0 { + dataDisks := make([]interface{}, 0, len(cvmInfo.InstanceAdvancedSettings.DataDisks)) + for i := range cvmInfo.InstanceAdvancedSettings.DataDisks { + item := cvmInfo.InstanceAdvancedSettings.DataDisks[i] + disk := make(map[string]interface{}) + disk["disk_type"] = helper.PString(item.DiskType) + disk["disk_size"] = helper.PInt64(item.DiskSize) + disk["file_system"] = helper.PString(item.FileSystem) + disk["auto_format_and_mount"] = helper.PBool(item.AutoFormatAndMount) + disk["mount_target"] = helper.PString(item.MountTarget) + disk["disk_partition"] = helper.PString(item.MountTarget) + dataDisks = append(dataDisks, disk) + } + if importFlag1 { + _ = d.Set("data_disk", dataDisks) + } + } + + if cvmInfo.InstanceAdvancedSettings.GPUArgs != nil { + setting := cvmInfo.InstanceAdvancedSettings.GPUArgs + + var driverEmptyFlag, cudaEmptyFlag, cudnnEmptyFlag, customDriverEmptyFlag bool + gpuArgs := map[string]interface{}{ + "mig_enable": helper.PBool(setting.MIGEnable), + } + + if !isDriverEmpty(setting.Driver) { + driverEmptyFlag = true + driver := map[string]interface{}{ + "version": helper.PString(setting.Driver.Version), + "name": helper.PString(setting.Driver.Name), + } + gpuArgs["driver"] = driver + } + + if !isCUDAEmpty(setting.CUDA) { + cudaEmptyFlag = true + cuda := map[string]interface{}{ + "version": helper.PString(setting.CUDA.Version), + "name": helper.PString(setting.CUDA.Name), + } + gpuArgs["cuda"] = cuda + } + + if !isCUDNNEmpty(setting.CUDNN) { + cudnnEmptyFlag = true + cudnn := map[string]interface{}{ + "version": helper.PString(setting.CUDNN.Version), + "name": helper.PString(setting.CUDNN.Name), + "doc_name": helper.PString(setting.CUDNN.DocName), + "dev_name": helper.PString(setting.CUDNN.DevName), + } + gpuArgs["cudnn"] = cudnn + } + + if !isCustomDriverEmpty(setting.CustomDriver) { + customDriverEmptyFlag = true + customDriver := map[string]interface{}{ + "address": helper.PString(setting.CustomDriver.Address), + } + gpuArgs["custom_driver"] = customDriver + } + + if importFlag1 { + if driverEmptyFlag || cudaEmptyFlag || cudnnEmptyFlag || customDriverEmptyFlag { + _ = d.Set("gpu_args", []interface{}{gpuArgs}) + } + } + } + } + } + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerReadPostRequest2(ctx context.Context, req *cvm.DescribeInstancesRequest, resp *cvm.DescribeInstancesResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + + instances := make([]*cvm.Instance, 0) + instances = append(instances, resp.Response.InstanceSet...) + + instanceList := make([]interface{}, 0, len(instances)) + for _, instance := range instances { + mapping := map[string]interface{}{ + "count": 1, + "instance_charge_type_prepaid_period": 1, + "instance_type": helper.PString(instance.InstanceType), + "subnet_id": helper.PString(instance.VirtualPrivateCloud.SubnetId), + "availability_zone": helper.PString(instance.Placement.Zone), + "instance_name": helper.PString(instance.InstanceName), + "instance_charge_type": helper.PString(instance.InstanceChargeType), + "system_disk_type": helper.PString(instance.SystemDisk.DiskType), + "system_disk_size": helper.PInt64(instance.SystemDisk.DiskSize), + "internet_charge_type": helper.PString(instance.InternetAccessible.InternetChargeType), + "bandwidth_package_id": helper.PString(instance.InternetAccessible.BandwidthPackageId), + "internet_max_bandwidth_out": helper.PInt64(instance.InternetAccessible.InternetMaxBandwidthOut), + "security_group_ids": helper.StringsInterfaces(instance.SecurityGroupIds), + "img_id": helper.PString(instance.ImageId), + } + + if instance.RenewFlag != nil && helper.PString(instance.InstanceChargeType) == "PREPAID" { + mapping["instance_charge_type_prepaid_renew_flag"] = helper.PString(instance.RenewFlag) + } else { + mapping["instance_charge_type_prepaid_renew_flag"] = "" + } + if helper.PInt64(instance.InternetAccessible.InternetMaxBandwidthOut) > 0 { + mapping["public_ip_assigned"] = true + } + + if instance.CamRoleName != nil { + mapping["cam_role_name"] = instance.CamRoleName + } + if instance.LoginSettings != nil { + if instance.LoginSettings.KeyIds != nil && len(instance.LoginSettings.KeyIds) > 0 { + mapping["key_ids"] = helper.StringsInterfaces(instance.LoginSettings.KeyIds) + } + if instance.LoginSettings.Password != nil { + mapping["password"] = helper.PString(instance.LoginSettings.Password) + } + } + if instance.DisasterRecoverGroupId != nil && helper.PString(instance.DisasterRecoverGroupId) != "" { + mapping["disaster_recover_group_ids"] = []string{helper.PString(instance.DisasterRecoverGroupId)} + } + if instance.HpcClusterId != nil { + mapping["hpc_cluster_id"] = helper.PString(instance.HpcClusterId) + } + + dataDisks := make([]interface{}, 0, len(instance.DataDisks)) + for _, v := range instance.DataDisks { + dataDisk := map[string]interface{}{ + "disk_type": helper.PString(v.DiskType), + "disk_size": helper.PInt64(v.DiskSize), + "snapshot_id": helper.PString(v.DiskId), + "encrypt": helper.PBool(v.Encrypt), + "kms_key_id": helper.PString(v.KmsKeyId), + } + dataDisks = append(dataDisks, dataDisk) + } + + mapping["data_disk"] = dataDisks + instanceList = append(instanceList, mapping) + } + if importFlag1 { + _ = d.Set("worker_config", instanceList) + } + + // The machines I generated was deleted by others. + if len(WorkersNewWorkerInstancesList) == 0 { + d.SetId("") + return nil + } + + _ = d.Set("cluster_id", GlobalClusterId) + _ = d.Set("labels", WorkersLabelsMap) + _ = d.Set("worker_instances_list", WorkersNewWorkerInstancesList) + + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerDeletePostRequest0(ctx context.Context, req *tke.DescribeClustersRequest, resp *tke.DescribeClustersResponse) error { + if len(resp.Response.Clusters) == 0 { + return fmt.Errorf("The cluster has been deleted") + } + + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerDeletePostRequest1(ctx context.Context, req *tke.DescribeClusterInstancesRequest, resp *tke.DescribeClusterInstancesResponse) (workers []InstanceInfo, err error) { + var has = map[string]bool{} + workers = make([]InstanceInfo, 0, 100) + for _, item := range resp.Response.InstanceSet { + if has[*item.InstanceId] { + return nil, fmt.Errorf("get repeated instance_id[%s] when doing DescribeClusterInstances", *item.InstanceId) + } + + has[*item.InstanceId] = true + instanceInfo := InstanceInfo{ + InstanceId: *item.InstanceId, + InstanceRole: *item.InstanceRole, + InstanceState: *item.InstanceState, + FailedReason: *item.FailedReason, + InstanceAdvancedSettings: item.InstanceAdvancedSettings, + } + + if item.CreatedTime != nil { + instanceInfo.CreatedTime = *item.CreatedTime + } + + if item.NodePoolId != nil { + instanceInfo.NodePoolId = *item.NodePoolId + } + + if item.LanIP != nil { + instanceInfo.LanIp = *item.LanIP + } + + if instanceInfo.InstanceRole == TKE_ROLE_WORKER { + workers = append(workers, instanceInfo) + } + } + + return workers, nil +} + +func resourceTencentCloudKubernetesScaleWorkerCreatePostFillRequest1(ctx context.Context, req *tke.CreateClusterInstancesRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + + var cvms RunInstancesForNode + var iAdvanced tke.InstanceAdvancedSettings + + dMap := make(map[string]interface{}, 5) + //mount_target, docker_graph_path, data_disk, extra_args, desired_pod_num + iAdvancedParas := []string{"mount_target", "docker_graph_path", "extra_args", "data_disk", "desired_pod_num", "gpu_args"} + for _, k := range iAdvancedParas { + if v, ok := d.GetOk(k); ok { + dMap[k] = v + } + } + + iAdvanced = tkeGetInstanceAdvancedPara(dMap, meta) + + iAdvanced.Labels = GetTkeLabels(d, "labels") + if temp, ok := d.GetOk("unschedulable"); ok { + iAdvanced.Unschedulable = helper.Int64(int64(temp.(int))) + } + + if workers, ok := d.GetOk("worker_config"); ok { + workerList := workers.([]interface{}) + for index := range workerList { + worker := workerList[index].(map[string]interface{}) + paraJson, _, err := tkeGetCvmRunInstancesPara(worker, meta, CreateClusterInstancesVpcId, CreateClusterInstancesProjectId) + if err != nil { + return err + } + cvms.Work = append(cvms.Work, paraJson) + } + } + if len(cvms.Work) != 1 { + return fmt.Errorf("only one additional configuration of virtual machines is now supported now, " + + "so len(cvms.Work) should be 1") + } + + req.RunInstancePara = &cvms.Work[0] + req.InstanceAdvancedSettings = &iAdvanced + + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerDeletePostFillRequest2(ctx context.Context, req *tke.DeleteClusterInstancesRequest, workers []InstanceInfo) error { + d := tccommon.ResourceDataFromContext(ctx) + + workerInstancesList := d.Get("worker_instances_list").([]interface{}) + instanceMap := make(map[string]bool) + for _, v := range workerInstancesList { + infoMap, ok := v.(map[string]interface{}) + if !ok || infoMap["instance_id"] == nil { + return fmt.Errorf("worker_instances_list is broken.") + } + + instanceId, ok := infoMap["instance_id"].(string) + if !ok || instanceId == "" { + return fmt.Errorf("worker_instances_list.instance_id is broken.") + } + + if instanceMap[instanceId] { + log.Printf("[WARN]The same instance id exists in the list") + } + + instanceMap[instanceId] = true + } + + needDeletes := []string{} + for _, cvmInfo := range workers { + if _, ok := instanceMap[cvmInfo.InstanceId]; ok { + needDeletes = append(needDeletes, cvmInfo.InstanceId) + } + } + + // The machines I generated was deleted by others. + if len(needDeletes) == 0 { + return fmt.Errorf("The machines I generated was deleted by others.") + } + + req.InstanceIds = make([]*string, 0, len(needDeletes)) + + for index := range needDeletes { + req.InstanceIds = append(req.InstanceIds, &needDeletes[index]) + } + + req.InstanceDeleteMode = helper.String("terminate") + + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerReadPostFillRequest0(ctx context.Context, req *tke.DescribeClustersRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + items := strings.Split(d.Id(), tccommon.FILED_SP) + + instanceMap := make(map[string]bool) + oldWorkerInstancesList := d.Get("worker_instances_list").([]interface{}) + if importFlag1 { + GlobalClusterId = items[0] + if len(items[1:]) >= 2 { + return fmt.Errorf("only one additional configuration of virtual machines is now supported now, " + + "so should be 1") + } + infoMap := map[string]interface{}{ + "instance_id": items[1], + } + oldWorkerInstancesList = append(oldWorkerInstancesList, infoMap) + } else { + GlobalClusterId = d.Get("cluster_id").(string) + } + + if GlobalClusterId == "" { + return fmt.Errorf("tke.`cluster_id` is empty.") + } + + for _, v := range oldWorkerInstancesList { + infoMap, ok := v.(map[string]interface{}) + if !ok || infoMap["instance_id"] == nil { + return fmt.Errorf("worker_instances_list is broken.") + } + instanceId, ok := infoMap["instance_id"].(string) + if !ok || instanceId == "" { + return fmt.Errorf("worker_instances_list.instance_id is broken.") + } + if instanceMap[instanceId] { + continue + } + instanceMap[instanceId] = true + } + + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerReadPostRequest0(ctx context.Context, req *tke.DescribeClustersRequest, resp *tke.DescribeClustersResponse) error { + if len(resp.Response.Clusters) == 0 { + return fmt.Errorf("The cluster has been deleted") + } + + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerCreatePostRequest0(ctx context.Context, req *tke.DescribeClustersRequest, resp *tke.DescribeClustersResponse) error { + if len(resp.Response.Clusters) == 0 { + return fmt.Errorf("The cluster has been deleted") + } + + CreateClusterInstancesVpcId = *resp.Response.Clusters[0].ClusterNetworkSettings.VpcId + projectIdUint64 := *resp.Response.Clusters[0].ProjectId + CreateClusterInstancesProjectId = int64(projectIdUint64) + + return nil +} + +func resourceTencentCloudKubernetesScaleWorkerReadPostFillRequest2(ctx context.Context, req *cvm.DescribeInstancesRequest) error { + req.InstanceIds = WorkersInstanceIds + return nil +} diff --git a/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker_test.go b/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker_test.go index 17616415af..a633a76cd7 100644 --- a/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker_test.go +++ b/tencentcloud/services/tke/resource_tc_kubernetes_scale_worker_test.go @@ -227,16 +227,13 @@ func testAccCheckTkeScaleWorkerExists(n string) resource.TestCheckFunc { } } -const testAccTkeScaleWorkerInstanceBasic = tcacctest.TkeExclusiveNetwork + tcacctest.TkeDataSource + tcacctest.DefaultSecurityGroupData +const testAccTkeScaleWorkerInstance = ` +resource "tencentcloud_kubernetes_scale_worker" "test_scale" { + cluster_id = "cls-r8gqwjw6" -const testAccTkeScaleWorkerInstance string = testAccTkeScaleWorkerInstanceBasic + ` - -resource tencentcloud_kubernetes_scale_worker test_scale { - cluster_id = local.cluster_id - extra_args = [ - "root-dir=/var/lib/kubelet" - ] + "root-dir=/var/lib/kubelet" + ] labels = { "test1" = "test1", @@ -246,13 +243,13 @@ resource tencentcloud_kubernetes_scale_worker test_scale { worker_config { count = 1 - availability_zone = var.default_az - instance_type = local.scale_instance_type - subnet_id = local.subnet_id + availability_zone = "ap-guangzhou-3" + instance_type = "S2.LARGE16" + subnet_id = "subnet-gaazc9di" system_disk_type = "CLOUD_SSD" system_disk_size = 50 internet_charge_type = "TRAFFIC_POSTPAID_BY_HOUR" - security_group_ids = [local.sg_id] + security_group_ids = ["sg-cm7fbbf3"] data_disk { disk_type = "CLOUD_PREMIUM" @@ -267,14 +264,13 @@ resource tencentcloud_kubernetes_scale_worker test_scale { } ` -const testAccTkeScaleWorkerInstanceGpuInsTypeUpdate string = testAccTkeScaleWorkerInstanceBasic + ` +const testAccTkeScaleWorkerInstanceGpuInsTypeUpdate = ` +resource "tencentcloud_kubernetes_scale_worker" "test_scale" { + cluster_id = "cls-r8gqwjw6" -resource tencentcloud_kubernetes_scale_worker test_scale { - cluster_id = local.cluster_id - extra_args = [ - "root-dir=/var/lib/kubelet" - ] + "root-dir=/var/lib/kubelet" + ] labels = { "test1" = "test1", @@ -283,39 +279,39 @@ resource tencentcloud_kubernetes_scale_worker test_scale { unschedulable = 0 worker_config { - count = 1 - availability_zone = var.default_az - instance_type = "GN6S.LARGE20" - subnet_id = local.subnet_id - system_disk_type = "CLOUD_SSD" - system_disk_size = 50 - internet_charge_type = "TRAFFIC_POSTPAID_BY_HOUR" - security_group_ids = [local.sg_id] - img_id = "img-eb30mz89" + count = 1 + availability_zone = "ap-guangzhou-3" + instance_type = "GN6S.LARGE20" + subnet_id = "subnet-gaazc9di" + system_disk_type = "CLOUD_SSD" + system_disk_size = 50 + internet_charge_type = "TRAFFIC_POSTPAID_BY_HOUR" + security_group_ids = ["sg-cm7fbbf3"] + img_id = "img-oyd1zdra" data_disk { disk_type = "CLOUD_PREMIUM" disk_size = 50 } - enhanced_security_service = false - enhanced_monitor_service = false - user_data = "dGVzdA==" - password = "AABBccdd1122" + enhanced_security_service = false + enhanced_monitor_service = false + user_data = "dGVzdA==" + password = "AABBccdd1122" } gpu_args { mig_enable = false - driver = { - name = "NVIDIA-Linux-x86_64-470.182.03.run" + driver = { + name = "NVIDIA-Linux-x86_64-470.182.03.run" version = "470.182.03" } cuda = { - name = "cuda_11.4.3_470.82.01_linux.run" + name = "cuda_11.4.3_470.82.01_linux.run" version = "11.4.3" } cudnn = { - name = "cudnn-11.4-linux-x64-v8.2.4.15.tgz" + name = "cudnn-11.4-linux-x64-v8.2.4.15.tgz" version = "8.2.4" } } diff --git a/tencentcloud/services/tke/service_tencentcloud_tke.go b/tencentcloud/services/tke/service_tencentcloud_tke.go index fc4618e132..43bb37ebac 100644 --- a/tencentcloud/services/tke/service_tencentcloud_tke.go +++ b/tencentcloud/services/tke/service_tencentcloud_tke.go @@ -3,6 +3,7 @@ package tke import ( "context" "fmt" + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" "log" "strings" @@ -1316,7 +1317,7 @@ func (me *TkeService) ModifyClusterVersion(ctx context.Context, id string, clust return } -func (me *TkeService) DescribeKubernetesAvailableClusterVersionsByFilter(ctx context.Context, param map[string]interface{}) (availableClusterVersions *tke.DescribeAvailableClusterVersionResponseParams, errRet error) { +func (me *TkeService) DescribeKubernetesAvailableClusterVersionsByFilter(ctx context.Context, param map[string]interface{}) (ret *tke.DescribeAvailableClusterVersionResponseParams, errRet error) { var ( logId = tccommon.GetLogId(ctx) request = tke.NewDescribeAvailableClusterVersionRequest() @@ -1329,10 +1330,10 @@ func (me *TkeService) DescribeKubernetesAvailableClusterVersionsByFilter(ctx con }() for k, v := range param { - if k == "cluster_id" { + if k == "ClusterId" { request.ClusterId = v.(*string) } - if k == "cluster_ids" { + if k == "ClusterIds" { request.ClusterIds = v.([]*string) } } @@ -1346,9 +1347,15 @@ func (me *TkeService) DescribeKubernetesAvailableClusterVersionsByFilter(ctx con } log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) - if response != nil { - availableClusterVersions = response.Response + if err := dataSourceTencentCloudKubernetesAvailableClusterVersionsReadPostRequest0(ctx, request, response); err != nil { + return nil, err + } + + if response == nil || response.Response == nil { + return } + + ret = response.Response return } @@ -2788,3 +2795,97 @@ func (me *TkeService) DescribeKubernetesClusterNodePoolsByFilter(ctx context.Con clusterNodePools = response.Response.NodePoolSet return } + +func (me *TkeService) DescribeKubernetesScaleWorkerById(ctx context.Context, clusterId string) (ret *tke.DescribeClustersResponseParams, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := tke.NewDescribeClustersRequest() + request.ClusterIds = []*string{&clusterId} + + if err := resourceTencentCloudKubernetesScaleWorkerReadPostFillRequest0(ctx, request); err != nil { + return nil, err + } + + 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 err = resourceTencentCloudKubernetesScaleWorkerReadPostRequest0(ctx, request, response); err != nil { + return nil, err + } + + ret = response.Response + return +} + +func (me *TkeService) DescribeKubernetesScaleWorkerById1(ctx context.Context, clusterId string) (ret *tke.DescribeClusterInstancesResponseParams, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := tke.NewDescribeClusterInstancesRequest() + request.ClusterId = &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().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 err = resourceTencentCloudKubernetesScaleWorkerReadPostRequest1(ctx, request, response); err != nil { + return nil, err + } + + ret = response.Response + return +} + +func (me *TkeService) DescribeKubernetesScaleWorkerById2(ctx context.Context) (ret *cvm.DescribeInstancesResponseParams, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := cvm.NewDescribeInstancesRequest() + + if err := resourceTencentCloudKubernetesScaleWorkerReadPostFillRequest2(ctx, request); err != nil { + return nil, err + } + + 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 err := resourceTencentCloudKubernetesScaleWorkerReadPostRequest2(ctx, request, response); err != nil { + return nil, err + } + + ret = response.Response + return +} diff --git a/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control.go b/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control.go new file mode 100644 index 0000000000..4624830126 --- /dev/null +++ b/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control.go @@ -0,0 +1,235 @@ +package tse + +import ( + "context" + "fmt" + "log" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + tse "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tse/v20201207" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func ResourceTencentCloudTseCngwNetworkAccessControl() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudTseCngwNetworkAccessControlCreate, + Read: resourceTencentCloudTseCngwNetworkAccessControlRead, + Update: resourceTencentCloudTseCngwNetworkAccessControlUpdate, + Delete: resourceTencentCloudTseCngwNetworkAccessControlDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "gateway_id": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "gateway ID.", + }, + + "group_id": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "gateway group ID.", + }, + + "network_id": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "network id.", + }, + + "access_control": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "access control policy.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Access mode: `Whitelist`, `Blacklist`.", + }, + "cidr_white_list": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "White list.", + }, + "cidr_black_list": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Black list.", + }, + }, + }, + }, + }, + } +} + +func resourceTencentCloudTseCngwNetworkAccessControlCreate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_tse_cngw_network_access_control.create")() + defer tccommon.InconsistentCheck(d, meta)() + + var ( + gatewayId string + groupId string + networkId string + ) + if v, ok := d.GetOk("gateway_id"); ok { + gatewayId = v.(string) + } + if v, ok := d.GetOk("group_id"); ok { + groupId = v.(string) + } + if v, ok := d.GetOk("network_id"); ok { + networkId = v.(string) + } + d.SetId(gatewayId + tccommon.FILED_SP + groupId + tccommon.FILED_SP + networkId) + + return resourceTencentCloudTseCngwNetworkAccessControlUpdate(d, meta) +} + +func resourceTencentCloudTseCngwNetworkAccessControlRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_tse_cngw_network_access_control.read")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + service := TseService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) != 3 { + return fmt.Errorf("id is broken,%s", d.Id()) + } + gatewayId := idSplit[0] + groupId := idSplit[1] + networkId := idSplit[2] + + cngwNetwork, err := service.DescribeTseCngwNetworkById(ctx, gatewayId, groupId, networkId) + if err != nil { + return err + } + + if cngwNetwork == nil { + d.SetId("") + log.Printf("[WARN]%s resource `TseCngwNetworkAccessControl` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil + } + + _ = d.Set("gateway_id", gatewayId) + _ = d.Set("group_id", groupId) + _ = d.Set("network_id", networkId) + + if cngwNetwork.PublicNetwork != nil { + internetConfig := cngwNetwork.PublicNetwork + if internetConfig.AccessControl != nil { + accessControlMap := map[string]interface{}{} + + accessControl := internetConfig.AccessControl + if accessControl.Mode != nil { + accessControlMap["mode"] = accessControl.Mode + } + if accessControl.Mode != nil { + accessControlMap["cidr_white_list"] = accessControl.CidrWhiteList + } + if accessControl.Mode != nil { + accessControlMap["cidr_black_list"] = accessControl.CidrBlackList + } + _ = d.Set("access_control", []interface{}{accessControlMap}) + } + } + + return nil +} + +func resourceTencentCloudTseCngwNetworkAccessControlUpdate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_tse_cngw_network_access_control.update")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + request := tse.NewModifyNetworkAccessStrategyRequest() + + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) != 3 { + return fmt.Errorf("id is broken,%s", d.Id()) + } + gatewayId := idSplit[0] + groupId := idSplit[1] + networkId := idSplit[2] + + service := TseService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + cngwNetwork, err := service.DescribeTseCngwNetworkById(ctx, gatewayId, groupId, networkId) + if err != nil { + return err + } + if cngwNetwork == nil { + return fmt.Errorf("[WARN]%s resource `TseCngwNetworkAccessControl` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + } + + request.GatewayId = helper.String(gatewayId) + request.GroupId = helper.String(groupId) + // The interface only supports public network + request.NetworkType = helper.String("Open") + request.Vip = cngwNetwork.PublicNetwork.Vip + + if d.HasChange("access_control") { + if dMap, ok := helper.InterfacesHeadMap(d, "access_control"); ok { + accessControl := tse.NetworkAccessControl{} + if v, ok := dMap["mode"]; ok { + accessControl.Mode = helper.String(v.(string)) + } + if v, ok := dMap["cidr_white_list"]; ok { + whitelist := v.([]interface{}) + accessControl.CidrWhiteList = helper.InterfacesStringsPoint(whitelist) + } + if v, ok := dMap["cidr_black_list"]; ok { + blacklist := v.([]interface{}) + accessControl.CidrBlackList = helper.InterfacesStringsPoint(blacklist) + } + request.AccessControl = &accessControl + } + } + + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseTseClient().ModifyNetworkAccessStrategy(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 tse cngwNetworkAccessStrategy failed, reason:%+v", logId, err) + return err + } + + conf := tccommon.BuildStateChangeConf([]string{}, []string{"Open"}, 5*tccommon.ReadRetryTimeout, time.Second, service.TseCngwNetworkStateRefreshFunc(gatewayId, groupId, networkId, []string{})) + + if _, e := conf.WaitForState(); e != nil { + return e + } + + return resourceTencentCloudTseCngwNetworkAccessControlRead(d, meta) +} + +func resourceTencentCloudTseCngwNetworkAccessControlDelete(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_tse_cngw_network_access_control.delete")() + defer tccommon.InconsistentCheck(d, meta)() + + return nil +} diff --git a/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control.md b/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control.md new file mode 100644 index 0000000000..802be65882 --- /dev/null +++ b/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control.md @@ -0,0 +1,23 @@ +Provides a resource to create a tse cngw_network_access_control + +Example Usage + +```hcl +resource "tencentcloud_tse_cngw_network_access_control" "cngw_network_access_control" { + gateway_id = "gateway-cf8c99c3" + group_id = "group-a160d123" + network_id = "network-372b1e84" + access_control { + mode = "Whitelist" + cidr_white_list = ["1.1.1.0"] + } +} +``` + +Import + +tse cngw_route_rate_limit can be imported using the id, e.g. + +``` +terraform import tencentcloud_tse_cngw_network_access_control.cngw_network_access_control gatewayId#groupId#networkId +``` \ No newline at end of file diff --git a/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control_test.go b/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control_test.go new file mode 100644 index 0000000000..2697bd8101 --- /dev/null +++ b/tencentcloud/services/tse/resource_tc_tse_cngw_network_access_control_test.go @@ -0,0 +1,48 @@ +package tse_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" +) + +func TestAccTencentCloudNeedFixTseCngwNetworkAccessControlResource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + tcacctest.AccPreCheck(t) + }, + Providers: tcacctest.AccProviders, + Steps: []resource.TestStep{ + { + Config: testAccTseCngwNetworkAccessControl, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("tencentcloud_tse_cngw_network_access_control.cngw_network_access_control", "id"), + resource.TestCheckResourceAttr("tencentcloud_tse_cngw_network_access_control.cngw_network_access_control", "access_control.#", "1"), + resource.TestCheckResourceAttr("tencentcloud_tse_cngw_network_access_control.cngw_network_access_control", "access_control.0.mode", "Whitelist"), + resource.TestCheckResourceAttr("tencentcloud_tse_cngw_network_access_control.cngw_network_access_control", "access_control.0.cidr_white_list.#", "1"), + ), + }, + { + ResourceName: "tencentcloud_tse_cngw_network_access_control.cngw_network_access_control", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +const testAccTseCngwNetworkAccessControl = ` + +resource "tencentcloud_tse_cngw_network_access_control" "cngw_network_access_control" { + gateway_id = "gateway-cf1790c7" + group_id = "group-d8d99615" + network_id = "network-9cd9821f" + access_control { + mode = "Whitelist" + cidr_white_list = ["1.1.1.0"] + } + } + +` diff --git a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go index 4bb304400a..217942ef87 100644 --- a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go @@ -234,6 +234,15 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource }, }, }, + "segment_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Segment type, valid when Format is HLS, optional values:\n" + + "- ts: ts segment;\n" + + "- fmp4: fmp4 segment;\n" + + "Default value: ts.", + }, // computed "create_time": { Type: schema.TypeString, @@ -257,6 +266,9 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res request = vod.NewCreateAdaptiveDynamicStreamingTemplateRequest() ) + if v, ok := d.GetOk("segment_type"); ok { + request.SegmentType = helper.String(v.(string)) + } request.Format = helper.String(d.Get("format").(string)) request.Name = helper.String(d.Get("name").(string)) if v, ok := d.GetOk("drm_type"); ok { @@ -403,6 +415,7 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateRead(d *schema.Resou _ = d.Set("comment", template.Comment) _ = d.Set("create_time", template.CreateTime) _ = d.Set("update_time", template.UpdateTime) + _ = d.Set("segment_type", template.SegmentType) var streamInfos = make([]interface{}, 0, len(template.StreamInfos)) for _, v := range template.StreamInfos { diff --git a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go index 59ec1ec241..d2346110a2 100644 --- a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go +++ b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go @@ -83,6 +83,7 @@ func TestAccTencentCloudVodAdaptiveDynamicStreamingTemplateResource(t *testing.T resource.TestCheckResourceAttrSet("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "create_time"), resource.TestCheckResourceAttrSet("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "update_time"), resource.TestCheckResourceAttrSet("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "sub_app_id"), + resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "segment_type", "ts"), ), }, { diff --git a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go index b0e8aaa928..3523cec212 100644 --- a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go @@ -334,6 +334,15 @@ func ResourceTencentCloudVodProcedureTemplate() *schema.Resource { Description: "List of up to `10` image or text watermarks. Note: this field may return null, indicating that no valid values can be obtained.", Elem: VodWatermarkResource(), }, + "subtitle_list": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "Subtitle list, element is subtitle ID, support multiple subtitles, up to 16.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, }, }, }, @@ -393,6 +402,12 @@ func ResourceTencentCloudVodProcedureTemplate() *schema.Resource { "- `Media`: The original audio/video;\n" + "- `Cover`: Thumbnails.", }, + "definition": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Review template.", + }, }, }, }, @@ -724,6 +739,17 @@ func generateMediaProcessTask(d *schema.ResourceData) (mediaReq *vod.MediaProces return &idUint }(item["definition"].(string)), WatermarkSet: genWatermarkList(item), + SubtitleSet: func() (list []*string) { + if _, ok := item["subtitle_list"]; !ok { + return nil + } + subtitleList := item["subtitle_list"].([]interface{}) + list = make([]*string, 0, len(subtitleList)) + for _, subTitle := range subtitleList { + list = append(list, helper.String(subTitle.(string))) + } + return list + }(), }) } mediaReq.AdaptiveDynamicStreamingTaskSet = adaptiveReq @@ -1084,6 +1110,16 @@ func resourceTencentCloudVodProcedureTemplateRead(d *schema.ResourceData, meta i } return waterList }(), + "subtitle_list": func() interface{} { + if item.SubtitleSet == nil { + return nil + } + subtitleList := make([]interface{}, 0, len(item.SubtitleSet)) + for _, subtitleV := range item.SubtitleSet { + subtitleList = append(subtitleList, subtitleV) + } + return subtitleList + }(), }) } mediaProcessTaskElem["adaptive_dynamic_streaming_task_list"] = list diff --git a/website/docs/d/mariadb_db_instances.html.markdown b/website/docs/d/mariadb_db_instances.html.markdown index b68a482821..0a8263d49d 100644 --- a/website/docs/d/mariadb_db_instances.html.markdown +++ b/website/docs/d/mariadb_db_instances.html.markdown @@ -41,6 +41,9 @@ In addition to all arguments above, the following attributes are exported: * `db_version_id` - db version id. * `instance_id` - instance id. * `instance_name` - instance name. + * `internet_domain` - Public network access domain name. + * `internet_ip` - Public IP address. + * `internet_port` - Public network port. * `memory` - meory of instance. * `project_id` - project id. * `region` - region. @@ -49,7 +52,9 @@ In addition to all arguments above, the following attributes are exported: * `tag_value` - tag value. * `storage` - storage of instance. * `subnet_id` - subnet id. + * `vip` - Intranet IP address. * `vpc_id` - vpc id. + * `vport` - Intranet port. * `zone` - available zone. diff --git a/website/docs/r/tse_cngw_network_access_control.html.markdown b/website/docs/r/tse_cngw_network_access_control.html.markdown new file mode 100644 index 0000000000..bdf84b4e7d --- /dev/null +++ b/website/docs/r/tse_cngw_network_access_control.html.markdown @@ -0,0 +1,58 @@ +--- +subcategory: "Tencent Cloud Service Engine(TSE)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_tse_cngw_network_access_control" +sidebar_current: "docs-tencentcloud-resource-tse_cngw_network_access_control" +description: |- + Provides a resource to create a tse cngw_network_access_control +--- + +# tencentcloud_tse_cngw_network_access_control + +Provides a resource to create a tse cngw_network_access_control + +## Example Usage + +```hcl +resource "tencentcloud_tse_cngw_network_access_control" "cngw_network_access_control" { + gateway_id = "gateway-cf8c99c3" + group_id = "group-a160d123" + network_id = "network-372b1e84" + access_control { + mode = "Whitelist" + cidr_white_list = ["1.1.1.0"] + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `gateway_id` - (Required, String, ForceNew) gateway ID. +* `group_id` - (Required, String, ForceNew) gateway group ID. +* `network_id` - (Required, String, ForceNew) network id. +* `access_control` - (Optional, List) access control policy. + +The `access_control` object supports the following: + +* `cidr_black_list` - (Optional, List) Black list. +* `cidr_white_list` - (Optional, List) White list. +* `mode` - (Optional, String) Access mode: `Whitelist`, `Blacklist`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the resource. + + + +## Import + +tse cngw_route_rate_limit can be imported using the id, e.g. + +``` +terraform import tencentcloud_tse_cngw_network_access_control.cngw_network_access_control gatewayId#groupId#networkId +``` + diff --git a/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown b/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown index 01e00af27e..faa5735271 100644 --- a/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown +++ b/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown @@ -59,6 +59,10 @@ The following arguments are supported: * `disable_higher_video_bitrate` - (Optional, Bool) Whether to prohibit transcoding video from low bitrate to high bitrate. Valid values: `false`,`true`. `false`: no, `true`: yes. Default value: `false`. * `disable_higher_video_resolution` - (Optional, Bool) Whether to prohibit transcoding from low resolution to high resolution. Valid values: `false`,`true`. `false`: no, `true`: yes. Default value: `false`. * `drm_type` - (Optional, String, ForceNew) DRM scheme type. Valid values: `SimpleAES`. If this field is an empty string, DRM will not be performed on the video. +* `segment_type` - (Optional, String) Segment type, valid when Format is HLS, optional values: +- ts: ts segment; +- fmp4: fmp4 segment; +Default value: ts. * `sub_app_id` - (Optional, Int) The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID. The `audio` object of `stream_info` supports the following: diff --git a/website/docs/r/vod_procedure_template.html.markdown b/website/docs/r/vod_procedure_template.html.markdown index 659db1466a..4ae5da1441 100644 --- a/website/docs/r/vod_procedure_template.html.markdown +++ b/website/docs/r/vod_procedure_template.html.markdown @@ -155,6 +155,7 @@ The following arguments are supported: The `adaptive_dynamic_streaming_task_list` object of `media_process_task` supports the following: * `definition` - (Required, String) Adaptive bitrate streaming template ID. +* `subtitle_list` - (Optional, List) Subtitle list, element is subtitle ID, support multiple subtitles, up to 16. * `watermark_list` - (Optional, List) List of up to `10` image or text watermarks. Note: this field may return null, indicating that no valid values can be obtained. The `ai_analysis_task` object supports the following: @@ -212,6 +213,7 @@ The `mosaic_list` object of `transcode_task_list` supports the following: The `review_audio_video_task` object supports the following: +* `definition` - (Optional, String) Review template. * `review_contents` - (Optional, List) The type of moderated content. Valid values: - `Media`: The original audio/video; - `Cover`: Thumbnails. diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index 92074bdab9..9544693b76 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -4397,6 +4397,9 @@
  • tencentcloud_tse_cngw_network
  • +
  • + tencentcloud_tse_cngw_network_access_control +
  • tencentcloud_tse_cngw_route
  • @@ -5881,9 +5884,6 @@
  • tencentcloud_vod_sub_application
  • -
  • - tencentcloud_vod_super_player_config -
  • tencentcloud_vod_transcode_template