From dac64ba3871d5547138c59db5a2b3b143e30e8af Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Tue, 21 Apr 2020 09:58:32 -0400 Subject: [PATCH 1/6] add support for importing aws_network_acl_rule resources --- aws/resource_aws_network_acl_rule.go | 63 +++++++++++++-- aws/resource_aws_network_acl_rule_test.go | 94 +++++++++++++++-------- 2 files changed, 122 insertions(+), 35 deletions(-) diff --git a/aws/resource_aws_network_acl_rule.go b/aws/resource_aws_network_acl_rule.go index ae3a52a8e16..48ec3e3f2d1 100644 --- a/aws/resource_aws_network_acl_rule.go +++ b/aws/resource_aws_network_acl_rule.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -19,6 +20,38 @@ func resourceAwsNetworkAclRule() *schema.Resource { Create: resourceAwsNetworkAclRuleCreate, Read: resourceAwsNetworkAclRuleRead, Delete: resourceAwsNetworkAclRuleDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + idParts := strings.Split(d.Id(), ":") + if len(idParts) != 4 || idParts[0] == "" || idParts[1] == "" || idParts[2] == "" || idParts[3] == "" { + return nil, fmt.Errorf("unexpected format of ID (%q), expected NETWORK_ACL_ID:RULE_NUMBER:PROTOCOL:EGRESS", d.Id()) + } + networkAclID := idParts[0] + ruleNumber, err := strconv.Atoi(idParts[1]) + if err != nil { + return nil, err + } + protocol, err := validateProtocolArgumentValue(idParts[2]) + if err != nil { + return nil, err + } + if protocol == nil { + return nil, fmt.Errorf("unknown protocol %s, expected one defined at %s", + idParts[2], "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)") + } + egress, err := strconv.ParseBool(idParts[3]) + if err != nil { + return nil, err + } + + d.Set("network_acl_id", networkAclID) + d.Set("rule_number", ruleNumber) + d.Set("egress", egress) + d.Set("protocol", protocol) + d.SetId(networkAclIdRuleNumberEgressHash(networkAclID, ruleNumber, egress, *protocol)) + return []*schema.ResourceData{d}, nil + }, + }, Schema: map[string]*schema.Schema{ "network_acl_id": { @@ -164,7 +197,11 @@ func resourceAwsNetworkAclRuleCreate(d *schema.ResourceData, meta interface{}) e if err != nil { return fmt.Errorf("Error Creating Network Acl Rule: %s", err.Error()) } - d.SetId(networkAclIdRuleNumberEgressHash(d.Get("network_acl_id").(string), d.Get("rule_number").(int), d.Get("egress").(bool), d.Get("protocol").(string))) + d.SetId(networkAclIdRuleNumberEgressHash( + d.Get("network_acl_id").(string), + d.Get("rule_number").(int), + d.Get("egress").(bool), + p)) // It appears it might be a while until the newly created rule is visible via the // API (see issue GH-4721). Retry the `findNetworkAclRule` function until it is @@ -210,9 +247,10 @@ func resourceAwsNetworkAclRuleRead(d *schema.ResourceData, meta interface{}) err d.Set("ipv6_cidr_block", resp.Ipv6CidrBlock) d.Set("egress", resp.Egress) if resp.IcmpTypeCode != nil { - d.Set("icmp_code", resp.IcmpTypeCode.Code) - d.Set("icmp_type", resp.IcmpTypeCode.Type) + d.Set("icmp_code", strconv.FormatInt(*resp.IcmpTypeCode.Code, 10)) + d.Set("icmp_type", strconv.FormatInt(*resp.IcmpTypeCode.Type, 10)) } + if resp.PortRange != nil { d.Set("from_port", resp.PortRange.From) d.Set("to_port", resp.PortRange.To) @@ -308,12 +346,12 @@ func findNetworkAclRule(d *schema.ResourceData, meta interface{}) (*ec2.NetworkA } -func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egress bool, protocol string) string { +func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egress bool, protocol int) string { var buf bytes.Buffer buf.WriteString(fmt.Sprintf("%s-", networkAclId)) buf.WriteString(fmt.Sprintf("%d-", ruleNumber)) buf.WriteString(fmt.Sprintf("%t-", egress)) - buf.WriteString(fmt.Sprintf("%s-", protocol)) + buf.WriteString(fmt.Sprintf("%d-", protocol)) return fmt.Sprintf("nacl-%d", hashcode.String(buf.String())) } @@ -325,3 +363,18 @@ func validateICMPArgumentValue(v interface{}, k string) (ws []string, errors []e } return } + +func validateProtocolArgumentValue(protocol string) (*int, error) { + pi := protocolIntegers() + if v, ok := pi[protocol]; ok { + return &v, nil + } + p, err := strconv.Atoi(protocol) + if err != nil { + return nil, err + } + if _, ok := protocolStrings(pi)[p]; ok { + return &p, nil + } + return nil, nil +} diff --git a/aws/resource_aws_network_acl_rule_test.go b/aws/resource_aws_network_acl_rule_test.go index db9186ce841..b89e650f790 100644 --- a/aws/resource_aws_network_acl_rule_test.go +++ b/aws/resource_aws_network_acl_rule_test.go @@ -15,8 +15,9 @@ import ( ) func TestAccAWSNetworkAclRule_basic(t *testing.T) { - var networkAcl ec2.NetworkAcl - + rnBaz := "aws_network_acl_rule.baz" + rnQux := "aws_network_acl_rule.qux" + rnWibble := "aws_network_acl_rule.wibble" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -24,11 +25,24 @@ func TestAccAWSNetworkAclRule_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleBasicConfig, - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.baz", &networkAcl), - testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.qux", &networkAcl), - testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.wibble", &networkAcl), - ), + }, + { + ResourceName: rnBaz, + ImportState: true, + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rnBaz), + ImportStateVerify: true, + }, + { + ResourceName: rnQux, + ImportState: true, + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rnQux), + ImportStateVerify: true, + }, + { + ResourceName: rnWibble, + ImportState: true, + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rnWibble), + ImportStateVerify: true, }, }, }) @@ -111,7 +125,7 @@ func TestAccAWSNetworkAclRule_missingParam(t *testing.T) { } func TestAccAWSNetworkAclRule_ipv6(t *testing.T) { - var networkAcl ec2.NetworkAcl + rn := "aws_network_acl_rule.baz" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -120,16 +134,18 @@ func TestAccAWSNetworkAclRule_ipv6(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleIpv6Config, - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.baz", &networkAcl), - ), + }, + { + ResourceName: rn, + ImportState: true, + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rn), + ImportStateVerify: true, }, }, }) } func TestAccAWSNetworkAclRule_ipv6ICMP(t *testing.T) { - var networkAcl ec2.NetworkAcl rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_network_acl_rule.test" @@ -140,9 +156,12 @@ func TestAccAWSNetworkAclRule_ipv6ICMP(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleConfigIpv6ICMP(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSNetworkAclRuleExists(resourceName, &networkAcl), - ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(resourceName), + ImportStateVerify: true, }, }, }) @@ -150,8 +169,6 @@ func TestAccAWSNetworkAclRule_ipv6ICMP(t *testing.T) { // Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/6710 func TestAccAWSNetworkAclRule_ipv6VpcAssignGeneratedIpv6CidrBlockUpdate(t *testing.T) { - var networkAcl ec2.NetworkAcl - var vpc ec2.Vpc vpcResourceName := "aws_vpc.test" resourceName := "aws_network_acl_rule.test" @@ -162,20 +179,25 @@ func TestAccAWSNetworkAclRule_ipv6VpcAssignGeneratedIpv6CidrBlockUpdate(t *testi Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleConfigIpv6VpcAssignGeneratedIpv6CidrBlockUpdate(false), - Check: resource.ComposeTestCheckFunc( - testAccCheckVpcExists(vpcResourceName, &vpc), - resource.TestCheckResourceAttr(vpcResourceName, "assign_generated_ipv6_cidr_block", "false"), - resource.TestCheckResourceAttr(vpcResourceName, "ipv6_cidr_block", ""), - ), + }, + { + ResourceName: vpcResourceName, + ImportState: true, + ImportStateVerify: true, }, { Config: testAccAWSNetworkAclRuleConfigIpv6VpcAssignGeneratedIpv6CidrBlockUpdate(true), - Check: resource.ComposeTestCheckFunc( - testAccCheckVpcExists(vpcResourceName, &vpc), - resource.TestCheckResourceAttr(vpcResourceName, "assign_generated_ipv6_cidr_block", "true"), - resource.TestMatchResourceAttr(vpcResourceName, "ipv6_cidr_block", regexp.MustCompile(`/56$`)), - testAccCheckAWSNetworkAclRuleExists(resourceName, &networkAcl), - ), + }, + { + ResourceName: vpcResourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(resourceName), + ImportStateVerify: true, }, }, }) @@ -632,7 +654,6 @@ resource "aws_network_acl" "test" { } resource "aws_network_acl_rule" "test" { - from_port = -1 icmp_code = -1 icmp_type = -1 ipv6_cidr_block = "::/0" @@ -640,7 +661,6 @@ resource "aws_network_acl_rule" "test" { protocol = 58 rule_action = "allow" rule_number = 150 - to_port = -1 } `, rName, rName) } @@ -677,3 +697,17 @@ resource "aws_network_acl_rule" "test" { } `, ipv6Enabled) } + +func testAccAWSNetworkAclRuleImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("not found: %s", resourceName) + } + networkAclId := rs.Primary.Attributes["network_acl_id"] + ruleNumber := rs.Primary.Attributes["rule_number"] + protocol := rs.Primary.Attributes["protocol"] + egress := rs.Primary.Attributes["egress"] + return fmt.Sprintf("%s:%s:%s:%s", networkAclId, ruleNumber, protocol, egress), nil + } +} From 9229e4594e3d75c479f958e172631373004e23a7 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Tue, 21 Apr 2020 10:54:41 -0400 Subject: [PATCH 2/6] update documentation for acl_rule importing --- website/docs/r/network_acl_rule.html.markdown | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/website/docs/r/network_acl_rule.html.markdown b/website/docs/r/network_acl_rule.html.markdown index 308aeac8ffc..5ae474ff743 100644 --- a/website/docs/r/network_acl_rule.html.markdown +++ b/website/docs/r/network_acl_rule.html.markdown @@ -64,3 +64,18 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the network ACL Rule + +## Import + +Individual rules can be imported using `NETWORK_ACL_ID:RULE_NUMBER:PROTOCOL:EGRESS`, where `PROTOCOL` can be a decimal (e.g. 6) or string (e.g. tcp) value. +For more information on protocol numbers and keywords, see here: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + +For example, import a network ACL Rule with an argument like this: + +```console +$ terraform import aws_network_acl_rule.my_rule acl-7aaabd18:100:tcp:false +``` +Or by the procotol's decimal value: +```console +$ terraform import aws_route.my_route acl-7aaabd18:100:6:false +``` From 1e77b6a6f55307a194a879fb83e1b438dc490e71 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Tue, 21 Apr 2020 11:30:44 -0400 Subject: [PATCH 3/6] formatting with linter --- website/docs/r/network_acl_rule.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/r/network_acl_rule.html.markdown b/website/docs/r/network_acl_rule.html.markdown index 5ae474ff743..da436d75ed4 100644 --- a/website/docs/r/network_acl_rule.html.markdown +++ b/website/docs/r/network_acl_rule.html.markdown @@ -75,7 +75,9 @@ For example, import a network ACL Rule with an argument like this: ```console $ terraform import aws_network_acl_rule.my_rule acl-7aaabd18:100:tcp:false ``` + Or by the procotol's decimal value: + ```console $ terraform import aws_route.my_route acl-7aaabd18:100:6:false ``` From ae9081d0e0a4a467f3766192c1d7ab90e1ecc004 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Tue, 21 Apr 2020 11:31:42 -0400 Subject: [PATCH 4/6] rename example resource --- website/docs/r/network_acl_rule.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/network_acl_rule.html.markdown b/website/docs/r/network_acl_rule.html.markdown index da436d75ed4..5afebe271a7 100644 --- a/website/docs/r/network_acl_rule.html.markdown +++ b/website/docs/r/network_acl_rule.html.markdown @@ -79,5 +79,5 @@ $ terraform import aws_network_acl_rule.my_rule acl-7aaabd18:100:tcp:false Or by the procotol's decimal value: ```console -$ terraform import aws_route.my_route acl-7aaabd18:100:6:false +$ terraform import aws_network_acl_rule.my_rule acl-7aaabd18:100:6:false ``` From dd6ad585663c66c0f53c5604625c8d4771ed3ca6 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 22 Apr 2020 01:29:36 -0400 Subject: [PATCH 5/6] code review updates and doc update --- aws/resource_aws_network_acl_rule.go | 38 +++---------------- aws/resource_aws_network_acl_rule_test.go | 13 +------ website/docs/r/network_acl_rule.html.markdown | 1 + 3 files changed, 7 insertions(+), 45 deletions(-) diff --git a/aws/resource_aws_network_acl_rule.go b/aws/resource_aws_network_acl_rule.go index 48ec3e3f2d1..01c52fd8453 100644 --- a/aws/resource_aws_network_acl_rule.go +++ b/aws/resource_aws_network_acl_rule.go @@ -31,14 +31,7 @@ func resourceAwsNetworkAclRule() *schema.Resource { if err != nil { return nil, err } - protocol, err := validateProtocolArgumentValue(idParts[2]) - if err != nil { - return nil, err - } - if protocol == nil { - return nil, fmt.Errorf("unknown protocol %s, expected one defined at %s", - idParts[2], "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)") - } + protocol := idParts[2] egress, err := strconv.ParseBool(idParts[3]) if err != nil { return nil, err @@ -47,8 +40,7 @@ func resourceAwsNetworkAclRule() *schema.Resource { d.Set("network_acl_id", networkAclID) d.Set("rule_number", ruleNumber) d.Set("egress", egress) - d.Set("protocol", protocol) - d.SetId(networkAclIdRuleNumberEgressHash(networkAclID, ruleNumber, egress, *protocol)) + d.SetId(networkAclIdRuleNumberEgressHash(networkAclID, ruleNumber, egress, protocol)) return []*schema.ResourceData{d}, nil }, }, @@ -197,11 +189,7 @@ func resourceAwsNetworkAclRuleCreate(d *schema.ResourceData, meta interface{}) e if err != nil { return fmt.Errorf("Error Creating Network Acl Rule: %s", err.Error()) } - d.SetId(networkAclIdRuleNumberEgressHash( - d.Get("network_acl_id").(string), - d.Get("rule_number").(int), - d.Get("egress").(bool), - p)) + d.SetId(networkAclIdRuleNumberEgressHash(d.Get("network_acl_id").(string), d.Get("rule_number").(int), d.Get("egress").(bool), d.Get("protocol").(string))) // It appears it might be a while until the newly created rule is visible via the // API (see issue GH-4721). Retry the `findNetworkAclRule` function until it is @@ -250,7 +238,6 @@ func resourceAwsNetworkAclRuleRead(d *schema.ResourceData, meta interface{}) err d.Set("icmp_code", strconv.FormatInt(*resp.IcmpTypeCode.Code, 10)) d.Set("icmp_type", strconv.FormatInt(*resp.IcmpTypeCode.Type, 10)) } - if resp.PortRange != nil { d.Set("from_port", resp.PortRange.From) d.Set("to_port", resp.PortRange.To) @@ -346,12 +333,12 @@ func findNetworkAclRule(d *schema.ResourceData, meta interface{}) (*ec2.NetworkA } -func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egress bool, protocol int) string { +func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egress bool, protocol string) string { var buf bytes.Buffer buf.WriteString(fmt.Sprintf("%s-", networkAclId)) buf.WriteString(fmt.Sprintf("%d-", ruleNumber)) buf.WriteString(fmt.Sprintf("%t-", egress)) - buf.WriteString(fmt.Sprintf("%d-", protocol)) + buf.WriteString(fmt.Sprintf("%s-", protocol)) return fmt.Sprintf("nacl-%d", hashcode.String(buf.String())) } @@ -363,18 +350,3 @@ func validateICMPArgumentValue(v interface{}, k string) (ws []string, errors []e } return } - -func validateProtocolArgumentValue(protocol string) (*int, error) { - pi := protocolIntegers() - if v, ok := pi[protocol]; ok { - return &v, nil - } - p, err := strconv.Atoi(protocol) - if err != nil { - return nil, err - } - if _, ok := protocolStrings(pi)[p]; ok { - return &p, nil - } - return nil, nil -} diff --git a/aws/resource_aws_network_acl_rule_test.go b/aws/resource_aws_network_acl_rule_test.go index b89e650f790..3cb3290aedd 100644 --- a/aws/resource_aws_network_acl_rule_test.go +++ b/aws/resource_aws_network_acl_rule_test.go @@ -169,7 +169,6 @@ func TestAccAWSNetworkAclRule_ipv6ICMP(t *testing.T) { // Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/6710 func TestAccAWSNetworkAclRule_ipv6VpcAssignGeneratedIpv6CidrBlockUpdate(t *testing.T) { - vpcResourceName := "aws_vpc.test" resourceName := "aws_network_acl_rule.test" resource.ParallelTest(t, resource.TestCase{ @@ -180,19 +179,9 @@ func TestAccAWSNetworkAclRule_ipv6VpcAssignGeneratedIpv6CidrBlockUpdate(t *testi { Config: testAccAWSNetworkAclRuleConfigIpv6VpcAssignGeneratedIpv6CidrBlockUpdate(false), }, - { - ResourceName: vpcResourceName, - ImportState: true, - ImportStateVerify: true, - }, { Config: testAccAWSNetworkAclRuleConfigIpv6VpcAssignGeneratedIpv6CidrBlockUpdate(true), }, - { - ResourceName: vpcResourceName, - ImportState: true, - ImportStateVerify: true, - }, { ResourceName: resourceName, ImportState: true, @@ -658,7 +647,7 @@ resource "aws_network_acl_rule" "test" { icmp_type = -1 ipv6_cidr_block = "::/0" network_acl_id = "${aws_network_acl.test.id}" - protocol = 58 + protocol = "ipv6-icmp" rule_action = "allow" rule_number = 150 } diff --git a/website/docs/r/network_acl_rule.html.markdown b/website/docs/r/network_acl_rule.html.markdown index 5afebe271a7..982d9e6255e 100644 --- a/website/docs/r/network_acl_rule.html.markdown +++ b/website/docs/r/network_acl_rule.html.markdown @@ -68,6 +68,7 @@ In addition to all arguments above, the following attributes are exported: ## Import Individual rules can be imported using `NETWORK_ACL_ID:RULE_NUMBER:PROTOCOL:EGRESS`, where `PROTOCOL` can be a decimal (e.g. 6) or string (e.g. tcp) value. +If importing a rule previously provisioned by Terraform, the `PROTOCOL` must be the input value used at creation time. For more information on protocol numbers and keywords, see here: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml For example, import a network ACL Rule with an argument like this: From c4d06beeca30e1b90b4cd49ead9a04eba606a109 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 22 Apr 2020 16:51:11 -0400 Subject: [PATCH 6/6] updates to add in resource attribute checks --- aws/resource_aws_network_acl_rule.go | 4 +- aws/resource_aws_network_acl_rule_test.go | 61 +++++++++++++++++------ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/aws/resource_aws_network_acl_rule.go b/aws/resource_aws_network_acl_rule.go index 01c52fd8453..c8adab7a897 100644 --- a/aws/resource_aws_network_acl_rule.go +++ b/aws/resource_aws_network_acl_rule.go @@ -235,8 +235,8 @@ func resourceAwsNetworkAclRuleRead(d *schema.ResourceData, meta interface{}) err d.Set("ipv6_cidr_block", resp.Ipv6CidrBlock) d.Set("egress", resp.Egress) if resp.IcmpTypeCode != nil { - d.Set("icmp_code", strconv.FormatInt(*resp.IcmpTypeCode.Code, 10)) - d.Set("icmp_type", strconv.FormatInt(*resp.IcmpTypeCode.Type, 10)) + d.Set("icmp_code", strconv.FormatInt(aws.Int64Value(resp.IcmpTypeCode.Code), 10)) + d.Set("icmp_type", strconv.FormatInt(aws.Int64Value(resp.IcmpTypeCode.Type), 10)) } if resp.PortRange != nil { d.Set("from_port", resp.PortRange.From) diff --git a/aws/resource_aws_network_acl_rule_test.go b/aws/resource_aws_network_acl_rule_test.go index 3cb3290aedd..60cdd3e134e 100644 --- a/aws/resource_aws_network_acl_rule_test.go +++ b/aws/resource_aws_network_acl_rule_test.go @@ -15,9 +15,8 @@ import ( ) func TestAccAWSNetworkAclRule_basic(t *testing.T) { - rnBaz := "aws_network_acl_rule.baz" - rnQux := "aws_network_acl_rule.qux" - rnWibble := "aws_network_acl_rule.wibble" + var networkAcl ec2.NetworkAcl + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -25,23 +24,28 @@ func TestAccAWSNetworkAclRule_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleBasicConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.baz", &networkAcl), + testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.qux", &networkAcl), + testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.wibble", &networkAcl), + ), }, { - ResourceName: rnBaz, + ResourceName: "aws_network_acl_rule.baz", ImportState: true, - ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rnBaz), + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc("aws_network_acl_rule.baz", "tcp"), ImportStateVerify: true, }, { - ResourceName: rnQux, + ResourceName: "aws_network_acl_rule.qux", ImportState: true, - ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rnQux), + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc("aws_network_acl_rule.qux", "icmp"), ImportStateVerify: true, }, { - ResourceName: rnWibble, + ResourceName: "aws_network_acl_rule.wibble", ImportState: true, - ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rnWibble), + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc("aws_network_acl_rule.wibble", "icmp"), ImportStateVerify: true, }, }, @@ -125,7 +129,7 @@ func TestAccAWSNetworkAclRule_missingParam(t *testing.T) { } func TestAccAWSNetworkAclRule_ipv6(t *testing.T) { - rn := "aws_network_acl_rule.baz" + var networkAcl ec2.NetworkAcl resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -134,11 +138,14 @@ func TestAccAWSNetworkAclRule_ipv6(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleIpv6Config, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSNetworkAclRuleExists("aws_network_acl_rule.baz", &networkAcl), + ), }, { - ResourceName: rn, + ResourceName: "aws_network_acl_rule.baz", ImportState: true, - ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(rn), + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc("aws_network_acl_rule.baz", "tcp"), ImportStateVerify: true, }, }, @@ -146,6 +153,7 @@ func TestAccAWSNetworkAclRule_ipv6(t *testing.T) { } func TestAccAWSNetworkAclRule_ipv6ICMP(t *testing.T) { + var networkAcl ec2.NetworkAcl rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_network_acl_rule.test" @@ -156,11 +164,14 @@ func TestAccAWSNetworkAclRule_ipv6ICMP(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleConfigIpv6ICMP(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSNetworkAclRuleExists(resourceName, &networkAcl), + ), }, { ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(resourceName), + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(resourceName, "58"), ImportStateVerify: true, }, }, @@ -169,6 +180,9 @@ func TestAccAWSNetworkAclRule_ipv6ICMP(t *testing.T) { // Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/6710 func TestAccAWSNetworkAclRule_ipv6VpcAssignGeneratedIpv6CidrBlockUpdate(t *testing.T) { + var networkAcl ec2.NetworkAcl + var vpc ec2.Vpc + vpcResourceName := "aws_vpc.test" resourceName := "aws_network_acl_rule.test" resource.ParallelTest(t, resource.TestCase{ @@ -178,14 +192,25 @@ func TestAccAWSNetworkAclRule_ipv6VpcAssignGeneratedIpv6CidrBlockUpdate(t *testi Steps: []resource.TestStep{ { Config: testAccAWSNetworkAclRuleConfigIpv6VpcAssignGeneratedIpv6CidrBlockUpdate(false), + Check: resource.ComposeTestCheckFunc( + testAccCheckVpcExists(vpcResourceName, &vpc), + resource.TestCheckResourceAttr(vpcResourceName, "assign_generated_ipv6_cidr_block", "false"), + resource.TestCheckResourceAttr(vpcResourceName, "ipv6_cidr_block", ""), + ), }, { Config: testAccAWSNetworkAclRuleConfigIpv6VpcAssignGeneratedIpv6CidrBlockUpdate(true), + Check: resource.ComposeTestCheckFunc( + testAccCheckVpcExists(vpcResourceName, &vpc), + resource.TestCheckResourceAttr(vpcResourceName, "assign_generated_ipv6_cidr_block", "true"), + resource.TestMatchResourceAttr(vpcResourceName, "ipv6_cidr_block", regexp.MustCompile(`/56$`)), + testAccCheckAWSNetworkAclRuleExists(resourceName, &networkAcl), + ), }, { ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(resourceName), + ImportStateIdFunc: testAccAWSNetworkAclRuleImportStateIdFunc(resourceName, "tcp"), ImportStateVerify: true, }, }, @@ -647,7 +672,7 @@ resource "aws_network_acl_rule" "test" { icmp_type = -1 ipv6_cidr_block = "::/0" network_acl_id = "${aws_network_acl.test.id}" - protocol = "ipv6-icmp" + protocol = 58 rule_action = "allow" rule_number = 150 } @@ -687,7 +712,7 @@ resource "aws_network_acl_rule" "test" { `, ipv6Enabled) } -func testAccAWSNetworkAclRuleImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { +func testAccAWSNetworkAclRuleImportStateIdFunc(resourceName, resourceProtocol string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[resourceName] if !ok { @@ -696,6 +721,10 @@ func testAccAWSNetworkAclRuleImportStateIdFunc(resourceName string) resource.Imp networkAclId := rs.Primary.Attributes["network_acl_id"] ruleNumber := rs.Primary.Attributes["rule_number"] protocol := rs.Primary.Attributes["protocol"] + // Ensure the resource's ID will be determined from the original protocol value set in the resource's config + if protocol != resourceProtocol { + protocol = resourceProtocol + } egress := rs.Primary.Attributes["egress"] return fmt.Sprintf("%s:%s:%s:%s", networkAclId, ruleNumber, protocol, egress), nil }