Skip to content

Commit

Permalink
Check for existing but unassigned LB policies
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jbardin committed Jun 16, 2016
1 parent 5fdcf5d commit cfd8254
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package aws

import (
"fmt"
"log"
"regexp"
"strconv"
"strings"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -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]
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down
12 changes: 12 additions & 0 deletions builtin/providers/aws/resource_aws_lb_cookie_stickiness_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down

0 comments on commit cfd8254

Please sign in to comment.