diff --git a/.changelog/3205.txt b/.changelog/3205.txt new file mode 100644 index 0000000000..5cfd819fe2 --- /dev/null +++ b/.changelog/3205.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/tencentcloud_elasticsearch_instance: Support for public_access fields. +``` \ No newline at end of file diff --git a/tencentcloud/services/es/extension_elasticsearch.go b/tencentcloud/services/es/extension_elasticsearch.go index cd680f21b2..b1b50d9324 100644 --- a/tencentcloud/services/es/extension_elasticsearch.go +++ b/tencentcloud/services/es/extension_elasticsearch.go @@ -34,6 +34,8 @@ const ( ES_KIBANA_PUBLIC_ACCESS_OPEN = "OPEN" ES_KIBANA_PUBLIC_ACCESS_CLOSE = "CLOSE" + ES_PUBLIC_ACCESS_OPEN = "OPEN" + ES_PUBLIC_ACCESS_CLOSE = "CLOSE" ) var ES_CHARGE_TYPE = []string{ @@ -81,3 +83,8 @@ var ES_KIBANA_PUBLIC_ACCESS = []string{ ES_KIBANA_PUBLIC_ACCESS_OPEN, ES_KIBANA_PUBLIC_ACCESS_CLOSE, } + +var ES_PUBLIC_ACCESS = []string{ + ES_PUBLIC_ACCESS_OPEN, + ES_PUBLIC_ACCESS_CLOSE, +} diff --git a/tencentcloud/services/es/resource_tc_elasticsearch_instance.go b/tencentcloud/services/es/resource_tc_elasticsearch_instance.go index 1670b6fe48..47a07a6f2d 100644 --- a/tencentcloud/services/es/resource_tc_elasticsearch_instance.go +++ b/tencentcloud/services/es/resource_tc_elasticsearch_instance.go @@ -263,6 +263,39 @@ func ResourceTencentCloudElasticsearchInstance() *schema.Resource { }, }, }, + "public_access": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: tccommon.ValidateAllowedStringValue(ES_PUBLIC_ACCESS), + Description: "ES cluster public network access status. Valid values are `OPEN` and `CLOSE`. Cannot be changed at the same time as `es_acl`.", + }, + "es_public_acl": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + RequiredWith: []string{"public_access"}, + Description: "Public network access control list.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + // "black_ip_list": { + // Type: schema.TypeSet, + // Elem: &schema.Schema{Type: schema.TypeString}, + // Optional: true, + // Computed: true, + // Description: "Access blacklist.", + // }, + "white_ip_list": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + Computed: true, + Description: "Access Whitelist.", + }, + }, + }, + }, // computed "elasticsearch_domain": { Type: schema.TypeString, @@ -284,6 +317,11 @@ func ResourceTencentCloudElasticsearchInstance() *schema.Resource { Computed: true, Description: "Kibana access URL.", }, + "es_public_url": { + Type: schema.TypeString, + Computed: true, + Description: "Es public network address.", + }, "create_time": { Type: schema.TypeString, Computed: true, @@ -469,9 +507,56 @@ func resourceTencentCloudElasticsearchInstanceCreate(d *schema.ResourceData, met isUpdate = true } } + + if isUpdate { + err = resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", kibanaPublicAccess, "", 0, nil, nil, &esAcl, nil, nil) + if errRet != nil { + return tccommon.RetryError(errRet) + } + return nil + }) + if err != nil { + return err + } + + err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId) + if err != nil { + return err + } + + isUpdate = false + } + + // PublicAccess + var publicAccess string + esPublicAcl := es.EsPublicAcl{} + if v, ok := d.GetOk("public_access"); ok { + access := v.(string) + if access != ES_PUBLIC_ACCESS_CLOSE { + publicAccess = access + isUpdate = true + + if aclMap, ok := helper.InterfacesHeadMap(d, "es_public_acl"); ok { + // if v, ok := aclMap["black_ip_list"]; ok { + // bList := v.(*schema.Set).List() + // for _, d := range bList { + // esPublicAcl.BlackIpList = append(esPublicAcl.BlackIpList, helper.String(d.(string))) + // } + // } + if v, ok := aclMap["white_ip_list"]; ok { + wList := v.(*schema.Set).List() + for _, d := range wList { + esPublicAcl.WhiteIpList = append(esPublicAcl.WhiteIpList, helper.String(d.(string))) + } + } + } + } + } + if isUpdate { err = resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", kibanaPublicAccess, 0, nil, nil, &esAcl, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", publicAccess, 0, nil, nil, nil, nil, &esPublicAcl) if errRet != nil { return tccommon.RetryError(errRet) } @@ -501,7 +586,7 @@ func resourceTencentCloudElasticsearchInstanceCreate(d *schema.ResourceData, met } err = resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", 0, nil, nil, nil, &cosBackup) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", 0, nil, nil, nil, &cosBackup, nil) if errRet != nil { return tccommon.RetryError(errRet) } @@ -625,6 +710,24 @@ func resourceTencentCloudElasticsearchInstanceRead(d *schema.ResourceData, meta _ = d.Set("es_acl", esAcls) } + if instance.EsPublicAcl != nil { + esAcls := make([]map[string]interface{}, 0, 1) + esAcl := map[string]interface{}{ + // "black_ip_list": instance.EsPublicAcl.BlackIpList, + "white_ip_list": instance.EsPublicAcl.WhiteIpList, + } + esAcls = append(esAcls, esAcl) + _ = d.Set("es_public_acl", esAcls) + } + + if instance.PublicAccess != nil { + _ = d.Set("public_access", instance.PublicAccess) + } + + if instance.EsPublicUrl != nil { + _ = d.Set("es_public_url", instance.EsPublicUrl) + } + if instance.CosBackup != nil { cosBackupList := make([]map[string]interface{}, 0, 1) cosBackupMap := map[string]interface{}{} @@ -667,7 +770,7 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met instanceName := d.Get("instance_name").(string) // Update operation support at most one item at the same time err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, instanceName, "", "", 0, nil, nil, nil, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, instanceName, "", "", "", 0, nil, nil, nil, nil, nil) if errRet != nil { return tccommon.RetryError(errRet) } @@ -684,7 +787,7 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met if d.HasChange("password") { password := d.Get("password").(string) err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", password, "", 0, nil, nil, nil, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", password, "", "", 0, nil, nil, nil, nil, nil) if errRet != nil { return tccommon.RetryError(errRet) } @@ -703,7 +806,7 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met if d.HasChange("kibana_public_access") { if v, ok := d.GetOk("kibana_public_access"); ok { err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", v.(string), 0, nil, nil, nil, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", v.(string), "", 0, nil, nil, nil, nil, nil) if errRet != nil { return tccommon.RetryError(errRet) } @@ -762,7 +865,7 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met licenseType := d.Get("license_type").(string) licenseTypeUpgrading := licenseType != "oss" err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", int64(basicSecurityType), nil, nil, nil, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", int64(basicSecurityType), nil, nil, nil, nil, nil) if errRet != nil { err := errRet.(*sdkErrors.TencentCloudSDKError) if err.Code == es.INVALIDPARAMETER && licenseTypeUpgrading { @@ -793,7 +896,7 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met NodeType: helper.String(value["node_type"].(string)), } err = resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", 0, nil, info, nil, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", 0, nil, info, nil, nil, nil) if errRet != nil { return tccommon.RetryError(errRet) } @@ -832,7 +935,44 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met nodeInfoList = append(nodeInfoList, &dataDisk) } err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", 0, nodeInfoList, nil, nil, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", 0, nodeInfoList, nil, nil, nil, nil) + if errRet != nil { + return tccommon.RetryError(errRet) + } + return nil + }) + if err != nil { + return err + } + err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId) + if err != nil { + return err + } + } + + if d.HasChange("public_access") || d.HasChange("es_public_acl") { + var publicAccess string + esPublicAcl := es.EsPublicAcl{} + if v, ok := d.GetOk("public_access"); ok { + publicAccess = v.(string) + } + + if aclMap, ok := helper.InterfacesHeadMap(d, "es_public_acl"); ok { + // if v, ok := aclMap["black_ip_list"]; ok { + // bList := v.(*schema.Set).List() + // for _, d := range bList { + // esPublicAcl.BlackIpList = append(esPublicAcl.BlackIpList, helper.String(d.(string))) + // } + // } + if v, ok := aclMap["white_ip_list"]; ok { + wList := v.(*schema.Set).List() + for _, d := range wList { + esPublicAcl.WhiteIpList = append(esPublicAcl.WhiteIpList, helper.String(d.(string))) + } + } + } + err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", publicAccess, 0, nil, nil, nil, nil, &esPublicAcl) if errRet != nil { return tccommon.RetryError(errRet) } @@ -883,7 +1023,7 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met } err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", 0, nil, nil, &esAcl, nil) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", 0, nil, nil, &esAcl, nil, nil) if errRet != nil { return tccommon.RetryError(errRet) } @@ -913,7 +1053,7 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met } err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError { - errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", 0, nil, nil, nil, &cosBackup) + errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", 0, nil, nil, nil, &cosBackup, nil) if errRet != nil { return tccommon.RetryError(errRet) } diff --git a/tencentcloud/services/es/resource_tc_elasticsearch_instance_test.go b/tencentcloud/services/es/resource_tc_elasticsearch_instance_test.go index bf4e7daed3..09df23be3b 100644 --- a/tencentcloud/services/es/resource_tc_elasticsearch_instance_test.go +++ b/tencentcloud/services/es/resource_tc_elasticsearch_instance_test.go @@ -133,6 +133,10 @@ func TestAccTencentCloudElasticsearchInstanceResource_kibanaPublicAccess(t *test Check: resource.ComposeTestCheckFunc( testAccCheckElasticsearchInstanceExists("tencentcloud_elasticsearch_instance.es_kibana"), resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "kibana_public_access", "OPEN"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "public_access", "OPEN"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "es_public_acl.#", "1"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "es_public_acl.0.white_ip_list.#", "1"), + resource.TestCheckResourceAttrSet("tencentcloud_elasticsearch_instance.es_kibana", "es_public_url"), ), }, { @@ -140,6 +144,9 @@ func TestAccTencentCloudElasticsearchInstanceResource_kibanaPublicAccess(t *test Check: resource.ComposeTestCheckFunc( testAccCheckElasticsearchInstanceExists("tencentcloud_elasticsearch_instance.es_kibana"), resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "kibana_public_access", "CLOSE"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "public_access", "CLOSE"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "es_public_acl.#", "1"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "es_public_acl.0.white_ip_list.#", "1"), ), }, { @@ -147,6 +154,9 @@ func TestAccTencentCloudElasticsearchInstanceResource_kibanaPublicAccess(t *test Check: resource.ComposeTestCheckFunc( testAccCheckElasticsearchInstanceExists("tencentcloud_elasticsearch_instance.es_kibana"), resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "kibana_public_access", "OPEN"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "public_access", "OPEN"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "es_public_acl.#", "1"), + resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_kibana", "es_public_acl.0.white_ip_list.#", "1"), ), }, }, @@ -298,6 +308,12 @@ resource "tencentcloud_elasticsearch_instance" "es_kibana" { license_type = "basic" basic_security_type = 2 kibana_public_access = "CLOSE" + public_access = "CLOSE" + es_public_acl { + white_ip_list = [ + "127.0.0.1" + ] + } node_info_list { node_num = 2 @@ -317,6 +333,12 @@ resource "tencentcloud_elasticsearch_instance" "es_kibana" { license_type = "basic" basic_security_type = 2 kibana_public_access = "OPEN" + public_access = "OPEN" + es_public_acl { + white_ip_list = [ + "127.0.0.1" + ] + } node_info_list { node_num = 2 diff --git a/tencentcloud/services/es/service_tencentcloud_elasticsearch.go b/tencentcloud/services/es/service_tencentcloud_elasticsearch.go index 27b89c9b95..6a5a36458b 100644 --- a/tencentcloud/services/es/service_tencentcloud_elasticsearch.go +++ b/tencentcloud/services/es/service_tencentcloud_elasticsearch.go @@ -107,7 +107,8 @@ func (me *ElasticsearchService) DeleteInstance(ctx context.Context, instanceId s } // UpdateInstance FIXME: use *Request instead of these suck params -func (me *ElasticsearchService) UpdateInstance(ctx context.Context, instanceId, instanceName, password, kibanaPublicAccess string, basicSecurityType int64, nodeList []*es.NodeInfo, nodeTypeInfo *es.WebNodeTypeInfo, esAcl *es.EsAcl, cosBackup *es.CosBackup) error { +func (me *ElasticsearchService) UpdateInstance(ctx context.Context, instanceId, instanceName, password, kibanaPublicAccess, publicAccess string, + basicSecurityType int64, nodeList []*es.NodeInfo, nodeTypeInfo *es.WebNodeTypeInfo, esAcl *es.EsAcl, cosBackup *es.CosBackup, esPublicAcl *es.EsPublicAcl) error { logId := tccommon.GetLogId(ctx) request := es.NewUpdateInstanceRequest() request.InstanceId = &instanceId @@ -135,6 +136,12 @@ func (me *ElasticsearchService) UpdateInstance(ctx context.Context, instanceId, if cosBackup != nil { request.CosBackup = cosBackup } + if publicAccess != "" { + request.PublicAccess = &publicAccess + } + if esPublicAcl != nil && (0 != len(esPublicAcl.BlackIpList) || 0 != len(esPublicAcl.WhiteIpList)) { + request.EsPublicAcl = esPublicAcl + } ratelimit.Check(request.GetAction()) _, err := me.client.UseEsClient().UpdateInstance(request) if err != nil { diff --git a/website/docs/r/elasticsearch_instance.html.markdown b/website/docs/r/elasticsearch_instance.html.markdown index ca66992d42..5ae4f8813d 100644 --- a/website/docs/r/elasticsearch_instance.html.markdown +++ b/website/docs/r/elasticsearch_instance.html.markdown @@ -171,10 +171,12 @@ The following arguments are supported: * `cos_backup` - (Optional, List) COS automatic backup information. * `deploy_mode` - (Optional, Int, ForceNew) Cluster deployment mode. Valid values are `0` and `1`. `0` is single-AZ deployment, and `1` is multi-AZ deployment. Default value is `0`. * `es_acl` - (Optional, List) Kibana Access Control Configuration. +* `es_public_acl` - (Optional, List) Public network access control list. * `instance_name` - (Optional, String) Name of the instance, which can contain 1 to 50 English letters, Chinese characters, digits, dashes(-), or underscores(_). * `kibana_public_access` - (Optional, String) Kibana public network access status. Valid values are `OPEN` and `CLOSE`. * `license_type` - (Optional, String) License type. Valid values are `oss`, `basic` and `platinum`. The default value is `platinum`. * `multi_zone_infos` - (Optional, List, ForceNew) Details of AZs in multi-AZ deployment mode (which is required when deploy_mode is `1`). +* `public_access` - (Optional, String) ES cluster public network access status. Valid values are `OPEN` and `CLOSE`. Cannot be changed at the same time as `es_acl`. * `renew_flag` - (Optional, String, ForceNew) When enabled, the instance will be renew automatically when it reach the end of the prepaid tenancy. Valid values are `RENEW_FLAG_AUTO` and `RENEW_FLAG_MANUAL`. NOTE: it only works when charge_type is set to `PREPAID`. * `subnet_id` - (Optional, String, ForceNew) The ID of a VPC subnetwork. When create multi-az es, this parameter must be omitted or `-`. * `tags` - (Optional, Map) A mapping of tags to assign to the instance. For tag limits, please refer to [Use Limits](https://intl.cloud.tencent.com/document/product/651/13354). @@ -190,6 +192,10 @@ The `es_acl` object supports the following: * `black_list` - (Optional, Set) Blacklist of kibana access. * `white_list` - (Optional, Set) Whitelist of kibana access. +The `es_public_acl` object supports the following: + +* `white_ip_list` - (Optional, Set) Access Whitelist. + The `multi_zone_infos` object supports the following: * `availability_zone` - (Required, String) Availability zone. @@ -218,6 +224,7 @@ In addition to all arguments above, the following attributes are exported: * `elasticsearch_domain` - Elasticsearch domain name. * `elasticsearch_port` - Elasticsearch port. * `elasticsearch_vip` - Elasticsearch VIP. +* `es_public_url` - Es public network address. * `kibana_url` - Kibana access URL.