Skip to content

Commit

Permalink
update diff func to account for all policy types
Browse files Browse the repository at this point in the history
  • Loading branch information
anGie44 committed Dec 21, 2021
1 parent cdf6bd6 commit 06860b8
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 43 deletions.
3 changes: 3 additions & 0 deletions .changelog/21776.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_load_balancer_policy: Suppress `policy_attribute` differences
```
4 changes: 4 additions & 0 deletions internal/service/elb/flex.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ func FlattenPolicyAttributes(list []*elb.PolicyAttributeDescription) []interface
var attributes []interface{}

for _, attrdef := range list {
if attrdef == nil {
continue
}

attribute := map[string]string{
"name": aws.StringValue(attrdef.AttributeName),
"value": aws.StringValue(attrdef.AttributeValue),
Expand Down
47 changes: 19 additions & 28 deletions internal/service/elb/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func ResourcePolicy() *schema.Resource {
"policy_attribute": {
Type: schema.TypeSet,
Optional: true,
// If policy_attribute(s) are not specified,
// default values per policy type (see https://awscli.amazonaws.com/v2/documentation/api/latest/reference/elb/describe-load-balancer-policies.html)
// will be returned by the API; thus, this TypeSet is marked as Computed.
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Expand All @@ -55,9 +59,9 @@ func ResourcePolicy() *schema.Resource {
},
},
},
// If policy_attribute(s) are not specified,
// default values per policy type (see https://awscli.amazonaws.com/v2/documentation/api/latest/reference/elb/describe-load-balancer-policies.html)
// will be returned by the API.
// For policy types like "SSLNegotiationPolicyType" that can reference predefined policies
// via the "Reference-Security-Policy" policy_attribute (https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html),
// differences caused by additional attributes returned by the API are suppressed.
DiffSuppressFunc: suppressPolicyAttributeDiffs,
},
},
Expand Down Expand Up @@ -352,33 +356,20 @@ func resourcePolicyUnassign(policyName, loadBalancerName string, conn *elb.ELB)
}

func suppressPolicyAttributeDiffs(k, old, new string, d *schema.ResourceData) bool {
o, n := d.GetChange("policy_attribute")
oldAttributes := ExpandPolicyAttributes(o.(*schema.Set).List())
newAttributes := ExpandPolicyAttributes(n.(*schema.Set).List())

if d.Get("policy_type_name").(string) == SSLNegotiationPolicyType {
if len(newAttributes) == 1 && aws.StringValue(newAttributes[0].AttributeName) == ReferenceSecurityPolicy {
for _, attr := range oldAttributes {
if aws.StringValue(attr.AttributeName) != aws.StringValue(newAttributes[0].AttributeName) {
continue
}
return aws.StringValue(attr.AttributeValue) == aws.StringValue(newAttributes[0].AttributeValue)
}
}
// Show difference for new resource
if d.Id() == "" {
return false
}

for _, na := range newAttributes {
found := false
for _, oa := range oldAttributes {
if aws.StringValue(oa.AttributeName) != aws.StringValue(na.AttributeName) {
continue
}
found = aws.StringValue(oa.AttributeValue) == aws.StringValue(na.AttributeValue)
}
if !found {
return false
}
// Show differences if configured attributes are not in state
if old == "0" && new != "0" {
return false
}

return true
o, n := d.GetChange("policy_attribute")
oldAttributes := o.(*schema.Set)
newAttributes := n.(*schema.Set)

// Suppress differences if the attributes returned from the API contain those configured
return oldAttributes.Intersection(newAttributes).Len() == newAttributes.Len()
}
95 changes: 80 additions & 15 deletions internal/service/elb/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestAccELBPolicy_disappears(t *testing.T) {
})
}

func TestAccELBPolicy_LBCookieStickinessPolicyType_computedAttributes(t *testing.T) {
func TestAccELBPolicy_LBCookieStickinessPolicyType_computedAttributesOnly(t *testing.T) {
var policy elb.PolicyDescription
resourceName := "aws_load_balancer_policy.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand All @@ -93,25 +93,37 @@ func TestAccELBPolicy_LBCookieStickinessPolicyType_computedAttributes(t *testing
Check: resource.ComposeTestCheckFunc(
testAccCheckPolicyExists(resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "policy_type_name", policyTypeName),
resource.TestCheckResourceAttr(resourceName, "policy_attribute.#", "0"),
resource.TestCheckResourceAttr(resourceName, "policy_attribute.#", "1"),
),
},
},
})
}

func TestAccELBPolicy_SSLNegotiationPolicyType_computedAttributesOnly(t *testing.T) {
var policy elb.PolicyDescription
resourceName := "aws_load_balancer_policy.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, elb.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccPolicyConfig_policyTypeNameOnly(rName, policyTypeName),
PlanOnly: true,
Config: testAccPolicyConfig_policyTypeNameOnly(rName, tfelb.SSLNegotiationPolicyType),
Check: resource.ComposeTestCheckFunc(
testAccCheckPolicyExists(resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "policy_attribute.#", "1"),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "policy_attribute.*", map[string]string{
"name": "CookieExpirationPeriod",
}),
resource.TestCheckResourceAttr(resourceName, "policy_type_name", tfelb.SSLNegotiationPolicyType),
resource.TestMatchResourceAttr(resourceName, "policy_attribute.#", regexp.MustCompile(`[^0]+`)),
),
},
},
})
}

func TestAccELBPolicy_SSLNegotiationPolicyType_computedAttributes(t *testing.T) {
func TestAccELBPolicy_SSLNegotiationPolicyType_customPolicy(t *testing.T) {
var policy elb.PolicyDescription
resourceName := "aws_load_balancer_policy.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand All @@ -123,27 +135,44 @@ func TestAccELBPolicy_SSLNegotiationPolicyType_computedAttributes(t *testing.T)
CheckDestroy: testAccCheckPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccPolicyConfig_policyTypeNameOnly(rName, tfelb.SSLNegotiationPolicyType),
Config: testAccPolicyConfig_customSSLSecurityPolicy(rName, "Protocol-TLSv1.1", "DHE-RSA-AES256-SHA256"),
Check: resource.ComposeTestCheckFunc(
testAccCheckPolicyExists(resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "policy_name", rName),
resource.TestCheckResourceAttr(resourceName, "policy_type_name", tfelb.SSLNegotiationPolicyType),
resource.TestCheckResourceAttr(resourceName, "policy_attribute.#", "0"),
resource.TestCheckResourceAttr(resourceName, "policy_attribute.#", "2"),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "policy_attribute.*", map[string]string{
"name": "Protocol-TLSv1.1",
"value": "true",
}),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "policy_attribute.*", map[string]string{
"name": "DHE-RSA-AES256-SHA256",
"value": "true",
}),
),
},
{
Config: testAccPolicyConfig_policyTypeNameOnly(rName, tfelb.SSLNegotiationPolicyType),
PlanOnly: true,
Config: testAccPolicyConfig_customSSLSecurityPolicy(rName, "Protocol-TLSv1.2", "ECDHE-ECDSA-AES128-GCM-SHA256"),
Check: resource.ComposeTestCheckFunc(
testAccCheckPolicyExists(resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "policy_name", rName),
resource.TestCheckResourceAttr(resourceName, "policy_type_name", tfelb.SSLNegotiationPolicyType),
resource.TestMatchResourceAttr(resourceName, "policy_attribute.#", regexp.MustCompile(`[^0]+`)),
resource.TestCheckResourceAttr(resourceName, "policy_attribute.#", "2"),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "policy_attribute.*", map[string]string{
"name": "Protocol-TLSv1.2",
"value": "true",
}),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "policy_attribute.*", map[string]string{
"name": "ECDHE-ECDSA-AES128-GCM-SHA256",
"value": "true",
}),
),
},
},
})
}

func TestAccELBPolicy_predefinedSSLSecurityPolicy(t *testing.T) {
func TestAccELBPolicy_SSLSecurityPolicy_predefined(t *testing.T) {
var policy elb.PolicyDescription
resourceName := "aws_load_balancer_policy.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand Down Expand Up @@ -408,6 +437,42 @@ resource "aws_load_balancer_policy" "test" {
`, rName, policyType))
}

func testAccPolicyConfig_customSSLSecurityPolicy(rName, protocol, cipher string) string {
return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(`
resource "aws_elb" "test" {
name = %[1]q
availability_zones = [data.aws_availability_zones.available.names[0]]
listener {
instance_port = 80
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
tags = {
Name = "tf-acc-test"
}
}
resource "aws_load_balancer_policy" "test" {
load_balancer_name = aws_elb.test.name
policy_name = %[1]q
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
name = %[2]q
value = "true"
}
policy_attribute {
name = %[3]q
value = "true"
}
}
`, rName, protocol, cipher))
}

func testAccPolicyConfig_predefinedSSLSecurityPolicy(rName, securityPolicy string) string {
return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(`
resource "aws_elb" "test" {
Expand Down

0 comments on commit 06860b8

Please sign in to comment.