From ff8dabdb8959d4f2fa683a9945a0de66932da49e Mon Sep 17 00:00:00 2001 From: hellertang Date: Fri, 18 Oct 2024 14:51:27 +0800 Subject: [PATCH 1/3] support default domain --- ...resource_tc_clb_listener_default_domain.go | 430 ++++++++++++++++++ 1 file changed, 430 insertions(+) create mode 100644 tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go diff --git a/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go b/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go new file mode 100644 index 0000000000..4cb98cc965 --- /dev/null +++ b/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go @@ -0,0 +1,430 @@ +package clb + +import ( + "context" + "fmt" + "log" + "strings" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pkg/errors" + clb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317" + + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func ResourceTencentCloudClbListenerDefaultDomain() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudClbListenerDefaultDomainCreate, + Read: resourceTencentCloudClbListenerDefaultDomainRead, + Update: resourceTencentCloudClbListenerDefaultDomainUpdate, + Delete: resourceTencentCloudClbListenerDefaultDomainDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "clb_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "ID of CLB instance.", + }, + "listener_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "ID of CLB listener.", + }, + "domain": { + Type: schema.TypeString, + Required: true, + Computed: true, + Description: "Domain name of the listener rule. Single domain rules are passed to `domain`, and multi domain rules are passed to `domains`.", + }, + }, + } +} + +func resourceTencentCloudClbListenerDefaultDomainCreate(d *schema.ResourceData, meta interface{}) error { + var ( + logId = tccommon.GetLogId(tccommon.ContextNil) + request = clb.NewModifyDomainAttributesRequest() + response *clb.ModifyDomainAttributesResponse + ) + + if v, ok := d.GetOk("clb_id"); ok { + request.LoadBalancerId = helper.String(v.(string)) + } + + if v, ok := d.GetOk("listener_id"); ok { + request.ListenerId = helper.String(v.(string)) + } + + if v, ok := d.GetOk("domain"); ok { + request.Domain = helper.String(v.(string)) + } + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient().ModifyDomainAttributes(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 result == nil { + e = fmt.Errorf("create cls topic failed") + return resource.NonRetryableError(e) + } + + response = result + return nil + }) + + if err != nil { + log.Printf("[CRITAL]%s create cls topic failed, reason:%+v", logId, err) + return err + } + + taskId := *response.Response.RequestId + + d.SetId(id) + return resourceTencentCloudClbListenerDefaultDomainRead(d, meta) +} + +func resourceTencentCloudClbListenerDefaultDomainRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_rule.read")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + resourceId := d.Id() + var locationId = resourceId + items := strings.Split(resourceId, tccommon.FILED_SP) + itemLength := len(items) + clbId := d.Get("clb_id").(string) + listenerId := d.Get("listener_id").(string) + checkErr := ListenerIdCheck(listenerId) + if checkErr != nil { + return checkErr + } + if itemLength == 1 && clbId == "" { + return fmt.Errorf("The old style listenerId %s does not support import, please use clbId#listenerId style", resourceId) + } else if itemLength == 3 && clbId == "" { + locationId = items[2] + listenerId = items[1] + clbId = items[0] + } else if itemLength == 3 && clbId != "" { + locationId = items[2] + listenerId = items[1] + } else if itemLength != 1 && itemLength != 3 { + return fmt.Errorf("broken ID %s", resourceId) + } + + clbService := ClbService{ + client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + } + //this function is not supported by api, need to be travelled + filter := map[string]string{"rule_id": locationId, "listener_id": listenerId, "clb_id": clbId} + var instances []*clb.RuleOutput + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + results, e := clbService.DescribeRulesByFilter(ctx, filter) + if e != nil { + return tccommon.RetryError(e) + } + instances = results + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s read CLB listener rule failed, reason:%+v", logId, err) + return err + } + + if len(instances) == 0 { + d.SetId("") + return nil + } + + instance := instances[0] + _ = d.Set("clb_id", clbId) + _ = d.Set("listener_id", listenerId) + if instance.Domain != nil { + _ = d.Set("domain", instance.Domain) + } + + if instance.Domains != nil { + _ = d.Set("domains", helper.StringsInterfaces(instance.Domains)) + } + + _ = d.Set("rule_id", instance.LocationId) + _ = d.Set("url", instance.Url) + _ = d.Set("scheduler", instance.Scheduler) + _ = d.Set("session_expire_time", instance.SessionExpireTime) + _ = d.Set("target_type", instance.TargetType) + _ = d.Set("forward_type", instance.ForwardType) + _ = d.Set("http2_switch", instance.Http2) + + if instance.QuicStatus != nil { + if *instance.QuicStatus == "QUIC_ACTIVE" { + _ = d.Set("quic", true) + } else { + _ = d.Set("quic", false) + } + } + + //health check + if instance.HealthCheck != nil { + health_check_switch := false + if *instance.HealthCheck.HealthSwitch == int64(1) { + health_check_switch = true + } + _ = d.Set("health_check_switch", health_check_switch) + _ = d.Set("health_check_interval_time", instance.HealthCheck.IntervalTime) + _ = d.Set("health_check_health_num", instance.HealthCheck.HealthNum) + _ = d.Set("health_check_unhealth_num", instance.HealthCheck.UnHealthNum) + _ = d.Set("health_check_http_method", helper.String(strings.ToUpper(*instance.HealthCheck.HttpCheckMethod))) + _ = d.Set("health_check_http_domain", instance.HealthCheck.HttpCheckDomain) + _ = d.Set("health_check_http_path", instance.HealthCheck.HttpCheckPath) + _ = d.Set("health_check_http_code", instance.HealthCheck.HttpCode) + _ = d.Set("health_check_type", instance.HealthCheck.CheckType) + _ = d.Set("health_check_time_out", instance.HealthCheck.TimeOut) + } + + if instance.Certificate != nil { + _ = d.Set("certificate_ssl_mode", instance.Certificate.SSLMode) + _ = d.Set("certificate_id", instance.Certificate.CertId) + if instance.Certificate.CertCaId != nil { + _ = d.Set("certificate_ca_id", instance.Certificate.CertCaId) + } + } + + return nil +} + +func resourceTencentCloudClbListenerDefaultDomainUpdate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_rule.update")() + + clbActionMu.Lock() + defer clbActionMu.Unlock() + + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + resourceId := d.Id() + items := strings.Split(resourceId, tccommon.FILED_SP) + itemLength := len(items) + locationId := items[itemLength-1] + listenerId := d.Get("listener_id").(string) + checkErr := ListenerIdCheck(listenerId) + if checkErr != nil { + return checkErr + } + clbId := d.Get("clb_id").(string) + protocol := "" + //get listener protocol + clbService := ClbService{ + client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + instance, e := clbService.DescribeListenerById(ctx, listenerId, clbId) + if e != nil { + return tccommon.RetryError(e) + } + protocol = *(instance.Protocol) + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s get CLB listener failed, reason:%s\n ", logId, err.Error()) + return err + } + + changed := false + url := "" + scheduler := "" + sessionExpireTime := 0 + + request := clb.NewModifyRuleRequest() + request.ListenerId = helper.String(listenerId) + request.LoadBalancerId = helper.String(clbId) + request.LocationId = helper.String(locationId) + if d.HasChange("url") { + changed = true + url = d.Get("url").(string) + request.Url = helper.String(url) + } + + if d.HasChange("forward_type") { + changed = true + request.ForwardType = helper.String(d.Get("forward_type").(string)) + } + + if d.HasChange("scheduler") { + changed = true + scheduler = d.Get("scheduler").(string) + if !(protocol == CLB_LISTENER_PROTOCOL_HTTP || protocol == CLB_LISTENER_PROTOCOL_HTTPS) { + return fmt.Errorf("[CHECK][CLB listener rule %s][Update] check: Scheduler can only be set with listener protocol TCP/UDP/TCP_SSL or rule of listener HTTP/HTTPS", locationId) + } + request.Scheduler = helper.String(scheduler) + } + + if d.HasChange("session_expire_time") { + changed = true + sessionExpireTime = d.Get("session_expire_time").(int) + if !(protocol == CLB_LISTENER_PROTOCOL_HTTP || protocol == CLB_LISTENER_PROTOCOL_HTTPS) { + return fmt.Errorf("[CHECK][CLB listener rule %s][Update] check: session_expire_time can only be set with protocol TCP/UDP or rule of listener HTTP/HTTPS", locationId) + } + if scheduler != CLB_LISTENER_SCHEDULER_WRR && scheduler != "" { + return fmt.Errorf("[CHECK][CLB listener rule %s][Update] check: session_expire_time can only be set when scheduler is WRR", locationId) + } + sessionExpireTime64 := int64(sessionExpireTime) + request.SessionExpireTime = &sessionExpireTime64 + } + + healthSetFlag, healthCheck, healthErr := checkHealthCheckPara(ctx, d, protocol, HEALTH_APPLY_TYPE_RULE) + if healthErr != nil { + return healthErr + } + + if healthSetFlag { + changed = true + request.HealthCheck = healthCheck + } + + if changed { + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + response, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient().ModifyRule(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(), response.ToJsonString()) + requestId := *response.Response.RequestId + retryErr := waitForTaskFinish(requestId, meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient()) + if retryErr != nil { + return resource.NonRetryableError(errors.WithStack(retryErr)) + } + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s update CLB listener rule failed, reason:%+v", logId, err) + return err + } + } + + //modify domain and ssl + domainChanged := false + domainRequest := clb.NewModifyDomainAttributesRequest() + if d.HasChange("domain") { + old, new := d.GetChange("domain") + domainChanged = true + domainRequest.Domain = helper.String(old.(string)) + domainRequest.NewDomain = helper.String(new.(string)) + } else { + domainRequest.Domain = helper.String(d.Get("domain").(string)) + } + + if d.HasChange("certificate_id") || d.HasChange("certificate_ca_id ") || d.HasChange("certificate_ssl_mode") { + domainChanged = true + certificateSetFlag, certificateInput, certErr := checkCertificateInputPara(ctx, d, meta) + if certErr != nil { + return certErr + } + if certificateSetFlag { + if !(protocol == CLB_LISTENER_PROTOCOL_HTTPS) { + return fmt.Errorf("[CHECK][CLB listener rule][Create] check: certificate para can only be set with rule of linstener with protocol 'HTTPS'") + } + domainRequest.Certificate = certificateInput + } + } + + if d.HasChange("http2_switch") { + if v, ok := d.GetOkExists("http2_switch"); ok { + if !(protocol == CLB_LISTENER_PROTOCOL_HTTPS) { + return fmt.Errorf("[CHECK][CLB listener rule][Create] check: certificate para can only be set with rule of linstener with protocol 'HTTPS'") + } + domainChanged = true + domainRequest.Http2 = helper.Bool(v.(bool)) + } + } + + if d.HasChange("quic") { + domainChanged = true + if v, ok := d.GetOkExists("quic"); ok { + domainRequest.Quic = helper.Bool(v.(bool)) + } + } + + if domainChanged { + domainRequest.ListenerId = &listenerId + domainRequest.LoadBalancerId = &clbId + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + response, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient().ModifyDomainAttributes(domainRequest) + if e != nil { + if err := processRetryErrMsg(e); err != nil { + return err + } + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", + logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + requestId := *response.Response.RequestId + retryErr := waitForTaskFinish(requestId, meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient()) + if retryErr != nil { + return resource.NonRetryableError(errors.WithStack(retryErr)) + } + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s update CLB listener rule failed, reason:%+v", logId, err) + return err + } + } + + return nil +} + +func resourceTencentCloudClbListenerDefaultDomainDelete(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_domain_default.delete")() + + clbActionMu.Lock() + defer clbActionMu.Unlock() + + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + resourceId := d.Id() + items := strings.Split(resourceId, tccommon.FILED_SP) + itemLength := len(items) + locationId := items[itemLength-1] + listenerId := d.Get("listener_id").(string) + checkErr := ListenerIdCheck(listenerId) + if checkErr != nil { + return checkErr + } + clbId := d.Get("clb_id").(string) + + clbService := ClbService{ + client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + e := clbService.DeleteRuleById(ctx, clbId, listenerId, locationId) + if e != nil { + if err := processRetryErrMsg(e); err != nil { + return err + } + return tccommon.RetryError(e) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s delete CLB listener rule failed, reason:%+v", logId, err) + return err + } + return nil +} From 8e01775598894749d4caaf0113a952f32b24ae5b Mon Sep 17 00:00:00 2001 From: hellertang Date: Fri, 18 Oct 2024 20:47:06 +0800 Subject: [PATCH 2/3] support default doamin --- tencentcloud/provider.go | 1 + tencentcloud/provider.md | 1 + ...resource_tc_clb_listener_default_domain.go | 353 +++++------------- ...resource_tc_clb_listener_default_domain.md | 21 ++ .../services/clb/service_tencentcloud_clb.go | 31 ++ .../clb_listener_default_domain.html.markdown | 49 +++ website/tencentcloud.erb | 3 + 7 files changed, 192 insertions(+), 267 deletions(-) create mode 100644 tencentcloud/services/clb/resource_tc_clb_listener_default_domain.md create mode 100644 website/docs/r/clb_listener_default_domain.html.markdown diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 8c980b3769..1d31018f44 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -1236,6 +1236,7 @@ func Provider() *schema.Provider { "tencentcloud_clb_instance": clb.ResourceTencentCloudClbInstance(), "tencentcloud_clb_listener": clb.ResourceTencentCloudClbListener(), "tencentcloud_clb_listener_rule": clb.ResourceTencentCloudClbListenerRule(), + "tencentcloud_clb_listener_default_domain": clb.ResourceTencentCloudClbListenerDefaultDomain(), "tencentcloud_clb_attachment": clb.ResourceTencentCloudClbServerAttachment(), "tencentcloud_clb_redirection": clb.ResourceTencentCloudClbRedirection(), "tencentcloud_clb_target_group": clb.ResourceTencentCloudClbTargetGroup(), diff --git a/tencentcloud/provider.md b/tencentcloud/provider.md index ed722f1138..05d31e84da 100644 --- a/tencentcloud/provider.md +++ b/tencentcloud/provider.md @@ -385,6 +385,7 @@ Cloud Load Balancer(CLB) tencentcloud_clb_instance tencentcloud_clb_listener tencentcloud_clb_listener_rule + tencentcloud_clb_listener_default_domain tencentcloud_clb_attachment tencentcloud_clb_redirection tencentcloud_lb diff --git a/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go b/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go index 4cb98cc965..5a6389b880 100644 --- a/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go +++ b/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/pkg/errors" clb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" @@ -42,34 +41,50 @@ func ResourceTencentCloudClbListenerDefaultDomain() *schema.Resource { "domain": { Type: schema.TypeString, Required: true, - Computed: true, Description: "Domain name of the listener rule. Single domain rules are passed to `domain`, and multi domain rules are passed to `domains`.", }, + + "rule_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of this CLB listener rule.", + }, }, } } func resourceTencentCloudClbListenerDefaultDomainCreate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_default_domain.create")() + defer tccommon.InconsistentCheck(d, meta)() + var ( - logId = tccommon.GetLogId(tccommon.ContextNil) - request = clb.NewModifyDomainAttributesRequest() - response *clb.ModifyDomainAttributesResponse + logId = tccommon.GetLogId(tccommon.ContextNil) + request = clb.NewModifyDomainAttributesRequest() + response *clb.ModifyDomainAttributesResponse + clbId string + listenerId string ) if v, ok := d.GetOk("clb_id"); ok { - request.LoadBalancerId = helper.String(v.(string)) + clbId = v.(string) + request.LoadBalancerId = helper.String(clbId) } if v, ok := d.GetOk("listener_id"); ok { - request.ListenerId = helper.String(v.(string)) + listenerId = v.(string) + request.ListenerId = helper.String(listenerId) } if v, ok := d.GetOk("domain"); ok { request.Domain = helper.String(v.(string)) } + request.DefaultServer = helper.Bool(true) + + client := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient() + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient().ModifyDomainAttributes(request) + result, e := client.ModifyDomainAttributes(request) if e != nil { return tccommon.RetryError(e) } else { @@ -78,7 +93,7 @@ func resourceTencentCloudClbListenerDefaultDomainCreate(d *schema.ResourceData, } if result == nil { - e = fmt.Errorf("create cls topic failed") + e = fmt.Errorf("modify domain failed") return resource.NonRetryableError(e) } @@ -93,45 +108,34 @@ func resourceTencentCloudClbListenerDefaultDomainCreate(d *schema.ResourceData, taskId := *response.Response.RequestId - d.SetId(id) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + _ = waitTaskReady(ctx, client, taskId) + + d.SetId(clbId + tccommon.FILED_SP + listenerId) return resourceTencentCloudClbListenerDefaultDomainRead(d, meta) } func resourceTencentCloudClbListenerDefaultDomainRead(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_rule.read")() + defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_default_domain.read")() defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) resourceId := d.Id() - var locationId = resourceId + items := strings.Split(resourceId, tccommon.FILED_SP) - itemLength := len(items) - clbId := d.Get("clb_id").(string) - listenerId := d.Get("listener_id").(string) - checkErr := ListenerIdCheck(listenerId) - if checkErr != nil { - return checkErr - } - if itemLength == 1 && clbId == "" { - return fmt.Errorf("The old style listenerId %s does not support import, please use clbId#listenerId style", resourceId) - } else if itemLength == 3 && clbId == "" { - locationId = items[2] - listenerId = items[1] - clbId = items[0] - } else if itemLength == 3 && clbId != "" { - locationId = items[2] - listenerId = items[1] - } else if itemLength != 1 && itemLength != 3 { - return fmt.Errorf("broken ID %s", resourceId) + if len(items) != 2 { + return fmt.Errorf("id is broken,%s", resourceId) } + clbId := items[0] + listenerId := items[1] clbService := ClbService{ client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), } - //this function is not supported by api, need to be travelled - filter := map[string]string{"rule_id": locationId, "listener_id": listenerId, "clb_id": clbId} + + filter := map[string]string{"listener_id": listenerId, "clb_id": clbId} var instances []*clb.RuleOutput err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { results, e := clbService.DescribeRulesByFilter(ctx, filter) @@ -151,280 +155,95 @@ func resourceTencentCloudClbListenerDefaultDomainRead(d *schema.ResourceData, me return nil } - instance := instances[0] - _ = d.Set("clb_id", clbId) - _ = d.Set("listener_id", listenerId) - if instance.Domain != nil { - _ = d.Set("domain", instance.Domain) - } - - if instance.Domains != nil { - _ = d.Set("domains", helper.StringsInterfaces(instance.Domains)) - } - - _ = d.Set("rule_id", instance.LocationId) - _ = d.Set("url", instance.Url) - _ = d.Set("scheduler", instance.Scheduler) - _ = d.Set("session_expire_time", instance.SessionExpireTime) - _ = d.Set("target_type", instance.TargetType) - _ = d.Set("forward_type", instance.ForwardType) - _ = d.Set("http2_switch", instance.Http2) - - if instance.QuicStatus != nil { - if *instance.QuicStatus == "QUIC_ACTIVE" { - _ = d.Set("quic", true) - } else { - _ = d.Set("quic", false) - } - } + var ( + domain string + ruleId string + ) - //health check - if instance.HealthCheck != nil { - health_check_switch := false - if *instance.HealthCheck.HealthSwitch == int64(1) { - health_check_switch = true + for _, rule := range instances { + if *rule.DefaultServer { + domain = *rule.Domain + ruleId = *rule.LocationId + break } - _ = d.Set("health_check_switch", health_check_switch) - _ = d.Set("health_check_interval_time", instance.HealthCheck.IntervalTime) - _ = d.Set("health_check_health_num", instance.HealthCheck.HealthNum) - _ = d.Set("health_check_unhealth_num", instance.HealthCheck.UnHealthNum) - _ = d.Set("health_check_http_method", helper.String(strings.ToUpper(*instance.HealthCheck.HttpCheckMethod))) - _ = d.Set("health_check_http_domain", instance.HealthCheck.HttpCheckDomain) - _ = d.Set("health_check_http_path", instance.HealthCheck.HttpCheckPath) - _ = d.Set("health_check_http_code", instance.HealthCheck.HttpCode) - _ = d.Set("health_check_type", instance.HealthCheck.CheckType) - _ = d.Set("health_check_time_out", instance.HealthCheck.TimeOut) } - if instance.Certificate != nil { - _ = d.Set("certificate_ssl_mode", instance.Certificate.SSLMode) - _ = d.Set("certificate_id", instance.Certificate.CertId) - if instance.Certificate.CertCaId != nil { - _ = d.Set("certificate_ca_id", instance.Certificate.CertCaId) - } - } + _ = d.Set("clb_id", clbId) + _ = d.Set("listener_id", listenerId) + _ = d.Set("domain", domain) + _ = d.Set("rule_id", ruleId) return nil } func resourceTencentCloudClbListenerDefaultDomainUpdate(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_rule.update")() - - clbActionMu.Lock() - defer clbActionMu.Unlock() - - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - resourceId := d.Id() - items := strings.Split(resourceId, tccommon.FILED_SP) - itemLength := len(items) - locationId := items[itemLength-1] - listenerId := d.Get("listener_id").(string) - checkErr := ListenerIdCheck(listenerId) - if checkErr != nil { - return checkErr - } - clbId := d.Get("clb_id").(string) - protocol := "" - //get listener protocol - clbService := ClbService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - instance, e := clbService.DescribeListenerById(ctx, listenerId, clbId) - if e != nil { - return tccommon.RetryError(e) - } - protocol = *(instance.Protocol) - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s get CLB listener failed, reason:%s\n ", logId, err.Error()) - return err - } + defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_default_domain.update")() + defer tccommon.InconsistentCheck(d, meta)() - changed := false - url := "" - scheduler := "" - sessionExpireTime := 0 - - request := clb.NewModifyRuleRequest() - request.ListenerId = helper.String(listenerId) - request.LoadBalancerId = helper.String(clbId) - request.LocationId = helper.String(locationId) - if d.HasChange("url") { - changed = true - url = d.Get("url").(string) - request.Url = helper.String(url) - } + if d.HasChange("domain") { - if d.HasChange("forward_type") { - changed = true - request.ForwardType = helper.String(d.Get("forward_type").(string)) - } + var ( + logId = tccommon.GetLogId(tccommon.ContextNil) + request = clb.NewModifyDomainAttributesRequest() + response *clb.ModifyDomainAttributesResponse + clbId string + listenerId string + ) - if d.HasChange("scheduler") { - changed = true - scheduler = d.Get("scheduler").(string) - if !(protocol == CLB_LISTENER_PROTOCOL_HTTP || protocol == CLB_LISTENER_PROTOCOL_HTTPS) { - return fmt.Errorf("[CHECK][CLB listener rule %s][Update] check: Scheduler can only be set with listener protocol TCP/UDP/TCP_SSL or rule of listener HTTP/HTTPS", locationId) + if v, ok := d.GetOk("clb_id"); ok { + clbId = v.(string) + request.LoadBalancerId = helper.String(clbId) } - request.Scheduler = helper.String(scheduler) - } - if d.HasChange("session_expire_time") { - changed = true - sessionExpireTime = d.Get("session_expire_time").(int) - if !(protocol == CLB_LISTENER_PROTOCOL_HTTP || protocol == CLB_LISTENER_PROTOCOL_HTTPS) { - return fmt.Errorf("[CHECK][CLB listener rule %s][Update] check: session_expire_time can only be set with protocol TCP/UDP or rule of listener HTTP/HTTPS", locationId) + if v, ok := d.GetOk("listener_id"); ok { + listenerId = v.(string) + request.ListenerId = helper.String(listenerId) } - if scheduler != CLB_LISTENER_SCHEDULER_WRR && scheduler != "" { - return fmt.Errorf("[CHECK][CLB listener rule %s][Update] check: session_expire_time can only be set when scheduler is WRR", locationId) + + if v, ok := d.GetOk("domain"); ok { + request.Domain = helper.String(v.(string)) } - sessionExpireTime64 := int64(sessionExpireTime) - request.SessionExpireTime = &sessionExpireTime64 - } - healthSetFlag, healthCheck, healthErr := checkHealthCheckPara(ctx, d, protocol, HEALTH_APPLY_TYPE_RULE) - if healthErr != nil { - return healthErr - } + request.DefaultServer = helper.Bool(true) - if healthSetFlag { - changed = true - request.HealthCheck = healthCheck - } + client := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient() - if changed { err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - response, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient().ModifyRule(request) + result, e := client.ModifyDomainAttributes(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(), response.ToJsonString()) - requestId := *response.Response.RequestId - retryErr := waitForTaskFinish(requestId, meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient()) - if retryErr != nil { - return resource.NonRetryableError(errors.WithStack(retryErr)) - } + logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s update CLB listener rule failed, reason:%+v", logId, err) - return err - } - } - - //modify domain and ssl - domainChanged := false - domainRequest := clb.NewModifyDomainAttributesRequest() - if d.HasChange("domain") { - old, new := d.GetChange("domain") - domainChanged = true - domainRequest.Domain = helper.String(old.(string)) - domainRequest.NewDomain = helper.String(new.(string)) - } else { - domainRequest.Domain = helper.String(d.Get("domain").(string)) - } - if d.HasChange("certificate_id") || d.HasChange("certificate_ca_id ") || d.HasChange("certificate_ssl_mode") { - domainChanged = true - certificateSetFlag, certificateInput, certErr := checkCertificateInputPara(ctx, d, meta) - if certErr != nil { - return certErr - } - if certificateSetFlag { - if !(protocol == CLB_LISTENER_PROTOCOL_HTTPS) { - return fmt.Errorf("[CHECK][CLB listener rule][Create] check: certificate para can only be set with rule of linstener with protocol 'HTTPS'") + if result == nil { + e = fmt.Errorf("modify domain failed") + return resource.NonRetryableError(e) } - domainRequest.Certificate = certificateInput - } - } - if d.HasChange("http2_switch") { - if v, ok := d.GetOkExists("http2_switch"); ok { - if !(protocol == CLB_LISTENER_PROTOCOL_HTTPS) { - return fmt.Errorf("[CHECK][CLB listener rule][Create] check: certificate para can only be set with rule of linstener with protocol 'HTTPS'") - } - domainChanged = true - domainRequest.Http2 = helper.Bool(v.(bool)) - } - } - - if d.HasChange("quic") { - domainChanged = true - if v, ok := d.GetOkExists("quic"); ok { - domainRequest.Quic = helper.Bool(v.(bool)) - } - } - - if domainChanged { - domainRequest.ListenerId = &listenerId - domainRequest.LoadBalancerId = &clbId - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - response, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient().ModifyDomainAttributes(domainRequest) - if e != nil { - if err := processRetryErrMsg(e); err != nil { - return err - } - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", - logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) - requestId := *response.Response.RequestId - retryErr := waitForTaskFinish(requestId, meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseClbClient()) - if retryErr != nil { - return resource.NonRetryableError(errors.WithStack(retryErr)) - } - } + response = result return nil }) + if err != nil { - log.Printf("[CRITAL]%s update CLB listener rule failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s create cls topic failed, reason:%+v", logId, err) return err } + + taskId := *response.Response.RequestId + + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + _ = waitTaskReady(ctx, client, taskId) + } - return nil + return resourceTencentCloudClbListenerDefaultDomainRead(d, meta) } func resourceTencentCloudClbListenerDefaultDomainDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_clb_listener_domain_default.delete")() + defer tccommon.InconsistentCheck(d, meta)() - clbActionMu.Lock() - defer clbActionMu.Unlock() - - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - resourceId := d.Id() - items := strings.Split(resourceId, tccommon.FILED_SP) - itemLength := len(items) - locationId := items[itemLength-1] - listenerId := d.Get("listener_id").(string) - checkErr := ListenerIdCheck(listenerId) - if checkErr != nil { - return checkErr - } - clbId := d.Get("clb_id").(string) - - clbService := ClbService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - e := clbService.DeleteRuleById(ctx, clbId, listenerId, locationId) - if e != nil { - if err := processRetryErrMsg(e); err != nil { - return err - } - return tccommon.RetryError(e) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s delete CLB listener rule failed, reason:%+v", logId, err) - return err - } return nil } diff --git a/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.md b/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.md new file mode 100644 index 0000000000..945039b7a7 --- /dev/null +++ b/tencentcloud/services/clb/resource_tc_clb_listener_default_domain.md @@ -0,0 +1,21 @@ +Provides a resource to set clb listener default domain + +Example Usage + +Set default domain + +```hcl +resource "tencentcloud_clb_listener_default_domain" "example" { + clb_id = "lb-g1miv1ok" + listener_id = "lbl-duilx5qm" + domain = "3.com" +} +``` + +Import + +CLB listener default domain can be imported using the id (version >= 1.47.0), e.g. + +``` +$ terraform import tencentcloud_clb_listener_default_domain.example lb-k2zjp9lv#lbl-hh141sn9 +``` diff --git a/tencentcloud/services/clb/service_tencentcloud_clb.go b/tencentcloud/services/clb/service_tencentcloud_clb.go index 86034ecf7e..7233efa3e7 100644 --- a/tencentcloud/services/clb/service_tencentcloud_clb.go +++ b/tencentcloud/services/clb/service_tencentcloud_clb.go @@ -2429,3 +2429,34 @@ func (me *ClbService) DescribeClbTargetGroupAttachmentsById(ctx context.Context, func IsHealthCheckEnable(healthSwitch int64) bool { return healthSwitch == int64(1) } + +func waitTaskReady(ctx context.Context, client *clb.Client, reqeustId string) error { + logId := tccommon.GetLogId(ctx) + + describeRequest := clb.NewDescribeTaskStatusRequest() + describeRequest.TaskId = helper.String(reqeustId) + + err := resource.Retry(2*tccommon.WriteRetryTimeout, func() *resource.RetryError { + ratelimit.Check(describeRequest.GetAction()) + response, err := client.DescribeTaskStatus(describeRequest) + if err != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]", + logId, describeRequest.GetAction(), describeRequest.ToJsonString(), err) + return tccommon.RetryError(err) + } + // 任务状态:RUNNING,FAIL,SUCCESS + status := *response.Response.Status + if status == 0 { + return nil + } else if status == 1 { + return resource.NonRetryableError(fmt.Errorf("Task[%s] failed", reqeustId)) + } else { + return resource.RetryableError(fmt.Errorf("Task[%s] status: %s", reqeustId, status)) + } + }) + if err != nil { + log.Printf("[CRITAL]%s task failed, reason: %v", logId, err) + return err + } + return nil +} diff --git a/website/docs/r/clb_listener_default_domain.html.markdown b/website/docs/r/clb_listener_default_domain.html.markdown new file mode 100644 index 0000000000..e487d218fa --- /dev/null +++ b/website/docs/r/clb_listener_default_domain.html.markdown @@ -0,0 +1,49 @@ +--- +subcategory: "Cloud Load Balancer(CLB)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_clb_listener_default_domain" +sidebar_current: "docs-tencentcloud-resource-clb_listener_default_domain" +description: |- + Provides a resource to set clb listener default domain +--- + +# tencentcloud_clb_listener_default_domain + +Provides a resource to set clb listener default domain + +## Example Usage + +### Set default domain + +```hcl +resource "tencentcloud_clb_listener_default_domain" "example" { + clb_id = "lb-g1miv1ok" + listener_id = "lbl-duilx5qm" + domain = "3.com" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `clb_id` - (Required, String, ForceNew) ID of CLB instance. +* `domain` - (Required, String) Domain name of the listener rule. Single domain rules are passed to `domain`, and multi domain rules are passed to `domains`. +* `listener_id` - (Required, String, ForceNew) ID of CLB listener. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the resource. +* `rule_id` - ID of this CLB listener rule. + + +## Import + +CLB listener default domain can be imported using the id (version >= 1.47.0), e.g. + +``` +$ terraform import tencentcloud_clb_listener_default_domain.example lb-k2zjp9lv#lbl-hh141sn9 +``` + diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index a1da1f6708..6cf27635a9 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -1422,6 +1422,9 @@
  • tencentcloud_clb_listener
  • +
  • + tencentcloud_clb_listener_default_domain +
  • tencentcloud_clb_listener_rule
  • From 4dc4f2e1a9e32904e51c4922d139adb815d53827 Mon Sep 17 00:00:00 2001 From: hellertang Date: Fri, 18 Oct 2024 20:48:28 +0800 Subject: [PATCH 3/3] add changelog --- .changelog/2899.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/2899.txt diff --git a/.changelog/2899.txt b/.changelog/2899.txt new file mode 100644 index 0000000000..b96a8edfea --- /dev/null +++ b/.changelog/2899.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +tencentcloud_clb_listener_default_domain +``` \ No newline at end of file