From f4ec3cedf5a7ede915d90741f71457f7a61619bf Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Sat, 16 Jul 2022 13:36:46 +0100 Subject: [PATCH 1/9] add monitor_port and monitor_address without breaking the LBaaS compatibility --- openstack/lb_v2_shared.go | 54 ++++ openstack/resource_openstack_lb_member_v2.go | 250 ++++++++++++++++++- 2 files changed, 291 insertions(+), 13 deletions(-) diff --git a/openstack/lb_v2_shared.go b/openstack/lb_v2_shared.go index 1c6a5619e..23eda38b9 100644 --- a/openstack/lb_v2_shared.go +++ b/openstack/lb_v2_shared.go @@ -683,6 +683,37 @@ func waitForLBV2Member(ctx context.Context, lbClient *gophercloud.ServiceClient, return nil } +func waitForLBV2OctaviaMember(ctx context.Context, lbClient *gophercloud.ServiceClient, parentPool *neutronpools.Pool, member *octaviapools.Member, target string, pending []string, timeout time.Duration) error { + log.Printf("[DEBUG] Waiting for member %s to become %s.", member.ID, target) + + lbID, err := lbV2FindLBIDviaPool(lbClient, parentPool) + if err != nil { + return err + } + + stateConf := &resource.StateChangeConf{ + Target: []string{target}, + Pending: pending, + Refresh: resourceLBV2OctaviaMemberRefreshFunc(lbClient, lbID, parentPool.ID, member), + Timeout: timeout, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + } + + _, err = stateConf.WaitForStateContext(ctx) + if err != nil { + if _, ok := err.(gophercloud.ErrDefault404); ok { + if target == "DELETED" { + return nil + } + } + + return fmt.Errorf("Error waiting for member %s to become %s: %s", member.ID, target, err) + } + + return nil +} + func resourceLBV2MemberRefreshFunc(lbClient *gophercloud.ServiceClient, lbID string, poolID string, member *neutronpools.Member) resource.StateRefreshFunc { if member.ProvisioningStatus != "" { return func() (interface{}, string, error) { @@ -706,6 +737,29 @@ func resourceLBV2MemberRefreshFunc(lbClient *gophercloud.ServiceClient, lbID str return resourceLBV2LoadBalancerStatusRefreshFuncNeutron(lbClient, lbID, "member", member.ID, poolID) } +func resourceLBV2OctaviaMemberRefreshFunc(lbClient *gophercloud.ServiceClient, lbID string, poolID string, member *octaviapools.Member) resource.StateRefreshFunc { + if member.ProvisioningStatus != "" { + return func() (interface{}, string, error) { + lb, status, err := resourceLBV2LoadBalancerRefreshFunc(lbClient, lbID)() + if err != nil { + return lb, status, err + } + if !strSliceContains(getLbSkipStatuses(), status) { + return lb, status, nil + } + + member, err := neutronpools.GetMember(lbClient, poolID, member.ID).Extract() + if err != nil { + return nil, "", err + } + + return member, member.ProvisioningStatus, nil + } + } + + return resourceLBV2LoadBalancerStatusRefreshFuncNeutron(lbClient, lbID, "member", member.ID, poolID) +} + func waitForLBV2Monitor(ctx context.Context, lbClient *gophercloud.ServiceClient, parentPool *neutronpools.Pool, monitor *neutronmonitors.Monitor, target string, pending []string, timeout time.Duration) error { log.Printf("[DEBUG] Waiting for openstack_lb_monitor_v2 %s to become %s.", monitor.ID, target) diff --git a/openstack/resource_openstack_lb_member_v2.go b/openstack/resource_openstack_lb_member_v2.go index 1efd034d4..279c59f70 100644 --- a/openstack/resource_openstack_lb_member_v2.go +++ b/openstack/resource_openstack_lb_member_v2.go @@ -12,7 +12,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools" + octaviapools "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools" + neutronpools "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools" ) func resourceMemberV2() *schema.Resource { @@ -88,6 +89,21 @@ func resourceMemberV2() *schema.Resource { Required: true, ForceNew: true, }, + + "monitor_address": { + Type: schema.TypeString, + Optional: true, + Default: nil, + ForceNew: false, + }, + + "monitor_port": { + Type: schema.TypeString, + Default: nil, + Optional: true, + ForceNew: false, + ValidateFunc: validation.IntBetween(1, 65535), + }, }, } } @@ -100,7 +116,76 @@ func resourceMemberV2Create(ctx context.Context, d *schema.ResourceData, meta in } adminStateUp := d.Get("admin_state_up").(bool) - createOpts := pools.CreateMemberOpts{ + + if config.UseOctavia { + monitorPort := d.Get("monitor_port").(int) + createOpts := octaviapools.CreateMemberOpts{ + Name: d.Get("name").(string), + ProjectID: d.Get("tenant_id").(string), + Address: d.Get("address").(string), + ProtocolPort: d.Get("protocol_port").(int), + AdminStateUp: &adminStateUp, + MonitorAddress: d.Get("monitor_address").(string), + MonitorPort: &monitorPort, + } + + // Must omit if not set + if v, ok := d.GetOk("subnet_id"); ok { + createOpts.SubnetID = v.(string) + } + + // Set the weight only if it's defined in the configuration. + // This prevents all members from being created with a default weight of 0. + if v, ok := d.GetOkExists("weight"); ok { + weight := v.(int) + createOpts.Weight = &weight + } + + log.Printf("[DEBUG] Create Options: %#v", createOpts) + + // Get a clean copy of the parent pool. + poolID := d.Get("pool_id").(string) + parentPool, err := neutronpools.Get(lbClient, poolID).Extract() + if err != nil { + return diag.Errorf("Unable to retrieve parent pool %s: %s", poolID, err) + } + + // Wait for parent pool to become active before continuing + timeout := d.Timeout(schema.TimeoutCreate) + err = waitForLBV2Pool(ctx, lbClient, parentPool, "ACTIVE", getLbPendingStatuses(), timeout) + if err != nil { + return diag.FromErr(err) + } + + log.Printf("[DEBUG] Attempting to create member") + var member *octaviapools.Member + err = resource.Retry(timeout, func() *resource.RetryError { + member, err = octaviapools.CreateMember(lbClient, poolID, createOpts).Extract() + + // neutronpools.Create(lbClient, poolID, createOpts).Extract() + if err != nil { + return checkForRetryableError(err) + } + return nil + }) + + if err != nil { + return diag.Errorf("Error creating member: %s", err) + } + + // Wait for member to become active before continuing + err = waitForLBV2OctaviaMember(ctx, lbClient, parentPool, member, "ACTIVE", getLbPendingStatuses(), timeout) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(member.ID) + + return resourceMemberV2Read(ctx, d, meta) + + } + + createOpts := neutronpools.CreateMemberOpts{ Name: d.Get("name").(string), TenantID: d.Get("tenant_id").(string), Address: d.Get("address").(string), @@ -124,7 +209,7 @@ func resourceMemberV2Create(ctx context.Context, d *schema.ResourceData, meta in // Get a clean copy of the parent pool. poolID := d.Get("pool_id").(string) - parentPool, err := pools.Get(lbClient, poolID).Extract() + parentPool, err := neutronpools.Get(lbClient, poolID).Extract() if err != nil { return diag.Errorf("Unable to retrieve parent pool %s: %s", poolID, err) } @@ -137,9 +222,11 @@ func resourceMemberV2Create(ctx context.Context, d *schema.ResourceData, meta in } log.Printf("[DEBUG] Attempting to create member") - var member *pools.Member + var member *neutronpools.Member err = resource.Retry(timeout, func() *resource.RetryError { - member, err = pools.CreateMember(lbClient, poolID, createOpts).Extract() + member, err = neutronpools.CreateMember(lbClient, poolID, createOpts).Extract() + + // neutronpools.Create(lbClient, poolID, createOpts).Extract() if err != nil { return checkForRetryableError(err) } @@ -170,7 +257,29 @@ func resourceMemberV2Read(ctx context.Context, d *schema.ResourceData, meta inte poolID := d.Get("pool_id").(string) - member, err := pools.GetMember(lbClient, poolID, d.Id()).Extract() + if config.UseOctavia { + member, err := octaviapools.GetMember(lbClient, poolID, d.Id()).Extract() + if err != nil { + return diag.FromErr(CheckDeleted(d, err, "member")) + } + + log.Printf("[DEBUG] Retrieved member %s: %#v", d.Id(), member) + + d.Set("name", member.Name) + d.Set("weight", member.Weight) + d.Set("admin_state_up", member.AdminStateUp) + d.Set("tenant_id", member.ProjectID) + d.Set("subnet_id", member.SubnetID) + d.Set("address", member.Address) + d.Set("protocol_port", member.ProtocolPort) + d.Set("region", GetRegion(d, config)) + d.Set("monitor_address", member.MonitorAddress) + d.Set("monitor_port", member.MonitorPort) + + return nil + } + + member, err := neutronpools.GetMember(lbClient, poolID, d.Id()).Extract() if err != nil { return diag.FromErr(CheckDeleted(d, err, "member")) } @@ -196,7 +305,79 @@ func resourceMemberV2Update(ctx context.Context, d *schema.ResourceData, meta in return diag.Errorf("Error creating OpenStack networking client: %s", err) } - var updateOpts pools.UpdateMemberOpts + if config.UseOctavia { + var updateOpts octaviapools.UpdateMemberOpts + if d.HasChange("name") { + name := d.Get("name").(string) + updateOpts.Name = &name + } + if d.HasChange("weight") { + weight := d.Get("weight").(int) + updateOpts.Weight = &weight + } + if d.HasChange("admin_state_up") { + asu := d.Get("admin_state_up").(bool) + updateOpts.AdminStateUp = &asu + } + if d.HasChange("monitor_address") { + monitorAddress := d.Get("monitor_address").(string) + updateOpts.MonitorAddress = &monitorAddress + } + if d.HasChange("monitor_port") { + monitorPort := d.Get("monitor_port").(int) + updateOpts.MonitorPort = &monitorPort + } + + // Get a clean copy of the parent pool. + poolID := d.Get("pool_id").(string) + parentPool, err := neutronpools.Get(lbClient, poolID).Extract() + if err != nil { + return diag.Errorf("Unable to retrieve parent pool %s: %s", poolID, err) + } + + // Get a clean copy of the member. + member, err := octaviapools.GetMember(lbClient, poolID, d.Id()).Extract() + if err != nil { + return diag.Errorf("Unable to retrieve member: %s: %s", d.Id(), err) + } + + // Wait for parent pool to become active before continuing. + timeout := d.Timeout(schema.TimeoutUpdate) + err = waitForLBV2Pool(ctx, lbClient, parentPool, "ACTIVE", getLbPendingStatuses(), timeout) + if err != nil { + return diag.FromErr(err) + } + + // Wait for the member to become active before continuing. + err = waitForLBV2OctaviaMember(ctx, lbClient, parentPool, member, "ACTIVE", getLbPendingStatuses(), timeout) + if err != nil { + return diag.FromErr(err) + } + + log.Printf("[DEBUG] Updating member %s with options: %#v", d.Id(), updateOpts) + err = resource.Retry(timeout, func() *resource.RetryError { + _, err = octaviapools.UpdateMember(lbClient, poolID, d.Id(), updateOpts).Extract() + if err != nil { + return checkForRetryableError(err) + } + return nil + }) + + if err != nil { + return diag.Errorf("Unable to update member %s: %s", d.Id(), err) + } + + // Wait for the member to become active before continuing. + err = waitForLBV2OctaviaMember(ctx, lbClient, parentPool, member, "ACTIVE", getLbPendingStatuses(), timeout) + if err != nil { + return diag.FromErr(err) + } + + return resourceMemberV2Read(ctx, d, meta) + + } + + var updateOpts neutronpools.UpdateMemberOpts if d.HasChange("name") { name := d.Get("name").(string) updateOpts.Name = &name @@ -212,13 +393,13 @@ func resourceMemberV2Update(ctx context.Context, d *schema.ResourceData, meta in // Get a clean copy of the parent pool. poolID := d.Get("pool_id").(string) - parentPool, err := pools.Get(lbClient, poolID).Extract() + parentPool, err := neutronpools.Get(lbClient, poolID).Extract() if err != nil { return diag.Errorf("Unable to retrieve parent pool %s: %s", poolID, err) } // Get a clean copy of the member. - member, err := pools.GetMember(lbClient, poolID, d.Id()).Extract() + member, err := neutronpools.GetMember(lbClient, poolID, d.Id()).Extract() if err != nil { return diag.Errorf("Unable to retrieve member: %s: %s", d.Id(), err) } @@ -238,7 +419,7 @@ func resourceMemberV2Update(ctx context.Context, d *schema.ResourceData, meta in log.Printf("[DEBUG] Updating member %s with options: %#v", d.Id(), updateOpts) err = resource.Retry(timeout, func() *resource.RetryError { - _, err = pools.UpdateMember(lbClient, poolID, d.Id(), updateOpts).Extract() + _, err = neutronpools.UpdateMember(lbClient, poolID, d.Id(), updateOpts).Extract() if err != nil { return checkForRetryableError(err) } @@ -265,15 +446,58 @@ func resourceMemberV2Delete(ctx context.Context, d *schema.ResourceData, meta in return diag.Errorf("Error creating OpenStack networking client: %s", err) } + if config.UseOctavia { + // Get a clean copy of the parent pool. + poolID := d.Get("pool_id").(string) + parentPool, err := neutronpools.Get(lbClient, poolID).Extract() + if err != nil { + return diag.Errorf("Unable to retrieve parent pool (%s) for the member: %s", poolID, err) + } + + // Get a clean copy of the member. + member, err := octaviapools.GetMember(lbClient, poolID, d.Id()).Extract() + if err != nil { + return diag.FromErr(CheckDeleted(d, err, "Unable to retrieve member")) + } + + // Wait for parent pool to become active before continuing. + timeout := d.Timeout(schema.TimeoutDelete) + err = waitForLBV2Pool(ctx, lbClient, parentPool, "ACTIVE", getLbPendingStatuses(), timeout) + if err != nil { + return diag.FromErr(CheckDeleted(d, err, "Error waiting for the members pool status")) + } + + log.Printf("[DEBUG] Attempting to delete member %s", d.Id()) + err = resource.Retry(timeout, func() *resource.RetryError { + err = neutronpools.DeleteMember(lbClient, poolID, d.Id()).ExtractErr() + if err != nil { + return checkForRetryableError(err) + } + return nil + }) + + if err != nil { + return diag.FromErr(CheckDeleted(d, err, "Error deleting member")) + } + + // Wait for the member to become DELETED. + err = waitForLBV2OctaviaMember(ctx, lbClient, parentPool, member, "DELETED", getLbPendingDeleteStatuses(), timeout) + if err != nil { + return diag.FromErr(err) + } + + return nil + } + // Get a clean copy of the parent pool. poolID := d.Get("pool_id").(string) - parentPool, err := pools.Get(lbClient, poolID).Extract() + parentPool, err := neutronpools.Get(lbClient, poolID).Extract() if err != nil { return diag.Errorf("Unable to retrieve parent pool (%s) for the member: %s", poolID, err) } // Get a clean copy of the member. - member, err := pools.GetMember(lbClient, poolID, d.Id()).Extract() + member, err := neutronpools.GetMember(lbClient, poolID, d.Id()).Extract() if err != nil { return diag.FromErr(CheckDeleted(d, err, "Unable to retrieve member")) } @@ -287,7 +511,7 @@ func resourceMemberV2Delete(ctx context.Context, d *schema.ResourceData, meta in log.Printf("[DEBUG] Attempting to delete member %s", d.Id()) err = resource.Retry(timeout, func() *resource.RetryError { - err = pools.DeleteMember(lbClient, poolID, d.Id()).ExtractErr() + err = neutronpools.DeleteMember(lbClient, poolID, d.Id()).ExtractErr() if err != nil { return checkForRetryableError(err) } From 69e17453d0441111bc6d770aa18f97021759bea8 Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Sat, 16 Jul 2022 14:05:57 +0100 Subject: [PATCH 2/9] fix type for monitor_port --- openstack/resource_openstack_lb_member_v2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openstack/resource_openstack_lb_member_v2.go b/openstack/resource_openstack_lb_member_v2.go index 279c59f70..80ef54e5a 100644 --- a/openstack/resource_openstack_lb_member_v2.go +++ b/openstack/resource_openstack_lb_member_v2.go @@ -98,7 +98,7 @@ func resourceMemberV2() *schema.Resource { }, "monitor_port": { - Type: schema.TypeString, + Type: schema.TypeInt, Default: nil, Optional: true, ForceNew: false, From 59cbf8477b9d9ff641e59e8ba1f6e267633ef54d Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Sat, 16 Jul 2022 14:50:20 +0100 Subject: [PATCH 3/9] monitor port/address set only when needed --- openstack/resource_openstack_lb_member_v2.go | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/openstack/resource_openstack_lb_member_v2.go b/openstack/resource_openstack_lb_member_v2.go index 80ef54e5a..4b00e7a86 100644 --- a/openstack/resource_openstack_lb_member_v2.go +++ b/openstack/resource_openstack_lb_member_v2.go @@ -118,15 +118,12 @@ func resourceMemberV2Create(ctx context.Context, d *schema.ResourceData, meta in adminStateUp := d.Get("admin_state_up").(bool) if config.UseOctavia { - monitorPort := d.Get("monitor_port").(int) createOpts := octaviapools.CreateMemberOpts{ - Name: d.Get("name").(string), - ProjectID: d.Get("tenant_id").(string), - Address: d.Get("address").(string), - ProtocolPort: d.Get("protocol_port").(int), - AdminStateUp: &adminStateUp, - MonitorAddress: d.Get("monitor_address").(string), - MonitorPort: &monitorPort, + Name: d.Get("name").(string), + ProjectID: d.Get("tenant_id").(string), + Address: d.Get("address").(string), + ProtocolPort: d.Get("protocol_port").(int), + AdminStateUp: &adminStateUp, } // Must omit if not set @@ -141,6 +138,15 @@ func resourceMemberV2Create(ctx context.Context, d *schema.ResourceData, meta in createOpts.Weight = &weight } + if v, ok := d.GetOk("monitor_address"); ok { + createOpts.MonitorAddress = v.(string) + } + + if v, ok := d.GetOk("monitor_port"); ok { + monitorPort := v.(int) + createOpts.MonitorPort = &monitorPort + } + log.Printf("[DEBUG] Create Options: %#v", createOpts) // Get a clean copy of the parent pool. From 347b91484b52b8c81bcb9f73b804a3bf3346e071 Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Tue, 19 Jul 2022 15:59:50 +0100 Subject: [PATCH 4/9] fix linting --- openstack/resource_openstack_lb_member_v2.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/openstack/resource_openstack_lb_member_v2.go b/openstack/resource_openstack_lb_member_v2.go index 4b00e7a86..2a81184ab 100644 --- a/openstack/resource_openstack_lb_member_v2.go +++ b/openstack/resource_openstack_lb_member_v2.go @@ -188,7 +188,6 @@ func resourceMemberV2Create(ctx context.Context, d *schema.ResourceData, meta in d.SetId(member.ID) return resourceMemberV2Read(ctx, d, meta) - } createOpts := neutronpools.CreateMemberOpts{ @@ -380,7 +379,6 @@ func resourceMemberV2Update(ctx context.Context, d *schema.ResourceData, meta in } return resourceMemberV2Read(ctx, d, meta) - } var updateOpts neutronpools.UpdateMemberOpts From e386463415e653207f62667ad9a37a890f1b7a40 Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Tue, 26 Jul 2022 10:12:38 +0100 Subject: [PATCH 5/9] updated docs --- website/docs/r/lb_member_v2.html.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/website/docs/r/lb_member_v2.html.markdown b/website/docs/r/lb_member_v2.html.markdown index 12c3983cb..5476f8c28 100644 --- a/website/docs/r/lb_member_v2.html.markdown +++ b/website/docs/r/lb_member_v2.html.markdown @@ -54,6 +54,12 @@ The following arguments are supported: * `admin_state_up` - (Optional) The administrative state of the member. A valid value is true (UP) or false (DOWN). Defaults to true. +* `monitor_address` - (Optional) An alternate IP address used for health monitoring a backend member. + Available only for Octavia + +* `monitor_port` - (Optional) An alternate protocol port used for health monitoring a backend member. + Available only for Octavia + ## Attributes Reference The following attributes are exported: @@ -67,6 +73,8 @@ The following attributes are exported: * `pool_id` - See Argument Reference above. * `address` - See Argument Reference above. * `protocol_port` - See Argument Reference above. +* `monitor_address` - See Argument reference above. +* `monitor_port` - See Argument reference above. ## Import From d039e91657635d9ca90e6e187b286055febeeb3e Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Tue, 26 Jul 2022 10:26:52 +0100 Subject: [PATCH 6/9] add acceptance tests --- openstack/resource_openstack_lb_member_v2.go | 1 - .../resource_openstack_lb_member_v2_test.go | 44 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/openstack/resource_openstack_lb_member_v2.go b/openstack/resource_openstack_lb_member_v2.go index 2a81184ab..2d3d03aa2 100644 --- a/openstack/resource_openstack_lb_member_v2.go +++ b/openstack/resource_openstack_lb_member_v2.go @@ -168,7 +168,6 @@ func resourceMemberV2Create(ctx context.Context, d *schema.ResourceData, meta in err = resource.Retry(timeout, func() *resource.RetryError { member, err = octaviapools.CreateMember(lbClient, poolID, createOpts).Extract() - // neutronpools.Create(lbClient, poolID, createOpts).Extract() if err != nil { return checkForRetryableError(err) } diff --git a/openstack/resource_openstack_lb_member_v2_test.go b/openstack/resource_openstack_lb_member_v2_test.go index fc8ab63bd..ec5349337 100644 --- a/openstack/resource_openstack_lb_member_v2_test.go +++ b/openstack/resource_openstack_lb_member_v2_test.go @@ -96,6 +96,42 @@ func testAccCheckLBV2MemberExists(n string, member *pools.Member) resource.TestC } } +func TestAccLBV2Member_monitor(t *testing.T) { + var member1 pools.Member + var member2 pools.Member + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckNonAdminOnly(t) + testAccPreCheckLB(t) + testAccPreCheckUseOctavia(t) + }, + ProviderFactories: testAccProviders, + CheckDestroy: testAccCheckLBV2MemberDestroy, + Steps: []resource.TestStep{ + { + Config: TestAccLbV2MemberConfigBasic, + Check: resource.ComposeTestCheckFunc( + testAccCheckLBV2MemberExists("openstack_lb_member_v2.member_1", &member1), + testAccCheckLBV2MemberExists("openstack_lb_member_v2.member_2", &member2), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_address", "192.168.199.110"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "8080"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_address", "192.168.199.111"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "8080"), + ), + }, + { + Config: TestAccLbV2MemberConfigUpdate, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_address", "192.168.199.110"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "443"), + ), + }, + }, + }) +} + const TestAccLbV2MemberConfigBasic = ` resource "openstack_networking_network_v2" "network_1" { name = "network_1" @@ -141,6 +177,8 @@ resource "openstack_lb_member_v2" "member_1" { pool_id = "${openstack_lb_pool_v2.pool_1.id}" subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" weight = 0 + monitor_address = "192.168.199.110" + monitor_port = 8080 timeouts { create = "5m" @@ -154,6 +192,8 @@ resource "openstack_lb_member_v2" "member_2" { protocol_port = 8080 pool_id = "${openstack_lb_pool_v2.pool_1.id}" subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + monitor_address = "192.168.199.111" + monitor_port = 8080 timeouts { create = "5m" @@ -208,6 +248,8 @@ resource "openstack_lb_member_v2" "member_1" { admin_state_up = "true" pool_id = "${openstack_lb_pool_v2.pool_1.id}" subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + monitor_address = "192.168.199.110" + monitor_port = 8080 timeouts { create = "5m" @@ -223,6 +265,8 @@ resource "openstack_lb_member_v2" "member_2" { admin_state_up = "true" pool_id = "${openstack_lb_pool_v2.pool_1.id}" subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + monitor_address = "192.168.199.110" + monitor_port = 443 timeouts { create = "5m" From e235b8e75b01804ec2a2758edbd1ac09de374a22 Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Tue, 26 Jul 2022 18:04:40 +0100 Subject: [PATCH 7/9] fix acceptance tests --- .../resource_openstack_lb_member_v2_test.go | 208 +++++++++++++++--- 1 file changed, 172 insertions(+), 36 deletions(-) diff --git a/openstack/resource_openstack_lb_member_v2_test.go b/openstack/resource_openstack_lb_member_v2_test.go index ec5349337..34b74dc41 100644 --- a/openstack/resource_openstack_lb_member_v2_test.go +++ b/openstack/resource_openstack_lb_member_v2_test.go @@ -41,6 +41,42 @@ func TestAccLBV2Member_basic(t *testing.T) { }) } +func TestAccLBV2Member_monitor(t *testing.T) { + var member1 pools.Member + var member2 pools.Member + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckNonAdminOnly(t) + testAccPreCheckLB(t) + testAccPreCheckUseOctavia(t) + }, + ProviderFactories: testAccProviders, + CheckDestroy: testAccCheckLBV2MemberDestroy, + Steps: []resource.TestStep{ + { + Config: TestAccLbV2MemberMonitor, + Check: resource.ComposeTestCheckFunc( + testAccCheckLBV2MemberExists("openstack_lb_member_v2.member_1", &member1), + testAccCheckLBV2MemberExists("openstack_lb_member_v2.member_2", &member2), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_address", "192.168.199.110"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "8080"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_address", "192.168.199.111"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_port", "8080"), + ), + }, + { + Config: TestAccLbV2MemberMonitorUpdate, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_address", "192.168.199.110"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_port", "443"), + ), + }, + }, + }) +} + func testAccCheckLBV2MemberDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) lbClient, err := chooseLBV2AccTestClient(config, osRegionName) @@ -96,43 +132,143 @@ func testAccCheckLBV2MemberExists(n string, member *pools.Member) resource.TestC } } -func TestAccLBV2Member_monitor(t *testing.T) { - var member1 pools.Member - var member2 pools.Member +const TestAccLbV2MemberConfigBasic = ` +resource "openstack_networking_network_v2" "network_1" { + name = "network_1" + admin_state_up = "true" +} - resource.Test(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - testAccPreCheckNonAdminOnly(t) - testAccPreCheckLB(t) - testAccPreCheckUseOctavia(t) - }, - ProviderFactories: testAccProviders, - CheckDestroy: testAccCheckLBV2MemberDestroy, - Steps: []resource.TestStep{ - { - Config: TestAccLbV2MemberConfigBasic, - Check: resource.ComposeTestCheckFunc( - testAccCheckLBV2MemberExists("openstack_lb_member_v2.member_1", &member1), - testAccCheckLBV2MemberExists("openstack_lb_member_v2.member_2", &member2), - resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_address", "192.168.199.110"), - resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "8080"), - resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_address", "192.168.199.111"), - resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "8080"), - ), - }, - { - Config: TestAccLbV2MemberConfigUpdate, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_address", "192.168.199.110"), - resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "443"), - ), - }, - }, - }) +resource "openstack_networking_subnet_v2" "subnet_1" { + name = "subnet_1" + network_id = "${openstack_networking_network_v2.network_1.id}" + cidr = "192.168.199.0/24" + ip_version = 4 } -const TestAccLbV2MemberConfigBasic = ` +resource "openstack_lb_loadbalancer_v2" "loadbalancer_1" { + name = "loadbalancer_1" + vip_subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + vip_address = "192.168.199.10" + + timeouts { + create = "15m" + update = "15m" + delete = "15m" + } +} + +resource "openstack_lb_listener_v2" "listener_1" { + name = "listener_1" + protocol = "HTTP" + protocol_port = 8080 + loadbalancer_id = "${openstack_lb_loadbalancer_v2.loadbalancer_1.id}" +} + +resource "openstack_lb_pool_v2" "pool_1" { + name = "pool_1" + protocol = "HTTP" + lb_method = "ROUND_ROBIN" + listener_id = "${openstack_lb_listener_v2.listener_1.id}" +} + +resource "openstack_lb_member_v2" "member_1" { + address = "192.168.199.110" + protocol_port = 8080 + pool_id = "${openstack_lb_pool_v2.pool_1.id}" + subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + weight = 0 + + timeouts { + create = "5m" + update = "5m" + delete = "5m" + } +} + +resource "openstack_lb_member_v2" "member_2" { + address = "192.168.199.111" + protocol_port = 8080 + pool_id = "${openstack_lb_pool_v2.pool_1.id}" + subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + + timeouts { + create = "5m" + update = "5m" + delete = "5m" + } +} +` + +const TestAccLbV2MemberConfigUpdate = ` +resource "openstack_networking_network_v2" "network_1" { + name = "network_1" + admin_state_up = "true" +} + +resource "openstack_networking_subnet_v2" "subnet_1" { + name = "subnet_1" + cidr = "192.168.199.0/24" + ip_version = 4 + network_id = "${openstack_networking_network_v2.network_1.id}" +} + +resource "openstack_lb_loadbalancer_v2" "loadbalancer_1" { + name = "loadbalancer_1" + vip_subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + + timeouts { + create = "15m" + update = "15m" + delete = "15m" + } +} + +resource "openstack_lb_listener_v2" "listener_1" { + name = "listener_1" + protocol = "HTTP" + protocol_port = 8080 + loadbalancer_id = "${openstack_lb_loadbalancer_v2.loadbalancer_1.id}" +} + +resource "openstack_lb_pool_v2" "pool_1" { + name = "pool_1" + protocol = "HTTP" + lb_method = "ROUND_ROBIN" + listener_id = "${openstack_lb_listener_v2.listener_1.id}" +} + +resource "openstack_lb_member_v2" "member_1" { + address = "192.168.199.110" + protocol_port = 8080 + weight = 10 + admin_state_up = "true" + pool_id = "${openstack_lb_pool_v2.pool_1.id}" + subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + + timeouts { + create = "5m" + update = "5m" + delete = "5m" + } +} + +resource "openstack_lb_member_v2" "member_2" { + address = "192.168.199.111" + protocol_port = 8080 + weight = 15 + admin_state_up = "true" + pool_id = "${openstack_lb_pool_v2.pool_1.id}" + subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" + + timeouts { + create = "5m" + update = "5m" + delete = "5m" + } +} +` + +const TestAccLbV2MemberMonitor = ` resource "openstack_networking_network_v2" "network_1" { name = "network_1" admin_state_up = "true" @@ -192,7 +328,7 @@ resource "openstack_lb_member_v2" "member_2" { protocol_port = 8080 pool_id = "${openstack_lb_pool_v2.pool_1.id}" subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" - monitor_address = "192.168.199.111" + monitor_address = "192.168.199.111 monitor_port = 8080 timeouts { @@ -203,7 +339,7 @@ resource "openstack_lb_member_v2" "member_2" { } ` -const TestAccLbV2MemberConfigUpdate = ` +const TestAccLbV2MemberMonitorUpdate = ` resource "openstack_networking_network_v2" "network_1" { name = "network_1" admin_state_up = "true" From 48b86a1f306a118d7fba718fdadf85ee5140ae04 Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Tue, 26 Jul 2022 18:06:15 +0100 Subject: [PATCH 8/9] making sure member1 does not change in this test case --- openstack/resource_openstack_lb_member_v2_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openstack/resource_openstack_lb_member_v2_test.go b/openstack/resource_openstack_lb_member_v2_test.go index 34b74dc41..2b19ecb66 100644 --- a/openstack/resource_openstack_lb_member_v2_test.go +++ b/openstack/resource_openstack_lb_member_v2_test.go @@ -69,6 +69,8 @@ func TestAccLBV2Member_monitor(t *testing.T) { { Config: TestAccLbV2MemberMonitorUpdate, Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_address", "192.168.199.110"), + resource.TestCheckResourceAttr("openstack_lb_member_v2.member_1", "monitor_port", "8080"), resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_address", "192.168.199.110"), resource.TestCheckResourceAttr("openstack_lb_member_v2.member_2", "monitor_port", "443"), ), From 9d10cc1adcaa2f5aa860f983e672782b53e2c3b1 Mon Sep 17 00:00:00 2001 From: Luigi Zhou Date: Wed, 27 Jul 2022 20:54:58 +0100 Subject: [PATCH 9/9] fix typo --- openstack/resource_openstack_lb_member_v2_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openstack/resource_openstack_lb_member_v2_test.go b/openstack/resource_openstack_lb_member_v2_test.go index 2b19ecb66..fbaecef6f 100644 --- a/openstack/resource_openstack_lb_member_v2_test.go +++ b/openstack/resource_openstack_lb_member_v2_test.go @@ -330,7 +330,7 @@ resource "openstack_lb_member_v2" "member_2" { protocol_port = 8080 pool_id = "${openstack_lb_pool_v2.pool_1.id}" subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}" - monitor_address = "192.168.199.111 + monitor_address = "192.168.199.111" monitor_port = 8080 timeouts {