Skip to content

Commit

Permalink
support tags for elb loadbalancer and listener resource (#613)
Browse files Browse the repository at this point in the history
* add elb v2 service client
* support tags for lb loadbalancer resource
* support tags for lb listener resource
  • Loading branch information
ShiChangkuo committed Oct 28, 2020
1 parent 1d229de commit 3159714
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 158 deletions.
7 changes: 7 additions & 0 deletions docs/resources/lb_listener_v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ resource "huaweicloud_lb_listener_v2" "listener_1" {
protocol = "HTTP"
protocol_port = 8080
loadbalancer_id = "d9415786-5f1a-428b-b35f-2f1523e146d2"
tags = {
key = "value"
}
}
```

Expand Down Expand Up @@ -63,6 +67,8 @@ The following arguments are supported:
* `admin_state_up` - (Optional) The administrative state of the Listener.
A valid value is true (UP) or false (DOWN).

* `tags` - (Optional) The key/value pairs to associate with the listener.

## Attributes Reference

The following attributes are exported:
Expand All @@ -79,3 +85,4 @@ The following attributes are exported:
* `default_tls_container_ref` - See Argument Reference above.
* `sni_container_refs` - See Argument Reference above.
* `admin_state_up` - See Argument Reference above.
* `tags` - See Argument Reference above.
15 changes: 11 additions & 4 deletions docs/resources/lb_loadbalancer_v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ Manages a V2 loadbalancer resource within HuaweiCloud.
```hcl
resource "huaweicloud_lb_loadbalancer_v2" "lb_1" {
vip_subnet_id = "d9415786-5f1a-428b-b35f-2f1523e146d2"
tags = {
key = "value"
}
}
```

Expand All @@ -33,22 +37,24 @@ resource "huaweicloud_networking_eip_associate" "eip_1" {

The following arguments are supported:

* `name` - (Optional) Human-readable name for the Loadbalancer. Does not have
* `name` - (Optional) Human-readable name for the loadbalancer. Does not have
to be unique.

* `description` - (Optional) Human-readable description for the Loadbalancer.
* `description` - (Optional) Human-readable description for the loadbalancer.

* `vip_subnet_id` - (Required) The network on which to allocate the
Loadbalancer's address. A tenant can only create Loadbalancers on networks
loadbalancer's address. A tenant can only create Loadbalancers on networks
authorized by policy (e.g. networks that belong to them or networks that
are shared). Changing this creates a new loadbalancer.

* `vip_address` - (Optional) The ip address of the load balancer.
Changing this creates a new loadbalancer.

* `admin_state_up` - (Optional) The administrative state of the Loadbalancer.
* `admin_state_up` - (Optional) The administrative state of the loadbalancer.
A valid value is true (UP) or false (DOWN).

* `tags` - (Optional) The key/value pairs to associate with the loadbalancer.

## Attributes Reference

The following attributes are exported:
Expand All @@ -59,4 +65,5 @@ The following attributes are exported:
* `tenant_id` - See Argument Reference above.
* `vip_address` - See Argument Reference above.
* `admin_state_up` - See Argument Reference above.
* `tags` - See Argument Reference above.
* `vip_port_id` - The Port ID of the Load Balancer IP.
4 changes: 4 additions & 0 deletions huaweicloud/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,10 @@ func (c *Config) elasticLBClient(region string) (*golangsdk.ServiceClient, error
return c.NewServiceClient("elb", region)
}

func (c *Config) elbV2Client(region string) (*golangsdk.ServiceClient, error) {
return c.NewServiceClient("elbv2", region)
}

func (c *Config) fwV2Client(region string) (*golangsdk.ServiceClient, error) {
return c.NewServiceClient("networkv2", region)
}
Expand Down
4 changes: 4 additions & 0 deletions huaweicloud/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ var allServiceCatalog = map[string]ServiceCatalog{
Version: "v1.0",
WithOutProjectID: true,
},
"elbv2": ServiceCatalog{
Name: "elb",
Version: "v2.0",
},
"fwv2": ServiceCatalog{
Name: "vpc",
Version: "v2.0",
Expand Down
14 changes: 12 additions & 2 deletions huaweicloud/endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,16 +603,26 @@ func TestAccServiceEndpoints_Network(t *testing.T) {
actualURL = serviceClient.ResourceBaseURL()
compareURL(expectedURL, actualURL, "vpc", "v1", t)

// test endpoint of loadElasticLoadBalancer v1.0
// test endpoint of elb v1.0
serviceClient, err = nil, nil
serviceClient, err = config.elasticLBClient(OS_REGION_NAME)
if err != nil {
t.Fatalf("Error creating HuaweiCloud loadElasticLoadBalancer v1.0 client: %s", err)
t.Fatalf("Error creating HuaweiCloud ELB v1.0 client: %s", err)
}
expectedURL = fmt.Sprintf("https://elb.%s.%s/v1.0/", OS_REGION_NAME, config.Cloud)
actualURL = serviceClient.ResourceBaseURL()
compareURL(expectedURL, actualURL, "elb", "v1.0", t)

// test endpoint of elb v2.0
serviceClient, err = nil, nil
serviceClient, err = config.elbV2Client(OS_REGION_NAME)
if err != nil {
t.Fatalf("Error creating HuaweiCloud ELB v2.0 client: %s", err)
}
expectedURL = fmt.Sprintf("https://elb.%s.%s/v2.0/%s/", OS_REGION_NAME, config.Cloud, config.TenantID)
actualURL = serviceClient.ResourceBaseURL()
compareURL(expectedURL, actualURL, "elb", "v2.0", t)

// test the endpoint of fw v2 service
serviceClient, err = config.fwV2Client(OS_REGION_NAME)
if err != nil {
Expand Down
163 changes: 102 additions & 61 deletions huaweicloud/resource_huaweicloud_lb_listener_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"

"github.com/huaweicloud/golangsdk/openstack/common/tags"
"github.com/huaweicloud/golangsdk/openstack/networking/v2/extensions/lbaas_v2/listeners"
)

Expand Down Expand Up @@ -36,14 +38,9 @@ func resourceListenerV2() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if value != "TCP" && value != "HTTP" && value != "HTTPS" && value != "TERMINATED_HTTPS" {
errors = append(errors, fmt.Errorf(
"Only 'TCP', 'HTTP', 'HTTPS' and 'TERMINATED_HTTPS' are supported values for 'protocol'"))
}
return
},
ValidateFunc: validation.StringInSlice([]string{
"TCP", "UDP", "HTTP", "HTTPS", "TERMINATED_HTTPS",
}, false),
},

"protocol_port": {
Expand Down Expand Up @@ -111,6 +108,7 @@ func resourceListenerV2() *schema.Resource {
Default: true,
Optional: true,
},
"tags": tagsSchema(),
},
}
}
Expand Down Expand Up @@ -181,6 +179,19 @@ func resourceListenerV2Create(d *schema.ResourceData, meta interface{}) error {

d.SetId(listener.ID)

//set tags
tagRaw := d.Get("tags").(map[string]interface{})
if len(tagRaw) > 0 {
elbv2Client, err := config.elbV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud elb v2 client: %s", err)
}
taglist := expandResourceTags(tagRaw)
if tagErr := tags.Create(elbv2Client, "listeners", listener.ID, taglist).ExtractErr(); tagErr != nil {
return fmt.Errorf("Error setting tags of elb listener %s: %s", listener.ID, tagErr)
}
}

return resourceListenerV2Read(d, meta)
}

Expand Down Expand Up @@ -211,74 +222,104 @@ func resourceListenerV2Read(d *schema.ResourceData, meta interface{}) error {
d.Set("default_tls_container_ref", listener.DefaultTlsContainerRef)
d.Set("region", GetRegion(d, config))

// set tags
elbv2Client, err := config.elbV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud elb v2 client: %s", err)
}

resourceTags, err := tags.Get(elbv2Client, "listeners", d.Id()).Extract()
if err != nil {
return fmt.Errorf("Error fetching tags of elb listener: %s", err)
}
tagmap := tagsToMap(resourceTags.Tags)
d.Set("tags", tagmap)

return nil
}

func resourceListenerV2Update(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
lbClient, err := config.NetworkingV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud networking client: %s", err)
}

var updateOpts listeners.UpdateOpts
if d.HasChange("name") {
updateOpts.Name = d.Get("name").(string)
}
if d.HasChange("description") {
updateOpts.Description = d.Get("description").(string)
}
if d.HasChange("connection_limit") {
connLimit := d.Get("connection_limit").(int)
updateOpts.ConnLimit = &connLimit
}
if d.HasChange("default_tls_container_ref") {
updateOpts.DefaultTlsContainerRef = d.Get("default_tls_container_ref").(string)
}
if d.HasChange("sni_container_refs") {
var sniContainerRefs []string
if raw, ok := d.GetOk("sni_container_refs"); ok {
for _, v := range raw.([]interface{}) {
sniContainerRefs = append(sniContainerRefs, v.(string))
if d.HasChanges("name", "description", "admin_state_up", "connection_limit",
"default_tls_container_ref", "sni_container_refs", "http2_enable") {
lbClient, err := config.NetworkingV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud networking client: %s", err)
}

var updateOpts listeners.UpdateOpts
if d.HasChange("name") {
updateOpts.Name = d.Get("name").(string)
}
if d.HasChange("description") {
updateOpts.Description = d.Get("description").(string)
}
if d.HasChange("connection_limit") {
connLimit := d.Get("connection_limit").(int)
updateOpts.ConnLimit = &connLimit
}
if d.HasChange("default_tls_container_ref") {
updateOpts.DefaultTlsContainerRef = d.Get("default_tls_container_ref").(string)
}
if d.HasChange("sni_container_refs") {
var sniContainerRefs []string
if raw, ok := d.GetOk("sni_container_refs"); ok {
for _, v := range raw.([]interface{}) {
sniContainerRefs = append(sniContainerRefs, v.(string))
}
}
updateOpts.SniContainerRefs = sniContainerRefs
}
if d.HasChange("admin_state_up") {
asu := d.Get("admin_state_up").(bool)
updateOpts.AdminStateUp = &asu
}
if d.HasChange("http2_enable") {
http2 := d.Get("http2_enable").(bool)
updateOpts.Http2Enable = &http2
}
updateOpts.SniContainerRefs = sniContainerRefs
}
if d.HasChange("admin_state_up") {
asu := d.Get("admin_state_up").(bool)
updateOpts.AdminStateUp = &asu
}
if d.HasChange("http2_enable") {
http2 := d.Get("http2_enable").(bool)
updateOpts.Http2Enable = &http2
}

// Wait for LoadBalancer to become active before continuing
lbID := d.Get("loadbalancer_id").(string)
timeout := d.Timeout(schema.TimeoutUpdate)
err = waitForLBV2LoadBalancer(lbClient, lbID, "ACTIVE", nil, timeout)
if err != nil {
return err
}
// Wait for LoadBalancer to become active before continuing
lbID := d.Get("loadbalancer_id").(string)
timeout := d.Timeout(schema.TimeoutUpdate)
err = waitForLBV2LoadBalancer(lbClient, lbID, "ACTIVE", nil, timeout)
if err != nil {
return err
}

log.Printf("[DEBUG] Updating listener %s with options: %#v", d.Id(), updateOpts)
//lintignore:R006
err = resource.Retry(timeout, func() *resource.RetryError {
_, err = listeners.Update(lbClient, d.Id(), updateOpts).Extract()
if err != nil {
return checkForRetryableError(err)
}
return nil
})

log.Printf("[DEBUG] Updating listener %s with options: %#v", d.Id(), updateOpts)
//lintignore:R006
err = resource.Retry(timeout, func() *resource.RetryError {
_, err = listeners.Update(lbClient, d.Id(), updateOpts).Extract()
if err != nil {
return checkForRetryableError(err)
return fmt.Errorf("Error updating listener %s: %s", d.Id(), err)
}
return nil
})

if err != nil {
return fmt.Errorf("Error updating listener %s: %s", d.Id(), err)
// Wait for LoadBalancer to become active again before continuing
err = waitForLBV2LoadBalancer(lbClient, lbID, "ACTIVE", nil, timeout)
if err != nil {
return err
}
}

// Wait for LoadBalancer to become active again before continuing
err = waitForLBV2LoadBalancer(lbClient, lbID, "ACTIVE", nil, timeout)
if err != nil {
return err
// update tags
if d.HasChange("tags") {
elbv2Client, err := config.elbV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud elb v2 client: %s", err)
}

tagErr := UpdateResourceTags(elbv2Client, d, "listeners", d.Id())
if tagErr != nil {
return fmt.Errorf("Error updating tags of elb listener:%s, err:%s", d.Id(), tagErr)
}
}

return resourceListenerV2Read(d, meta)
Expand Down
Loading

0 comments on commit 3159714

Please sign in to comment.