From cfd8254db863312e25af2235c1c2c8c8fd8def41 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 15 Jun 2016 16:59:40 -0400 Subject: [PATCH] Check for existing but unassigned LB policies If an AWS Cookie Stickiness Policy is removed from the listener in the AWS console the policy isn't deleted. Cross reference the policy name with those assigned to the listener to determine if the policy is actually being used. --- ...source_aws_app_cookie_stickiness_policy.go | 52 ++++++++++++++++++- ...e_aws_app_cookie_stickiness_policy_test.go | 48 +++++++++++++++++ ...esource_aws_lb_cookie_stickiness_policy.go | 12 +++++ ...ce_aws_lb_cookie_stickiness_policy_test.go | 47 +++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy.go b/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy.go index 2b25064c5..ecdc8eff4 100644 --- a/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy.go +++ b/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy.go @@ -2,7 +2,9 @@ package aws import ( "fmt" + "log" "regexp" + "strconv" "strings" "github.com/aws/aws-sdk-go/aws" @@ -106,11 +108,22 @@ func resourceAwsAppCookieStickinessPolicyRead(d *schema.ResourceData, meta inter } return fmt.Errorf("Error retrieving policy: %s", err) } - if len(getResp.PolicyDescriptions) != 1 { return fmt.Errorf("Unable to find policy %#v", getResp.PolicyDescriptions) } + // we know the policy exists now, but we have to check if it's assigned to a listener + assigned, err := resourceAwsELBSticknessPolicyAssigned(policyName, lbName, lbPort, elbconn) + if err != nil { + return err + } + if !assigned { + // policy exists, but isn't assigned to a listener + log.Printf("[DEBUG] policy '%s' exists, but isn't assigned to a listener", policyName) + d.SetId("") + return nil + } + // We can get away with this because there's only one attribute, the // cookie expiration, in these descriptions. policyDesc := getResp.PolicyDescriptions[0] @@ -127,6 +140,43 @@ func resourceAwsAppCookieStickinessPolicyRead(d *schema.ResourceData, meta inter return nil } +// Determine if a particular policy is assigned to an ELB listener +func resourceAwsELBSticknessPolicyAssigned(policyName, lbName, lbPort string, elbconn *elb.ELB) (bool, error) { + describeElbOpts := &elb.DescribeLoadBalancersInput{ + LoadBalancerNames: []*string{aws.String(lbName)}, + } + describeResp, err := elbconn.DescribeLoadBalancers(describeElbOpts) + if err != nil { + if ec2err, ok := err.(awserr.Error); ok { + if ec2err.Code() == "LoadBalancerNotFound" { + return false, nil + } + } + return false, fmt.Errorf("Error retrieving ELB description: %s", err) + } + + if len(describeResp.LoadBalancerDescriptions) != 1 { + return false, fmt.Errorf("Unable to find ELB: %#v", describeResp.LoadBalancerDescriptions) + } + + lb := describeResp.LoadBalancerDescriptions[0] + assigned := false + for _, listener := range lb.ListenerDescriptions { + if lbPort != strconv.Itoa(int(*listener.Listener.LoadBalancerPort)) { + continue + } + + for _, name := range listener.PolicyNames { + if policyName == *name { + assigned = true + break + } + } + } + + return assigned, nil +} + func resourceAwsAppCookieStickinessPolicyDelete(d *schema.ResourceData, meta interface{}) error { elbconn := meta.(*AWSClient).elbconn diff --git a/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy_test.go b/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy_test.go index 5b2bd3612..ed0d25a46 100644 --- a/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy_test.go +++ b/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy_test.go @@ -139,6 +139,54 @@ func testAccCheckAppCookieStickinessPolicy(elbResource string, policyResource st } } +// ensure the policy is re-added is it goes missing +func TestAccAWSAppCookieStickinessPolicy_drift(t *testing.T) { + lbName := fmt.Sprintf("tf-test-lb-%s", acctest.RandString(5)) + + // We only want to remove the reference to the policy from the listner, + // beacause that's all that can be done via the console. + removePolicy := func() { + conn := testAccProvider.Meta().(*AWSClient).elbconn + + setLoadBalancerOpts := &elb.SetLoadBalancerPoliciesOfListenerInput{ + LoadBalancerName: aws.String(lbName), + LoadBalancerPort: aws.Int64(80), + PolicyNames: []*string{}, + } + + if _, err := conn.SetLoadBalancerPoliciesOfListener(setLoadBalancerOpts); err != nil { + t.Fatalf("Error removing AppCookieStickinessPolicy: %s", err) + } + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppCookieStickinessPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAppCookieStickinessPolicyConfig(lbName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppCookieStickinessPolicy( + "aws_elb.lb", + "aws_app_cookie_stickiness_policy.foo", + ), + ), + }, + resource.TestStep{ + PreConfig: removePolicy, + Config: testAccAppCookieStickinessPolicyConfig(lbName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppCookieStickinessPolicy( + "aws_elb.lb", + "aws_app_cookie_stickiness_policy.foo", + ), + ), + }, + }, + }) +} + func testAccAppCookieStickinessPolicyConfig(rName string) string { return fmt.Sprintf(` resource "aws_elb" "lb" { diff --git a/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy.go b/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy.go index ea2215b6a..6ef5042bf 100644 --- a/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy.go +++ b/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy.go @@ -115,6 +115,18 @@ func resourceAwsLBCookieStickinessPolicyRead(d *schema.ResourceData, meta interf return fmt.Errorf("Unable to find policy %#v", getResp.PolicyDescriptions) } + // we know the policy exists now, but we have to check if it's assigned to a listener + assigned, err := resourceAwsELBSticknessPolicyAssigned(policyName, lbName, lbPort, elbconn) + if err != nil { + return err + } + if !assigned { + // policy exists, but isn't assigned to a listener + log.Printf("[DEBUG] policy '%s' exists, but isn't assigned to a listener", policyName) + d.SetId("") + return nil + } + // We can get away with this because there's only one attribute, the // cookie expiration, in these descriptions. policyDesc := getResp.PolicyDescriptions[0] diff --git a/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy_test.go b/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy_test.go index 088848a13..877e49b76 100644 --- a/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy_test.go +++ b/builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy_test.go @@ -102,6 +102,53 @@ func testAccCheckLBCookieStickinessPolicy(elbResource string, policyResource str } } +func TestAccCheckLBCookieStickinessPolicy_drift(t *testing.T) { + lbName := fmt.Sprintf("tf-test-lb-%s", acctest.RandString(5)) + + // We only want to remove the reference to the policy from the listner, + // beacause that's all that can be done via the console. + removePolicy := func() { + conn := testAccProvider.Meta().(*AWSClient).elbconn + + setLoadBalancerOpts := &elb.SetLoadBalancerPoliciesOfListenerInput{ + LoadBalancerName: aws.String(lbName), + LoadBalancerPort: aws.Int64(80), + PolicyNames: []*string{}, + } + + if _, err := conn.SetLoadBalancerPoliciesOfListener(setLoadBalancerOpts); err != nil { + t.Fatalf("Error removing LBCookieStickinessPolicy: %s", err) + } + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLBCookieStickinessPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccLBCookieStickinessPolicyConfig(lbName), + Check: resource.ComposeTestCheckFunc( + testAccCheckLBCookieStickinessPolicy( + "aws_elb.lb", + "aws_lb_cookie_stickiness_policy.foo", + ), + ), + }, + resource.TestStep{ + PreConfig: removePolicy, + Config: testAccLBCookieStickinessPolicyConfig(lbName), + Check: resource.ComposeTestCheckFunc( + testAccCheckLBCookieStickinessPolicy( + "aws_elb.lb", + "aws_lb_cookie_stickiness_policy.foo", + ), + ), + }, + }, + }) +} + func testAccLBCookieStickinessPolicyConfig(rName string) string { return fmt.Sprintf(` resource "aws_elb" "lb" {