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.
This commit is contained in:
James Bardin 2016-06-15 16:59:40 -04:00
parent 5fdcf5d16a
commit cfd8254db8
4 changed files with 158 additions and 1 deletions

View File

@ -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

View File

@ -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" {

View File

@ -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]

View File

@ -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" {