diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c646b427c..12a6924af0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 1.39.1 (Unreleased) +ENHANCEMENTS: + +* Resource: `tencentcloud_gaap_http_rule` argument `realservers` now is optional. + ## 1.39.0 (July 18, 2020) ENHANCEMENTS: diff --git a/tencentcloud/resource_tc_gaap_http_rule.go b/tencentcloud/resource_tc_gaap_http_rule.go index 307f1324ae..9f6b2f802b 100644 --- a/tencentcloud/resource_tc_gaap_http_rule.go +++ b/tencentcloud/resource_tc_gaap_http_rule.go @@ -179,7 +179,7 @@ func resourceTencentCloudGaapHttpRule() *schema.Resource { }, "realservers": { Type: schema.TypeSet, - Required: true, + Optional: true, Set: func(v interface{}) int { m := v.(map[string]interface{}) return hashcode.String(fmt.Sprintf("%s-%s-%d-%d", m["id"].(string), m["ip"].(string), m["port"].(int), m["weight"].(int))) @@ -268,22 +268,6 @@ func resourceTencentCloudGaapHttpRuleCreate(d *schema.ResourceData, m interface{ return errors.New("health_check_status_codes can't be empty") } - realserverSet := d.Get("realservers").(*schema.Set).List() - realservers := make([]gaapRealserverBind, 0, len(realserverSet)) - for _, v := range realserverSet { - m := v.(map[string]interface{}) - realservers = append(realservers, gaapRealserverBind{ - id: m["id"].(string), - ip: m["ip"].(string), - port: m["port"].(int), - weight: m["weight"].(int), - }) - } - - if len(realservers) == 0 { - return errors.New("realserver can't be empty") - } - service := GaapService{client: m.(*TencentCloudClient).apiV3Conn} id, err := service.CreateHttpRule(ctx, rule) @@ -293,8 +277,23 @@ func resourceTencentCloudGaapHttpRuleCreate(d *schema.ResourceData, m interface{ d.SetId(id) - if err := service.BindHttpRuleRealservers(ctx, rule.listenerId, id, realservers); err != nil { - return err + if raw, ok := d.GetOk("realservers"); ok { + realserverSet := raw.(*schema.Set).List() + realservers := make([]gaapRealserverBind, 0, len(realserverSet)) + + for _, v := range realserverSet { + m := v.(map[string]interface{}) + realservers = append(realservers, gaapRealserverBind{ + id: m["id"].(string), + ip: m["ip"].(string), + port: m["port"].(int), + weight: m["weight"].(int), + }) + } + + if err := service.BindHttpRuleRealservers(ctx, rule.listenerId, id, realservers); err != nil { + return err + } } return resourceTencentCloudGaapHttpRuleRead(d, m) @@ -427,7 +426,9 @@ func resourceTencentCloudGaapHttpRuleUpdate(d *schema.ResourceData, m interface{ } var realservers []gaapRealserverBind - if d.HasChange("realservers") { + realserverUpdate := d.HasChange("realservers") + + if realserverUpdate { set := d.Get("realservers").(*schema.Set).List() realservers = make([]gaapRealserverBind, 0, len(set)) for _, v := range set { @@ -466,10 +467,11 @@ func resourceTencentCloudGaapHttpRuleUpdate(d *schema.ResourceData, m interface{ d.SetPartial("forward_host") } - if len(realservers) > 0 { + if realserverUpdate { if err := service.BindHttpRuleRealservers(ctx, listenerId, id, realservers); err != nil { return err } + d.SetPartial("realservers") } diff --git a/tencentcloud/resource_tc_gaap_http_rule_test.go b/tencentcloud/resource_tc_gaap_http_rule_test.go index c34cae2d1b..93354d3c36 100644 --- a/tencentcloud/resource_tc_gaap_http_rule_test.go +++ b/tencentcloud/resource_tc_gaap_http_rule_test.go @@ -206,6 +206,85 @@ func TestAccTencentCloudGaapHttpRule_domainRealserver(t *testing.T) { }) } +func TestAccTencentCloudGaapHttpRule_noRealserver(t *testing.T) { + id := new(string) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGaapHttpRuleDestroy(id), + Steps: []resource.TestStep{ + { + Config: testAccGaapHttpRuleNoRealserver, + Check: resource.ComposeTestCheckFunc( + testAccCheckGaapHttpRuleExists("tencentcloud_gaap_http_rule.foo", id), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "domain", "www.qq.com"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "path", "/"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "scheduler", "rr"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "realserver_type", "IP"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check", "true"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "interval", "5"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "connect_timeout", "2"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_path", "/"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_method", "GET"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_status_codes.#", "1"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_status_codes."+strconv.Itoa(schema.HashInt(200)), "200"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "realservers.#", "0"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "forward_host", "default"), + ), + }, + { + ResourceName: "tencentcloud_gaap_http_rule.foo", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccTencentCloudGaapHttpRule_deleteRealserver(t *testing.T) { + id := new(string) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGaapHttpRuleDestroy(id), + Steps: []resource.TestStep{ + { + Config: testAccGaapHttpRuleBasic, + Check: resource.ComposeTestCheckFunc( + testAccCheckGaapHttpRuleExists("tencentcloud_gaap_http_rule.foo", id), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "domain", "www.qq.com"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "path", "/"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "scheduler", "rr"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "realserver_type", "IP"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check", "true"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "interval", "5"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "connect_timeout", "2"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_path", "/"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_method", "GET"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_status_codes.#", "1"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "health_check_status_codes."+strconv.Itoa(schema.HashInt(200)), "200"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "realservers.#", "2"), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "forward_host", "default"), + ), + }, + { + Config: testAccGaapHttpRuleNoRealserver, + Check: resource.ComposeTestCheckFunc( + testAccCheckGaapHttpRuleExists("tencentcloud_gaap_http_rule.foo", id), + resource.TestCheckResourceAttr("tencentcloud_gaap_http_rule.foo", "realservers.#", "0"), + ), + }, + { + ResourceName: "tencentcloud_gaap_http_rule.foo", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckGaapHttpRuleExists(n string, id *string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -578,3 +657,28 @@ resource tencentcloud_gaap_http_rule "foo" { } } `, defaultGaapProxyId) + +var testAccGaapHttpRuleNoRealserver = fmt.Sprintf(` +resource tencentcloud_gaap_layer7_listener "foo" { + protocol = "HTTP" + name = "ci-test-gaap-l7-listener" + port = 80 + proxy_id = "%s" +} + +resource tencentcloud_gaap_http_domain "foo" { + listener_id = tencentcloud_gaap_layer7_listener.foo.id + domain = "www.qq.com" +} + +resource tencentcloud_gaap_http_rule "foo" { + listener_id = tencentcloud_gaap_layer7_listener.foo.id + domain = tencentcloud_gaap_http_domain.foo.domain + path = "/" + realserver_type = "IP" + health_check = true + health_check_path = "/" + health_check_method = "GET" + health_check_status_codes = [200] +} +`, defaultGaapProxyId) diff --git a/tencentcloud/service_tencentcloud_gaap.go b/tencentcloud/service_tencentcloud_gaap.go index 9254a79b5f..f40c8cf049 100644 --- a/tencentcloud/service_tencentcloud_gaap.go +++ b/tencentcloud/service_tencentcloud_gaap.go @@ -2665,7 +2665,8 @@ func (me *GaapService) BindHttpRuleRealservers(ctx context.Context, listenerId, request := gaap.NewBindRuleRealServersRequest() request.RuleId = &ruleId - request.RealServerBindSet = make([]*gaap.RealServerBindSetReq, 0, len(realservers)) + + // if realservers is nil, request.RealServerBindSet will bi nil and remove realserver binding for _, realserver := range realservers { request.RealServerBindSet = append(request.RealServerBindSet, &gaap.RealServerBindSetReq{ RealServerId: helper.String(realserver.id), diff --git a/website/docs/r/gaap_http_rule.html.markdown b/website/docs/r/gaap_http_rule.html.markdown index c24a8db9fc..fec323a1be 100644 --- a/website/docs/r/gaap_http_rule.html.markdown +++ b/website/docs/r/gaap_http_rule.html.markdown @@ -76,13 +76,13 @@ The following arguments are supported: * `listener_id` - (Required, ForceNew) ID of the layer7 listener. * `path` - (Required) Path of the forward rule. Maximum length is 80. * `realserver_type` - (Required, ForceNew) Type of the realserver, the available values include `IP` and `DOMAIN`. -* `realservers` - (Required) An information list of GAAP realserver. * `connect_timeout` - (Optional) Timeout of the health check response, default value is 2s. * `forward_host` - (Optional) The default value of requested host which is forwarded to the realserver by the listener is `default`. * `health_check_method` - (Optional) Method of the health check, the available values includes `GET` and `HEAD`. * `health_check_path` - (Optional) Path of health check. Maximum length is 80. * `health_check_status_codes` - (Optional) Return code of confirmed normal, the available values include `100`, `200`, `300`, `400` and `500`. * `interval` - (Optional) Interval of the health check, default value is 5s. +* `realservers` - (Optional) An information list of GAAP realserver. * `scheduler` - (Optional) Scheduling policy of the forward rule, default value is `rr`, the available values include `rr`, `wrr` and `lc`. The `realservers` object supports the following: