From 49408fa687b7bf048dd1281a51b949b31e34aea5 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 16 Feb 2021 21:09:10 -0600 Subject: [PATCH 01/67] created resource files. Copied test file from another resource --- aws/resource_aws_subnet_nacl_association.go | 112 ++++++++++++++++++ ...source_aws_subnet_nacl_association_test.go | 111 +++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 aws/resource_aws_subnet_nacl_association.go create mode 100644 aws/resource_aws_subnet_nacl_association_test.go diff --git a/aws/resource_aws_subnet_nacl_association.go b/aws/resource_aws_subnet_nacl_association.go new file mode 100644 index 000000000000..7fb491ef6c8a --- /dev/null +++ b/aws/resource_aws_subnet_nacl_association.go @@ -0,0 +1,112 @@ +package aws + +import ( + "fmt" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceAwsSubnetNaclAssociation() *schema.Resource { + //lintignore:R011 + return &schema.Resource{ + Create: resourceAwsSubnetNaclAssociationCreate, + Read: resourceAwsSubnetNaclAssociationRead, + Update: resourceAwsSubnetNaclAssociationUpdate, + Delete: resourceAwsSubnetNaclAssociationDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + SchemaVersion: 1, + + Schema: map[string]*schema.Schema{ + "subnet_id": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + + "network_acl_id": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + }, + } +} + +func resourceAwsSubnetNaclAssociationCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + // find all current nacls with subnet id + subnetId := d.Get("subnet_id").(string) + existingAssociation := findNetworkAclAssociation(subnetId, conn) + + log.Printf(existingAssociation.(string)) + createOpts := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: aws.String(existingAssociation.NetworkAclAssociationId.(string)), + NetworkAclId: aws.String(d.Get("network_acl_id").(string)), + } + + var err error + resp, err := conn.ReplaceNetworkAclAssociation(createOpts) + + if err != nil { + return fmt.Errorf("error replacing subnet network acl association: %w", err) + } + + // Get the ID and store it + associationId := aws.StringValue(resp.NewAssociationId) + d.SetId(associationId.(string)) + log.Printf("[INFO] New Association ID: %s", associationId) + + _, err = stateConf.WaitForState() + + if err != nil { + return fmt.Errorf("error waiting for subnet (%s) to become ready: %w", d.Id(), err) + } + + return resourceAwsSubnetNaclAssociationRead(d, meta) +} + +func resourceAwsSubnetNaclAssociationRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + subnetId := d.Get("subnet_id").(string) + existingAssociation, err := findNetworkAclAssociation(subnetId, conn) + + if err != nil { + if isAWSErr(err, "InvalidNetworkAclSubnetAssociation.NotFound", "") { + log.Printf("[WARN] Network Acl Association for Subnet Id (%s) not found, removing from state", d.Get("network_acl_id"), d.Get("subnet_id")) + d.SetId("") + return nil + } + return err + } + + if d.Get("subnet_id") == aws.StringValue(existingAssociation.SubnetId) { + d.SetId(aws.StringValue(existingAssociation.NetworkAclAssociationId)) + d.Set("network_acl_id", aws.StringValue(existingAssociation.NetworkAclId)) + return nil + } + + return nil +} + +func resourceAwsSubnetNaclAssociationUpdate(d *schema.ResourceData, meta interface{}) error { + return resourceAwsSubnetNaclAssociationCreate(d, meta) +} + +func resourceAwsSubnetNaclAssociationDelete(d *schema.ResourceData, meta interface{}) error { + log.Printf("[WARN] Cannot destroy Network ACL Association. Terraform will remove this resource from the state file, however resources may remain.") + return nil +} diff --git a/aws/resource_aws_subnet_nacl_association_test.go b/aws/resource_aws_subnet_nacl_association_test.go new file mode 100644 index 000000000000..bdfa0947f715 --- /dev/null +++ b/aws/resource_aws_subnet_nacl_association_test.go @@ -0,0 +1,111 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccAWSNetworkInterfaceAttachment_basic(t *testing.T) { + var conf ec2.NetworkInterface + rInt := acctest.RandInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_network_interface.bar", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSENIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSNetworkInterfaceAttachmentConfig_basic(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSENIExists("aws_network_interface.bar", &conf), + resource.TestCheckResourceAttr( + "aws_network_interface_attachment.test", "device_index", "1"), + resource.TestCheckResourceAttrSet( + "aws_network_interface_attachment.test", "instance_id"), + resource.TestCheckResourceAttrSet( + "aws_network_interface_attachment.test", "network_interface_id"), + resource.TestCheckResourceAttrSet( + "aws_network_interface_attachment.test", "attachment_id"), + resource.TestCheckResourceAttrSet( + "aws_network_interface_attachment.test", "status"), + ), + }, + }, + }) +} + +func testAccAWSNetworkInterfaceAttachmentConfig_basic(rInt int) string { + return testAccLatestAmazonLinuxHvmEbsAmiConfig() + fmt.Sprintf(` +resource "aws_vpc" "foo" { + cidr_block = "172.16.0.0/16" + + tags = { + Name = "terraform-testacc-network-iface-attachment-basic" + } +} + +data "aws_availability_zones" "available" { + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_subnet" "foo" { + vpc_id = aws_vpc.foo.id + cidr_block = "172.16.10.0/24" + availability_zone = data.aws_availability_zones.available.names[0] + + tags = { + Name = "tf-acc-network-iface-attachment-basic" + } +} + +resource "aws_security_group" "foo" { + vpc_id = aws_vpc.foo.id + description = "foo" + name = "foo-%d" + + egress { + from_port = 0 + to_port = 0 + protocol = "tcp" + cidr_blocks = ["10.0.0.0/16"] + } +} + +resource "aws_network_interface" "bar" { + subnet_id = aws_subnet.foo.id + private_ips = ["172.16.10.100"] + security_groups = [aws_security_group.foo.id] + description = "Managed by Terraform" + + tags = { + Name = "bar_interface" + } +} + +resource "aws_instance" "foo" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = "t2.micro" + subnet_id = aws_subnet.foo.id + + tags = { + Name = "foo-%d" + } +} + +resource "aws_network_interface_attachment" "test" { + device_index = 1 + instance_id = aws_instance.foo.id + network_interface_id = aws_network_interface.bar.id +} +`, rInt, rInt) +} From 88f90a2950afa8b53e264cf4788b6bd064412973 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 12 Apr 2021 16:55:02 -0500 Subject: [PATCH 02/67] working test case --- aws/provider.go | 1 + aws/resource_aws_network_acl_association.go | 181 ++++++++++++++++++ ...source_aws_network_acl_association_test.go | 62 ++++++ aws/resource_aws_subnet_nacl_association.go | 112 ----------- ...source_aws_subnet_nacl_association_test.go | 111 ----------- .../docs/r/network_acl_association.markdown | 35 ++++ 6 files changed, 279 insertions(+), 223 deletions(-) create mode 100644 aws/resource_aws_network_acl_association.go create mode 100644 aws/resource_aws_network_acl_association_test.go delete mode 100644 aws/resource_aws_subnet_nacl_association.go delete mode 100644 aws/resource_aws_subnet_nacl_association_test.go create mode 100644 website/docs/r/network_acl_association.markdown diff --git a/aws/provider.go b/aws/provider.go index d07e1c7deca5..58443c1691e3 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -809,6 +809,7 @@ func Provider() *schema.Provider { "aws_msk_scram_secret_association": resourceAwsMskScramSecretAssociation(), "aws_nat_gateway": resourceAwsNatGateway(), "aws_network_acl": resourceAwsNetworkAcl(), + "aws_network_acl_association": resourceAwsNetworkAclAssociation(), "aws_default_network_acl": resourceAwsDefaultNetworkAcl(), "aws_neptune_cluster": resourceAwsNeptuneCluster(), "aws_neptune_cluster_instance": resourceAwsNeptuneClusterInstance(), diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go new file mode 100644 index 000000000000..b6ec56399e81 --- /dev/null +++ b/aws/resource_aws_network_acl_association.go @@ -0,0 +1,181 @@ +package aws + +import ( + "fmt" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceAwsNetworkAclAssociation() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsNetworkAclAssociationCreate, + Read: resourceAwsNetworkAclAssociationRead, + Update: resourceAwsNetworkAclAssociationUpdate, + Delete: resourceAwsNetworkAclAssociationDelete, + + Schema: map[string]*schema.Schema{ + "subnet_id": { + Type: schema.TypeString, + Required: true, + }, + + "network_acl_id": { + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func resourceAwsNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + naclId := d.Get("network_acl_id").(string) + subnetId := d.Get("subnet_id").(string) + + association, errAssociation := findNetworkAclAssociation(subnetId, conn) + if errAssociation != nil { + return fmt.Errorf("Failed to find association for subnet %s: %s", subnetId, errAssociation) + } + + associationOpts := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: aws.String(naclId), + } + log.Printf("[DEBUG] Creating Network ACL association: %#v", associationOpts) + + resp, err := conn.ReplaceNetworkAclAssociation(associationOpts) + if err != nil { + return fmt.Errorf("Error creating network acl association: %w", err) + } + + associationId := resp.NewAssociationId + d.SetId(aws.StringValue(associationId)) + log.Printf("[INFO] New Association ID: %s", d.Id()) + + //_, err = stateConf.WaitForState() + + // if err != nil { + // return fmt.Errorf("error waiting for network acl association (%s) to become ready: %w", d.Id(), err) + // } + + return resourceAwsNetworkAclAssociationRead(d, meta) +} + +func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + // Inspect that the association exists + subnetId := d.Get("subnet_id").(string) + _, errAssociation := findNetworkAclAssociation(subnetId, conn) + if errAssociation != nil { + log.Printf("[WARN] Association for subnet %s was not found, removing from state", subnetId) + d.SetId("") + return nil + } + + return nil +} + +func resourceAwsNetworkAclAssociationUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + naclId := d.Get("network_acl_id").(string) + subnetId := d.Get("subnet_id").(string) + + association, errAssociation := findNetworkAclAssociation(subnetId, conn) + if errAssociation != nil { + return fmt.Errorf("Failed to find association for subnet %s: %s", subnetId, errAssociation) + } + + associationOpts := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: aws.String(naclId), + } + + _, err := conn.ReplaceNetworkAclAssociation(associationOpts) + + log.Printf("[DEBUG] Updating Network ACL association: %#v", associationOpts) + + if err != nil { + if isAWSErr(err, "InvalidAssociationID.NotFound", "") { + // Not found, so just create a new one + return resourceAwsNetworkAclAssociationCreate(d, meta) + } + + return err + } + + return resourceAwsNetworkAclAssociationRead(d, meta) +} + +func resourceAwsNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { + + conn := meta.(*AWSClient).ec2conn + + subnetId := d.Get("subnet_id").(string) + + req := &ec2.DescribeNetworkAclsInput{} + req.Filters = buildEC2AttributeFilterList( + map[string]string{ + "association.subnet-id": subnetId, + }, + ) + + resp, err := conn.DescribeNetworkAcls(req) + if err != nil { + return err + } + + if len(resp.NetworkAcls) == 0 { + return fmt.Errorf("Unable to find Network ACL for subnet: %s", subnetId) + } + + nacl := resp.NetworkAcls[0] + var association *ec2.NetworkAclAssociation + if len(resp.NetworkAcls) > 0 { + for _, assoc := range nacl.Associations { + if aws.StringValue(assoc.SubnetId) == subnetId { + association = assoc + } + } + } + + defaultAcl, err := getDefaultNetworkAcl(*nacl.VpcId, conn) + + if err != nil { + return fmt.Errorf("Failed to get default Network Acl : %s", err) + } + + associationOpts := ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: defaultAcl.NetworkAclId, + } + + log.Printf("[DEBUG] Replacing Network ACL association: %#v", associationOpts) + + err = resource.Retry(5*time.Minute, func() *resource.RetryError { + _, err = conn.ReplaceNetworkAclAssociation(&associationOpts) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok { + if awsErr != nil { + return resource.RetryableError(awsErr) + } + } + return resource.NonRetryableError(err) + } + return nil + }) + if err != nil { + return err + } + + d.SetId("") + return nil +} diff --git a/aws/resource_aws_network_acl_association_test.go b/aws/resource_aws_network_acl_association_test.go new file mode 100644 index 000000000000..7d2868ce7f7a --- /dev/null +++ b/aws/resource_aws_network_acl_association_test.go @@ -0,0 +1,62 @@ +package aws + +import ( + "testing" + + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func init() { + resource.AddTestSweepers("aws_network_acl_association", &resource.Sweeper{ + Name: "aws_network_acl_association", + F: testSweepNetworkAcls, + }) +} + +func TestAccAWSNetworkAclAssociation(t *testing.T) { + var networkAcl ec2.NetworkAcl + resourceName := "aws_network_acl.acl_a" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: resourceName, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSNetworkAclDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSNetworkAclAssoc, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSNetworkAclExists(resourceName, &networkAcl), + testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.subnet_a"), + ), + }, + }, + }) +} + +const testAccAWSNetworkAclAssoc = ` +resource "aws_vpc" "test_vpc" { + cidr_block = "10.1.0.0/16" + tags = { + Name = "testAccAWSNetworkAclEsp" + } +} +resource "aws_network_acl" "acl_a" { + vpc_id = aws_vpc.test_vpc.id + tags = { + Name = "terraform test" + } +} +resource "aws_subnet" "subnet_a" { + vpc_id = aws_vpc.test_vpc.id + cidr_block = "10.1.33.0/24" + tags = { + Name = "terraform test" + } +} +resource "aws_network_acl_association" "test" { + network_acl_id = aws_network_acl.acl_a.id + subnet_id = aws_subnet.subnet_a.id +} +` diff --git a/aws/resource_aws_subnet_nacl_association.go b/aws/resource_aws_subnet_nacl_association.go deleted file mode 100644 index 7fb491ef6c8a..000000000000 --- a/aws/resource_aws_subnet_nacl_association.go +++ /dev/null @@ -1,112 +0,0 @@ -package aws - -import ( - "fmt" - "log" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func resourceAwsSubnetNaclAssociation() *schema.Resource { - //lintignore:R011 - return &schema.Resource{ - Create: resourceAwsSubnetNaclAssociationCreate, - Read: resourceAwsSubnetNaclAssociationRead, - Update: resourceAwsSubnetNaclAssociationUpdate, - Delete: resourceAwsSubnetNaclAssociationDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(20 * time.Minute), - }, - - SchemaVersion: 1, - - Schema: map[string]*schema.Schema{ - "subnet_id": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - - "network_acl_id": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - }, - } -} - -func resourceAwsSubnetNaclAssociationCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).ec2conn - - // find all current nacls with subnet id - subnetId := d.Get("subnet_id").(string) - existingAssociation := findNetworkAclAssociation(subnetId, conn) - - log.Printf(existingAssociation.(string)) - createOpts := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: aws.String(existingAssociation.NetworkAclAssociationId.(string)), - NetworkAclId: aws.String(d.Get("network_acl_id").(string)), - } - - var err error - resp, err := conn.ReplaceNetworkAclAssociation(createOpts) - - if err != nil { - return fmt.Errorf("error replacing subnet network acl association: %w", err) - } - - // Get the ID and store it - associationId := aws.StringValue(resp.NewAssociationId) - d.SetId(associationId.(string)) - log.Printf("[INFO] New Association ID: %s", associationId) - - _, err = stateConf.WaitForState() - - if err != nil { - return fmt.Errorf("error waiting for subnet (%s) to become ready: %w", d.Id(), err) - } - - return resourceAwsSubnetNaclAssociationRead(d, meta) -} - -func resourceAwsSubnetNaclAssociationRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).ec2conn - - subnetId := d.Get("subnet_id").(string) - existingAssociation, err := findNetworkAclAssociation(subnetId, conn) - - if err != nil { - if isAWSErr(err, "InvalidNetworkAclSubnetAssociation.NotFound", "") { - log.Printf("[WARN] Network Acl Association for Subnet Id (%s) not found, removing from state", d.Get("network_acl_id"), d.Get("subnet_id")) - d.SetId("") - return nil - } - return err - } - - if d.Get("subnet_id") == aws.StringValue(existingAssociation.SubnetId) { - d.SetId(aws.StringValue(existingAssociation.NetworkAclAssociationId)) - d.Set("network_acl_id", aws.StringValue(existingAssociation.NetworkAclId)) - return nil - } - - return nil -} - -func resourceAwsSubnetNaclAssociationUpdate(d *schema.ResourceData, meta interface{}) error { - return resourceAwsSubnetNaclAssociationCreate(d, meta) -} - -func resourceAwsSubnetNaclAssociationDelete(d *schema.ResourceData, meta interface{}) error { - log.Printf("[WARN] Cannot destroy Network ACL Association. Terraform will remove this resource from the state file, however resources may remain.") - return nil -} diff --git a/aws/resource_aws_subnet_nacl_association_test.go b/aws/resource_aws_subnet_nacl_association_test.go deleted file mode 100644 index bdfa0947f715..000000000000 --- a/aws/resource_aws_subnet_nacl_association_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package aws - -import ( - "fmt" - "testing" - - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAccAWSNetworkInterfaceAttachment_basic(t *testing.T) { - var conf ec2.NetworkInterface - rInt := acctest.RandInt() - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_network_interface.bar", - Providers: testAccProviders, - CheckDestroy: testAccCheckAWSENIDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAWSNetworkInterfaceAttachmentConfig_basic(rInt), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSENIExists("aws_network_interface.bar", &conf), - resource.TestCheckResourceAttr( - "aws_network_interface_attachment.test", "device_index", "1"), - resource.TestCheckResourceAttrSet( - "aws_network_interface_attachment.test", "instance_id"), - resource.TestCheckResourceAttrSet( - "aws_network_interface_attachment.test", "network_interface_id"), - resource.TestCheckResourceAttrSet( - "aws_network_interface_attachment.test", "attachment_id"), - resource.TestCheckResourceAttrSet( - "aws_network_interface_attachment.test", "status"), - ), - }, - }, - }) -} - -func testAccAWSNetworkInterfaceAttachmentConfig_basic(rInt int) string { - return testAccLatestAmazonLinuxHvmEbsAmiConfig() + fmt.Sprintf(` -resource "aws_vpc" "foo" { - cidr_block = "172.16.0.0/16" - - tags = { - Name = "terraform-testacc-network-iface-attachment-basic" - } -} - -data "aws_availability_zones" "available" { - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - -resource "aws_subnet" "foo" { - vpc_id = aws_vpc.foo.id - cidr_block = "172.16.10.0/24" - availability_zone = data.aws_availability_zones.available.names[0] - - tags = { - Name = "tf-acc-network-iface-attachment-basic" - } -} - -resource "aws_security_group" "foo" { - vpc_id = aws_vpc.foo.id - description = "foo" - name = "foo-%d" - - egress { - from_port = 0 - to_port = 0 - protocol = "tcp" - cidr_blocks = ["10.0.0.0/16"] - } -} - -resource "aws_network_interface" "bar" { - subnet_id = aws_subnet.foo.id - private_ips = ["172.16.10.100"] - security_groups = [aws_security_group.foo.id] - description = "Managed by Terraform" - - tags = { - Name = "bar_interface" - } -} - -resource "aws_instance" "foo" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id - instance_type = "t2.micro" - subnet_id = aws_subnet.foo.id - - tags = { - Name = "foo-%d" - } -} - -resource "aws_network_interface_attachment" "test" { - device_index = 1 - instance_id = aws_instance.foo.id - network_interface_id = aws_network_interface.bar.id -} -`, rInt, rInt) -} diff --git a/website/docs/r/network_acl_association.markdown b/website/docs/r/network_acl_association.markdown new file mode 100644 index 000000000000..61427449c5b3 --- /dev/null +++ b/website/docs/r/network_acl_association.markdown @@ -0,0 +1,35 @@ +--- +subcategory: "VPC" +layout: "aws" +page_title: "AWS: aws_network_acl_association" +description: |- + Provides an network ACL association resource. +--- + +# Resource: aws_network_acl_association + +Provides an network ACL association resource. You might set up network ACLs associate to your subnet. + +## Example Usage + +```hcl +resource "aws_network_acl_association" "main" { + network_acl_id = aws_network_acl.main.id + subnet_id = aws_subnet.main.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `network_acl_id` - (Required) The ID of the network acl . +* `subnet_id` - (Required) The ID of the associated Subnet. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the network ACL +* `network_acl_id` - The ID of the network ACL +* `subnet_id` - The ID of the subnet id \ No newline at end of file From 382b6cb36fb026a164fde357711b6ace01362fa6 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 12 Apr 2021 17:00:01 -0500 Subject: [PATCH 03/67] removed unused code --- aws/resource_aws_network_acl_association.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index b6ec56399e81..41bf6b0217ba 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -59,12 +59,6 @@ func resourceAwsNetworkAclAssociationCreate(d *schema.ResourceData, meta interfa d.SetId(aws.StringValue(associationId)) log.Printf("[INFO] New Association ID: %s", d.Id()) - //_, err = stateConf.WaitForState() - - // if err != nil { - // return fmt.Errorf("error waiting for network acl association (%s) to become ready: %w", d.Id(), err) - // } - return resourceAwsNetworkAclAssociationRead(d, meta) } From 5a682abcfa2676eb2bff49b80b1fe79902287940 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 12 Apr 2021 17:31:46 -0500 Subject: [PATCH 04/67] updated read function --- aws/resource_aws_network_acl_association.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index 41bf6b0217ba..392d5148465f 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -67,13 +67,15 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface // Inspect that the association exists subnetId := d.Get("subnet_id").(string) - _, errAssociation := findNetworkAclAssociation(subnetId, conn) - if errAssociation != nil { + association, err := findNetworkAclAssociation(subnetId, conn) + if err != nil { log.Printf("[WARN] Association for subnet %s was not found, removing from state", subnetId) d.SetId("") return nil } + d.Set("network_acl_id", aws.StringValue(association.NetworkAclId)) + return nil } From 1017b0697df886210fe49226d2d86efb8c1ce418 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 12 Apr 2021 17:39:18 -0500 Subject: [PATCH 05/67] reformated markdown --- website/docs/r/network_acl_association.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/network_acl_association.markdown b/website/docs/r/network_acl_association.markdown index 61427449c5b3..6745826b1b8d 100644 --- a/website/docs/r/network_acl_association.markdown +++ b/website/docs/r/network_acl_association.markdown @@ -14,8 +14,8 @@ Provides an network ACL association resource. You might set up network ACLs asso ```hcl resource "aws_network_acl_association" "main" { - network_acl_id = aws_network_acl.main.id - subnet_id = aws_subnet.main.id + network_acl_id = aws_network_acl.main.id + subnet_id = aws_subnet.main.id } ``` From fa6df7b5355c59ce6d86a83318b8ee50446458b8 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 12 Apr 2021 17:44:09 -0500 Subject: [PATCH 06/67] fixed lint errors --- aws/resource_aws_network_acl_association_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_network_acl_association_test.go b/aws/resource_aws_network_acl_association_test.go index 7d2868ce7f7a..4202b7882623 100644 --- a/aws/resource_aws_network_acl_association_test.go +++ b/aws/resource_aws_network_acl_association_test.go @@ -14,7 +14,7 @@ func init() { }) } -func TestAccAWSNetworkAclAssociation(t *testing.T) { +func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { var networkAcl ec2.NetworkAcl resourceName := "aws_network_acl.acl_a" @@ -49,7 +49,7 @@ resource "aws_network_acl" "acl_a" { } } resource "aws_subnet" "subnet_a" { - vpc_id = aws_vpc.test_vpc.id + vpc_id = aws_vpc.test_vpc.id cidr_block = "10.1.33.0/24" tags = { Name = "terraform test" @@ -57,6 +57,6 @@ resource "aws_subnet" "subnet_a" { } resource "aws_network_acl_association" "test" { network_acl_id = aws_network_acl.acl_a.id - subnet_id = aws_subnet.subnet_a.id + subnet_id = aws_subnet.subnet_a.id } ` From 98181a557d2d489200f028a163cba6dc9d564aa3 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 12 Apr 2021 17:44:38 -0500 Subject: [PATCH 07/67] fixed md lint error --- website/docs/r/network_acl_association.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/network_acl_association.markdown b/website/docs/r/network_acl_association.markdown index 6745826b1b8d..7bd436282e33 100644 --- a/website/docs/r/network_acl_association.markdown +++ b/website/docs/r/network_acl_association.markdown @@ -12,7 +12,7 @@ Provides an network ACL association resource. You might set up network ACLs asso ## Example Usage -```hcl +```terraform resource "aws_network_acl_association" "main" { network_acl_id = aws_network_acl.main.id subnet_id = aws_subnet.main.id From e0d21a434dc3d06d6885df1433c80a9d6d49c4db Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 13:07:42 -0500 Subject: [PATCH 08/67] lint updates --- aws/resource_aws_network_acl_association.go | 7 ++++--- aws/resource_aws_network_acl_association_test.go | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index 392d5148465f..e43085cf1a3d 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -69,9 +69,7 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface subnetId := d.Get("subnet_id").(string) association, err := findNetworkAclAssociation(subnetId, conn) if err != nil { - log.Printf("[WARN] Association for subnet %s was not found, removing from state", subnetId) - d.SetId("") - return nil + return fmt.Errorf("Unable to find association for subnet %s", subnetId) } d.Set("network_acl_id", aws.StringValue(association.NetworkAclId)) @@ -168,6 +166,9 @@ func resourceAwsNetworkAclAssociationDelete(d *schema.ResourceData, meta interfa } return nil }) + if isResourceTimeoutError(err) { + _, err = conn.ReplaceNetworkAclAssociation(&associationOpts) + } if err != nil { return err } diff --git a/aws/resource_aws_network_acl_association_test.go b/aws/resource_aws_network_acl_association_test.go index 4202b7882623..7c61467ae829 100644 --- a/aws/resource_aws_network_acl_association_test.go +++ b/aws/resource_aws_network_acl_association_test.go @@ -15,6 +15,7 @@ func init() { } func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { + //lintignore:XAT001 var networkAcl ec2.NetworkAcl resourceName := "aws_network_acl.acl_a" From c6cb16c29a7b9e49f98f10fe3d25f75178971cba Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 13:21:04 -0500 Subject: [PATCH 09/67] lint error fixes --- aws/resource_aws_network_acl_association_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_network_acl_association_test.go b/aws/resource_aws_network_acl_association_test.go index 7c61467ae829..3b4153635457 100644 --- a/aws/resource_aws_network_acl_association_test.go +++ b/aws/resource_aws_network_acl_association_test.go @@ -15,10 +15,11 @@ func init() { } func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { - //lintignore:XAT001 + var networkAcl ec2.NetworkAcl resourceName := "aws_network_acl.acl_a" + //lintignore:XAT001 resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, IDRefreshName: resourceName, From daa5fc56f59c7f9a58b83e23a032501de45fd009 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 13:33:34 -0500 Subject: [PATCH 10/67] update markdown --- website/docs/r/network_acl_association.markdown | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/website/docs/r/network_acl_association.markdown b/website/docs/r/network_acl_association.markdown index 7bd436282e33..a961624f060b 100644 --- a/website/docs/r/network_acl_association.markdown +++ b/website/docs/r/network_acl_association.markdown @@ -8,7 +8,7 @@ description: |- # Resource: aws_network_acl_association -Provides an network ACL association resource. You might set up network ACLs associate to your subnet. +Provides an network ACL association resource which allows you to associate your network ACL with any subnet(s). ## Example Usage @@ -23,13 +23,11 @@ resource "aws_network_acl_association" "main" { The following arguments are supported: -* `network_acl_id` - (Required) The ID of the network acl . +* `network_acl_id` - (Required) The ID of the network ACL. * `subnet_id` - (Required) The ID of the associated Subnet. ## Attributes Reference -The following attributes are exported: +In addition to all arguments above, the following attributes are exported: -* `id` - The ID of the network ACL -* `network_acl_id` - The ID of the network ACL -* `subnet_id` - The ID of the subnet id \ No newline at end of file +* `id` - The ID of the network ACL association \ No newline at end of file From 456a2f9151e7687b441e9e120f6d92f72b020e55 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 13:34:09 -0500 Subject: [PATCH 11/67] fixed fmt --- aws/resource_aws_network_acl_association_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_network_acl_association_test.go b/aws/resource_aws_network_acl_association_test.go index 3b4153635457..3dfe8fb5b90f 100644 --- a/aws/resource_aws_network_acl_association_test.go +++ b/aws/resource_aws_network_acl_association_test.go @@ -19,7 +19,7 @@ func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { var networkAcl ec2.NetworkAcl resourceName := "aws_network_acl.acl_a" - //lintignore:XAT001 + //lintignore:XAT001 resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, IDRefreshName: resourceName, From 7a6816a759465eda0d30bccd01f785aaf84b5353 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 19:48:40 -0500 Subject: [PATCH 12/67] fixed missing subnet association error --- aws/resource_aws_network_acl_association.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index e43085cf1a3d..59572f2b91d7 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -28,6 +28,7 @@ func resourceAwsNetworkAclAssociation() *schema.Resource { "network_acl_id": { Type: schema.TypeString, Required: true, + ForceNew: true, }, }, } @@ -69,7 +70,9 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface subnetId := d.Get("subnet_id").(string) association, err := findNetworkAclAssociation(subnetId, conn) if err != nil { - return fmt.Errorf("Unable to find association for subnet %s", subnetId) + log.Printf("[WARN] Unable to find association for subnet %s", subnetId) + d.SetId("") + return nil } d.Set("network_acl_id", aws.StringValue(association.NetworkAclId)) From 98dc232304b574c3c686b5c976b21f27424b3907 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 20:05:28 -0500 Subject: [PATCH 13/67] added lint ignore --- aws/resource_aws_network_acl_association.go | 1 + 1 file changed, 1 insertion(+) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index 59572f2b91d7..23bf617410c8 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -72,6 +72,7 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface if err != nil { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") + //lint:ignore nilerr subnet likely doesn't exist so there is nothing more that we can do return nil } From 5b84987c1ddd2158c314d6ee111a7df9e3be5afb Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 21:18:09 -0500 Subject: [PATCH 14/67] trying to get the nilerr lint to pass --- aws/resource_aws_network_acl_association.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index 23bf617410c8..98ef5f6ef7d6 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -70,10 +70,21 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface subnetId := d.Get("subnet_id").(string) association, err := findNetworkAclAssociation(subnetId, conn) if err != nil { - log.Printf("[WARN] Unable to find association for subnet %s", subnetId) - d.SetId("") - //lint:ignore nilerr subnet likely doesn't exist so there is nothing more that we can do - return nil + if isResourceNotFoundError(err) { + log.Printf("[WARN] Unable to find association for subnet %s", subnetId) + d.SetId("") + // lint:ignore nilerr subnet likely doesn't exist so there is nothing more that we can do + return nil + } + if awsErr, ok := err.(awserr.Error); ok { + if awsErr != nil { + log.Printf("[WARN] Unable to find association for subnet %s", subnetId) + d.SetId("") + // lint:ignore nilerr subnet likely doesn't exist so there is nothing more that we can do + return nil + } + } + return err } d.Set("network_acl_id", aws.StringValue(association.NetworkAclId)) From 894f3581b8ad22cd4f987ce2bb907ad6a4895834 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 13 Apr 2021 21:31:30 -0500 Subject: [PATCH 15/67] switch from lint:ignore to nolint --- aws/resource_aws_network_acl_association.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index 98ef5f6ef7d6..c6150578878f 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -73,14 +73,14 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface if isResourceNotFoundError(err) { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - // lint:ignore nilerr subnet likely doesn't exist so there is nothing more that we can do + //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } if awsErr, ok := err.(awserr.Error); ok { if awsErr != nil { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - // lint:ignore nilerr subnet likely doesn't exist so there is nothing more that we can do + //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } } From f08c8dae88be3d96f69e6602a574bf6f750ccfb7 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Wed, 14 Apr 2021 11:09:53 -0500 Subject: [PATCH 16/67] removed update code since it isn't used --- aws/resource_aws_network_acl_association.go | 34 +-------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/aws/resource_aws_network_acl_association.go b/aws/resource_aws_network_acl_association.go index c6150578878f..f33148c19463 100644 --- a/aws/resource_aws_network_acl_association.go +++ b/aws/resource_aws_network_acl_association.go @@ -16,13 +16,13 @@ func resourceAwsNetworkAclAssociation() *schema.Resource { return &schema.Resource{ Create: resourceAwsNetworkAclAssociationCreate, Read: resourceAwsNetworkAclAssociationRead, - Update: resourceAwsNetworkAclAssociationUpdate, Delete: resourceAwsNetworkAclAssociationDelete, Schema: map[string]*schema.Schema{ "subnet_id": { Type: schema.TypeString, Required: true, + ForceNew: true, }, "network_acl_id": { @@ -92,38 +92,6 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface return nil } -func resourceAwsNetworkAclAssociationUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).ec2conn - - naclId := d.Get("network_acl_id").(string) - subnetId := d.Get("subnet_id").(string) - - association, errAssociation := findNetworkAclAssociation(subnetId, conn) - if errAssociation != nil { - return fmt.Errorf("Failed to find association for subnet %s: %s", subnetId, errAssociation) - } - - associationOpts := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(naclId), - } - - _, err := conn.ReplaceNetworkAclAssociation(associationOpts) - - log.Printf("[DEBUG] Updating Network ACL association: %#v", associationOpts) - - if err != nil { - if isAWSErr(err, "InvalidAssociationID.NotFound", "") { - // Not found, so just create a new one - return resourceAwsNetworkAclAssociationCreate(d, meta) - } - - return err - } - - return resourceAwsNetworkAclAssociationRead(d, meta) -} - func resourceAwsNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn From 9d0cbb0622f1e881c37ee72393b8b32294a30884 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 09:52:23 -0500 Subject: [PATCH 17/67] updated per refactor --- internal/provider/provider.go | 1 + internal/service/ec2/network_acl_association.go | 10 +++++----- internal/service/ec2/network_acl_association_test.go | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3fea8dc2ce20..eda11884eb54 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1115,6 +1115,7 @@ func Provider() *schema.Provider { "aws_neptune_event_subscription": neptune.ResourceEventSubscription(), "aws_neptune_parameter_group": neptune.ResourceParameterGroup(), "aws_neptune_subnet_group": neptune.ResourceSubnetGroup(), + "aws_network_acl_association": ec2.ResourceNetworkAclAssociation(), "aws_network_acl_rule": ec2.ResourceNetworkACLRule(), "aws_network_interface": ec2.ResourceNetworkInterface(), "aws_network_interface_attachment": ec2.ResourceNetworkInterfaceAttachment(), diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index f33148c19463..bf381d49acd7 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func resourceAwsNetworkAclAssociation() *schema.Resource { +func ResourceNetworkAclAssociation() *schema.Resource { return &schema.Resource{ Create: resourceAwsNetworkAclAssociationCreate, Read: resourceAwsNetworkAclAssociationRead, @@ -34,7 +34,7 @@ func resourceAwsNetworkAclAssociation() *schema.Resource { } } -func resourceAwsNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{}) error { +func ResourceNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn naclId := d.Get("network_acl_id").(string) @@ -60,10 +60,10 @@ func resourceAwsNetworkAclAssociationCreate(d *schema.ResourceData, meta interfa d.SetId(aws.StringValue(associationId)) log.Printf("[INFO] New Association ID: %s", d.Id()) - return resourceAwsNetworkAclAssociationRead(d, meta) + return ResourceNetworkAclAssociationRead(d, meta) } -func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) error { +func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn // Inspect that the association exists @@ -92,7 +92,7 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface return nil } -func resourceAwsNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { +func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 3dfe8fb5b90f..ce3a96b8d693 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -14,7 +14,7 @@ func init() { }) } -func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { +func TestAccNetworkAclAssociation_basic(t *testing.T) { var networkAcl ec2.NetworkAcl resourceName := "aws_network_acl.acl_a" @@ -27,7 +27,7 @@ func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSNetworkAclAssoc, + Config: testAccNetworkAclAssoc, Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSNetworkAclExists(resourceName, &networkAcl), testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.subnet_a"), @@ -37,7 +37,7 @@ func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { }) } -const testAccAWSNetworkAclAssoc = ` +const testAccNetworkAclAssoc = ` resource "aws_vpc" "test_vpc" { cidr_block = "10.1.0.0/16" tags = { From f732ceec1a2826162826db80161d4fc91a9626ce Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 09:52:23 -0500 Subject: [PATCH 18/67] updated per refactor --- internal/provider/provider.go | 2285 +++++++++-------- .../service/ec2/network_acl_association.go | 10 +- .../ec2/network_acl_association_test.go | 6 +- 3 files changed, 1257 insertions(+), 1044 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3fea8dc2ce20..4d1b8b96db4f 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -12,8 +12,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/service/amplify" "github.com/hashicorp/terraform-provider-aws/internal/service/apigateway" "github.com/hashicorp/terraform-provider-aws/internal/service/apigatewayv2" + "github.com/hashicorp/terraform-provider-aws/internal/service/appautoscaling" "github.com/hashicorp/terraform-provider-aws/internal/service/appconfig" - "github.com/hashicorp/terraform-provider-aws/internal/service/applicationautoscaling" "github.com/hashicorp/terraform-provider-aws/internal/service/appmesh" "github.com/hashicorp/terraform-provider-aws/internal/service/apprunner" "github.com/hashicorp/terraform-provider-aws/internal/service/appstream" @@ -335,71 +335,87 @@ func Provider() *schema.Provider { }, DataSourcesMap: map[string]*schema.Resource{ - "aws_acm_certificate": acm.DataSourceCertificate(), - "aws_acmpca_certificate_authority": acmpca.DataSourceCertificateAuthority(), - "aws_acmpca_certificate": acmpca.DataSourceCertificate(), + "aws_acm_certificate": acm.DataSourceCertificate(), + + "aws_acmpca_certificate_authority": acmpca.DataSourceCertificateAuthority(), + "aws_acmpca_certificate": acmpca.DataSourceCertificate(), + + "aws_api_gateway_api_key": apigateway.DataSourceAPIKey(), + "aws_api_gateway_domain_name": apigateway.DataSourceDomainName(), + "aws_api_gateway_resource": apigateway.DataSourceResource(), + "aws_api_gateway_rest_api": apigateway.DataSourceRestAPI(), + "aws_api_gateway_vpc_link": apigateway.DataSourceVPCLink(), + + "aws_apigatewayv2_api": apigatewayv2.DataSourceAPI(), + "aws_apigatewayv2_apis": apigatewayv2.DataSourceAPIs(), + + "aws_appmesh_mesh": appmesh.DataSourceMesh(), + "aws_appmesh_virtual_service": appmesh.DataSourceVirtualService(), + + "aws_autoscaling_group": autoscaling.DataSourceGroup(), + "aws_autoscaling_groups": autoscaling.DataSourceGroups(), + "aws_launch_configuration": autoscaling.DataSourceLaunchConfiguration(), + + "aws_backup_plan": backup.DataSourcePlan(), + "aws_backup_selection": backup.DataSourceSelection(), + "aws_backup_vault": backup.DataSourceVault(), + + "aws_batch_compute_environment": batch.DataSourceComputeEnvironment(), + "aws_batch_job_queue": batch.DataSourceJobQueue(), + + "aws_cloudcontrolapi_resource": cloudcontrol.DataSourceResource(), + + "aws_cloudformation_export": cloudformation.DataSourceExport(), + "aws_cloudformation_stack": cloudformation.DataSourceStack(), + "aws_cloudformation_type": cloudformation.DataSourceType(), + + "aws_cloudfront_cache_policy": cloudfront.DataSourceCachePolicy(), + "aws_cloudfront_distribution": cloudfront.DataSourceDistribution(), + "aws_cloudfront_function": cloudfront.DataSourceFunction(), + "aws_cloudfront_log_delivery_canonical_user_id": cloudfront.DataSourceLogDeliveryCanonicalUserID(), + "aws_cloudfront_origin_request_policy": cloudfront.DataSourceOriginRequestPolicy(), + + "aws_cloudhsm_v2_cluster": cloudhsmv2.DataSourceCluster(), + + "aws_cloudtrail_service_account": cloudtrail.DataSourceServiceAccount(), + + "aws_cloudwatch_event_connection": cloudwatchevents.DataSourceConnection(), + "aws_cloudwatch_event_source": cloudwatchevents.DataSourceSource(), + + "aws_cloudwatch_log_group": cloudwatchlogs.DataSourceGroup(), + "aws_cloudwatch_log_groups": cloudwatchlogs.DataSourceGroups(), + + "aws_codeartifact_authorization_token": codeartifact.DataSourceAuthorizationToken(), + "aws_codeartifact_repository_endpoint": codeartifact.DataSourceRepositoryEndpoint(), + + "aws_codecommit_repository": codecommit.DataSourceRepository(), + + "aws_codestarconnections_connection": codestarconnections.DataSourceConnection(), + + "aws_cognito_user_pools": cognitoidp.DataSourceUserPools(), + + "aws_connect_contact_flow": connect.DataSourceContactFlow(), + "aws_connect_instance": connect.DataSourceInstance(), + + "aws_cur_report_definition": cur.DataSourceReportDefinition(), + + "aws_docdb_engine_version": docdb.DataSourceEngineVersion(), + "aws_docdb_orderable_db_instance": docdb.DataSourceOrderableDBInstance(), + + "aws_dx_connection": directconnect.DataSourceConnection(), + "aws_dx_gateway": directconnect.DataSourceGateway(), + "aws_dx_location": directconnect.DataSourceLocation(), + "aws_dx_locations": directconnect.DataSourceLocations(), + + "aws_directory_service_directory": ds.DataSourceDirectory(), + + "aws_dynamodb_table": dynamodb.DataSourceTable(), + "aws_ami": ec2.DataSourceAMI(), "aws_ami_ids": ec2.DataSourceAMIIDs(), - "aws_api_gateway_api_key": apigateway.DataSourceAPIKey(), - "aws_api_gateway_domain_name": apigateway.DataSourceDomainName(), - "aws_api_gateway_resource": apigateway.DataSourceResource(), - "aws_api_gateway_rest_api": apigateway.DataSourceRestAPI(), - "aws_api_gateway_vpc_link": apigateway.DataSourceVPCLink(), - "aws_apigatewayv2_api": apigatewayv2.DataSourceAPI(), - "aws_apigatewayv2_apis": apigatewayv2.DataSourceAPIs(), - "aws_appmesh_mesh": appmesh.DataSourceMesh(), - "aws_appmesh_virtual_service": appmesh.DataSourceVirtualService(), - "aws_arn": nas.DataSourceARN(), - "aws_autoscaling_group": autoscaling.DataSourceGroup(), - "aws_autoscaling_groups": autoscaling.DataSourceGroups(), "aws_availability_zone": ec2.DataSourceAvailabilityZone(), "aws_availability_zones": ec2.DataSourceAvailabilityZones(), - "aws_backup_plan": backup.DataSourcePlan(), - "aws_backup_selection": backup.DataSourceSelection(), - "aws_backup_vault": backup.DataSourceVault(), - "aws_batch_compute_environment": batch.DataSourceComputeEnvironment(), - "aws_batch_job_queue": batch.DataSourceJobQueue(), - "aws_billing_service_account": nas.DataSourceBillingServiceAccount(), - "aws_caller_identity": nas.DataSourceCallerIdentity(), - "aws_canonical_user_id": nas.DataSourceCanonicalUserID(), - "aws_cloudcontrolapi_resource": cloudcontrol.DataSourceResource(), - "aws_cloudformation_export": cloudformation.DataSourceExport(), - "aws_cloudformation_stack": cloudformation.DataSourceStack(), - "aws_cloudformation_type": cloudformation.DataSourceType(), - "aws_cloudfront_cache_policy": cloudfront.DataSourceCachePolicy(), - "aws_cloudfront_distribution": cloudfront.DataSourceDistribution(), - "aws_cloudfront_function": cloudfront.DataSourceFunction(), - "aws_cloudfront_log_delivery_canonical_user_id": cloudfront.DataSourceLogDeliveryCanonicalUserID(), - "aws_cloudfront_origin_request_policy": cloudfront.DataSourceOriginRequestPolicy(), - "aws_cloudhsm_v2_cluster": cloudhsmv2.DataSourceCluster(), - "aws_cloudtrail_service_account": cloudtrail.DataSourceServiceAccount(), - "aws_cloudwatch_event_connection": cloudwatchevents.DataSourceConnection(), - "aws_cloudwatch_event_source": cloudwatchevents.DataSourceSource(), - "aws_cloudwatch_log_group": cloudwatchlogs.DataSourceGroup(), - "aws_cloudwatch_log_groups": cloudwatchlogs.DataSourceGroups(), - "aws_codeartifact_authorization_token": codeartifact.DataSourceAuthorizationToken(), - "aws_codeartifact_repository_endpoint": codeartifact.DataSourceRepositoryEndpoint(), - "aws_cognito_user_pools": cognitoidp.DataSourceUserPools(), - "aws_codecommit_repository": codecommit.DataSourceRepository(), - "aws_codestarconnections_connection": codestarconnections.DataSourceConnection(), - "aws_connect_contact_flow": connect.DataSourceContactFlow(), - "aws_connect_instance": connect.DataSourceInstance(), - "aws_cur_report_definition": cur.DataSourceReportDefinition(), - "aws_default_tags": nas.DataSourceDefaultTags(), - "aws_db_cluster_snapshot": rds.DataSourceClusterSnapshot(), - "aws_db_event_categories": rds.DataSourceEventCategories(), - "aws_db_instance": rds.DataSourceInstance(), - "aws_db_proxy": rds.DataSourceProxy(), - "aws_db_snapshot": rds.DataSourceSnapshot(), - "aws_db_subnet_group": rds.DataSourceSubnetGroup(), - "aws_directory_service_directory": ds.DataSourceDirectory(), - "aws_docdb_engine_version": docdb.DataSourceEngineVersion(), - "aws_docdb_orderable_db_instance": docdb.DataSourceOrderableDBInstance(), - "aws_dx_connection": directconnect.DataSourceConnection(), - "aws_dx_gateway": directconnect.DataSourceGateway(), - "aws_dx_location": directconnect.DataSourceLocation(), - "aws_dx_locations": directconnect.DataSourceLocations(), - "aws_dynamodb_table": dynamodb.DataSourceTable(), + "aws_customer_gateway": ec2.DataSourceCustomerGateway(), "aws_ebs_default_kms_key": ec2.DataSourceEBSDefaultKMSKey(), "aws_ebs_encryption_by_default": ec2.DataSourceEBSEncryptionByDefault(), "aws_ebs_snapshot": ec2.DataSourceEBSSnapshot(), @@ -409,16 +425,16 @@ func Provider() *schema.Provider { "aws_ec2_coip_pool": ec2.DataSourceCoIPPool(), "aws_ec2_coip_pools": ec2.DataSourceCoIPPools(), "aws_ec2_host": ec2.DataSourceHost(), - "aws_ec2_instance_type": ec2.DataSourceInstanceType(), "aws_ec2_instance_type_offering": ec2.DataSourceInstanceTypeOffering(), "aws_ec2_instance_type_offerings": ec2.DataSourceInstanceTypeOfferings(), - "aws_ec2_local_gateway": ec2.DataSourceLocalGateway(), - "aws_ec2_local_gateways": ec2.DataSourceLocalGateways(), + "aws_ec2_instance_type": ec2.DataSourceInstanceType(), "aws_ec2_local_gateway_route_table": ec2.DataSourceLocalGatewayRouteTable(), "aws_ec2_local_gateway_route_tables": ec2.DataSourceLocalGatewayRouteTables(), "aws_ec2_local_gateway_virtual_interface": ec2.DataSourceLocalGatewayVirtualInterface(), "aws_ec2_local_gateway_virtual_interface_group": ec2.DataSourceLocalGatewayVirtualInterfaceGroup(), "aws_ec2_local_gateway_virtual_interface_groups": ec2.DataSourceLocalGatewayVirtualInterfaceGroups(), + "aws_ec2_local_gateway": ec2.DataSourceLocalGateway(), + "aws_ec2_local_gateways": ec2.DataSourceLocalGateways(), "aws_ec2_managed_prefix_list": ec2.DataSourceManagedPrefixList(), "aws_ec2_spot_price": ec2.DataSourceSpotPrice(), "aws_ec2_transit_gateway": ec2.DataSourceTransitGateway(), @@ -428,783 +444,1035 @@ func Provider() *schema.Provider { "aws_ec2_transit_gateway_route_tables": ec2.DataSourceTransitGatewayRouteTables(), "aws_ec2_transit_gateway_vpc_attachment": ec2.DataSourceTransitGatewayVPCAttachment(), "aws_ec2_transit_gateway_vpn_attachment": ec2.DataSourceTransitGatewayVPNAttachment(), - "aws_ecr_authorization_token": ecr.DataSourceAuthorizationToken(), - "aws_ecr_image": ecr.DataSourceImage(), - "aws_ecr_repository": ecr.DataSourceRepository(), - "aws_ecs_cluster": ecs.DataSourceCluster(), - "aws_ecs_container_definition": ecs.DataSourceContainerDefinition(), - "aws_ecs_service": ecs.DataSourceService(), - "aws_ecs_task_definition": ecs.DataSourceTaskDefinition(), - "aws_customer_gateway": ec2.DataSourceCustomerGateway(), - "aws_efs_access_point": efs.DataSourceAccessPoint(), - "aws_efs_access_points": efs.DataSourceAccessPoints(), - "aws_efs_file_system": efs.DataSourceFileSystem(), - "aws_efs_mount_target": efs.DataSourceMountTarget(), "aws_eip": ec2.DataSourceEIP(), - "aws_eks_addon": eks.DataSourceAddon(), - "aws_eks_cluster": eks.DataSourceCluster(), - "aws_eks_clusters": eks.DataSourceClusters(), - "aws_eks_cluster_auth": eks.DataSourceClusterAuth(), - "aws_eks_node_group": eks.DataSourceNodeGroup(), - "aws_eks_node_groups": eks.DataSourceNodeGroups(), - "aws_elastic_beanstalk_application": elasticbeanstalk.DataSourceApplication(), - "aws_elastic_beanstalk_hosted_zone": elasticbeanstalk.DataSourceHostedZone(), - "aws_elastic_beanstalk_solution_stack": elasticbeanstalk.DataSourceSolutionStack(), - "aws_elasticache_cluster": elasticache.DataSourceCluster(), - "aws_elasticache_replication_group": elasticache.DataSourceReplicationGroup(), - "aws_elasticache_user": elasticache.DataSourceUser(), - "aws_elasticsearch_domain": elasticsearch.DataSourceDomain(), - "aws_elb": elb.DataSourceLoadBalancer(), - "aws_elb_hosted_zone_id": elb.DataSourceHostedZoneID(), - "aws_elb_service_account": elb.DataSourceServiceAccount(), - "aws_globalaccelerator_accelerator": globalaccelerator.DataSourceAccelerator(), - "aws_glue_connection": glue.DataSourceConnection(), - "aws_glue_data_catalog_encryption_settings": glue.DataSourceDataCatalogEncryptionSettings(), - "aws_glue_script": glue.DataSourceScript(), - "aws_guardduty_detector": guardduty.DataSourceDetector(), - "aws_iam_account_alias": iam.DataSourceAccountAlias(), - "aws_iam_group": iam.DataSourceGroup(), - "aws_iam_instance_profile": iam.DataSourceInstanceProfile(), - "aws_iam_policy": iam.DataSourcePolicy(), - "aws_iam_policy_document": iam.DataSourcePolicyDocument(), - "aws_iam_role": iam.DataSourceRole(), - "aws_iam_roles": iam.DataSourceRoles(), - "aws_iam_server_certificate": iam.DataSourceServerCertificate(), - "aws_iam_session_context": iam.DataSourceSessionContext(), - "aws_iam_user": iam.DataSourceUser(), - "aws_iam_users": iam.DataSourceUsers(), - "aws_identitystore_group": identitystore.DataSourceGroup(), - "aws_identitystore_user": identitystore.DataSourceUser(), - "aws_imagebuilder_component": imagebuilder.DataSourceComponent(), - "aws_imagebuilder_distribution_configuration": imagebuilder.DataSourceDistributionConfiguration(), - "aws_imagebuilder_image": imagebuilder.DataSourceImage(), - "aws_imagebuilder_image_pipeline": imagebuilder.DataSourceImagePipeline(), - "aws_imagebuilder_image_recipe": imagebuilder.DataSourceImageRecipe(), - "aws_imagebuilder_infrastructure_configuration": imagebuilder.DataSourceInfrastructureConfiguration(), - "aws_inspector_rules_packages": inspector.DataSourceRulesPackages(), "aws_instance": ec2.DataSourceInstance(), "aws_instances": ec2.DataSourceInstances(), "aws_internet_gateway": ec2.DataSourceInternetGateway(), - "aws_iot_endpoint": iot.DataSourceEndpoint(), - "aws_ip_ranges": nas.DataSourceIPRanges(), - "aws_kinesis_firehose_delivery_stream": firehose.DataSourceDeliveryStream(), - "aws_kinesis_stream": kinesis.DataSourceStream(), - "aws_kinesis_stream_consumer": kinesis.DataSourceStreamConsumer(), - "aws_kms_alias": kms.DataSourceAlias(), - "aws_kms_ciphertext": kms.DataSourceCiphertext(), - "aws_kms_key": kms.DataSourceKey(), - "aws_kms_public_key": kms.DataSourcePublicKey(), - "aws_kms_secret": kms.DataSourceSecret(), - "aws_kms_secrets": kms.DataSourceSecrets(), - "aws_lakeformation_data_lake_settings": lakeformation.DataSourceDataLakeSettings(), - "aws_lakeformation_permissions": lakeformation.DataSourcePermissions(), - "aws_lakeformation_resource": lakeformation.DataSourceResource(), - "aws_lambda_alias": lambda.DataSourceAlias(), - "aws_lambda_code_signing_config": lambda.DataSourceCodeSigningConfig(), - "aws_lambda_function": lambda.DataSourceFunction(), - "aws_lambda_invocation": lambda.DataSourceInvocation(), - "aws_lambda_layer_version": lambda.DataSourceLayerVersion(), - "aws_launch_configuration": autoscaling.DataSourceLaunchConfiguration(), "aws_launch_template": ec2.DataSourceLaunchTemplate(), - "aws_lex_bot_alias": lexmodelbuilding.DataSourceBotAlias(), - "aws_lex_bot": lexmodelbuilding.DataSourceBot(), - "aws_lex_intent": lexmodelbuilding.DataSourceIntent(), - "aws_lex_slot_type": lexmodelbuilding.DataSourceSlotType(), - "aws_mq_broker": mq.DataSourceBroker(), - "aws_msk_broker_nodes": kafka.DataSourceBrokerNodes(), - "aws_msk_cluster": kafka.DataSourceCluster(), - "aws_msk_configuration": kafka.DataSourceConfiguration(), - "aws_msk_kafka_version": kafka.DataSourceVersion(), "aws_nat_gateway": ec2.DataSourceNatGateway(), - "aws_neptune_orderable_db_instance": neptune.DataSourceOrderableDBInstance(), - "aws_neptune_engine_version": neptune.DataSourceEngineVersion(), "aws_network_acls": ec2.DataSourceNetworkACLs(), "aws_network_interface": ec2.DataSourceNetworkInterface(), "aws_network_interfaces": ec2.DataSourceNetworkInterfaces(), - "aws_organizations_delegated_administrators": organizations.DataSourceDelegatedAdministrators(), - "aws_organizations_delegated_services": organizations.DataSourceDelegatedServices(), - "aws_organizations_organization": organizations.DataSourceOrganization(), - "aws_organizations_organizational_units": organizations.DataSourceOrganizationalUnits(), - "aws_outposts_outpost": outposts.DataSourceOutpost(), - "aws_outposts_outpost_instance_type": outposts.DataSourceOutpostInstanceType(), - "aws_outposts_outpost_instance_types": outposts.DataSourceOutpostInstanceTypes(), - "aws_outposts_outposts": outposts.DataSourceOutposts(), - "aws_outposts_site": outposts.DataSourceSite(), - "aws_outposts_sites": outposts.DataSourceSites(), - "aws_partition": nas.DataSourcePartition(), "aws_prefix_list": ec2.DataSourcePrefixList(), - "aws_pricing_product": pricing.DataSourceProduct(), - "aws_qldb_ledger": qldb.DataSourceLedger(), - "aws_ram_resource_share": ram.DataSourceResourceShare(), - "aws_rds_certificate": rds.DataSourceCertificate(), - "aws_rds_cluster": rds.DataSourceCluster(), - "aws_rds_engine_version": rds.DataSourceEngineVersion(), - "aws_rds_orderable_db_instance": rds.DataSourceOrderableInstance(), - "aws_redshift_cluster": redshift.DataSourceCluster(), - "aws_redshift_orderable_cluster": redshift.DataSourceOrderableCluster(), - "aws_redshift_service_account": redshift.DataSourceServiceAccount(), - "aws_region": nas.DataSourceRegion(), - "aws_regions": nas.DataSourceRegions(), - "aws_resourcegroupstaggingapi_resources": resourcegroupstagging.DataSourceResources(), - "aws_route": ec2.DataSourceRoute(), "aws_route_table": ec2.DataSourceRouteTable(), "aws_route_tables": ec2.DataSourceRouteTables(), - "aws_route53_delegation_set": route53.DataSourceDelegationSet(), - "aws_route53_resolver_endpoint": route53resolver.DataSourceEndpoint(), - "aws_route53_resolver_rule": route53resolver.DataSourceRule(), - "aws_route53_resolver_rules": route53resolver.DataSourceRules(), - "aws_route53_zone": route53.DataSourceZone(), - "aws_s3_bucket": s3.DataSourceBucket(), - "aws_s3_bucket_object": s3.DataSourceBucketObject(), - "aws_s3_bucket_objects": s3.DataSourceBucketObjects(), - "aws_sagemaker_prebuilt_ecr_image": sagemaker.DataSourcePrebuiltECRImage(), - "aws_secretsmanager_secret": secretsmanager.DataSourceSecret(), - "aws_secretsmanager_secret_rotation": secretsmanager.DataSourceSecretRotation(), - "aws_secretsmanager_secret_version": secretsmanager.DataSourceSecretVersion(), - "aws_servicecatalog_constraint": servicecatalog.DataSourceConstraint(), - "aws_servicecatalog_launch_paths": servicecatalog.DataSourceLaunchPaths(), - "aws_servicecatalog_portfolio_constraints": servicecatalog.DataSourcePortfolioConstraints(), - "aws_servicecatalog_portfolio": servicecatalog.DataSourcePortfolio(), - "aws_servicecatalog_product": servicecatalog.DataSourceProduct(), - "aws_servicequotas_service": servicequotas.DataSourceService(), - "aws_servicequotas_service_quota": servicequotas.DataSourceServiceQuota(), - "aws_service_discovery_dns_namespace": servicediscovery.DataSourceDNSNamespace(), - "aws_sfn_activity": sfn.DataSourceActivity(), - "aws_sfn_state_machine": sfn.DataSourceStateMachine(), - "aws_signer_signing_job": signer.DataSourceSigningJob(), - "aws_signer_signing_profile": signer.DataSourceSigningProfile(), - "aws_sns_topic": sns.DataSourceTopic(), - "aws_sqs_queue": sqs.DataSourceQueue(), - "aws_ssm_document": ssm.DataSourceDocument(), - "aws_ssm_parameter": ssm.DataSourceParameter(), - "aws_ssm_parameters_by_path": ssm.DataSourceParametersByPath(), - "aws_ssm_patch_baseline": ssm.DataSourcePatchBaseline(), - "aws_ssoadmin_instances": ssoadmin.DataSourceInstances(), - "aws_ssoadmin_permission_set": ssoadmin.DataSourcePermissionSet(), - "aws_storagegateway_local_disk": storagegateway.DataSourceLocalDisk(), - "aws_subnet": ec2.DataSourceSubnet(), - "aws_subnets": ec2.DataSourceSubnets(), - "aws_subnet_ids": ec2.DataSourceSubnetIDs(), - "aws_transfer_server": transfer.DataSourceServer(), - "aws_vpcs": ec2.DataSourceVPCs(), + "aws_route": ec2.DataSourceRoute(), "aws_security_group": ec2.DataSourceSecurityGroup(), "aws_security_groups": ec2.DataSourceSecurityGroups(), - "aws_vpc": ec2.DataSourceVPC(), + "aws_subnet_ids": ec2.DataSourceSubnetIDs(), + "aws_subnet": ec2.DataSourceSubnet(), + "aws_subnets": ec2.DataSourceSubnets(), "aws_vpc_dhcp_options": ec2.DataSourceVPCDHCPOptions(), - "aws_vpc_endpoint": ec2.DataSourceVPCEndpoint(), "aws_vpc_endpoint_service": ec2.DataSourceVPCEndpointService(), + "aws_vpc_endpoint": ec2.DataSourceVPCEndpoint(), "aws_vpc_peering_connection": ec2.DataSourceVPCPeeringConnection(), "aws_vpc_peering_connections": ec2.DataSourceVPCPeeringConnections(), + "aws_vpc": ec2.DataSourceVPC(), + "aws_vpcs": ec2.DataSourceVPCs(), "aws_vpn_gateway": ec2.DataSourceVPNGateway(), - "aws_waf_ipset": waf.DataSourceIPSet(), - "aws_waf_rule": waf.DataSourceRule(), - "aws_waf_rate_based_rule": waf.DataSourceRateBasedRule(), - "aws_waf_web_acl": waf.DataSourceWebACL(), - "aws_wafregional_ipset": wafregional.DataSourceIPSet(), - "aws_wafregional_rule": wafregional.DataSourceRule(), - "aws_wafregional_rate_based_rule": wafregional.DataSourceRateBasedRule(), - "aws_wafregional_web_acl": wafregional.DataSourceWebACL(), - "aws_wafv2_ip_set": wafv2.DataSourceIPSet(), - "aws_wafv2_regex_pattern_set": wafv2.DataSourceRegexPatternSet(), - "aws_wafv2_rule_group": wafv2.DataSourceRuleGroup(), - "aws_wafv2_web_acl": wafv2.DataSourceWebACL(), - "aws_workspaces_bundle": workspaces.DataSourceBundle(), - "aws_workspaces_directory": workspaces.DataSourceDirectory(), - "aws_workspaces_image": workspaces.DataSourceImage(), - "aws_workspaces_workspace": workspaces.DataSourceWorkspace(), + + "aws_ecr_authorization_token": ecr.DataSourceAuthorizationToken(), + "aws_ecr_image": ecr.DataSourceImage(), + "aws_ecr_repository": ecr.DataSourceRepository(), + + "aws_ecs_cluster": ecs.DataSourceCluster(), + "aws_ecs_container_definition": ecs.DataSourceContainerDefinition(), + "aws_ecs_service": ecs.DataSourceService(), + "aws_ecs_task_definition": ecs.DataSourceTaskDefinition(), + + "aws_efs_access_point": efs.DataSourceAccessPoint(), + "aws_efs_access_points": efs.DataSourceAccessPoints(), + "aws_efs_file_system": efs.DataSourceFileSystem(), + "aws_efs_mount_target": efs.DataSourceMountTarget(), + + "aws_eks_addon": eks.DataSourceAddon(), + "aws_eks_cluster": eks.DataSourceCluster(), + "aws_eks_clusters": eks.DataSourceClusters(), + "aws_eks_cluster_auth": eks.DataSourceClusterAuth(), + "aws_eks_node_group": eks.DataSourceNodeGroup(), + "aws_eks_node_groups": eks.DataSourceNodeGroups(), + + "aws_elasticache_cluster": elasticache.DataSourceCluster(), + "aws_elasticache_replication_group": elasticache.DataSourceReplicationGroup(), + "aws_elasticache_user": elasticache.DataSourceUser(), + + "aws_elastic_beanstalk_application": elasticbeanstalk.DataSourceApplication(), + "aws_elastic_beanstalk_hosted_zone": elasticbeanstalk.DataSourceHostedZone(), + "aws_elastic_beanstalk_solution_stack": elasticbeanstalk.DataSourceSolutionStack(), + + "aws_elasticsearch_domain": elasticsearch.DataSourceDomain(), + + "aws_elb": elb.DataSourceLoadBalancer(), + "aws_elb_hosted_zone_id": elb.DataSourceHostedZoneID(), + "aws_elb_service_account": elb.DataSourceServiceAccount(), // Adding the Aliases for the ALB -> LB Rename - "aws_lb": elbv2.DataSourceLoadBalancer(), + "aws_alb_listener": elbv2.DataSourceListener(), + "aws_alb_target_group": elbv2.DataSourceTargetGroup(), "aws_alb": elbv2.DataSourceLoadBalancer(), "aws_lb_listener": elbv2.DataSourceListener(), - "aws_alb_listener": elbv2.DataSourceListener(), "aws_lb_target_group": elbv2.DataSourceTargetGroup(), - "aws_alb_target_group": elbv2.DataSourceTargetGroup(), + "aws_lb": elbv2.DataSourceLoadBalancer(), + + "aws_kinesis_firehose_delivery_stream": firehose.DataSourceDeliveryStream(), + + "aws_globalaccelerator_accelerator": globalaccelerator.DataSourceAccelerator(), + + "aws_glue_connection": glue.DataSourceConnection(), + "aws_glue_data_catalog_encryption_settings": glue.DataSourceDataCatalogEncryptionSettings(), + "aws_glue_script": glue.DataSourceScript(), + + "aws_guardduty_detector": guardduty.DataSourceDetector(), + + "aws_iam_account_alias": iam.DataSourceAccountAlias(), + "aws_iam_group": iam.DataSourceGroup(), + "aws_iam_instance_profile": iam.DataSourceInstanceProfile(), + "aws_iam_policy": iam.DataSourcePolicy(), + "aws_iam_policy_document": iam.DataSourcePolicyDocument(), + "aws_iam_role": iam.DataSourceRole(), + "aws_iam_roles": iam.DataSourceRoles(), + "aws_iam_server_certificate": iam.DataSourceServerCertificate(), + "aws_iam_session_context": iam.DataSourceSessionContext(), + "aws_iam_user": iam.DataSourceUser(), + "aws_iam_user_ssh_key": iam.DataSourceUserSSHKey(), + "aws_iam_users": iam.DataSourceUsers(), + + "aws_identitystore_group": identitystore.DataSourceGroup(), + "aws_identitystore_user": identitystore.DataSourceUser(), + + "aws_imagebuilder_component": imagebuilder.DataSourceComponent(), + "aws_imagebuilder_distribution_configuration": imagebuilder.DataSourceDistributionConfiguration(), + "aws_imagebuilder_image": imagebuilder.DataSourceImage(), + "aws_imagebuilder_image_pipeline": imagebuilder.DataSourceImagePipeline(), + "aws_imagebuilder_image_recipe": imagebuilder.DataSourceImageRecipe(), + "aws_imagebuilder_infrastructure_configuration": imagebuilder.DataSourceInfrastructureConfiguration(), + + "aws_inspector_rules_packages": inspector.DataSourceRulesPackages(), + + "aws_iot_endpoint": iot.DataSourceEndpoint(), + + "aws_msk_broker_nodes": kafka.DataSourceBrokerNodes(), + "aws_msk_cluster": kafka.DataSourceCluster(), + "aws_msk_configuration": kafka.DataSourceConfiguration(), + "aws_msk_kafka_version": kafka.DataSourceVersion(), + + "aws_kinesis_stream": kinesis.DataSourceStream(), + "aws_kinesis_stream_consumer": kinesis.DataSourceStreamConsumer(), + + "aws_kms_alias": kms.DataSourceAlias(), + "aws_kms_ciphertext": kms.DataSourceCiphertext(), + "aws_kms_key": kms.DataSourceKey(), + "aws_kms_public_key": kms.DataSourcePublicKey(), + "aws_kms_secret": kms.DataSourceSecret(), + "aws_kms_secrets": kms.DataSourceSecrets(), + + "aws_lakeformation_data_lake_settings": lakeformation.DataSourceDataLakeSettings(), + "aws_lakeformation_permissions": lakeformation.DataSourcePermissions(), + "aws_lakeformation_resource": lakeformation.DataSourceResource(), + + "aws_lambda_alias": lambda.DataSourceAlias(), + "aws_lambda_code_signing_config": lambda.DataSourceCodeSigningConfig(), + "aws_lambda_function": lambda.DataSourceFunction(), + "aws_lambda_invocation": lambda.DataSourceInvocation(), + "aws_lambda_layer_version": lambda.DataSourceLayerVersion(), + + "aws_lex_bot": lexmodelbuilding.DataSourceBot(), + "aws_lex_bot_alias": lexmodelbuilding.DataSourceBotAlias(), + "aws_lex_intent": lexmodelbuilding.DataSourceIntent(), + "aws_lex_slot_type": lexmodelbuilding.DataSourceSlotType(), + + "aws_mq_broker": mq.DataSourceBroker(), + + "aws_arn": nas.DataSourceARN(), + "aws_billing_service_account": nas.DataSourceBillingServiceAccount(), + "aws_caller_identity": nas.DataSourceCallerIdentity(), + "aws_canonical_user_id": nas.DataSourceCanonicalUserID(), + "aws_default_tags": nas.DataSourceDefaultTags(), + "aws_ip_ranges": nas.DataSourceIPRanges(), + "aws_partition": nas.DataSourcePartition(), + "aws_region": nas.DataSourceRegion(), + "aws_regions": nas.DataSourceRegions(), + + "aws_neptune_engine_version": neptune.DataSourceEngineVersion(), + "aws_neptune_orderable_db_instance": neptune.DataSourceOrderableDBInstance(), + + "aws_organizations_delegated_administrators": organizations.DataSourceDelegatedAdministrators(), + "aws_organizations_delegated_services": organizations.DataSourceDelegatedServices(), + "aws_organizations_organization": organizations.DataSourceOrganization(), + "aws_organizations_organizational_units": organizations.DataSourceOrganizationalUnits(), + + "aws_outposts_outpost": outposts.DataSourceOutpost(), + "aws_outposts_outpost_instance_type": outposts.DataSourceOutpostInstanceType(), + "aws_outposts_outpost_instance_types": outposts.DataSourceOutpostInstanceTypes(), + "aws_outposts_outposts": outposts.DataSourceOutposts(), + "aws_outposts_site": outposts.DataSourceSite(), + "aws_outposts_sites": outposts.DataSourceSites(), + + "aws_pricing_product": pricing.DataSourceProduct(), + + "aws_qldb_ledger": qldb.DataSourceLedger(), + + "aws_ram_resource_share": ram.DataSourceResourceShare(), + + "aws_db_cluster_snapshot": rds.DataSourceClusterSnapshot(), + "aws_db_event_categories": rds.DataSourceEventCategories(), + "aws_db_instance": rds.DataSourceInstance(), + "aws_db_proxy": rds.DataSourceProxy(), + "aws_db_snapshot": rds.DataSourceSnapshot(), + "aws_db_subnet_group": rds.DataSourceSubnetGroup(), + "aws_rds_certificate": rds.DataSourceCertificate(), + "aws_rds_cluster": rds.DataSourceCluster(), + "aws_rds_engine_version": rds.DataSourceEngineVersion(), + "aws_rds_orderable_db_instance": rds.DataSourceOrderableInstance(), + + "aws_redshift_cluster": redshift.DataSourceCluster(), + "aws_redshift_orderable_cluster": redshift.DataSourceOrderableCluster(), + "aws_redshift_service_account": redshift.DataSourceServiceAccount(), + + "aws_resourcegroupstaggingapi_resources": resourcegroupstagging.DataSourceResources(), + + "aws_route53_delegation_set": route53.DataSourceDelegationSet(), + "aws_route53_zone": route53.DataSourceZone(), + + "aws_route53_resolver_endpoint": route53resolver.DataSourceEndpoint(), + "aws_route53_resolver_rule": route53resolver.DataSourceRule(), + "aws_route53_resolver_rules": route53resolver.DataSourceRules(), + + "aws_s3_bucket": s3.DataSourceBucket(), + "aws_s3_bucket_object": s3.DataSourceBucketObject(), + "aws_s3_bucket_objects": s3.DataSourceBucketObjects(), + + "aws_sagemaker_prebuilt_ecr_image": sagemaker.DataSourcePrebuiltECRImage(), + + "aws_secretsmanager_secret": secretsmanager.DataSourceSecret(), + "aws_secretsmanager_secret_rotation": secretsmanager.DataSourceSecretRotation(), + "aws_secretsmanager_secret_version": secretsmanager.DataSourceSecretVersion(), + + "aws_serverlessapplicationrepository_application": serverlessapprepo.DataSourceApplication(), + + "aws_servicecatalog_constraint": servicecatalog.DataSourceConstraint(), + "aws_servicecatalog_launch_paths": servicecatalog.DataSourceLaunchPaths(), + "aws_servicecatalog_portfolio_constraints": servicecatalog.DataSourcePortfolioConstraints(), + "aws_servicecatalog_portfolio": servicecatalog.DataSourcePortfolio(), + "aws_servicecatalog_product": servicecatalog.DataSourceProduct(), + + "aws_service_discovery_dns_namespace": servicediscovery.DataSourceDNSNamespace(), + + "aws_servicequotas_service": servicequotas.DataSourceService(), + "aws_servicequotas_service_quota": servicequotas.DataSourceServiceQuota(), + + "aws_sfn_activity": sfn.DataSourceActivity(), + "aws_sfn_state_machine": sfn.DataSourceStateMachine(), + + "aws_signer_signing_job": signer.DataSourceSigningJob(), + "aws_signer_signing_profile": signer.DataSourceSigningProfile(), + + "aws_sns_topic": sns.DataSourceTopic(), + + "aws_sqs_queue": sqs.DataSourceQueue(), + + "aws_ssm_document": ssm.DataSourceDocument(), + "aws_ssm_parameter": ssm.DataSourceParameter(), + "aws_ssm_parameters_by_path": ssm.DataSourceParametersByPath(), + "aws_ssm_patch_baseline": ssm.DataSourcePatchBaseline(), + + "aws_ssoadmin_instances": ssoadmin.DataSourceInstances(), + "aws_ssoadmin_permission_set": ssoadmin.DataSourcePermissionSet(), + + "aws_storagegateway_local_disk": storagegateway.DataSourceLocalDisk(), + + "aws_transfer_server": transfer.DataSourceServer(), + + "aws_waf_ipset": waf.DataSourceIPSet(), + "aws_waf_rule": waf.DataSourceRule(), + "aws_waf_rate_based_rule": waf.DataSourceRateBasedRule(), + "aws_waf_web_acl": waf.DataSourceWebACL(), + + "aws_wafregional_ipset": wafregional.DataSourceIPSet(), + "aws_wafregional_rule": wafregional.DataSourceRule(), + "aws_wafregional_rate_based_rule": wafregional.DataSourceRateBasedRule(), + "aws_wafregional_web_acl": wafregional.DataSourceWebACL(), + + "aws_wafv2_ip_set": wafv2.DataSourceIPSet(), + "aws_wafv2_regex_pattern_set": wafv2.DataSourceRegexPatternSet(), + "aws_wafv2_rule_group": wafv2.DataSourceRuleGroup(), + "aws_wafv2_web_acl": wafv2.DataSourceWebACL(), + + "aws_workspaces_bundle": workspaces.DataSourceBundle(), + "aws_workspaces_directory": workspaces.DataSourceDirectory(), + "aws_workspaces_image": workspaces.DataSourceImage(), + "aws_workspaces_workspace": workspaces.DataSourceWorkspace(), }, ResourcesMap: map[string]*schema.Resource{ - "aws_accessanalyzer_analyzer": accessanalyzer.ResourceAnalyzer(), - "aws_acm_certificate": acm.ResourceCertificate(), - "aws_acm_certificate_validation": acm.ResourceCertificateValidation(), - "aws_acmpca_certificate_authority": acmpca.ResourceCertificateAuthority(), - "aws_acmpca_certificate_authority_certificate": acmpca.ResourceCertificateAuthorityCertificate(), - "aws_acmpca_certificate": acmpca.ResourceCertificate(), - "aws_ami": ec2.ResourceAMI(), - "aws_ami_copy": ec2.ResourceAMICopy(), - "aws_ami_from_instance": ec2.ResourceAMIFromInstance(), - "aws_ami_launch_permission": ec2.ResourceAMILaunchPermission(), - "aws_amplify_app": amplify.ResourceApp(), - "aws_amplify_backend_environment": amplify.ResourceBackendEnvironment(), - "aws_amplify_branch": amplify.ResourceBranch(), - "aws_amplify_domain_association": amplify.ResourceDomainAssociation(), - "aws_amplify_webhook": amplify.ResourceWebhook(), - "aws_api_gateway_account": apigateway.ResourceAccount(), - "aws_api_gateway_api_key": apigateway.ResourceAPIKey(), - "aws_api_gateway_authorizer": apigateway.ResourceAuthorizer(), - "aws_api_gateway_base_path_mapping": apigateway.ResourceBasePathMapping(), - "aws_api_gateway_client_certificate": apigateway.ResourceClientCertificate(), - "aws_api_gateway_deployment": apigateway.ResourceDeployment(), - "aws_api_gateway_documentation_part": apigateway.ResourceDocumentationPart(), - "aws_api_gateway_documentation_version": apigateway.ResourceDocumentationVersion(), - "aws_api_gateway_domain_name": apigateway.ResourceDomainName(), - "aws_api_gateway_gateway_response": apigateway.ResourceGatewayResponse(), - "aws_api_gateway_integration": apigateway.ResourceIntegration(), - "aws_api_gateway_integration_response": apigateway.ResourceIntegrationResponse(), - "aws_api_gateway_method": apigateway.ResourceMethod(), - "aws_api_gateway_method_response": apigateway.ResourceMethodResponse(), - "aws_api_gateway_method_settings": apigateway.ResourceMethodSettings(), - "aws_api_gateway_model": apigateway.ResourceModel(), - "aws_api_gateway_request_validator": apigateway.ResourceRequestValidator(), - "aws_api_gateway_resource": apigateway.ResourceResource(), - "aws_api_gateway_rest_api": apigateway.ResourceRestAPI(), - "aws_api_gateway_rest_api_policy": apigateway.ResourceRestAPIPolicy(), - "aws_api_gateway_stage": apigateway.ResourceStage(), - "aws_api_gateway_usage_plan": apigateway.ResourceUsagePlan(), - "aws_api_gateway_usage_plan_key": apigateway.ResourceUsagePlanKey(), - "aws_api_gateway_vpc_link": apigateway.ResourceVPCLink(), - "aws_apigatewayv2_api": apigatewayv2.ResourceAPI(), - "aws_apigatewayv2_api_mapping": apigatewayv2.ResourceAPIMapping(), - "aws_apigatewayv2_authorizer": apigatewayv2.ResourceAuthorizer(), - "aws_apigatewayv2_deployment": apigatewayv2.ResourceDeployment(), - "aws_apigatewayv2_domain_name": apigatewayv2.ResourceDomainName(), - "aws_apigatewayv2_integration": apigatewayv2.ResourceIntegration(), - "aws_apigatewayv2_integration_response": apigatewayv2.ResourceIntegrationResponse(), - "aws_apigatewayv2_model": apigatewayv2.ResourceModel(), - "aws_apigatewayv2_route": apigatewayv2.ResourceRoute(), - "aws_apigatewayv2_route_response": apigatewayv2.ResourceRouteResponse(), - "aws_apigatewayv2_stage": apigatewayv2.ResourceStage(), - "aws_apigatewayv2_vpc_link": apigatewayv2.ResourceVPCLink(), - "aws_app_cookie_stickiness_policy": elb.ResourceAppCookieStickinessPolicy(), - "aws_appautoscaling_target": applicationautoscaling.ResourceTarget(), - "aws_appautoscaling_policy": applicationautoscaling.ResourcePolicy(), - "aws_appautoscaling_scheduled_action": applicationautoscaling.ResourceScheduledAction(), - "aws_appconfig_application": appconfig.ResourceApplication(), - "aws_appconfig_configuration_profile": appconfig.ResourceConfigurationProfile(), - "aws_appconfig_deployment": appconfig.ResourceDeployment(), - "aws_appconfig_deployment_strategy": appconfig.ResourceDeploymentStrategy(), - "aws_appconfig_environment": appconfig.ResourceEnvironment(), - "aws_appconfig_hosted_configuration_version": appconfig.ResourceHostedConfigurationVersion(), - "aws_appmesh_gateway_route": appmesh.ResourceGatewayRoute(), - "aws_appmesh_mesh": appmesh.ResourceMesh(), - "aws_appmesh_route": appmesh.ResourceRoute(), - "aws_appmesh_virtual_gateway": appmesh.ResourceVirtualGateway(), - "aws_appmesh_virtual_node": appmesh.ResourceVirtualNode(), - "aws_appmesh_virtual_router": appmesh.ResourceVirtualRouter(), - "aws_appmesh_virtual_service": appmesh.ResourceVirtualService(), - "aws_apprunner_auto_scaling_configuration_version": apprunner.ResourceAutoScalingConfigurationVersion(), - "aws_apprunner_connection": apprunner.ResourceConnection(), - "aws_apprunner_custom_domain_association": apprunner.ResourceCustomDomainAssociation(), - "aws_apprunner_service": apprunner.ResourceService(), - "aws_appstream_stack": appstream.ResourceStack(), - "aws_appstream_fleet": appstream.ResourceFleet(), - "aws_appstream_image_builder": appstream.ResourceImageBuilder(), - "aws_appsync_api_key": appsync.ResourceAPIKey(), - "aws_appsync_datasource": appsync.ResourceDataSource(), - "aws_appsync_function": appsync.ResourceFunction(), - "aws_appsync_graphql_api": appsync.ResourceGraphQLAPI(), - "aws_appsync_resolver": appsync.ResourceResolver(), - "aws_athena_database": athena.ResourceDatabase(), - "aws_athena_named_query": athena.ResourceNamedQuery(), - "aws_athena_workgroup": athena.ResourceWorkGroup(), - "aws_autoscaling_attachment": autoscaling.ResourceAttachment(), - "aws_autoscaling_group": autoscaling.ResourceGroup(), - "aws_autoscaling_group_tag": autoscaling.ResourceGroupTag(), - "aws_autoscaling_lifecycle_hook": autoscaling.ResourceLifecycleHook(), - "aws_autoscaling_notification": autoscaling.ResourceNotification(), - "aws_autoscaling_policy": autoscaling.ResourcePolicy(), - "aws_autoscaling_schedule": autoscaling.ResourceSchedule(), - "aws_autoscalingplans_scaling_plan": autoscalingplans.ResourceScalingPlan(), - "aws_backup_global_settings": backup.ResourceGlobalSettings(), - "aws_backup_plan": backup.ResourcePlan(), - "aws_backup_region_settings": backup.ResourceRegionSettings(), - "aws_backup_selection": backup.ResourceSelection(), - "aws_backup_vault": backup.ResourceVault(), - "aws_backup_vault_notifications": backup.ResourceVaultNotifications(), - "aws_backup_vault_policy": backup.ResourceVaultPolicy(), - "aws_budgets_budget": budgets.ResourceBudget(), - "aws_budgets_budget_action": budgets.ResourceBudgetAction(), - "aws_chime_voice_connector": chime.ResourceVoiceConnector(), - "aws_chime_voice_connector_group": chime.ResourceVoiceConnectorGroup(), - "aws_chime_voice_connector_logging": chime.ResourceVoiceConnectorLogging(), - "aws_chime_voice_connector_streaming": chime.ResourceVoiceConnectorStreaming(), - "aws_chime_voice_connector_origination": chime.ResourceVoiceConnectorOrigination(), - "aws_chime_voice_connector_termination": chime.ResourceVoiceConnectorTermination(), - "aws_chime_voice_connector_termination_credentials": chime.ResourceVoiceConnectorTerminationCredentials(), - "aws_cloud9_environment_ec2": cloud9.ResourceEnvironmentEC2(), - "aws_cloudcontrolapi_resource": cloudcontrol.ResourceResource(), - "aws_cloudformation_stack": cloudformation.ResourceStack(), - "aws_cloudformation_stack_set": cloudformation.ResourceStackSet(), - "aws_cloudformation_stack_set_instance": cloudformation.ResourceStackSetInstance(), - "aws_cloudformation_type": cloudformation.ResourceType(), - "aws_cloudfront_cache_policy": cloudfront.ResourceCachePolicy(), - "aws_cloudfront_distribution": cloudfront.ResourceDistribution(), - "aws_cloudfront_function": cloudfront.ResourceFunction(), - "aws_cloudfront_key_group": cloudfront.ResourceKeyGroup(), - "aws_cloudfront_monitoring_subscription": cloudfront.ResourceMonitoringSubscription(), - "aws_cloudfront_origin_access_identity": cloudfront.ResourceOriginAccessIdentity(), - "aws_cloudfront_origin_request_policy": cloudfront.ResourceOriginRequestPolicy(), - "aws_cloudfront_public_key": cloudfront.ResourcePublicKey(), - "aws_cloudfront_realtime_log_config": cloudfront.ResourceRealtimeLogConfig(), - "aws_cloudtrail": cloudtrail.ResourceCloudTrail(), - "aws_cloudwatch_event_bus": cloudwatchevents.ResourceBus(), - "aws_cloudwatch_event_bus_policy": cloudwatchevents.ResourceBusPolicy(), - "aws_cloudwatch_event_permission": cloudwatchevents.ResourcePermission(), - "aws_cloudwatch_event_rule": cloudwatchevents.ResourceRule(), - "aws_cloudwatch_event_target": cloudwatchevents.ResourceTarget(), - "aws_cloudwatch_event_archive": cloudwatchevents.ResourceArchive(), - "aws_cloudwatch_event_connection": cloudwatchevents.ResourceConnection(), - "aws_cloudwatch_event_api_destination": cloudwatchevents.ResourceAPIDestination(), - "aws_cloudwatch_log_destination": cloudwatchlogs.ResourceDestination(), - "aws_cloudwatch_log_destination_policy": cloudwatchlogs.ResourceDestinationPolicy(), - "aws_cloudwatch_log_group": cloudwatchlogs.ResourceGroup(), - "aws_cloudwatch_log_metric_filter": cloudwatchlogs.ResourceMetricFilter(), - "aws_cloudwatch_log_resource_policy": cloudwatchlogs.ResourceResourcePolicy(), - "aws_cloudwatch_log_stream": cloudwatchlogs.ResourceStream(), - "aws_cloudwatch_log_subscription_filter": cloudwatchlogs.ResourceSubscriptionFilter(), - "aws_config_aggregate_authorization": config.ResourceAggregateAuthorization(), - "aws_config_config_rule": config.ResourceConfigRule(), - "aws_config_configuration_aggregator": config.ResourceConfigurationAggregator(), - "aws_config_configuration_recorder": config.ResourceConfigurationRecorder(), - "aws_config_configuration_recorder_status": config.ResourceConfigurationRecorderStatus(), - "aws_config_conformance_pack": config.ResourceConformancePack(), - "aws_config_delivery_channel": config.ResourceDeliveryChannel(), - "aws_config_organization_conformance_pack": config.ResourceOrganizationConformancePack(), - "aws_config_organization_custom_rule": config.ResourceOrganizationCustomRule(), - "aws_config_organization_managed_rule": config.ResourceOrganizationManagedRule(), - "aws_config_remediation_configuration": config.ResourceRemediationConfiguration(), - "aws_cognito_identity_pool": cognitoidentity.ResourcePool(), - "aws_cognito_identity_pool_roles_attachment": cognitoidentity.ResourcePoolRolesAttachment(), - "aws_cognito_identity_provider": cognitoidp.ResourceIdentityProvider(), - "aws_cognito_resource_server": cognitoidp.ResourceResourceServer(), - "aws_cognito_user_group": cognitoidp.ResourceUserGroup(), - "aws_cognito_user_pool": cognitoidp.ResourceUserPool(), - "aws_cognito_user_pool_client": cognitoidp.ResourceUserPoolClient(), - "aws_cognito_user_pool_domain": cognitoidp.ResourceUserPoolDomain(), - "aws_cognito_user_pool_ui_customization": cognitoidp.ResourceUserPoolUICustomization(), - "aws_cloudhsm_v2_cluster": cloudhsmv2.ResourceCluster(), - "aws_cloudhsm_v2_hsm": cloudhsmv2.ResourceHSM(), - "aws_cloudwatch_composite_alarm": cloudwatch.ResourceCompositeAlarm(), - "aws_cloudwatch_metric_alarm": cloudwatch.ResourceMetricAlarm(), - "aws_cloudwatch_dashboard": cloudwatch.ResourceDashboard(), - "aws_cloudwatch_metric_stream": cloudwatch.ResourceMetricStream(), - "aws_cloudwatch_query_definition": cloudwatchlogs.ResourceQueryDefinition(), - "aws_codedeploy_app": codedeploy.ResourceApp(), - "aws_codedeploy_deployment_config": codedeploy.ResourceDeploymentConfig(), - "aws_codedeploy_deployment_group": codedeploy.ResourceDeploymentGroup(), - "aws_codecommit_repository": codecommit.ResourceRepository(), - "aws_codecommit_trigger": codecommit.ResourceTrigger(), - "aws_codeartifact_domain": codeartifact.ResourceDomain(), - "aws_codeartifact_domain_permissions_policy": codeartifact.ResourceDomainPermissionsPolicy(), - "aws_codeartifact_repository": codeartifact.ResourceRepository(), - "aws_codeartifact_repository_permissions_policy": codeartifact.ResourceRepositoryPermissionsPolicy(), - "aws_codebuild_project": codebuild.ResourceProject(), - "aws_codebuild_report_group": codebuild.ResourceReportGroup(), - "aws_codebuild_source_credential": codebuild.ResourceSourceCredential(), - "aws_codebuild_webhook": codebuild.ResourceWebhook(), - "aws_codepipeline": codepipeline.ResourceCodePipeline(), - "aws_codepipeline_webhook": codepipeline.ResourceWebhook(), - "aws_codestarconnections_connection": codestarconnections.ResourceConnection(), - "aws_codestarconnections_host": codestarconnections.ResourceHost(), - "aws_codestarnotifications_notification_rule": codestarnotifications.ResourceNotificationRule(), - "aws_connect_contact_flow": connect.ResourceContactFlow(), - "aws_connect_instance": connect.ResourceInstance(), - "aws_cur_report_definition": cur.ResourceReportDefinition(), - "aws_customer_gateway": ec2.ResourceCustomerGateway(), - "aws_datapipeline_pipeline": datapipeline.ResourcePipeline(), - "aws_datasync_agent": datasync.ResourceAgent(), - "aws_datasync_location_efs": datasync.ResourceLocationEFS(), - "aws_datasync_location_fsx_windows_file_system": datasync.ResourceLocationFSxWindowsFileSystem(), - "aws_datasync_location_nfs": datasync.ResourceLocationNFS(), - "aws_datasync_location_s3": datasync.ResourceLocationS3(), - "aws_datasync_location_smb": datasync.ResourceLocationSMB(), - "aws_datasync_task": datasync.ResourceTask(), - "aws_dax_cluster": dax.ResourceCluster(), - "aws_dax_parameter_group": dax.ResourceParameterGroup(), - "aws_dax_subnet_group": dax.ResourceSubnetGroup(), - "aws_db_cluster_snapshot": rds.ResourceClusterSnapshot(), - "aws_db_event_subscription": rds.ResourceEventSubscription(), - "aws_db_instance": rds.ResourceInstance(), - "aws_db_instance_role_association": rds.ResourceInstanceRoleAssociation(), - "aws_db_option_group": rds.ResourceOptionGroup(), - "aws_db_parameter_group": rds.ResourceParameterGroup(), - "aws_db_proxy": rds.ResourceProxy(), - "aws_db_proxy_default_target_group": rds.ResourceProxyDefaultTargetGroup(), - "aws_db_proxy_endpoint": rds.ResourceProxyEndpoint(), - "aws_db_proxy_target": rds.ResourceProxyTarget(), - "aws_db_security_group": rds.ResourceSecurityGroup(), - "aws_db_snapshot": rds.ResourceSnapshot(), - "aws_db_subnet_group": rds.ResourceSubnetGroup(), - "aws_devicefarm_project": devicefarm.ResourceProject(), - "aws_directory_service_directory": ds.ResourceDirectory(), - "aws_directory_service_conditional_forwarder": ds.ResourceConditionalForwarder(), - "aws_directory_service_log_subscription": ds.ResourceLogSubscription(), - "aws_dlm_lifecycle_policy": dlm.ResourceLifecyclePolicy(), - "aws_dms_certificate": dms.ResourceCertificate(), - "aws_dms_endpoint": dms.ResourceEndpoint(), - "aws_dms_event_subscription": dms.ResourceEventSubscription(), - "aws_dms_replication_instance": dms.ResourceReplicationInstance(), - "aws_dms_replication_subnet_group": dms.ResourceReplicationSubnetGroup(), - "aws_dms_replication_task": dms.ResourceReplicationTask(), - "aws_docdb_cluster": docdb.ResourceCluster(), - "aws_docdb_cluster_instance": docdb.ResourceClusterInstance(), - "aws_docdb_cluster_parameter_group": docdb.ResourceClusterParameterGroup(), - "aws_docdb_cluster_snapshot": docdb.ResourceClusterSnapshot(), - "aws_docdb_subnet_group": docdb.ResourceSubnetGroup(), - "aws_dx_bgp_peer": directconnect.ResourceBGPPeer(), - "aws_dx_connection": directconnect.ResourceConnection(), - "aws_dx_connection_association": directconnect.ResourceConnectionAssociation(), - "aws_dx_connection_confirmation": directconnect.ResourceConnectionConfirmation(), - "aws_dx_gateway": directconnect.ResourceGateway(), - "aws_dx_gateway_association": directconnect.ResourceGatewayAssociation(), - "aws_dx_gateway_association_proposal": directconnect.ResourceGatewayAssociationProposal(), - "aws_dx_hosted_connection": directconnect.ResourceHostedConnection(), - "aws_dx_hosted_private_virtual_interface": directconnect.ResourceHostedPrivateVirtualInterface(), - "aws_dx_hosted_private_virtual_interface_accepter": directconnect.ResourceHostedPrivateVirtualInterfaceAccepter(), - "aws_dx_hosted_public_virtual_interface": directconnect.ResourceHostedPublicVirtualInterface(), - "aws_dx_hosted_public_virtual_interface_accepter": directconnect.ResourceHostedPublicVirtualInterfaceAccepter(), - "aws_dx_hosted_transit_virtual_interface": directconnect.ResourceHostedTransitVirtualInterface(), - "aws_dx_hosted_transit_virtual_interface_accepter": directconnect.ResourceHostedTransitVirtualInterfaceAccepter(), - "aws_dx_lag": directconnect.ResourceLag(), - "aws_dx_private_virtual_interface": directconnect.ResourcePrivateVirtualInterface(), - "aws_dx_public_virtual_interface": directconnect.ResourcePublicVirtualInterface(), - "aws_dx_transit_virtual_interface": directconnect.ResourceTransitVirtualInterface(), - "aws_dynamodb_table": dynamodb.ResourceTable(), - "aws_dynamodb_table_item": dynamodb.ResourceTableItem(), - "aws_dynamodb_tag": dynamodb.ResourceTag(), - "aws_dynamodb_global_table": dynamodb.ResourceGlobalTable(), - "aws_dynamodb_kinesis_streaming_destination": dynamodb.ResourceKinesisStreamingDestination(), - "aws_ebs_default_kms_key": ec2.ResourceEBSDefaultKMSKey(), - "aws_ebs_encryption_by_default": ec2.ResourceEBSEncryptionByDefault(), - "aws_ebs_snapshot": ec2.ResourceEBSSnapshot(), - "aws_ebs_snapshot_copy": ec2.ResourceEBSSnapshotCopy(), - "aws_ebs_snapshot_import": ec2.ResourceEBSSnapshotImport(), - "aws_ebs_volume": ec2.ResourceEBSVolume(), - "aws_ec2_availability_zone_group": ec2.ResourceAvailabilityZoneGroup(), - "aws_ec2_capacity_reservation": ec2.ResourceCapacityReservation(), - "aws_ec2_carrier_gateway": ec2.ResourceCarrierGateway(), - "aws_ec2_client_vpn_authorization_rule": ec2.ResourceClientVPNAuthorizationRule(), - "aws_ec2_client_vpn_endpoint": ec2.ResourceClientVPNEndpoint(), - "aws_ec2_client_vpn_network_association": ec2.ResourceClientVPNNetworkAssociation(), - "aws_ec2_client_vpn_route": ec2.ResourceClientVPNRoute(), - "aws_ec2_fleet": ec2.ResourceFleet(), - "aws_ec2_host": ec2.ResourceHost(), - "aws_ec2_local_gateway_route": ec2.ResourceLocalGatewayRoute(), - "aws_ec2_local_gateway_route_table_vpc_association": ec2.ResourceLocalGatewayRouteTableVPCAssociation(), - "aws_ec2_managed_prefix_list": ec2.ResourceManagedPrefixList(), - "aws_ec2_managed_prefix_list_entry": ec2.ResourceManagedPrefixListEntry(), - "aws_ec2_tag": ec2.ResourceTag(), - "aws_ec2_traffic_mirror_filter": ec2.ResourceTrafficMirrorFilter(), - "aws_ec2_traffic_mirror_filter_rule": ec2.ResourceTrafficMirrorFilterRule(), - "aws_ec2_traffic_mirror_target": ec2.ResourceTrafficMirrorTarget(), - "aws_ec2_traffic_mirror_session": ec2.ResourceTrafficMirrorSession(), - "aws_ec2_transit_gateway": ec2.ResourceTransitGateway(), - "aws_ec2_transit_gateway_peering_attachment": ec2.ResourceTransitGatewayPeeringAttachment(), - "aws_ec2_transit_gateway_peering_attachment_accepter": ec2.ResourceTransitGatewayPeeringAttachmentAccepter(), - "aws_ec2_transit_gateway_prefix_list_reference": ec2.ResourceTransitGatewayPrefixListReference(), - "aws_ec2_transit_gateway_route": ec2.ResourceTransitGatewayRoute(), - "aws_ec2_transit_gateway_route_table": ec2.ResourceTransitGatewayRouteTable(), - "aws_ec2_transit_gateway_route_table_association": ec2.ResourceTransitGatewayRouteTableAssociation(), - "aws_ec2_transit_gateway_route_table_propagation": ec2.ResourceTransitGatewayRouteTablePropagation(), - "aws_ec2_transit_gateway_vpc_attachment": ec2.ResourceTransitGatewayVPCAttachment(), - "aws_ec2_transit_gateway_vpc_attachment_accepter": ec2.ResourceTransitGatewayVPCAttachmentAccepter(), - "aws_ecr_lifecycle_policy": ecr.ResourceLifecyclePolicy(), - "aws_ecrpublic_repository": ecrpublic.ResourceRepository(), - "aws_ecr_registry_policy": ecr.ResourceRegistryPolicy(), - "aws_ecr_replication_configuration": ecr.ResourceReplicationConfiguration(), - "aws_ecr_repository": ecr.ResourceRepository(), - "aws_ecr_repository_policy": ecr.ResourceRepositoryPolicy(), - "aws_ecs_capacity_provider": ecs.ResourceCapacityProvider(), - "aws_ecs_cluster": ecs.ResourceCluster(), - "aws_ecs_service": ecs.ResourceService(), - "aws_ecs_tag": ecs.ResourceTag(), - "aws_ecs_task_definition": ecs.ResourceTaskDefinition(), - "aws_efs_access_point": efs.ResourceAccessPoint(), - "aws_efs_backup_policy": efs.ResourceBackupPolicy(), - "aws_efs_file_system": efs.ResourceFileSystem(), - "aws_efs_file_system_policy": efs.ResourceFileSystemPolicy(), - "aws_efs_mount_target": efs.ResourceMountTarget(), - "aws_egress_only_internet_gateway": ec2.ResourceEgressOnlyInternetGateway(), - "aws_eip": ec2.ResourceEIP(), - "aws_eip_association": ec2.ResourceEIPAssociation(), - "aws_eks_cluster": eks.ResourceCluster(), - "aws_eks_addon": eks.ResourceAddon(), - "aws_eks_fargate_profile": eks.ResourceFargateProfile(), - "aws_eks_identity_provider_config": eks.ResourceIdentityProviderConfig(), - "aws_eks_node_group": eks.ResourceNodeGroup(), - "aws_elasticache_cluster": elasticache.ResourceCluster(), - "aws_elasticache_global_replication_group": elasticache.ResourceGlobalReplicationGroup(), - "aws_elasticache_parameter_group": elasticache.ResourceParameterGroup(), - "aws_elasticache_replication_group": elasticache.ResourceReplicationGroup(), - "aws_elasticache_security_group": elasticache.ResourceSecurityGroup(), - "aws_elasticache_subnet_group": elasticache.ResourceSubnetGroup(), - "aws_elasticache_user": elasticache.ResourceUser(), - "aws_elasticache_user_group": elasticache.ResourceUserGroup(), - "aws_elastic_beanstalk_application": elasticbeanstalk.ResourceApplication(), - "aws_elastic_beanstalk_application_version": elasticbeanstalk.ResourceApplicationVersion(), - "aws_elastic_beanstalk_configuration_template": elasticbeanstalk.ResourceConfigurationTemplate(), - "aws_elastic_beanstalk_environment": elasticbeanstalk.ResourceEnvironment(), - "aws_elasticsearch_domain": elasticsearch.ResourceDomain(), - "aws_elasticsearch_domain_policy": elasticsearch.ResourceDomainPolicy(), - "aws_elasticsearch_domain_saml_options": elasticsearch.ResourceDomainSAMLOptions(), - "aws_elastictranscoder_pipeline": elastictranscoder.ResourcePipeline(), - "aws_elastictranscoder_preset": elastictranscoder.ResourcePreset(), - "aws_elb": elb.ResourceLoadBalancer(), - "aws_elb_attachment": elb.ResourceAttachment(), - "aws_emr_cluster": emr.ResourceCluster(), - "aws_emr_instance_group": emr.ResourceInstanceGroup(), - "aws_emr_instance_fleet": emr.ResourceInstanceFleet(), - "aws_emr_managed_scaling_policy": emr.ResourceManagedScalingPolicy(), - "aws_emr_security_configuration": emr.ResourceSecurityConfiguration(), - "aws_flow_log": ec2.ResourceFlowLog(), - "aws_fsx_backup": fsx.ResourceBackup(), - "aws_fsx_lustre_file_system": fsx.ResourceLustreFileSystem(), - "aws_fsx_ontap_file_system": fsx.ResourceOntapFileSystem(), - "aws_fsx_windows_file_system": fsx.ResourceWindowsFileSystem(), - "aws_fms_admin_account": fms.ResourceAdminAccount(), - "aws_fms_policy": fms.ResourcePolicy(), - "aws_gamelift_alias": gamelift.ResourceAlias(), - "aws_gamelift_build": gamelift.ResourceBuild(), - "aws_gamelift_fleet": gamelift.ResourceFleet(), - "aws_gamelift_game_session_queue": gamelift.ResourceGameSessionQueue(), - "aws_glacier_vault": glacier.ResourceVault(), - "aws_glacier_vault_lock": glacier.ResourceVaultLock(), - "aws_globalaccelerator_accelerator": globalaccelerator.ResourceAccelerator(), - "aws_globalaccelerator_endpoint_group": globalaccelerator.ResourceEndpointGroup(), - "aws_globalaccelerator_listener": globalaccelerator.ResourceListener(), - "aws_glue_catalog_database": glue.ResourceCatalogDatabase(), - "aws_glue_catalog_table": glue.ResourceCatalogTable(), - "aws_glue_classifier": glue.ResourceClassifier(), - "aws_glue_connection": glue.ResourceConnection(), - "aws_glue_dev_endpoint": glue.ResourceDevEndpoint(), - "aws_glue_crawler": glue.ResourceCrawler(), - "aws_glue_data_catalog_encryption_settings": glue.ResourceDataCatalogEncryptionSettings(), - "aws_glue_job": glue.ResourceJob(), - "aws_glue_ml_transform": glue.ResourceMLTransform(), - "aws_glue_partition": glue.ResourcePartition(), - "aws_glue_partition_index": glue.ResourcePartitionIndex(), - "aws_glue_registry": glue.ResourceRegistry(), - "aws_glue_resource_policy": glue.ResourceResourcePolicy(), - "aws_glue_schema": glue.ResourceSchema(), - "aws_glue_security_configuration": glue.ResourceSecurityConfiguration(), - "aws_glue_trigger": glue.ResourceTrigger(), - "aws_glue_user_defined_function": glue.ResourceUserDefinedFunction(), - "aws_glue_workflow": glue.ResourceWorkflow(), - "aws_guardduty_detector": guardduty.ResourceDetector(), - "aws_guardduty_filter": guardduty.ResourceFilter(), - "aws_guardduty_invite_accepter": guardduty.ResourceInviteAccepter(), - "aws_guardduty_ipset": guardduty.ResourceIPSet(), - "aws_guardduty_member": guardduty.ResourceMember(), - "aws_guardduty_organization_admin_account": guardduty.ResourceOrganizationAdminAccount(), - "aws_guardduty_organization_configuration": guardduty.ResourceOrganizationConfiguration(), - "aws_guardduty_publishing_destination": guardduty.ResourcePublishingDestination(), - "aws_guardduty_threatintelset": guardduty.ResourceThreatintelset(), - "aws_iam_access_key": iam.ResourceAccessKey(), - "aws_iam_account_alias": iam.ResourceAccountAlias(), - "aws_iam_account_password_policy": iam.ResourceAccountPasswordPolicy(), - "aws_iam_group_policy": iam.ResourceGroupPolicy(), - "aws_iam_group": iam.ResourceGroup(), - "aws_iam_group_membership": iam.ResourceGroupMembership(), - "aws_iam_group_policy_attachment": iam.ResourceGroupPolicyAttachment(), - "aws_iam_instance_profile": iam.ResourceInstanceProfile(), - "aws_iam_openid_connect_provider": iam.ResourceOpenIDConnectProvider(), - "aws_iam_policy": iam.ResourcePolicy(), - "aws_iam_policy_attachment": iam.ResourcePolicyAttachment(), - "aws_iam_role_policy_attachment": iam.ResourceRolePolicyAttachment(), - "aws_iam_role_policy": iam.ResourceRolePolicy(), - "aws_iam_role": iam.ResourceRole(), - "aws_iam_saml_provider": iam.ResourceSamlProvider(), - "aws_iam_server_certificate": iam.ResourceServerCertificate(), - "aws_iam_service_linked_role": iam.ResourceServiceLinkedRole(), - "aws_iam_user_group_membership": iam.ResourceUserGroupMembership(), - "aws_iam_user_policy_attachment": iam.ResourceUserPolicyAttachment(), - "aws_iam_user_policy": iam.ResourceUserPolicy(), - "aws_iam_user_ssh_key": iam.ResourceUserSSHKey(), - "aws_iam_user": iam.ResourceUser(), - "aws_iam_user_login_profile": iam.ResourceUserLoginProfile(), - "aws_imagebuilder_component": imagebuilder.ResourceComponent(), - "aws_imagebuilder_distribution_configuration": imagebuilder.ResourceDistributionConfiguration(), - "aws_imagebuilder_image": imagebuilder.ResourceImage(), - "aws_imagebuilder_image_pipeline": imagebuilder.ResourceImagePipeline(), - "aws_imagebuilder_image_recipe": imagebuilder.ResourceImageRecipe(), - "aws_imagebuilder_infrastructure_configuration": imagebuilder.ResourceInfrastructureConfiguration(), - "aws_inspector_assessment_target": inspector.ResourceAssessmentTarget(), - "aws_inspector_assessment_template": inspector.ResourceAssessmentTemplate(), - "aws_inspector_resource_group": inspector.ResourceResourceGroup(), - "aws_instance": ec2.ResourceInstance(), - "aws_internet_gateway": ec2.ResourceInternetGateway(), - "aws_iot_authorizer": iot.ResourceAuthorizer(), - "aws_iot_certificate": iot.ResourceCertificate(), - "aws_iot_policy": iot.ResourcePolicy(), - "aws_iot_policy_attachment": iot.ResourcePolicyAttachment(), - "aws_iot_thing": iot.ResourceThing(), - "aws_iot_thing_principal_attachment": iot.ResourceThingPrincipalAttachment(), - "aws_iot_thing_type": iot.ResourceThingType(), - "aws_iot_topic_rule": iot.ResourceTopicRule(), - "aws_iot_role_alias": iot.ResourceRoleAlias(), - "aws_key_pair": ec2.ResourceKeyPair(), - "aws_kinesis_analytics_application": kinesisanalytics.ResourceApplication(), - "aws_kinesisanalyticsv2_application": kinesisanalyticsv2.ResourceApplication(), - "aws_kinesisanalyticsv2_application_snapshot": kinesisanalyticsv2.ResourceApplicationSnapshot(), - "aws_kinesis_firehose_delivery_stream": firehose.ResourceDeliveryStream(), - "aws_kinesis_stream": kinesis.ResourceStream(), - "aws_kinesis_stream_consumer": kinesis.ResourceStreamConsumer(), - "aws_kinesis_video_stream": kinesisvideo.ResourceStream(), - "aws_kms_alias": kms.ResourceAlias(), - "aws_kms_external_key": kms.ResourceExternalKey(), - "aws_kms_grant": kms.ResourceGrant(), - "aws_kms_key": kms.ResourceKey(), - "aws_kms_ciphertext": kms.ResourceCiphertext(), - "aws_lakeformation_data_lake_settings": lakeformation.ResourceDataLakeSettings(), - "aws_lakeformation_permissions": lakeformation.ResourcePermissions(), - "aws_lakeformation_resource": lakeformation.ResourceResource(), - "aws_lambda_alias": lambda.ResourceAlias(), - "aws_lambda_code_signing_config": lambda.ResourceCodeSigningConfig(), - "aws_lambda_event_source_mapping": lambda.ResourceEventSourceMapping(), - "aws_lambda_function_event_invoke_config": lambda.ResourceFunctionEventInvokeConfig(), - "aws_lambda_function": lambda.ResourceFunction(), - "aws_lambda_layer_version": lambda.ResourceLayerVersion(), - "aws_lambda_permission": lambda.ResourcePermission(), - "aws_lambda_provisioned_concurrency_config": lambda.ResourceProvisionedConcurrencyConfig(), - "aws_launch_configuration": autoscaling.ResourceLaunchConfiguration(), - "aws_launch_template": ec2.ResourceLaunchTemplate(), - "aws_lex_bot": lexmodelbuilding.ResourceBot(), - "aws_lex_bot_alias": lexmodelbuilding.ResourceBotAlias(), - "aws_lex_intent": lexmodelbuilding.ResourceIntent(), - "aws_lex_slot_type": lexmodelbuilding.ResourceSlotType(), - "aws_licensemanager_association": licensemanager.ResourceAssociation(), - "aws_licensemanager_license_configuration": licensemanager.ResourceLicenseConfiguration(), - "aws_lightsail_domain": lightsail.ResourceDomain(), - "aws_lightsail_instance": lightsail.ResourceInstance(), - "aws_lightsail_instance_public_ports": lightsail.ResourceInstancePublicPorts(), - "aws_lightsail_key_pair": lightsail.ResourceKeyPair(), - "aws_lightsail_static_ip": lightsail.ResourceStaticIP(), - "aws_lightsail_static_ip_attachment": lightsail.ResourceStaticIPAttachment(), - "aws_lb_cookie_stickiness_policy": elb.ResourceCookieStickinessPolicy(), - "aws_load_balancer_policy": elb.ResourcePolicy(), - "aws_load_balancer_backend_server_policy": elb.ResourceBackendServerPolicy(), - "aws_load_balancer_listener_policy": elb.ResourceListenerPolicy(), - "aws_lb_ssl_negotiation_policy": elb.ResourceSSLNegotiationPolicy(), - "aws_macie2_account": macie2.ResourceAccount(), - "aws_macie2_classification_job": macie2.ResourceClassificationJob(), - "aws_macie2_custom_data_identifier": macie2.ResourceCustomDataIdentifier(), - "aws_macie2_findings_filter": macie2.ResourceFindingsFilter(), - "aws_macie2_invitation_accepter": macie2.ResourceInvitationAccepter(), - "aws_macie2_member": macie2.ResourceMember(), - "aws_macie2_organization_admin_account": macie2.ResourceOrganizationAdminAccount(), - "aws_macie_member_account_association": macie.ResourceMemberAccountAssociation(), - "aws_macie_s3_bucket_association": macie.ResourceS3BucketAssociation(), - "aws_main_route_table_association": ec2.ResourceMainRouteTableAssociation(), - "aws_mq_broker": mq.ResourceBroker(), - "aws_mq_configuration": mq.ResourceConfiguration(), - "aws_media_convert_queue": mediaconvert.ResourceQueue(), - "aws_media_package_channel": mediapackage.ResourceChannel(), - "aws_media_store_container": mediastore.ResourceContainer(), - "aws_media_store_container_policy": mediastore.ResourceContainerPolicy(), - "aws_msk_cluster": kafka.ResourceCluster(), - "aws_msk_configuration": kafka.ResourceConfiguration(), - "aws_msk_scram_secret_association": kafka.ResourceScramSecretAssociation(), - "aws_mwaa_environment": mwaa.ResourceEnvironment(), - "aws_nat_gateway": ec2.ResourceNatGateway(), - "aws_network_acl": ec2.ResourceNetworkACL(), - "aws_default_network_acl": ec2.ResourceDefaultNetworkACL(), - "aws_neptune_cluster": neptune.ResourceCluster(), - "aws_neptune_cluster_endpoint": neptune.ResourceClusterEndpoint(), - "aws_neptune_cluster_instance": neptune.ResourceClusterInstance(), - "aws_neptune_cluster_parameter_group": neptune.ResourceClusterParameterGroup(), - "aws_neptune_cluster_snapshot": neptune.ResourceClusterSnapshot(), - "aws_neptune_event_subscription": neptune.ResourceEventSubscription(), - "aws_neptune_parameter_group": neptune.ResourceParameterGroup(), - "aws_neptune_subnet_group": neptune.ResourceSubnetGroup(), - "aws_network_acl_rule": ec2.ResourceNetworkACLRule(), - "aws_network_interface": ec2.ResourceNetworkInterface(), - "aws_network_interface_attachment": ec2.ResourceNetworkInterfaceAttachment(), - "aws_networkfirewall_firewall": networkfirewall.ResourceFirewall(), - "aws_networkfirewall_firewall_policy": networkfirewall.ResourceFirewallPolicy(), - "aws_networkfirewall_logging_configuration": networkfirewall.ResourceLoggingConfiguration(), - "aws_networkfirewall_resource_policy": networkfirewall.ResourceResourcePolicy(), - "aws_networkfirewall_rule_group": networkfirewall.ResourceRuleGroup(), - "aws_opsworks_application": opsworks.ResourceApplication(), - "aws_opsworks_stack": opsworks.ResourceStack(), - "aws_opsworks_java_app_layer": opsworks.ResourceJavaAppLayer(), - "aws_opsworks_haproxy_layer": opsworks.ResourceHAProxyLayer(), - "aws_opsworks_static_web_layer": opsworks.ResourceStaticWebLayer(), - "aws_opsworks_php_app_layer": opsworks.ResourcePHPAppLayer(), - "aws_opsworks_rails_app_layer": opsworks.ResourceRailsAppLayer(), - "aws_opsworks_nodejs_app_layer": opsworks.ResourceNodejsAppLayer(), - "aws_opsworks_memcached_layer": opsworks.ResourceMemcachedLayer(), - "aws_opsworks_mysql_layer": opsworks.ResourceMySQLLayer(), - "aws_opsworks_ganglia_layer": opsworks.ResourceGangliaLayer(), - "aws_opsworks_custom_layer": opsworks.ResourceCustomLayer(), - "aws_opsworks_instance": opsworks.ResourceInstance(), - "aws_opsworks_user_profile": opsworks.ResourceUserProfile(), - "aws_opsworks_permission": opsworks.ResourcePermission(), - "aws_opsworks_rds_db_instance": opsworks.ResourceRDSDBInstance(), - "aws_organizations_organization": organizations.ResourceOrganization(), - "aws_organizations_account": organizations.ResourceAccount(), - "aws_organizations_delegated_administrator": organizations.ResourceDelegatedAdministrator(), - "aws_organizations_policy": organizations.ResourcePolicy(), - "aws_organizations_policy_attachment": organizations.ResourcePolicyAttachment(), - "aws_organizations_organizational_unit": organizations.ResourceOrganizationalUnit(), - "aws_placement_group": ec2.ResourcePlacementGroup(), - "aws_prometheus_workspace": prometheus.ResourceWorkspace(), - "aws_proxy_protocol_policy": elb.ResourceProxyProtocolPolicy(), - "aws_qldb_ledger": qldb.ResourceLedger(), - "aws_quicksight_data_source": quicksight.ResourceDataSource(), - "aws_quicksight_group": quicksight.ResourceGroup(), - "aws_quicksight_group_membership": quicksight.ResourceGroupMembership(), - "aws_quicksight_user": quicksight.ResourceUser(), - "aws_ram_principal_association": ram.ResourcePrincipalAssociation(), - "aws_ram_resource_association": ram.ResourceResourceAssociation(), - "aws_ram_resource_share": ram.ResourceResourceShare(), - "aws_ram_resource_share_accepter": ram.ResourceResourceShareAccepter(), - "aws_rds_cluster": rds.ResourceCluster(), - "aws_rds_cluster_endpoint": rds.ResourceClusterEndpoint(), - "aws_rds_cluster_instance": rds.ResourceClusterInstance(), - "aws_rds_cluster_parameter_group": rds.ResourceClusterParameterGroup(), - "aws_rds_cluster_role_association": rds.ResourceClusterRoleAssociation(), - "aws_rds_global_cluster": rds.ResourceGlobalCluster(), - "aws_redshift_cluster": redshift.ResourceCluster(), - "aws_redshift_security_group": redshift.ResourceSecurityGroup(), - "aws_redshift_parameter_group": redshift.ResourceParameterGroup(), - "aws_redshift_subnet_group": redshift.ResourceSubnetGroup(), - "aws_redshift_snapshot_copy_grant": redshift.ResourceSnapshotCopyGrant(), - "aws_redshift_snapshot_schedule": redshift.ResourceSnapshotSchedule(), - "aws_redshift_snapshot_schedule_association": redshift.ResourceSnapshotScheduleAssociation(), - "aws_redshift_event_subscription": redshift.ResourceEventSubscription(), - "aws_redshift_scheduled_action": redshift.ResourceScheduledAction(), - "aws_resourcegroups_group": resourcegroups.ResourceGroup(), - "aws_route53_delegation_set": route53.ResourceDelegationSet(), - "aws_route53_hosted_zone_dnssec": route53.ResourceHostedZoneDNSSEC(), - "aws_route53_key_signing_key": route53.ResourceKeySigningKey(), - "aws_route53_query_log": route53.ResourceQueryLog(), - "aws_route53_record": route53.ResourceRecord(), - "aws_route53_zone_association": route53.ResourceZoneAssociation(), - "aws_route53_vpc_association_authorization": route53.ResourceVPCAssociationAuthorization(), - "aws_route53_zone": route53.ResourceZone(), - "aws_route53_health_check": route53.ResourceHealthCheck(), - "aws_route53_resolver_dnssec_config": route53resolver.ResourceDNSSECConfig(), - "aws_route53_resolver_endpoint": route53resolver.ResourceEndpoint(), - "aws_route53_resolver_firewall_config": route53resolver.ResourceFirewallConfig(), - "aws_route53_resolver_firewall_domain_list": route53resolver.ResourceFirewallDomainList(), - "aws_route53_resolver_firewall_rule": route53resolver.ResourceFirewallRule(), - "aws_route53_resolver_firewall_rule_group": route53resolver.ResourceFirewallRuleGroup(), - "aws_route53_resolver_firewall_rule_group_association": route53resolver.ResourceFirewallRuleGroupAssociation(), - "aws_route53_resolver_query_log_config": route53resolver.ResourceQueryLogConfig(), - "aws_route53_resolver_query_log_config_association": route53resolver.ResourceQueryLogConfigAssociation(), - "aws_route53_resolver_rule_association": route53resolver.ResourceRuleAssociation(), - "aws_route53_resolver_rule": route53resolver.ResourceRule(), - "aws_route53recoverycontrolconfig_cluster": route53recoverycontrolconfig.ResourceCluster(), - "aws_route53recoverycontrolconfig_control_panel": route53recoverycontrolconfig.ResourceControlPanel(), - "aws_route53recoverycontrolconfig_routing_control": route53recoverycontrolconfig.ResourceRoutingControl(), - "aws_route53recoverycontrolconfig_safety_rule": route53recoverycontrolconfig.ResourceSafetyRule(), - "aws_route53recoveryreadiness_cell": route53recoveryreadiness.ResourceCell(), - "aws_route53recoveryreadiness_readiness_check": route53recoveryreadiness.ResourceReadinessCheck(), - "aws_route53recoveryreadiness_recovery_group": route53recoveryreadiness.ResourceRecoveryGroup(), - "aws_route53recoveryreadiness_resource_set": route53recoveryreadiness.ResourceResourceSet(), - "aws_route": ec2.ResourceRoute(), - "aws_route_table": ec2.ResourceRouteTable(), - "aws_default_route_table": ec2.ResourceDefaultRouteTable(), - "aws_route_table_association": ec2.ResourceRouteTableAssociation(), + "aws_accessanalyzer_analyzer": accessanalyzer.ResourceAnalyzer(), + + "aws_acm_certificate": acm.ResourceCertificate(), + "aws_acm_certificate_validation": acm.ResourceCertificateValidation(), + + "aws_acmpca_certificate": acmpca.ResourceCertificate(), + "aws_acmpca_certificate_authority": acmpca.ResourceCertificateAuthority(), + "aws_acmpca_certificate_authority_certificate": acmpca.ResourceCertificateAuthorityCertificate(), + + "aws_amplify_app": amplify.ResourceApp(), + "aws_amplify_backend_environment": amplify.ResourceBackendEnvironment(), + "aws_amplify_branch": amplify.ResourceBranch(), + "aws_amplify_domain_association": amplify.ResourceDomainAssociation(), + "aws_amplify_webhook": amplify.ResourceWebhook(), + + "aws_api_gateway_account": apigateway.ResourceAccount(), + "aws_api_gateway_api_key": apigateway.ResourceAPIKey(), + "aws_api_gateway_authorizer": apigateway.ResourceAuthorizer(), + "aws_api_gateway_base_path_mapping": apigateway.ResourceBasePathMapping(), + "aws_api_gateway_client_certificate": apigateway.ResourceClientCertificate(), + "aws_api_gateway_deployment": apigateway.ResourceDeployment(), + "aws_api_gateway_documentation_part": apigateway.ResourceDocumentationPart(), + "aws_api_gateway_documentation_version": apigateway.ResourceDocumentationVersion(), + "aws_api_gateway_domain_name": apigateway.ResourceDomainName(), + "aws_api_gateway_gateway_response": apigateway.ResourceGatewayResponse(), + "aws_api_gateway_integration": apigateway.ResourceIntegration(), + "aws_api_gateway_integration_response": apigateway.ResourceIntegrationResponse(), + "aws_api_gateway_method": apigateway.ResourceMethod(), + "aws_api_gateway_method_response": apigateway.ResourceMethodResponse(), + "aws_api_gateway_method_settings": apigateway.ResourceMethodSettings(), + "aws_api_gateway_model": apigateway.ResourceModel(), + "aws_api_gateway_request_validator": apigateway.ResourceRequestValidator(), + "aws_api_gateway_resource": apigateway.ResourceResource(), + "aws_api_gateway_rest_api": apigateway.ResourceRestAPI(), + "aws_api_gateway_rest_api_policy": apigateway.ResourceRestAPIPolicy(), + "aws_api_gateway_stage": apigateway.ResourceStage(), + "aws_api_gateway_usage_plan": apigateway.ResourceUsagePlan(), + "aws_api_gateway_usage_plan_key": apigateway.ResourceUsagePlanKey(), + "aws_api_gateway_vpc_link": apigateway.ResourceVPCLink(), + + "aws_apigatewayv2_api": apigatewayv2.ResourceAPI(), + "aws_apigatewayv2_api_mapping": apigatewayv2.ResourceAPIMapping(), + "aws_apigatewayv2_authorizer": apigatewayv2.ResourceAuthorizer(), + "aws_apigatewayv2_deployment": apigatewayv2.ResourceDeployment(), + "aws_apigatewayv2_domain_name": apigatewayv2.ResourceDomainName(), + "aws_apigatewayv2_integration": apigatewayv2.ResourceIntegration(), + "aws_apigatewayv2_integration_response": apigatewayv2.ResourceIntegrationResponse(), + "aws_apigatewayv2_model": apigatewayv2.ResourceModel(), + "aws_apigatewayv2_route": apigatewayv2.ResourceRoute(), + "aws_apigatewayv2_route_response": apigatewayv2.ResourceRouteResponse(), + "aws_apigatewayv2_stage": apigatewayv2.ResourceStage(), + "aws_apigatewayv2_vpc_link": apigatewayv2.ResourceVPCLink(), + + "aws_appconfig_application": appconfig.ResourceApplication(), + "aws_appconfig_configuration_profile": appconfig.ResourceConfigurationProfile(), + "aws_appconfig_deployment": appconfig.ResourceDeployment(), + "aws_appconfig_deployment_strategy": appconfig.ResourceDeploymentStrategy(), + "aws_appconfig_environment": appconfig.ResourceEnvironment(), + "aws_appconfig_hosted_configuration_version": appconfig.ResourceHostedConfigurationVersion(), + + "aws_appautoscaling_policy": appautoscaling.ResourcePolicy(), + "aws_appautoscaling_scheduled_action": appautoscaling.ResourceScheduledAction(), + "aws_appautoscaling_target": appautoscaling.ResourceTarget(), + + "aws_appmesh_gateway_route": appmesh.ResourceGatewayRoute(), + "aws_appmesh_mesh": appmesh.ResourceMesh(), + "aws_appmesh_route": appmesh.ResourceRoute(), + "aws_appmesh_virtual_gateway": appmesh.ResourceVirtualGateway(), + "aws_appmesh_virtual_node": appmesh.ResourceVirtualNode(), + "aws_appmesh_virtual_router": appmesh.ResourceVirtualRouter(), + "aws_appmesh_virtual_service": appmesh.ResourceVirtualService(), + + "aws_apprunner_auto_scaling_configuration_version": apprunner.ResourceAutoScalingConfigurationVersion(), + "aws_apprunner_connection": apprunner.ResourceConnection(), + "aws_apprunner_custom_domain_association": apprunner.ResourceCustomDomainAssociation(), + "aws_apprunner_service": apprunner.ResourceService(), + + "aws_appstream_fleet": appstream.ResourceFleet(), + "aws_appstream_image_builder": appstream.ResourceImageBuilder(), + "aws_appstream_stack": appstream.ResourceStack(), + + "aws_appsync_api_key": appsync.ResourceAPIKey(), + "aws_appsync_datasource": appsync.ResourceDataSource(), + "aws_appsync_function": appsync.ResourceFunction(), + "aws_appsync_graphql_api": appsync.ResourceGraphQLAPI(), + "aws_appsync_resolver": appsync.ResourceResolver(), + + "aws_athena_database": athena.ResourceDatabase(), + "aws_athena_named_query": athena.ResourceNamedQuery(), + "aws_athena_workgroup": athena.ResourceWorkGroup(), + + "aws_autoscaling_attachment": autoscaling.ResourceAttachment(), + "aws_autoscaling_group": autoscaling.ResourceGroup(), + "aws_autoscaling_group_tag": autoscaling.ResourceGroupTag(), + "aws_autoscaling_lifecycle_hook": autoscaling.ResourceLifecycleHook(), + "aws_autoscaling_notification": autoscaling.ResourceNotification(), + "aws_autoscaling_policy": autoscaling.ResourcePolicy(), + "aws_autoscaling_schedule": autoscaling.ResourceSchedule(), + "aws_launch_configuration": autoscaling.ResourceLaunchConfiguration(), + + "aws_autoscalingplans_scaling_plan": autoscalingplans.ResourceScalingPlan(), + + "aws_backup_global_settings": backup.ResourceGlobalSettings(), + "aws_backup_plan": backup.ResourcePlan(), + "aws_backup_region_settings": backup.ResourceRegionSettings(), + "aws_backup_selection": backup.ResourceSelection(), + "aws_backup_vault": backup.ResourceVault(), + "aws_backup_vault_notifications": backup.ResourceVaultNotifications(), + "aws_backup_vault_policy": backup.ResourceVaultPolicy(), + + "aws_batch_compute_environment": batch.ResourceComputeEnvironment(), + "aws_batch_job_definition": batch.ResourceJobDefinition(), + "aws_batch_job_queue": batch.ResourceJobQueue(), + + "aws_budgets_budget": budgets.ResourceBudget(), + "aws_budgets_budget_action": budgets.ResourceBudgetAction(), + + "aws_chime_voice_connector": chime.ResourceVoiceConnector(), + "aws_chime_voice_connector_group": chime.ResourceVoiceConnectorGroup(), + "aws_chime_voice_connector_logging": chime.ResourceVoiceConnectorLogging(), + "aws_chime_voice_connector_origination": chime.ResourceVoiceConnectorOrigination(), + "aws_chime_voice_connector_streaming": chime.ResourceVoiceConnectorStreaming(), + "aws_chime_voice_connector_termination": chime.ResourceVoiceConnectorTermination(), + "aws_chime_voice_connector_termination_credentials": chime.ResourceVoiceConnectorTerminationCredentials(), + + "aws_cloud9_environment_ec2": cloud9.ResourceEnvironmentEC2(), + + "aws_cloudcontrolapi_resource": cloudcontrol.ResourceResource(), + + "aws_cloudformation_stack": cloudformation.ResourceStack(), + "aws_cloudformation_stack_set": cloudformation.ResourceStackSet(), + "aws_cloudformation_stack_set_instance": cloudformation.ResourceStackSetInstance(), + "aws_cloudformation_type": cloudformation.ResourceType(), + + "aws_cloudfront_cache_policy": cloudfront.ResourceCachePolicy(), + "aws_cloudfront_distribution": cloudfront.ResourceDistribution(), + "aws_cloudfront_function": cloudfront.ResourceFunction(), + "aws_cloudfront_key_group": cloudfront.ResourceKeyGroup(), + "aws_cloudfront_monitoring_subscription": cloudfront.ResourceMonitoringSubscription(), + "aws_cloudfront_origin_access_identity": cloudfront.ResourceOriginAccessIdentity(), + "aws_cloudfront_origin_request_policy": cloudfront.ResourceOriginRequestPolicy(), + "aws_cloudfront_public_key": cloudfront.ResourcePublicKey(), + "aws_cloudfront_realtime_log_config": cloudfront.ResourceRealtimeLogConfig(), + + "aws_cloudhsm_v2_cluster": cloudhsmv2.ResourceCluster(), + "aws_cloudhsm_v2_hsm": cloudhsmv2.ResourceHSM(), + + "aws_cloudtrail": cloudtrail.ResourceCloudTrail(), + + "aws_cloudwatch_composite_alarm": cloudwatch.ResourceCompositeAlarm(), + "aws_cloudwatch_dashboard": cloudwatch.ResourceDashboard(), + "aws_cloudwatch_metric_alarm": cloudwatch.ResourceMetricAlarm(), + "aws_cloudwatch_metric_stream": cloudwatch.ResourceMetricStream(), + + "aws_cloudwatch_event_api_destination": cloudwatchevents.ResourceAPIDestination(), + "aws_cloudwatch_event_archive": cloudwatchevents.ResourceArchive(), + "aws_cloudwatch_event_bus": cloudwatchevents.ResourceBus(), + "aws_cloudwatch_event_bus_policy": cloudwatchevents.ResourceBusPolicy(), + "aws_cloudwatch_event_connection": cloudwatchevents.ResourceConnection(), + "aws_cloudwatch_event_permission": cloudwatchevents.ResourcePermission(), + "aws_cloudwatch_event_rule": cloudwatchevents.ResourceRule(), + "aws_cloudwatch_event_target": cloudwatchevents.ResourceTarget(), + + "aws_cloudwatch_log_destination": cloudwatchlogs.ResourceDestination(), + "aws_cloudwatch_log_destination_policy": cloudwatchlogs.ResourceDestinationPolicy(), + "aws_cloudwatch_log_group": cloudwatchlogs.ResourceGroup(), + "aws_cloudwatch_log_metric_filter": cloudwatchlogs.ResourceMetricFilter(), + "aws_cloudwatch_log_resource_policy": cloudwatchlogs.ResourceResourcePolicy(), + "aws_cloudwatch_log_stream": cloudwatchlogs.ResourceStream(), + "aws_cloudwatch_log_subscription_filter": cloudwatchlogs.ResourceSubscriptionFilter(), + "aws_cloudwatch_query_definition": cloudwatchlogs.ResourceQueryDefinition(), + + "aws_codeartifact_domain": codeartifact.ResourceDomain(), + "aws_codeartifact_domain_permissions_policy": codeartifact.ResourceDomainPermissionsPolicy(), + "aws_codeartifact_repository": codeartifact.ResourceRepository(), + "aws_codeartifact_repository_permissions_policy": codeartifact.ResourceRepositoryPermissionsPolicy(), + + "aws_codebuild_project": codebuild.ResourceProject(), + "aws_codebuild_report_group": codebuild.ResourceReportGroup(), + "aws_codebuild_source_credential": codebuild.ResourceSourceCredential(), + "aws_codebuild_webhook": codebuild.ResourceWebhook(), + + "aws_codecommit_repository": codecommit.ResourceRepository(), + "aws_codecommit_trigger": codecommit.ResourceTrigger(), + + "aws_codedeploy_app": codedeploy.ResourceApp(), + "aws_codedeploy_deployment_config": codedeploy.ResourceDeploymentConfig(), + "aws_codedeploy_deployment_group": codedeploy.ResourceDeploymentGroup(), + + "aws_codepipeline": codepipeline.ResourceCodePipeline(), + "aws_codepipeline_webhook": codepipeline.ResourceWebhook(), + + "aws_codestarconnections_connection": codestarconnections.ResourceConnection(), + "aws_codestarconnections_host": codestarconnections.ResourceHost(), + + "aws_codestarnotifications_notification_rule": codestarnotifications.ResourceNotificationRule(), + + "aws_cognito_identity_pool": cognitoidentity.ResourcePool(), + "aws_cognito_identity_pool_roles_attachment": cognitoidentity.ResourcePoolRolesAttachment(), + + "aws_cognito_identity_provider": cognitoidp.ResourceIdentityProvider(), + "aws_cognito_resource_server": cognitoidp.ResourceResourceServer(), + "aws_cognito_user_group": cognitoidp.ResourceUserGroup(), + "aws_cognito_user_pool": cognitoidp.ResourceUserPool(), + "aws_cognito_user_pool_client": cognitoidp.ResourceUserPoolClient(), + "aws_cognito_user_pool_domain": cognitoidp.ResourceUserPoolDomain(), + "aws_cognito_user_pool_ui_customization": cognitoidp.ResourceUserPoolUICustomization(), + + "aws_config_aggregate_authorization": config.ResourceAggregateAuthorization(), + "aws_config_config_rule": config.ResourceConfigRule(), + "aws_config_configuration_aggregator": config.ResourceConfigurationAggregator(), + "aws_config_configuration_recorder": config.ResourceConfigurationRecorder(), + "aws_config_configuration_recorder_status": config.ResourceConfigurationRecorderStatus(), + "aws_config_conformance_pack": config.ResourceConformancePack(), + "aws_config_delivery_channel": config.ResourceDeliveryChannel(), + "aws_config_organization_conformance_pack": config.ResourceOrganizationConformancePack(), + "aws_config_organization_custom_rule": config.ResourceOrganizationCustomRule(), + "aws_config_organization_managed_rule": config.ResourceOrganizationManagedRule(), + "aws_config_remediation_configuration": config.ResourceRemediationConfiguration(), + + "aws_connect_contact_flow": connect.ResourceContactFlow(), + "aws_connect_instance": connect.ResourceInstance(), + + "aws_cur_report_definition": cur.ResourceReportDefinition(), + + "aws_datapipeline_pipeline": datapipeline.ResourcePipeline(), + + "aws_datasync_agent": datasync.ResourceAgent(), + "aws_datasync_location_efs": datasync.ResourceLocationEFS(), + "aws_datasync_location_fsx_windows_file_system": datasync.ResourceLocationFSxWindowsFileSystem(), + "aws_datasync_location_nfs": datasync.ResourceLocationNFS(), + "aws_datasync_location_s3": datasync.ResourceLocationS3(), + "aws_datasync_location_smb": datasync.ResourceLocationSMB(), + "aws_datasync_task": datasync.ResourceTask(), + + "aws_dax_cluster": dax.ResourceCluster(), + "aws_dax_parameter_group": dax.ResourceParameterGroup(), + "aws_dax_subnet_group": dax.ResourceSubnetGroup(), + + "aws_devicefarm_project": devicefarm.ResourceProject(), + + "aws_dx_bgp_peer": directconnect.ResourceBGPPeer(), + "aws_dx_connection": directconnect.ResourceConnection(), + "aws_dx_connection_association": directconnect.ResourceConnectionAssociation(), + "aws_dx_connection_confirmation": directconnect.ResourceConnectionConfirmation(), + "aws_dx_gateway": directconnect.ResourceGateway(), + "aws_dx_gateway_association": directconnect.ResourceGatewayAssociation(), + "aws_dx_gateway_association_proposal": directconnect.ResourceGatewayAssociationProposal(), + "aws_dx_hosted_connection": directconnect.ResourceHostedConnection(), + "aws_dx_hosted_private_virtual_interface": directconnect.ResourceHostedPrivateVirtualInterface(), + "aws_dx_hosted_private_virtual_interface_accepter": directconnect.ResourceHostedPrivateVirtualInterfaceAccepter(), + "aws_dx_hosted_public_virtual_interface": directconnect.ResourceHostedPublicVirtualInterface(), + "aws_dx_hosted_public_virtual_interface_accepter": directconnect.ResourceHostedPublicVirtualInterfaceAccepter(), + "aws_dx_hosted_transit_virtual_interface": directconnect.ResourceHostedTransitVirtualInterface(), + "aws_dx_hosted_transit_virtual_interface_accepter": directconnect.ResourceHostedTransitVirtualInterfaceAccepter(), + "aws_dx_lag": directconnect.ResourceLag(), + "aws_dx_private_virtual_interface": directconnect.ResourcePrivateVirtualInterface(), + "aws_dx_public_virtual_interface": directconnect.ResourcePublicVirtualInterface(), + "aws_dx_transit_virtual_interface": directconnect.ResourceTransitVirtualInterface(), + + "aws_dlm_lifecycle_policy": dlm.ResourceLifecyclePolicy(), + + "aws_dms_certificate": dms.ResourceCertificate(), + "aws_dms_endpoint": dms.ResourceEndpoint(), + "aws_dms_event_subscription": dms.ResourceEventSubscription(), + "aws_dms_replication_instance": dms.ResourceReplicationInstance(), + "aws_dms_replication_subnet_group": dms.ResourceReplicationSubnetGroup(), + "aws_dms_replication_task": dms.ResourceReplicationTask(), + + "aws_docdb_cluster": docdb.ResourceCluster(), + "aws_docdb_cluster_instance": docdb.ResourceClusterInstance(), + "aws_docdb_cluster_parameter_group": docdb.ResourceClusterParameterGroup(), + "aws_docdb_cluster_snapshot": docdb.ResourceClusterSnapshot(), + "aws_docdb_subnet_group": docdb.ResourceSubnetGroup(), + + "aws_directory_service_conditional_forwarder": ds.ResourceConditionalForwarder(), + "aws_directory_service_directory": ds.ResourceDirectory(), + "aws_directory_service_log_subscription": ds.ResourceLogSubscription(), + + "aws_dynamodb_global_table": dynamodb.ResourceGlobalTable(), + "aws_dynamodb_kinesis_streaming_destination": dynamodb.ResourceKinesisStreamingDestination(), + "aws_dynamodb_table": dynamodb.ResourceTable(), + "aws_dynamodb_table_item": dynamodb.ResourceTableItem(), + "aws_dynamodb_tag": dynamodb.ResourceTag(), + + "aws_ami": ec2.ResourceAMI(), + "aws_ami_copy": ec2.ResourceAMICopy(), + "aws_ami_from_instance": ec2.ResourceAMIFromInstance(), + "aws_ami_launch_permission": ec2.ResourceAMILaunchPermission(), + "aws_customer_gateway": ec2.ResourceCustomerGateway(), + "aws_default_network_acl": ec2.ResourceDefaultNetworkACL(), + "aws_default_route_table": ec2.ResourceDefaultRouteTable(), + "aws_default_security_group": ec2.ResourceDefaultSecurityGroup(), + "aws_default_subnet": ec2.ResourceDefaultSubnet(), + "aws_default_vpc": ec2.ResourceDefaultVPC(), + "aws_default_vpc_dhcp_options": ec2.ResourceDefaultVPCDHCPOptions(), + "aws_ebs_default_kms_key": ec2.ResourceEBSDefaultKMSKey(), + "aws_ebs_encryption_by_default": ec2.ResourceEBSEncryptionByDefault(), + "aws_ebs_snapshot": ec2.ResourceEBSSnapshot(), + "aws_ebs_snapshot_copy": ec2.ResourceEBSSnapshotCopy(), + "aws_ebs_snapshot_import": ec2.ResourceEBSSnapshotImport(), + "aws_ebs_volume": ec2.ResourceEBSVolume(), + "aws_ec2_availability_zone_group": ec2.ResourceAvailabilityZoneGroup(), + "aws_ec2_capacity_reservation": ec2.ResourceCapacityReservation(), + "aws_ec2_carrier_gateway": ec2.ResourceCarrierGateway(), + "aws_ec2_client_vpn_authorization_rule": ec2.ResourceClientVPNAuthorizationRule(), + "aws_ec2_client_vpn_endpoint": ec2.ResourceClientVPNEndpoint(), + "aws_ec2_client_vpn_network_association": ec2.ResourceClientVPNNetworkAssociation(), + "aws_ec2_client_vpn_route": ec2.ResourceClientVPNRoute(), + "aws_ec2_fleet": ec2.ResourceFleet(), + "aws_ec2_host": ec2.ResourceHost(), + "aws_ec2_local_gateway_route": ec2.ResourceLocalGatewayRoute(), + "aws_ec2_local_gateway_route_table_vpc_association": ec2.ResourceLocalGatewayRouteTableVPCAssociation(), + "aws_ec2_managed_prefix_list": ec2.ResourceManagedPrefixList(), + "aws_ec2_managed_prefix_list_entry": ec2.ResourceManagedPrefixListEntry(), + "aws_ec2_tag": ec2.ResourceTag(), + "aws_ec2_traffic_mirror_filter": ec2.ResourceTrafficMirrorFilter(), + "aws_ec2_traffic_mirror_filter_rule": ec2.ResourceTrafficMirrorFilterRule(), + "aws_ec2_traffic_mirror_session": ec2.ResourceTrafficMirrorSession(), + "aws_ec2_traffic_mirror_target": ec2.ResourceTrafficMirrorTarget(), + "aws_ec2_transit_gateway": ec2.ResourceTransitGateway(), + "aws_ec2_transit_gateway_peering_attachment": ec2.ResourceTransitGatewayPeeringAttachment(), + "aws_ec2_transit_gateway_peering_attachment_accepter": ec2.ResourceTransitGatewayPeeringAttachmentAccepter(), + "aws_ec2_transit_gateway_prefix_list_reference": ec2.ResourceTransitGatewayPrefixListReference(), + "aws_ec2_transit_gateway_route": ec2.ResourceTransitGatewayRoute(), + "aws_ec2_transit_gateway_route_table": ec2.ResourceTransitGatewayRouteTable(), + "aws_ec2_transit_gateway_route_table_association": ec2.ResourceTransitGatewayRouteTableAssociation(), + "aws_ec2_transit_gateway_route_table_propagation": ec2.ResourceTransitGatewayRouteTablePropagation(), + "aws_ec2_transit_gateway_vpc_attachment": ec2.ResourceTransitGatewayVPCAttachment(), + "aws_ec2_transit_gateway_vpc_attachment_accepter": ec2.ResourceTransitGatewayVPCAttachmentAccepter(), + "aws_egress_only_internet_gateway": ec2.ResourceEgressOnlyInternetGateway(), + "aws_eip": ec2.ResourceEIP(), + "aws_eip_association": ec2.ResourceEIPAssociation(), + "aws_flow_log": ec2.ResourceFlowLog(), + "aws_instance": ec2.ResourceInstance(), + "aws_internet_gateway": ec2.ResourceInternetGateway(), + "aws_key_pair": ec2.ResourceKeyPair(), + "aws_launch_template": ec2.ResourceLaunchTemplate(), + "aws_main_route_table_association": ec2.ResourceMainRouteTableAssociation(), + "aws_nat_gateway": ec2.ResourceNatGateway(), + "aws_network_acl": ec2.ResourceNetworkACL(), + "aws_network_acl_association": ec2.ResourceNetworkAclAssociation(), + "aws_network_acl_rule": ec2.ResourceNetworkACLRule(), + "aws_network_interface": ec2.ResourceNetworkInterface(), + "aws_network_interface_attachment": ec2.ResourceNetworkInterfaceAttachment(), + "aws_network_interface_sg_attachment": ec2.ResourceNetworkInterfaceSGAttachment(), + "aws_placement_group": ec2.ResourcePlacementGroup(), + "aws_route": ec2.ResourceRoute(), + "aws_route_table": ec2.ResourceRouteTable(), + "aws_route_table_association": ec2.ResourceRouteTableAssociation(), + "aws_security_group": ec2.ResourceSecurityGroup(), + "aws_security_group_rule": ec2.ResourceSecurityGroupRule(), + "aws_snapshot_create_volume_permission": ec2.ResourceSnapshotCreateVolumePermission(), + "aws_spot_datafeed_subscription": ec2.ResourceSpotDataFeedSubscription(), + "aws_spot_fleet_request": ec2.ResourceSpotFleetRequest(), + "aws_spot_instance_request": ec2.ResourceSpotInstanceRequest(), + "aws_subnet": ec2.ResourceSubnet(), + "aws_volume_attachment": ec2.ResourceVolumeAttachment(), + "aws_vpc": ec2.ResourceVPC(), + "aws_vpc_dhcp_options": ec2.ResourceVPCDHCPOptions(), + "aws_vpc_dhcp_options_association": ec2.ResourceVPCDHCPOptionsAssociation(), + "aws_vpc_endpoint": ec2.ResourceVPCEndpoint(), + "aws_vpc_endpoint_connection_notification": ec2.ResourceVPCEndpointConnectionNotification(), + "aws_vpc_endpoint_route_table_association": ec2.ResourceVPCEndpointRouteTableAssociation(), + "aws_vpc_endpoint_service": ec2.ResourceVPCEndpointService(), + "aws_vpc_endpoint_service_allowed_principal": ec2.ResourceVPCEndpointServiceAllowedPrincipal(), + "aws_vpc_endpoint_subnet_association": ec2.ResourceVPCEndpointSubnetAssociation(), + "aws_vpc_ipv4_cidr_block_association": ec2.ResourceVPCIPv4CIDRBlockAssociation(), + "aws_vpc_peering_connection": ec2.ResourceVPCPeeringConnection(), + "aws_vpc_peering_connection_accepter": ec2.ResourceVPCPeeringConnectionAccepter(), + "aws_vpc_peering_connection_options": ec2.ResourceVPCPeeringConnectionOptions(), + "aws_vpn_connection": ec2.ResourceVPNConnection(), + "aws_vpn_connection_route": ec2.ResourceVPNConnectionRoute(), + "aws_vpn_gateway": ec2.ResourceVPNGateway(), + "aws_vpn_gateway_attachment": ec2.ResourceVPNGatewayAttachment(), + "aws_vpn_gateway_route_propagation": ec2.ResourceVPNGatewayRoutePropagation(), + + "aws_ecr_lifecycle_policy": ecr.ResourceLifecyclePolicy(), + "aws_ecr_registry_policy": ecr.ResourceRegistryPolicy(), + "aws_ecr_replication_configuration": ecr.ResourceReplicationConfiguration(), + "aws_ecr_repository": ecr.ResourceRepository(), + "aws_ecr_repository_policy": ecr.ResourceRepositoryPolicy(), + + "aws_ecrpublic_repository": ecrpublic.ResourceRepository(), + + "aws_ecs_capacity_provider": ecs.ResourceCapacityProvider(), + "aws_ecs_cluster": ecs.ResourceCluster(), + "aws_ecs_service": ecs.ResourceService(), + "aws_ecs_tag": ecs.ResourceTag(), + "aws_ecs_task_definition": ecs.ResourceTaskDefinition(), + + "aws_efs_access_point": efs.ResourceAccessPoint(), + "aws_efs_backup_policy": efs.ResourceBackupPolicy(), + "aws_efs_file_system": efs.ResourceFileSystem(), + "aws_efs_file_system_policy": efs.ResourceFileSystemPolicy(), + "aws_efs_mount_target": efs.ResourceMountTarget(), + + "aws_eks_addon": eks.ResourceAddon(), + "aws_eks_cluster": eks.ResourceCluster(), + "aws_eks_fargate_profile": eks.ResourceFargateProfile(), + "aws_eks_identity_provider_config": eks.ResourceIdentityProviderConfig(), + "aws_eks_node_group": eks.ResourceNodeGroup(), + + "aws_elasticache_cluster": elasticache.ResourceCluster(), + "aws_elasticache_global_replication_group": elasticache.ResourceGlobalReplicationGroup(), + "aws_elasticache_parameter_group": elasticache.ResourceParameterGroup(), + "aws_elasticache_replication_group": elasticache.ResourceReplicationGroup(), + "aws_elasticache_security_group": elasticache.ResourceSecurityGroup(), + "aws_elasticache_subnet_group": elasticache.ResourceSubnetGroup(), + "aws_elasticache_user": elasticache.ResourceUser(), + "aws_elasticache_user_group": elasticache.ResourceUserGroup(), + + "aws_elastic_beanstalk_application": elasticbeanstalk.ResourceApplication(), + "aws_elastic_beanstalk_application_version": elasticbeanstalk.ResourceApplicationVersion(), + "aws_elastic_beanstalk_configuration_template": elasticbeanstalk.ResourceConfigurationTemplate(), + "aws_elastic_beanstalk_environment": elasticbeanstalk.ResourceEnvironment(), + + "aws_elasticsearch_domain": elasticsearch.ResourceDomain(), + "aws_elasticsearch_domain_policy": elasticsearch.ResourceDomainPolicy(), + "aws_elasticsearch_domain_saml_options": elasticsearch.ResourceDomainSAMLOptions(), + + "aws_elastictranscoder_pipeline": elastictranscoder.ResourcePipeline(), + "aws_elastictranscoder_preset": elastictranscoder.ResourcePreset(), + + "aws_app_cookie_stickiness_policy": elb.ResourceAppCookieStickinessPolicy(), + "aws_elb": elb.ResourceLoadBalancer(), + "aws_elb_attachment": elb.ResourceAttachment(), + "aws_lb_cookie_stickiness_policy": elb.ResourceCookieStickinessPolicy(), + "aws_lb_ssl_negotiation_policy": elb.ResourceSSLNegotiationPolicy(), + "aws_load_balancer_backend_server_policy": elb.ResourceBackendServerPolicy(), + "aws_load_balancer_listener_policy": elb.ResourceListenerPolicy(), + "aws_load_balancer_policy": elb.ResourcePolicy(), + "aws_proxy_protocol_policy": elb.ResourceProxyProtocolPolicy(), + + "aws_alb": elbv2.ResourceLoadBalancer(), + "aws_alb_listener": elbv2.ResourceListener(), + "aws_alb_listener_certificate": elbv2.ResourceListenerCertificate(), + "aws_alb_listener_rule": elbv2.ResourceListenerRule(), + "aws_alb_target_group": elbv2.ResourceTargetGroup(), + "aws_alb_target_group_attachment": elbv2.ResourceTargetGroupAttachment(), + "aws_lb": elbv2.ResourceLoadBalancer(), + "aws_lb_listener": elbv2.ResourceListener(), + "aws_lb_listener_certificate": elbv2.ResourceListenerCertificate(), + "aws_lb_listener_rule": elbv2.ResourceListenerRule(), + "aws_lb_target_group": elbv2.ResourceTargetGroup(), + "aws_lb_target_group_attachment": elbv2.ResourceTargetGroupAttachment(), + + "aws_emr_cluster": emr.ResourceCluster(), + "aws_emr_instance_fleet": emr.ResourceInstanceFleet(), + "aws_emr_instance_group": emr.ResourceInstanceGroup(), + "aws_emr_managed_scaling_policy": emr.ResourceManagedScalingPolicy(), + "aws_emr_security_configuration": emr.ResourceSecurityConfiguration(), + + "aws_kinesis_firehose_delivery_stream": firehose.ResourceDeliveryStream(), + + "aws_fms_admin_account": fms.ResourceAdminAccount(), + "aws_fms_policy": fms.ResourcePolicy(), + + "aws_fsx_backup": fsx.ResourceBackup(), + "aws_fsx_lustre_file_system": fsx.ResourceLustreFileSystem(), + "aws_fsx_ontap_file_system": fsx.ResourceOntapFileSystem(), + "aws_fsx_windows_file_system": fsx.ResourceWindowsFileSystem(), + + "aws_gamelift_alias": gamelift.ResourceAlias(), + "aws_gamelift_build": gamelift.ResourceBuild(), + "aws_gamelift_fleet": gamelift.ResourceFleet(), + "aws_gamelift_game_session_queue": gamelift.ResourceGameSessionQueue(), + + "aws_glacier_vault": glacier.ResourceVault(), + "aws_glacier_vault_lock": glacier.ResourceVaultLock(), + + "aws_globalaccelerator_accelerator": globalaccelerator.ResourceAccelerator(), + "aws_globalaccelerator_endpoint_group": globalaccelerator.ResourceEndpointGroup(), + "aws_globalaccelerator_listener": globalaccelerator.ResourceListener(), + + "aws_glue_catalog_database": glue.ResourceCatalogDatabase(), + "aws_glue_catalog_table": glue.ResourceCatalogTable(), + "aws_glue_classifier": glue.ResourceClassifier(), + "aws_glue_connection": glue.ResourceConnection(), + "aws_glue_crawler": glue.ResourceCrawler(), + "aws_glue_data_catalog_encryption_settings": glue.ResourceDataCatalogEncryptionSettings(), + "aws_glue_dev_endpoint": glue.ResourceDevEndpoint(), + "aws_glue_job": glue.ResourceJob(), + "aws_glue_ml_transform": glue.ResourceMLTransform(), + "aws_glue_partition": glue.ResourcePartition(), + "aws_glue_partition_index": glue.ResourcePartitionIndex(), + "aws_glue_registry": glue.ResourceRegistry(), + "aws_glue_resource_policy": glue.ResourceResourcePolicy(), + "aws_glue_schema": glue.ResourceSchema(), + "aws_glue_security_configuration": glue.ResourceSecurityConfiguration(), + "aws_glue_trigger": glue.ResourceTrigger(), + "aws_glue_user_defined_function": glue.ResourceUserDefinedFunction(), + "aws_glue_workflow": glue.ResourceWorkflow(), + + "aws_guardduty_detector": guardduty.ResourceDetector(), + "aws_guardduty_filter": guardduty.ResourceFilter(), + "aws_guardduty_invite_accepter": guardduty.ResourceInviteAccepter(), + "aws_guardduty_ipset": guardduty.ResourceIPSet(), + "aws_guardduty_member": guardduty.ResourceMember(), + "aws_guardduty_organization_admin_account": guardduty.ResourceOrganizationAdminAccount(), + "aws_guardduty_organization_configuration": guardduty.ResourceOrganizationConfiguration(), + "aws_guardduty_publishing_destination": guardduty.ResourcePublishingDestination(), + "aws_guardduty_threatintelset": guardduty.ResourceThreatintelset(), + + "aws_iam_access_key": iam.ResourceAccessKey(), + "aws_iam_account_alias": iam.ResourceAccountAlias(), + "aws_iam_account_password_policy": iam.ResourceAccountPasswordPolicy(), + "aws_iam_group": iam.ResourceGroup(), + "aws_iam_group_membership": iam.ResourceGroupMembership(), + "aws_iam_group_policy": iam.ResourceGroupPolicy(), + "aws_iam_group_policy_attachment": iam.ResourceGroupPolicyAttachment(), + "aws_iam_instance_profile": iam.ResourceInstanceProfile(), + "aws_iam_openid_connect_provider": iam.ResourceOpenIDConnectProvider(), + "aws_iam_policy": iam.ResourcePolicy(), + "aws_iam_policy_attachment": iam.ResourcePolicyAttachment(), + "aws_iam_role": iam.ResourceRole(), + "aws_iam_role_policy": iam.ResourceRolePolicy(), + "aws_iam_role_policy_attachment": iam.ResourceRolePolicyAttachment(), + "aws_iam_saml_provider": iam.ResourceSamlProvider(), + "aws_iam_server_certificate": iam.ResourceServerCertificate(), + "aws_iam_service_linked_role": iam.ResourceServiceLinkedRole(), + "aws_iam_user": iam.ResourceUser(), + "aws_iam_user_group_membership": iam.ResourceUserGroupMembership(), + "aws_iam_user_login_profile": iam.ResourceUserLoginProfile(), + "aws_iam_user_policy": iam.ResourceUserPolicy(), + "aws_iam_user_policy_attachment": iam.ResourceUserPolicyAttachment(), + "aws_iam_user_ssh_key": iam.ResourceUserSSHKey(), + + "aws_imagebuilder_component": imagebuilder.ResourceComponent(), + "aws_imagebuilder_distribution_configuration": imagebuilder.ResourceDistributionConfiguration(), + "aws_imagebuilder_image": imagebuilder.ResourceImage(), + "aws_imagebuilder_image_pipeline": imagebuilder.ResourceImagePipeline(), + "aws_imagebuilder_image_recipe": imagebuilder.ResourceImageRecipe(), + "aws_imagebuilder_infrastructure_configuration": imagebuilder.ResourceInfrastructureConfiguration(), + + "aws_inspector_assessment_target": inspector.ResourceAssessmentTarget(), + "aws_inspector_assessment_template": inspector.ResourceAssessmentTemplate(), + "aws_inspector_resource_group": inspector.ResourceResourceGroup(), + + "aws_iot_authorizer": iot.ResourceAuthorizer(), + "aws_iot_certificate": iot.ResourceCertificate(), + "aws_iot_policy": iot.ResourcePolicy(), + "aws_iot_policy_attachment": iot.ResourcePolicyAttachment(), + "aws_iot_role_alias": iot.ResourceRoleAlias(), + "aws_iot_thing": iot.ResourceThing(), + "aws_iot_thing_principal_attachment": iot.ResourceThingPrincipalAttachment(), + "aws_iot_thing_type": iot.ResourceThingType(), + "aws_iot_topic_rule": iot.ResourceTopicRule(), + + "aws_msk_cluster": kafka.ResourceCluster(), + "aws_msk_configuration": kafka.ResourceConfiguration(), + "aws_msk_scram_secret_association": kafka.ResourceScramSecretAssociation(), + + "aws_kinesis_stream": kinesis.ResourceStream(), + "aws_kinesis_stream_consumer": kinesis.ResourceStreamConsumer(), + + "aws_kinesis_analytics_application": kinesisanalytics.ResourceApplication(), + "aws_kinesisanalyticsv2_application": kinesisanalyticsv2.ResourceApplication(), + "aws_kinesisanalyticsv2_application_snapshot": kinesisanalyticsv2.ResourceApplicationSnapshot(), + + "aws_kinesis_video_stream": kinesisvideo.ResourceStream(), + + "aws_kms_alias": kms.ResourceAlias(), + "aws_kms_ciphertext": kms.ResourceCiphertext(), + "aws_kms_external_key": kms.ResourceExternalKey(), + "aws_kms_grant": kms.ResourceGrant(), + "aws_kms_key": kms.ResourceKey(), + + "aws_lakeformation_data_lake_settings": lakeformation.ResourceDataLakeSettings(), + "aws_lakeformation_permissions": lakeformation.ResourcePermissions(), + "aws_lakeformation_resource": lakeformation.ResourceResource(), + + "aws_lambda_alias": lambda.ResourceAlias(), + "aws_lambda_code_signing_config": lambda.ResourceCodeSigningConfig(), + "aws_lambda_event_source_mapping": lambda.ResourceEventSourceMapping(), + "aws_lambda_function": lambda.ResourceFunction(), + "aws_lambda_function_event_invoke_config": lambda.ResourceFunctionEventInvokeConfig(), + "aws_lambda_layer_version": lambda.ResourceLayerVersion(), + "aws_lambda_permission": lambda.ResourcePermission(), + "aws_lambda_provisioned_concurrency_config": lambda.ResourceProvisionedConcurrencyConfig(), + + "aws_lex_bot": lexmodelbuilding.ResourceBot(), + "aws_lex_bot_alias": lexmodelbuilding.ResourceBotAlias(), + "aws_lex_intent": lexmodelbuilding.ResourceIntent(), + "aws_lex_slot_type": lexmodelbuilding.ResourceSlotType(), + + "aws_licensemanager_association": licensemanager.ResourceAssociation(), + "aws_licensemanager_license_configuration": licensemanager.ResourceLicenseConfiguration(), + + "aws_lightsail_domain": lightsail.ResourceDomain(), + "aws_lightsail_instance": lightsail.ResourceInstance(), + "aws_lightsail_instance_public_ports": lightsail.ResourceInstancePublicPorts(), + "aws_lightsail_key_pair": lightsail.ResourceKeyPair(), + "aws_lightsail_static_ip": lightsail.ResourceStaticIP(), + "aws_lightsail_static_ip_attachment": lightsail.ResourceStaticIPAttachment(), + + "aws_macie_member_account_association": macie.ResourceMemberAccountAssociation(), + "aws_macie_s3_bucket_association": macie.ResourceS3BucketAssociation(), + + "aws_macie2_account": macie2.ResourceAccount(), + "aws_macie2_classification_job": macie2.ResourceClassificationJob(), + "aws_macie2_custom_data_identifier": macie2.ResourceCustomDataIdentifier(), + "aws_macie2_findings_filter": macie2.ResourceFindingsFilter(), + "aws_macie2_invitation_accepter": macie2.ResourceInvitationAccepter(), + "aws_macie2_member": macie2.ResourceMember(), + "aws_macie2_organization_admin_account": macie2.ResourceOrganizationAdminAccount(), + + "aws_media_convert_queue": mediaconvert.ResourceQueue(), + + "aws_media_package_channel": mediapackage.ResourceChannel(), + + "aws_media_store_container": mediastore.ResourceContainer(), + "aws_media_store_container_policy": mediastore.ResourceContainerPolicy(), + + "aws_mq_broker": mq.ResourceBroker(), + "aws_mq_configuration": mq.ResourceConfiguration(), + + "aws_mwaa_environment": mwaa.ResourceEnvironment(), + + "aws_neptune_cluster": neptune.ResourceCluster(), + "aws_neptune_cluster_endpoint": neptune.ResourceClusterEndpoint(), + "aws_neptune_cluster_instance": neptune.ResourceClusterInstance(), + "aws_neptune_cluster_parameter_group": neptune.ResourceClusterParameterGroup(), + "aws_neptune_cluster_snapshot": neptune.ResourceClusterSnapshot(), + "aws_neptune_event_subscription": neptune.ResourceEventSubscription(), + "aws_neptune_parameter_group": neptune.ResourceParameterGroup(), + "aws_neptune_subnet_group": neptune.ResourceSubnetGroup(), + + "aws_networkfirewall_firewall": networkfirewall.ResourceFirewall(), + "aws_networkfirewall_firewall_policy": networkfirewall.ResourceFirewallPolicy(), + "aws_networkfirewall_logging_configuration": networkfirewall.ResourceLoggingConfiguration(), + "aws_networkfirewall_resource_policy": networkfirewall.ResourceResourcePolicy(), + "aws_networkfirewall_rule_group": networkfirewall.ResourceRuleGroup(), + + "aws_opsworks_application": opsworks.ResourceApplication(), + "aws_opsworks_custom_layer": opsworks.ResourceCustomLayer(), + "aws_opsworks_ganglia_layer": opsworks.ResourceGangliaLayer(), + "aws_opsworks_haproxy_layer": opsworks.ResourceHAProxyLayer(), + "aws_opsworks_instance": opsworks.ResourceInstance(), + "aws_opsworks_java_app_layer": opsworks.ResourceJavaAppLayer(), + "aws_opsworks_memcached_layer": opsworks.ResourceMemcachedLayer(), + "aws_opsworks_mysql_layer": opsworks.ResourceMySQLLayer(), + "aws_opsworks_nodejs_app_layer": opsworks.ResourceNodejsAppLayer(), + "aws_opsworks_permission": opsworks.ResourcePermission(), + "aws_opsworks_php_app_layer": opsworks.ResourcePHPAppLayer(), + "aws_opsworks_rails_app_layer": opsworks.ResourceRailsAppLayer(), + "aws_opsworks_rds_db_instance": opsworks.ResourceRDSDBInstance(), + "aws_opsworks_stack": opsworks.ResourceStack(), + "aws_opsworks_static_web_layer": opsworks.ResourceStaticWebLayer(), + "aws_opsworks_user_profile": opsworks.ResourceUserProfile(), + + "aws_organizations_account": organizations.ResourceAccount(), + "aws_organizations_delegated_administrator": organizations.ResourceDelegatedAdministrator(), + "aws_organizations_organization": organizations.ResourceOrganization(), + "aws_organizations_organizational_unit": organizations.ResourceOrganizationalUnit(), + "aws_organizations_policy": organizations.ResourcePolicy(), + "aws_organizations_policy_attachment": organizations.ResourcePolicyAttachment(), + + "aws_pinpoint_adm_channel": pinpoint.ResourceADMChannel(), + "aws_pinpoint_apns_channel": pinpoint.ResourceAPNSChannel(), + "aws_pinpoint_apns_sandbox_channel": pinpoint.ResourceAPNSSandboxChannel(), + "aws_pinpoint_apns_voip_channel": pinpoint.ResourceAPNSVoIPChannel(), + "aws_pinpoint_apns_voip_sandbox_channel": pinpoint.ResourceAPNSVoIPSandboxChannel(), + "aws_pinpoint_app": pinpoint.ResourceApp(), + "aws_pinpoint_baidu_channel": pinpoint.ResourceBaiduChannel(), + "aws_pinpoint_email_channel": pinpoint.ResourceEmailChannel(), + "aws_pinpoint_event_stream": pinpoint.ResourceEventStream(), + "aws_pinpoint_gcm_channel": pinpoint.ResourceGCMChannel(), + "aws_pinpoint_sms_channel": pinpoint.ResourceSMSChannel(), + + "aws_prometheus_workspace": prometheus.ResourceWorkspace(), + "aws_prometheus_alert_manager_definition": prometheus.ResourceAlertManagerDefinition(), + + "aws_qldb_ledger": qldb.ResourceLedger(), + + "aws_quicksight_data_source": quicksight.ResourceDataSource(), + "aws_quicksight_group": quicksight.ResourceGroup(), + "aws_quicksight_group_membership": quicksight.ResourceGroupMembership(), + "aws_quicksight_user": quicksight.ResourceUser(), + + "aws_ram_principal_association": ram.ResourcePrincipalAssociation(), + "aws_ram_resource_association": ram.ResourceResourceAssociation(), + "aws_ram_resource_share": ram.ResourceResourceShare(), + "aws_ram_resource_share_accepter": ram.ResourceResourceShareAccepter(), + + "aws_db_cluster_snapshot": rds.ResourceClusterSnapshot(), + "aws_db_event_subscription": rds.ResourceEventSubscription(), + "aws_db_instance": rds.ResourceInstance(), + "aws_db_instance_role_association": rds.ResourceInstanceRoleAssociation(), + "aws_db_option_group": rds.ResourceOptionGroup(), + "aws_db_parameter_group": rds.ResourceParameterGroup(), + "aws_db_proxy": rds.ResourceProxy(), + "aws_db_proxy_default_target_group": rds.ResourceProxyDefaultTargetGroup(), + "aws_db_proxy_endpoint": rds.ResourceProxyEndpoint(), + "aws_db_proxy_target": rds.ResourceProxyTarget(), + "aws_db_security_group": rds.ResourceSecurityGroup(), + "aws_db_snapshot": rds.ResourceSnapshot(), + "aws_db_subnet_group": rds.ResourceSubnetGroup(), + "aws_rds_cluster": rds.ResourceCluster(), + "aws_rds_cluster_endpoint": rds.ResourceClusterEndpoint(), + "aws_rds_cluster_instance": rds.ResourceClusterInstance(), + "aws_rds_cluster_parameter_group": rds.ResourceClusterParameterGroup(), + "aws_rds_cluster_role_association": rds.ResourceClusterRoleAssociation(), + "aws_rds_global_cluster": rds.ResourceGlobalCluster(), + + "aws_redshift_cluster": redshift.ResourceCluster(), + "aws_redshift_event_subscription": redshift.ResourceEventSubscription(), + "aws_redshift_parameter_group": redshift.ResourceParameterGroup(), + "aws_redshift_scheduled_action": redshift.ResourceScheduledAction(), + "aws_redshift_security_group": redshift.ResourceSecurityGroup(), + "aws_redshift_snapshot_copy_grant": redshift.ResourceSnapshotCopyGrant(), + "aws_redshift_snapshot_schedule": redshift.ResourceSnapshotSchedule(), + "aws_redshift_snapshot_schedule_association": redshift.ResourceSnapshotScheduleAssociation(), + "aws_redshift_subnet_group": redshift.ResourceSubnetGroup(), + + "aws_resourcegroups_group": resourcegroups.ResourceGroup(), + + "aws_route53_delegation_set": route53.ResourceDelegationSet(), + "aws_route53_health_check": route53.ResourceHealthCheck(), + "aws_route53_hosted_zone_dnssec": route53.ResourceHostedZoneDNSSEC(), + "aws_route53_key_signing_key": route53.ResourceKeySigningKey(), + "aws_route53_query_log": route53.ResourceQueryLog(), + "aws_route53_record": route53.ResourceRecord(), + "aws_route53_vpc_association_authorization": route53.ResourceVPCAssociationAuthorization(), + "aws_route53_zone": route53.ResourceZone(), + "aws_route53_zone_association": route53.ResourceZoneAssociation(), + + "aws_route53recoverycontrolconfig_cluster": route53recoverycontrolconfig.ResourceCluster(), + "aws_route53recoverycontrolconfig_control_panel": route53recoverycontrolconfig.ResourceControlPanel(), + "aws_route53recoverycontrolconfig_routing_control": route53recoverycontrolconfig.ResourceRoutingControl(), + "aws_route53recoverycontrolconfig_safety_rule": route53recoverycontrolconfig.ResourceSafetyRule(), + + "aws_route53recoveryreadiness_cell": route53recoveryreadiness.ResourceCell(), + "aws_route53recoveryreadiness_readiness_check": route53recoveryreadiness.ResourceReadinessCheck(), + "aws_route53recoveryreadiness_recovery_group": route53recoveryreadiness.ResourceRecoveryGroup(), + "aws_route53recoveryreadiness_resource_set": route53recoveryreadiness.ResourceResourceSet(), + + "aws_route53_resolver_dnssec_config": route53resolver.ResourceDNSSECConfig(), + "aws_route53_resolver_endpoint": route53resolver.ResourceEndpoint(), + "aws_route53_resolver_firewall_config": route53resolver.ResourceFirewallConfig(), + "aws_route53_resolver_firewall_domain_list": route53resolver.ResourceFirewallDomainList(), + "aws_route53_resolver_firewall_rule": route53resolver.ResourceFirewallRule(), + "aws_route53_resolver_firewall_rule_group": route53resolver.ResourceFirewallRuleGroup(), + "aws_route53_resolver_firewall_rule_group_association": route53resolver.ResourceFirewallRuleGroupAssociation(), + "aws_route53_resolver_query_log_config": route53resolver.ResourceQueryLogConfig(), + "aws_route53_resolver_query_log_config_association": route53resolver.ResourceQueryLogConfigAssociation(), + "aws_route53_resolver_rule": route53resolver.ResourceRule(), + "aws_route53_resolver_rule_association": route53resolver.ResourceRuleAssociation(), + + "aws_s3_bucket": s3.ResourceBucket(), + "aws_s3_bucket_analytics_configuration": s3.ResourceBucketAnalyticsConfiguration(), + "aws_s3_bucket_inventory": s3.ResourceBucketInventory(), + "aws_s3_bucket_metric": s3.ResourceBucketMetric(), + "aws_s3_bucket_notification": s3.ResourceBucketNotification(), + "aws_s3_bucket_object": s3.ResourceBucketObject(), + "aws_s3_bucket_ownership_controls": s3.ResourceBucketOwnershipControls(), + "aws_s3_bucket_policy": s3.ResourceBucketPolicy(), + "aws_s3_bucket_public_access_block": s3.ResourceBucketPublicAccessBlock(), + "aws_s3_object_copy": s3.ResourceObjectCopy(), + + "aws_s3_access_point": s3control.ResourceAccessPoint(), + "aws_s3_account_public_access_block": s3control.ResourceAccountPublicAccessBlock(), + "aws_s3control_bucket": s3control.ResourceBucket(), + "aws_s3control_bucket_lifecycle_configuration": s3control.ResourceBucketLifecycleConfiguration(), + "aws_s3control_bucket_policy": s3control.ResourceBucketPolicy(), + + "aws_s3outposts_endpoint": s3outposts.ResourceEndpoint(), + "aws_sagemaker_app": sagemaker.ResourceApp(), "aws_sagemaker_app_image_config": sagemaker.ResourceAppImageConfig(), "aws_sagemaker_code_repository": sagemaker.ResourceCodeRepository(), @@ -1214,240 +1482,185 @@ func Provider() *schema.Provider { "aws_sagemaker_endpoint_configuration": sagemaker.ResourceEndpointConfiguration(), "aws_sagemaker_feature_group": sagemaker.ResourceFeatureGroup(), "aws_sagemaker_flow_definition": sagemaker.ResourceFlowDefinition(), + "aws_sagemaker_human_task_ui": sagemaker.ResourceHumanTaskUI(), "aws_sagemaker_image": sagemaker.ResourceImage(), "aws_sagemaker_image_version": sagemaker.ResourceImageVersion(), - "aws_sagemaker_human_task_ui": sagemaker.ResourceHumanTaskUI(), "aws_sagemaker_model": sagemaker.ResourceModel(), "aws_sagemaker_model_package_group": sagemaker.ResourceModelPackageGroup(), "aws_sagemaker_model_package_group_policy": sagemaker.ResourceModelPackageGroupPolicy(), - "aws_sagemaker_notebook_instance_lifecycle_configuration": sagemaker.ResourceNotebookInstanceLifeCycleConfiguration(), "aws_sagemaker_notebook_instance": sagemaker.ResourceNotebookInstance(), + "aws_sagemaker_notebook_instance_lifecycle_configuration": sagemaker.ResourceNotebookInstanceLifeCycleConfiguration(), "aws_sagemaker_studio_lifecycle_config": sagemaker.ResourceStudioLifecycleConfig(), "aws_sagemaker_user_profile": sagemaker.ResourceUserProfile(), "aws_sagemaker_workforce": sagemaker.ResourceWorkforce(), "aws_sagemaker_workteam": sagemaker.ResourceWorkteam(), - "aws_schemas_discoverer": schemas.ResourceDiscoverer(), - "aws_schemas_registry": schemas.ResourceRegistry(), - "aws_schemas_schema": schemas.ResourceSchema(), - "aws_secretsmanager_secret": secretsmanager.ResourceSecret(), - "aws_secretsmanager_secret_policy": secretsmanager.ResourceSecretPolicy(), - "aws_secretsmanager_secret_version": secretsmanager.ResourceSecretVersion(), - "aws_secretsmanager_secret_rotation": secretsmanager.ResourceSecretRotation(), - "aws_ses_active_receipt_rule_set": ses.ResourceActiveReceiptRuleSet(), - "aws_ses_domain_identity": ses.ResourceDomainIdentity(), - "aws_ses_domain_identity_verification": ses.ResourceDomainIdentityVerification(), - "aws_ses_domain_dkim": ses.ResourceDomainDKIM(), - "aws_ses_domain_mail_from": ses.ResourceDomainMailFrom(), - "aws_ses_email_identity": ses.ResourceEmailIdentity(), - "aws_ses_identity_policy": ses.ResourceIdentityPolicy(), - "aws_ses_receipt_filter": ses.ResourceReceiptFilter(), - "aws_ses_receipt_rule": ses.ResourceReceiptRule(), - "aws_ses_receipt_rule_set": ses.ResourceReceiptRuleSet(), - "aws_ses_configuration_set": ses.ResourceConfigurationSet(), - "aws_ses_event_destination": ses.ResourceEventDestination(), - "aws_ses_identity_notification_topic": ses.ResourceIdentityNotificationTopic(), - "aws_ses_template": ses.ResourceTemplate(), - "aws_s3_access_point": s3control.ResourceAccessPoint(), - "aws_s3_account_public_access_block": s3control.ResourceAccountPublicAccessBlock(), - "aws_s3_bucket": s3.ResourceBucket(), - "aws_s3_bucket_analytics_configuration": s3.ResourceBucketAnalyticsConfiguration(), - "aws_s3_bucket_policy": s3.ResourceBucketPolicy(), - "aws_s3_bucket_public_access_block": s3.ResourceBucketPublicAccessBlock(), - "aws_s3_bucket_object": s3.ResourceBucketObject(), - "aws_s3_bucket_ownership_controls": s3.ResourceBucketOwnershipControls(), - "aws_s3_bucket_notification": s3.ResourceBucketNotification(), - "aws_s3_bucket_metric": s3.ResourceBucketMetric(), - "aws_s3_bucket_inventory": s3.ResourceBucketInventory(), - "aws_s3_object_copy": s3.ResourceObjectCopy(), - "aws_s3control_bucket": s3control.ResourceBucket(), - "aws_s3control_bucket_policy": s3control.ResourceBucketPolicy(), - "aws_s3control_bucket_lifecycle_configuration": s3control.ResourceBucketLifecycleConfiguration(), - "aws_s3outposts_endpoint": s3outposts.ResourceEndpoint(), - "aws_security_group": ec2.ResourceSecurityGroup(), - "aws_network_interface_sg_attachment": ec2.ResourceNetworkInterfaceSGAttachment(), - "aws_default_security_group": ec2.ResourceDefaultSecurityGroup(), - "aws_security_group_rule": ec2.ResourceSecurityGroupRule(), - "aws_securityhub_account": securityhub.ResourceAccount(), - "aws_securityhub_action_target": securityhub.ResourceActionTarget(), - "aws_securityhub_insight": securityhub.ResourceInsight(), - "aws_securityhub_invite_accepter": securityhub.ResourceInviteAccepter(), - "aws_securityhub_member": securityhub.ResourceMember(), - "aws_securityhub_organization_admin_account": securityhub.ResourceOrganizationAdminAccount(), - "aws_securityhub_organization_configuration": securityhub.ResourceOrganizationConfiguration(), - "aws_securityhub_product_subscription": securityhub.ResourceProductSubscription(), - "aws_securityhub_standards_control": securityhub.ResourceStandardsControl(), - "aws_securityhub_standards_subscription": securityhub.ResourceStandardsSubscription(), - "aws_servicecatalog_budget_resource_association": servicecatalog.ResourceBudgetResourceAssociation(), - "aws_servicecatalog_constraint": servicecatalog.ResourceConstraint(), - "aws_servicecatalog_organizations_access": servicecatalog.ResourceOrganizationsAccess(), - "aws_servicecatalog_portfolio": servicecatalog.ResourcePortfolio(), - "aws_servicecatalog_portfolio_share": servicecatalog.ResourcePortfolioShare(), - "aws_servicecatalog_product": servicecatalog.ResourceProduct(), - "aws_servicecatalog_provisioned_product": servicecatalog.ResourceProvisionedProduct(), - "aws_servicecatalog_service_action": servicecatalog.ResourceServiceAction(), - "aws_servicecatalog_tag_option": servicecatalog.ResourceTagOption(), - "aws_servicecatalog_tag_option_resource_association": servicecatalog.ResourceTagOptionResourceAssociation(), - "aws_servicecatalog_principal_portfolio_association": servicecatalog.ResourcePrincipalPortfolioAssociation(), - "aws_servicecatalog_product_portfolio_association": servicecatalog.ResourceProductPortfolioAssociation(), - "aws_servicecatalog_provisioning_artifact": servicecatalog.ResourceProvisioningArtifact(), - "aws_service_discovery_instance": servicediscovery.ResourceInstance(), - "aws_service_discovery_http_namespace": servicediscovery.ResourceHTTPNamespace(), - "aws_service_discovery_private_dns_namespace": servicediscovery.ResourcePrivateDNSNamespace(), - "aws_service_discovery_public_dns_namespace": servicediscovery.ResourcePublicDNSNamespace(), - "aws_service_discovery_service": servicediscovery.ResourceService(), - "aws_servicequotas_service_quota": servicequotas.ResourceServiceQuota(), - "aws_shield_protection": shield.ResourceProtection(), - "aws_shield_protection_group": shield.ResourceProtectionGroup(), - "aws_signer_signing_job": signer.ResourceSigningJob(), - "aws_signer_signing_profile": signer.ResourceSigningProfile(), - "aws_signer_signing_profile_permission": signer.ResourceSigningProfilePermission(), - "aws_simpledb_domain": simpledb.ResourceDomain(), - "aws_ssm_activation": ssm.ResourceActivation(), - "aws_ssm_association": ssm.ResourceAssociation(), - "aws_ssm_document": ssm.ResourceDocument(), - "aws_ssm_maintenance_window": ssm.ResourceMaintenanceWindow(), - "aws_ssm_maintenance_window_target": ssm.ResourceMaintenanceWindowTarget(), - "aws_ssm_maintenance_window_task": ssm.ResourceMaintenanceWindowTask(), - "aws_ssm_patch_baseline": ssm.ResourcePatchBaseline(), - "aws_ssm_patch_group": ssm.ResourcePatchGroup(), - "aws_ssm_parameter": ssm.ResourceParameter(), - "aws_ssm_resource_data_sync": ssm.ResourceResourceDataSync(), - "aws_ssoadmin_account_assignment": ssoadmin.ResourceAccountAssignment(), - "aws_ssoadmin_managed_policy_attachment": ssoadmin.ResourceManagedPolicyAttachment(), - "aws_ssoadmin_permission_set": ssoadmin.ResourcePermissionSet(), - "aws_ssoadmin_permission_set_inline_policy": ssoadmin.ResourcePermissionSetInlinePolicy(), - "aws_storagegateway_cache": storagegateway.ResourceCache(), - "aws_storagegateway_cached_iscsi_volume": storagegateway.ResourceCachediSCSIVolume(), - "aws_storagegateway_file_system_association": storagegateway.ResourceFileSystemAssociation(), - "aws_storagegateway_gateway": storagegateway.ResourceGateway(), - "aws_storagegateway_nfs_file_share": storagegateway.ResourceNFSFileShare(), - "aws_storagegateway_smb_file_share": storagegateway.ResourceSMBFileShare(), - "aws_storagegateway_stored_iscsi_volume": storagegateway.ResourceStorediSCSIVolume(), - "aws_storagegateway_tape_pool": storagegateway.ResourceTapePool(), - "aws_storagegateway_upload_buffer": storagegateway.ResourceUploadBuffer(), - "aws_storagegateway_working_storage": storagegateway.ResourceWorkingStorage(), - "aws_spot_datafeed_subscription": ec2.ResourceSpotDataFeedSubscription(), - "aws_spot_instance_request": ec2.ResourceSpotInstanceRequest(), - "aws_spot_fleet_request": ec2.ResourceSpotFleetRequest(), - "aws_sqs_queue": sqs.ResourceQueue(), - "aws_sqs_queue_policy": sqs.ResourceQueuePolicy(), - "aws_snapshot_create_volume_permission": ec2.ResourceSnapshotCreateVolumePermission(), - "aws_sns_platform_application": sns.ResourcePlatformApplication(), - "aws_sns_sms_preferences": sns.ResourceSMSPreferences(), - "aws_sns_topic": sns.ResourceTopic(), - "aws_sns_topic_policy": sns.ResourceTopicPolicy(), - "aws_sns_topic_subscription": sns.ResourceTopicSubscription(), - "aws_sfn_activity": sfn.ResourceActivity(), - "aws_sfn_state_machine": sfn.ResourceStateMachine(), - "aws_default_subnet": ec2.ResourceDefaultSubnet(), - "aws_subnet": ec2.ResourceSubnet(), - "aws_swf_domain": swf.ResourceDomain(), - "aws_synthetics_canary": synthetics.ResourceCanary(), - "aws_timestreamwrite_database": timestreamwrite.ResourceDatabase(), - "aws_timestreamwrite_table": timestreamwrite.ResourceTable(), - "aws_transfer_server": transfer.ResourceServer(), - "aws_transfer_access": transfer.ResourceAccess(), - "aws_transfer_ssh_key": transfer.ResourceSSHKey(), - "aws_transfer_user": transfer.ResourceUser(), - "aws_volume_attachment": ec2.ResourceVolumeAttachment(), - "aws_vpc_dhcp_options_association": ec2.ResourceVPCDHCPOptionsAssociation(), - "aws_default_vpc_dhcp_options": ec2.ResourceDefaultVPCDHCPOptions(), - "aws_vpc_dhcp_options": ec2.ResourceVPCDHCPOptions(), - "aws_vpc_peering_connection": ec2.ResourceVPCPeeringConnection(), - "aws_vpc_peering_connection_accepter": ec2.ResourceVPCPeeringConnectionAccepter(), - "aws_vpc_peering_connection_options": ec2.ResourceVPCPeeringConnectionOptions(), - "aws_default_vpc": ec2.ResourceDefaultVPC(), - "aws_vpc": ec2.ResourceVPC(), - "aws_vpc_endpoint": ec2.ResourceVPCEndpoint(), - "aws_vpc_endpoint_connection_notification": ec2.ResourceVPCEndpointConnectionNotification(), - "aws_vpc_endpoint_route_table_association": ec2.ResourceVPCEndpointRouteTableAssociation(), - "aws_vpc_endpoint_subnet_association": ec2.ResourceVPCEndpointSubnetAssociation(), - "aws_vpc_endpoint_service": ec2.ResourceVPCEndpointService(), - "aws_vpc_endpoint_service_allowed_principal": ec2.ResourceVPCEndpointServiceAllowedPrincipal(), - "aws_vpc_ipv4_cidr_block_association": ec2.ResourceVPCIPv4CIDRBlockAssociation(), - "aws_vpn_connection": ec2.ResourceVPNConnection(), - "aws_vpn_connection_route": ec2.ResourceVPNConnectionRoute(), - "aws_vpn_gateway": ec2.ResourceVPNGateway(), - "aws_vpn_gateway_attachment": ec2.ResourceVPNGatewayAttachment(), - "aws_vpn_gateway_route_propagation": ec2.ResourceVPNGatewayRoutePropagation(), - "aws_waf_byte_match_set": waf.ResourceByteMatchSet(), - "aws_waf_ipset": waf.ResourceIPSet(), - "aws_waf_rate_based_rule": waf.ResourceRateBasedRule(), - "aws_waf_regex_match_set": waf.ResourceRegexMatchSet(), - "aws_waf_regex_pattern_set": waf.ResourceRegexPatternSet(), - "aws_waf_rule": waf.ResourceRule(), - "aws_waf_rule_group": waf.ResourceRuleGroup(), - "aws_waf_size_constraint_set": waf.ResourceSizeConstraintSet(), - "aws_waf_web_acl": waf.ResourceWebACL(), - "aws_waf_xss_match_set": waf.ResourceXSSMatchSet(), - "aws_waf_sql_injection_match_set": waf.ResourceSQLInjectionMatchSet(), - "aws_waf_geo_match_set": waf.ResourceGeoMatchSet(), - "aws_wafregional_byte_match_set": wafregional.ResourceByteMatchSet(), - "aws_wafregional_geo_match_set": wafregional.ResourceGeoMatchSet(), - "aws_wafregional_ipset": wafregional.ResourceIPSet(), - "aws_wafregional_rate_based_rule": wafregional.ResourceRateBasedRule(), - "aws_wafregional_regex_match_set": wafregional.ResourceRegexMatchSet(), - "aws_wafregional_regex_pattern_set": wafregional.ResourceRegexPatternSet(), - "aws_wafregional_rule": wafregional.ResourceRule(), - "aws_wafregional_rule_group": wafregional.ResourceRuleGroup(), - "aws_wafregional_size_constraint_set": wafregional.ResourceSizeConstraintSet(), - "aws_wafregional_sql_injection_match_set": wafregional.ResourceSQLInjectionMatchSet(), - "aws_wafregional_xss_match_set": wafregional.ResourceXSSMatchSet(), - "aws_wafregional_web_acl": wafregional.ResourceWebACL(), - "aws_wafregional_web_acl_association": wafregional.ResourceWebACLAssociation(), - "aws_wafv2_ip_set": wafv2.ResourceIPSet(), - "aws_wafv2_regex_pattern_set": wafv2.ResourceRegexPatternSet(), - "aws_wafv2_rule_group": wafv2.ResourceRuleGroup(), - "aws_wafv2_web_acl": wafv2.ResourceWebACL(), - "aws_wafv2_web_acl_association": wafv2.ResourceWebACLAssociation(), - "aws_wafv2_web_acl_logging_configuration": wafv2.ResourceWebACLLoggingConfiguration(), - "aws_worklink_fleet": worklink.ResourceFleet(), - "aws_worklink_website_certificate_authority_association": worklink.ResourceWebsiteCertificateAuthorityAssociation(), - "aws_workspaces_directory": workspaces.ResourceDirectory(), - "aws_workspaces_workspace": workspaces.ResourceWorkspace(), - "aws_batch_compute_environment": batch.ResourceComputeEnvironment(), - "aws_batch_job_definition": batch.ResourceJobDefinition(), - "aws_batch_job_queue": batch.ResourceJobQueue(), - "aws_pinpoint_app": pinpoint.ResourceApp(), - "aws_pinpoint_adm_channel": pinpoint.ResourceADMChannel(), - "aws_pinpoint_apns_channel": pinpoint.ResourceAPNSChannel(), - "aws_pinpoint_apns_sandbox_channel": pinpoint.ResourceAPNSSandboxChannel(), - "aws_pinpoint_apns_voip_channel": pinpoint.ResourceAPNSVoIPChannel(), - "aws_pinpoint_apns_voip_sandbox_channel": pinpoint.ResourceAPNSVoIPSandboxChannel(), - "aws_pinpoint_baidu_channel": pinpoint.ResourceBaiduChannel(), - "aws_pinpoint_email_channel": pinpoint.ResourceEmailChannel(), - "aws_pinpoint_event_stream": pinpoint.ResourceEventStream(), - "aws_pinpoint_gcm_channel": pinpoint.ResourceGCMChannel(), - "aws_pinpoint_sms_channel": pinpoint.ResourceSMSChannel(), - "aws_xray_encryption_config": xray.ResourceEncryptionConfig(), - "aws_xray_group": xray.ResourceGroup(), - "aws_xray_sampling_rule": xray.ResourceSamplingRule(), - "aws_workspaces_ip_group": workspaces.ResourceIPGroup(), - - // ALBs are actually LBs because they can be type `network` or `application` - // To avoid regressions, we will add a new resource for each and they both point - // back to the old ALB version. IF the Terraform supported aliases for resources - // this would be a whole lot simpler - "aws_alb": elbv2.ResourceLoadBalancer(), - "aws_lb": elbv2.ResourceLoadBalancer(), - "aws_alb_listener": elbv2.ResourceListener(), - "aws_lb_listener": elbv2.ResourceListener(), - "aws_alb_listener_certificate": elbv2.ResourceListenerCertificate(), - "aws_lb_listener_certificate": elbv2.ResourceListenerCertificate(), - "aws_alb_listener_rule": elbv2.ResourceListenerRule(), - "aws_lb_listener_rule": elbv2.ResourceListenerRule(), - "aws_alb_target_group": elbv2.ResourceTargetGroup(), - "aws_lb_target_group": elbv2.ResourceTargetGroup(), - "aws_alb_target_group_attachment": elbv2.ResourceTargetGroupAttachment(), - "aws_lb_target_group_attachment": elbv2.ResourceTargetGroupAttachment(), + + "aws_schemas_discoverer": schemas.ResourceDiscoverer(), + "aws_schemas_registry": schemas.ResourceRegistry(), + "aws_schemas_schema": schemas.ResourceSchema(), + + "aws_secretsmanager_secret": secretsmanager.ResourceSecret(), + "aws_secretsmanager_secret_policy": secretsmanager.ResourceSecretPolicy(), + "aws_secretsmanager_secret_rotation": secretsmanager.ResourceSecretRotation(), + "aws_secretsmanager_secret_version": secretsmanager.ResourceSecretVersion(), + + "aws_securityhub_account": securityhub.ResourceAccount(), + "aws_securityhub_action_target": securityhub.ResourceActionTarget(), + "aws_securityhub_insight": securityhub.ResourceInsight(), + "aws_securityhub_invite_accepter": securityhub.ResourceInviteAccepter(), + "aws_securityhub_member": securityhub.ResourceMember(), + "aws_securityhub_organization_admin_account": securityhub.ResourceOrganizationAdminAccount(), + "aws_securityhub_organization_configuration": securityhub.ResourceOrganizationConfiguration(), + "aws_securityhub_product_subscription": securityhub.ResourceProductSubscription(), + "aws_securityhub_standards_control": securityhub.ResourceStandardsControl(), + "aws_securityhub_standards_subscription": securityhub.ResourceStandardsSubscription(), + + "aws_serverlessapplicationrepository_cloudformation_stack": serverlessapprepo.ResourceCloudFormationStack(), + + "aws_servicecatalog_budget_resource_association": servicecatalog.ResourceBudgetResourceAssociation(), + "aws_servicecatalog_constraint": servicecatalog.ResourceConstraint(), + "aws_servicecatalog_organizations_access": servicecatalog.ResourceOrganizationsAccess(), + "aws_servicecatalog_portfolio": servicecatalog.ResourcePortfolio(), + "aws_servicecatalog_portfolio_share": servicecatalog.ResourcePortfolioShare(), + "aws_servicecatalog_principal_portfolio_association": servicecatalog.ResourcePrincipalPortfolioAssociation(), + "aws_servicecatalog_product": servicecatalog.ResourceProduct(), + "aws_servicecatalog_product_portfolio_association": servicecatalog.ResourceProductPortfolioAssociation(), + "aws_servicecatalog_provisioned_product": servicecatalog.ResourceProvisionedProduct(), + "aws_servicecatalog_provisioning_artifact": servicecatalog.ResourceProvisioningArtifact(), + "aws_servicecatalog_service_action": servicecatalog.ResourceServiceAction(), + "aws_servicecatalog_tag_option": servicecatalog.ResourceTagOption(), + "aws_servicecatalog_tag_option_resource_association": servicecatalog.ResourceTagOptionResourceAssociation(), + + "aws_service_discovery_http_namespace": servicediscovery.ResourceHTTPNamespace(), + "aws_service_discovery_instance": servicediscovery.ResourceInstance(), + "aws_service_discovery_private_dns_namespace": servicediscovery.ResourcePrivateDNSNamespace(), + "aws_service_discovery_public_dns_namespace": servicediscovery.ResourcePublicDNSNamespace(), + "aws_service_discovery_service": servicediscovery.ResourceService(), + + "aws_servicequotas_service_quota": servicequotas.ResourceServiceQuota(), + + "aws_ses_active_receipt_rule_set": ses.ResourceActiveReceiptRuleSet(), + "aws_ses_configuration_set": ses.ResourceConfigurationSet(), + "aws_ses_domain_dkim": ses.ResourceDomainDKIM(), + "aws_ses_domain_identity": ses.ResourceDomainIdentity(), + "aws_ses_domain_identity_verification": ses.ResourceDomainIdentityVerification(), + "aws_ses_domain_mail_from": ses.ResourceDomainMailFrom(), + "aws_ses_email_identity": ses.ResourceEmailIdentity(), + "aws_ses_event_destination": ses.ResourceEventDestination(), + "aws_ses_identity_notification_topic": ses.ResourceIdentityNotificationTopic(), + "aws_ses_identity_policy": ses.ResourceIdentityPolicy(), + "aws_ses_receipt_filter": ses.ResourceReceiptFilter(), + "aws_ses_receipt_rule": ses.ResourceReceiptRule(), + "aws_ses_receipt_rule_set": ses.ResourceReceiptRuleSet(), + "aws_ses_template": ses.ResourceTemplate(), + + "aws_sfn_activity": sfn.ResourceActivity(), + "aws_sfn_state_machine": sfn.ResourceStateMachine(), + + "aws_shield_protection": shield.ResourceProtection(), + "aws_shield_protection_group": shield.ResourceProtectionGroup(), + + "aws_signer_signing_job": signer.ResourceSigningJob(), + "aws_signer_signing_profile": signer.ResourceSigningProfile(), + "aws_signer_signing_profile_permission": signer.ResourceSigningProfilePermission(), + + "aws_simpledb_domain": simpledb.ResourceDomain(), + + "aws_sns_platform_application": sns.ResourcePlatformApplication(), + "aws_sns_sms_preferences": sns.ResourceSMSPreferences(), + "aws_sns_topic": sns.ResourceTopic(), + "aws_sns_topic_policy": sns.ResourceTopicPolicy(), + "aws_sns_topic_subscription": sns.ResourceTopicSubscription(), + + "aws_sqs_queue": sqs.ResourceQueue(), + "aws_sqs_queue_policy": sqs.ResourceQueuePolicy(), + + "aws_ssm_activation": ssm.ResourceActivation(), + "aws_ssm_association": ssm.ResourceAssociation(), + "aws_ssm_document": ssm.ResourceDocument(), + "aws_ssm_maintenance_window": ssm.ResourceMaintenanceWindow(), + "aws_ssm_maintenance_window_target": ssm.ResourceMaintenanceWindowTarget(), + "aws_ssm_maintenance_window_task": ssm.ResourceMaintenanceWindowTask(), + "aws_ssm_parameter": ssm.ResourceParameter(), + "aws_ssm_patch_baseline": ssm.ResourcePatchBaseline(), + "aws_ssm_patch_group": ssm.ResourcePatchGroup(), + "aws_ssm_resource_data_sync": ssm.ResourceResourceDataSync(), + + "aws_ssoadmin_account_assignment": ssoadmin.ResourceAccountAssignment(), + "aws_ssoadmin_managed_policy_attachment": ssoadmin.ResourceManagedPolicyAttachment(), + "aws_ssoadmin_permission_set": ssoadmin.ResourcePermissionSet(), + "aws_ssoadmin_permission_set_inline_policy": ssoadmin.ResourcePermissionSetInlinePolicy(), + + "aws_storagegateway_cache": storagegateway.ResourceCache(), + "aws_storagegateway_cached_iscsi_volume": storagegateway.ResourceCachediSCSIVolume(), + "aws_storagegateway_file_system_association": storagegateway.ResourceFileSystemAssociation(), + "aws_storagegateway_gateway": storagegateway.ResourceGateway(), + "aws_storagegateway_nfs_file_share": storagegateway.ResourceNFSFileShare(), + "aws_storagegateway_smb_file_share": storagegateway.ResourceSMBFileShare(), + "aws_storagegateway_stored_iscsi_volume": storagegateway.ResourceStorediSCSIVolume(), + "aws_storagegateway_tape_pool": storagegateway.ResourceTapePool(), + "aws_storagegateway_upload_buffer": storagegateway.ResourceUploadBuffer(), + "aws_storagegateway_working_storage": storagegateway.ResourceWorkingStorage(), + + "aws_swf_domain": swf.ResourceDomain(), + + "aws_synthetics_canary": synthetics.ResourceCanary(), + + "aws_timestreamwrite_database": timestreamwrite.ResourceDatabase(), + "aws_timestreamwrite_table": timestreamwrite.ResourceTable(), + + "aws_transfer_access": transfer.ResourceAccess(), + "aws_transfer_server": transfer.ResourceServer(), + "aws_transfer_ssh_key": transfer.ResourceSSHKey(), + "aws_transfer_user": transfer.ResourceUser(), + + "aws_waf_byte_match_set": waf.ResourceByteMatchSet(), + "aws_waf_geo_match_set": waf.ResourceGeoMatchSet(), + "aws_waf_ipset": waf.ResourceIPSet(), + "aws_waf_rate_based_rule": waf.ResourceRateBasedRule(), + "aws_waf_regex_match_set": waf.ResourceRegexMatchSet(), + "aws_waf_regex_pattern_set": waf.ResourceRegexPatternSet(), + "aws_waf_rule": waf.ResourceRule(), + "aws_waf_rule_group": waf.ResourceRuleGroup(), + "aws_waf_size_constraint_set": waf.ResourceSizeConstraintSet(), + "aws_waf_sql_injection_match_set": waf.ResourceSQLInjectionMatchSet(), + "aws_waf_web_acl": waf.ResourceWebACL(), + "aws_waf_xss_match_set": waf.ResourceXSSMatchSet(), + + "aws_wafregional_byte_match_set": wafregional.ResourceByteMatchSet(), + "aws_wafregional_geo_match_set": wafregional.ResourceGeoMatchSet(), + "aws_wafregional_ipset": wafregional.ResourceIPSet(), + "aws_wafregional_rate_based_rule": wafregional.ResourceRateBasedRule(), + "aws_wafregional_regex_match_set": wafregional.ResourceRegexMatchSet(), + "aws_wafregional_regex_pattern_set": wafregional.ResourceRegexPatternSet(), + "aws_wafregional_rule": wafregional.ResourceRule(), + "aws_wafregional_rule_group": wafregional.ResourceRuleGroup(), + "aws_wafregional_size_constraint_set": wafregional.ResourceSizeConstraintSet(), + "aws_wafregional_sql_injection_match_set": wafregional.ResourceSQLInjectionMatchSet(), + "aws_wafregional_web_acl": wafregional.ResourceWebACL(), + "aws_wafregional_web_acl_association": wafregional.ResourceWebACLAssociation(), + "aws_wafregional_xss_match_set": wafregional.ResourceXSSMatchSet(), + + "aws_wafv2_ip_set": wafv2.ResourceIPSet(), + "aws_wafv2_regex_pattern_set": wafv2.ResourceRegexPatternSet(), + "aws_wafv2_rule_group": wafv2.ResourceRuleGroup(), + "aws_wafv2_web_acl": wafv2.ResourceWebACL(), + "aws_wafv2_web_acl_association": wafv2.ResourceWebACLAssociation(), + "aws_wafv2_web_acl_logging_configuration": wafv2.ResourceWebACLLoggingConfiguration(), + + "aws_worklink_fleet": worklink.ResourceFleet(), + "aws_worklink_website_certificate_authority_association": worklink.ResourceWebsiteCertificateAuthorityAssociation(), + + "aws_workspaces_directory": workspaces.ResourceDirectory(), + "aws_workspaces_ip_group": workspaces.ResourceIPGroup(), + "aws_workspaces_workspace": workspaces.ResourceWorkspace(), + + "aws_xray_encryption_config": xray.ResourceEncryptionConfig(), + "aws_xray_group": xray.ResourceGroup(), + "aws_xray_sampling_rule": xray.ResourceSamplingRule(), }, } - // Avoid Go formatting churn and Git conflicts - // You probably should not do this - provider.DataSourcesMap["aws_serverlessapplicationrepository_application"] = serverlessapprepo.DataSourceApplication() - provider.ResourcesMap["aws_serverlessapplicationrepository_cloudformation_stack"] = serverlessapprepo.ResourceCloudFormationStack() - provider.ConfigureFunc = func(d *schema.ResourceData) (interface{}, error) { terraformVersion := provider.TerraformVersion if terraformVersion == "" { diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index f33148c19463..bf381d49acd7 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func resourceAwsNetworkAclAssociation() *schema.Resource { +func ResourceNetworkAclAssociation() *schema.Resource { return &schema.Resource{ Create: resourceAwsNetworkAclAssociationCreate, Read: resourceAwsNetworkAclAssociationRead, @@ -34,7 +34,7 @@ func resourceAwsNetworkAclAssociation() *schema.Resource { } } -func resourceAwsNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{}) error { +func ResourceNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn naclId := d.Get("network_acl_id").(string) @@ -60,10 +60,10 @@ func resourceAwsNetworkAclAssociationCreate(d *schema.ResourceData, meta interfa d.SetId(aws.StringValue(associationId)) log.Printf("[INFO] New Association ID: %s", d.Id()) - return resourceAwsNetworkAclAssociationRead(d, meta) + return ResourceNetworkAclAssociationRead(d, meta) } -func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) error { +func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn // Inspect that the association exists @@ -92,7 +92,7 @@ func resourceAwsNetworkAclAssociationRead(d *schema.ResourceData, meta interface return nil } -func resourceAwsNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { +func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 3dfe8fb5b90f..ce3a96b8d693 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -14,7 +14,7 @@ func init() { }) } -func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { +func TestAccNetworkAclAssociation_basic(t *testing.T) { var networkAcl ec2.NetworkAcl resourceName := "aws_network_acl.acl_a" @@ -27,7 +27,7 @@ func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSNetworkAclAssoc, + Config: testAccNetworkAclAssoc, Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSNetworkAclExists(resourceName, &networkAcl), testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.subnet_a"), @@ -37,7 +37,7 @@ func TestAccAWSNetworkAclAssociation_basic(t *testing.T) { }) } -const testAccAWSNetworkAclAssoc = ` +const testAccNetworkAclAssoc = ` resource "aws_vpc" "test_vpc" { cidr_block = "10.1.0.0/16" tags = { From d3650c600c97afd776d46a359abc95b8b98c32ac Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 10:44:10 -0500 Subject: [PATCH 19/67] updated package name --- internal/service/ec2/network_acl_association.go | 8 ++++---- internal/service/ec2/network_acl_association_test.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index bf381d49acd7..363d55036561 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -1,4 +1,4 @@ -package aws +package ec2 import ( "fmt" @@ -14,9 +14,9 @@ import ( func ResourceNetworkAclAssociation() *schema.Resource { return &schema.Resource{ - Create: resourceAwsNetworkAclAssociationCreate, - Read: resourceAwsNetworkAclAssociationRead, - Delete: resourceAwsNetworkAclAssociationDelete, + Create: ResourceNetworkAclAssociationCreate, + Read: ResourceNetworkAclAssociationRead, + Delete: ResourceNetworkAclAssociationDelete, Schema: map[string]*schema.Schema{ "subnet_id": { diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index ce3a96b8d693..ddf30f083041 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -1,4 +1,4 @@ -package aws +package ec2 import ( "testing" From 6e8fe296339530f12db074d829ef7d183bb61602 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 11:50:07 -0500 Subject: [PATCH 20/67] fixed most missing dependencies --- internal/service/ec2/network_acl_association.go | 17 +++++++++++------ .../service/ec2/network_acl_association_test.go | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 363d55036561..f8808bf34c73 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -8,6 +8,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -35,7 +36,7 @@ func ResourceNetworkAclAssociation() *schema.Resource { } func ResourceNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).ec2conn + conn := meta.(*conns.AWSClient).EC2Conn naclId := d.Get("network_acl_id").(string) subnetId := d.Get("subnet_id").(string) @@ -64,13 +65,13 @@ func ResourceNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{ } func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).ec2conn + conn := meta.(*conns.AWSClient).EC2Conn // Inspect that the association exists subnetId := d.Get("subnet_id").(string) association, err := findNetworkAclAssociation(subnetId, conn) if err != nil { - if isResourceNotFoundError(err) { + if tfawserr.ErrCodeContains(err, "InvalidNetworkAclID.NotFound") { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do @@ -93,8 +94,7 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) } func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { - - conn := meta.(*AWSClient).ec2conn + conn := meta.(*conns.AWSClient).EC2Conn subnetId := d.Get("subnet_id").(string) @@ -124,7 +124,7 @@ func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{ } } - defaultAcl, err := getDefaultNetworkAcl(*nacl.VpcId, conn) + defaultAcl, err := GetDefaultNetworkACL(*nacl.VpcId, conn) if err != nil { return fmt.Errorf("Failed to get default Network Acl : %s", err) @@ -159,3 +159,8 @@ func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{ d.SetId("") return nil } + +func isResourceTimeoutError(err error) bool { + timeoutErr, ok := err.(*resource.TimeoutError) + return ok && timeoutErr.LastError == nil +} \ No newline at end of file diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index ddf30f083041..c7efd1745d47 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -24,12 +24,12 @@ func TestAccNetworkAclAssociation_basic(t *testing.T) { PreCheck: func() { testAccPreCheck(t) }, IDRefreshName: resourceName, Providers: testAccProviders, - CheckDestroy: testAccCheckAWSNetworkAclDestroy, + CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { Config: testAccNetworkAclAssoc, Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSNetworkAclExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &networkAcl), testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.subnet_a"), ), }, From b7fccd1f4fc735a71b127d37613612bedc70f3d0 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 12:30:32 -0500 Subject: [PATCH 21/67] refactor --- internal/service/ec2/network_acl_association.go | 12 ++++-------- internal/service/ec2/network_acl_association_test.go | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index f8808bf34c73..a4f81305d59c 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -8,9 +8,10 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func ResourceNetworkAclAssociation() *schema.Resource { @@ -71,7 +72,7 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) subnetId := d.Get("subnet_id").(string) association, err := findNetworkAclAssociation(subnetId, conn) if err != nil { - if tfawserr.ErrCodeContains(err, "InvalidNetworkAclID.NotFound") { + if tfresource.NotFound(err) { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do @@ -149,7 +150,7 @@ func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{ } return nil }) - if isResourceTimeoutError(err) { + if tfresource.TimedOut(err) { _, err = conn.ReplaceNetworkAclAssociation(&associationOpts) } if err != nil { @@ -159,8 +160,3 @@ func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{ d.SetId("") return nil } - -func isResourceTimeoutError(err error) bool { - timeoutErr, ok := err.(*resource.TimeoutError) - return ok && timeoutErr.LastError == nil -} \ No newline at end of file diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index c7efd1745d47..cc859de7c707 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -1,4 +1,4 @@ -package ec2 +package ec2_test import ( "testing" From d06b2cb7a084bc293650fd51879686f5313f4649 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 12:55:42 -0500 Subject: [PATCH 22/67] refactor 2 --- internal/service/ec2/network_acl_association.go | 2 +- internal/service/ec2/network_acl_association_test.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index a4f81305d59c..7b467d3774b9 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -100,7 +100,7 @@ func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{ subnetId := d.Get("subnet_id").(string) req := &ec2.DescribeNetworkAclsInput{} - req.Filters = buildEC2AttributeFilterList( + req.Filters = BuildAttributeFilterList( map[string]string{ "association.subnet-id": subnetId, }, diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index cc859de7c707..57c806497556 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -5,12 +5,13 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" ) func init() { resource.AddTestSweepers("aws_network_acl_association", &resource.Sweeper{ Name: "aws_network_acl_association", - F: testSweepNetworkAcls, + F: sweepNetworkAcls, }) } @@ -21,9 +22,9 @@ func TestAccNetworkAclAssociation_basic(t *testing.T) { //lintignore:XAT001 resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { acctest.PreCheck(t) }, IDRefreshName: resourceName, - Providers: testAccProviders, + Providers: acctest.Providers, CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { From 9bfc3e1b7c811eae1c99b9a47709d0f2509366ea Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 13:07:08 -0500 Subject: [PATCH 23/67] removed test init --- internal/service/ec2/network_acl_association_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 57c806497556..a98588e3f40e 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -8,13 +8,6 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" ) -func init() { - resource.AddTestSweepers("aws_network_acl_association", &resource.Sweeper{ - Name: "aws_network_acl_association", - F: sweepNetworkAcls, - }) -} - func TestAccNetworkAclAssociation_basic(t *testing.T) { var networkAcl ec2.NetworkAcl From c2f1ba71d1462b2313fd70237bac8fc1ec4b712b Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 13:40:19 -0500 Subject: [PATCH 24/67] updated test --- internal/provider/provider.go | 2 +- internal/service/ec2/network_acl_association_test.go | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3429d1b78d93..81b23cd25aa6 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1046,7 +1046,7 @@ func Provider() *schema.Provider { "aws_main_route_table_association": ec2.ResourceMainRouteTableAssociation(), "aws_nat_gateway": ec2.ResourceNatGateway(), "aws_network_acl": ec2.ResourceNetworkACL(), - "aws_network_acl_association": ec2.ResourceNetworkAclAssociation(), + "aws_network_acl_association": ec2.ResourceNetworkAclAssociation(), "aws_network_acl_rule": ec2.ResourceNetworkACLRule(), "aws_network_interface": ec2.ResourceNetworkInterface(), "aws_network_interface_attachment": ec2.ResourceNetworkInterfaceAttachment(), diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index a98588e3f40e..5f9cb48f560b 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -15,10 +15,9 @@ func TestAccNetworkAclAssociation_basic(t *testing.T) { //lintignore:XAT001 resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - IDRefreshName: resourceName, - Providers: acctest.Providers, - CheckDestroy: testAccCheckNetworkACLDestroy, + PreCheck: func() { acctest.PreCheck(t) }, + Providers: acctest.Providers, + CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { Config: testAccNetworkAclAssoc, @@ -27,6 +26,11 @@ func TestAccNetworkAclAssociation_basic(t *testing.T) { testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.subnet_a"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } From 292a36ddb93b85922855c5e33462703a1550e3d5 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 14:11:24 -0500 Subject: [PATCH 25/67] removed nolint comments --- internal/service/ec2/network_acl_association.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 7b467d3774b9..8435cbeb670e 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -75,14 +75,12 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) if tfresource.NotFound(err) { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } if awsErr, ok := err.(awserr.Error); ok { if awsErr != nil { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } } From 7f23ede2bf993af2bfeba37bda036948fc912dc4 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 14:39:37 -0500 Subject: [PATCH 26/67] fixing lint errors --- internal/service/ec2/network_acl_association.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 8435cbeb670e..5d58262b3212 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -75,12 +75,14 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) if tfresource.NotFound(err) { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") + //nolint:ignore,nolintlint nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } if awsErr, ok := err.(awserr.Error); ok { if awsErr != nil { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") + //nolint:ignore,nolintlint nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } } From 0abb17b32c00cbce2d70119065f15e62e675df50 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 15:51:25 -0500 Subject: [PATCH 27/67] trying to fix lint error --- internal/service/ec2/network_acl_association.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 5d58262b3212..d6b5920044ba 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -75,14 +75,14 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) if tfresource.NotFound(err) { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - //nolint:ignore,nolintlint nilerr // subnet likely doesn't exist so there is nothing more that we can do + //nolint:ignore nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } if awsErr, ok := err.(awserr.Error); ok { if awsErr != nil { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - //nolint:ignore,nolintlint nilerr // subnet likely doesn't exist so there is nothing more that we can do + //nolint:ignore nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } } From 0ef5b02e40ad7796ba6f97d902d05d079b46d204 Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Mon, 25 Oct 2021 16:27:10 -0500 Subject: [PATCH 28/67] linting --- internal/service/ec2/network_acl_association.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index d6b5920044ba..7b467d3774b9 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -75,14 +75,14 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) if tfresource.NotFound(err) { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - //nolint:ignore nilerr // subnet likely doesn't exist so there is nothing more that we can do + //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } if awsErr, ok := err.(awserr.Error); ok { if awsErr != nil { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - //nolint:ignore nilerr // subnet likely doesn't exist so there is nothing more that we can do + //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } } From c8f0b22f9ae13e3a769abb48186a250d1ed94b6b Mon Sep 17 00:00:00 2001 From: Geoff Lancaster Date: Tue, 26 Oct 2021 09:51:00 -0500 Subject: [PATCH 29/67] lint --- internal/service/ec2/network_acl_association.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 7b467d3774b9..93c06a1406f6 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -75,7 +75,6 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) if tfresource.NotFound(err) { log.Printf("[WARN] Unable to find association for subnet %s", subnetId) d.SetId("") - //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do return nil } if awsErr, ok := err.(awserr.Error); ok { From 0ddc84aab4f718b5bac283fcf6b20f7084b6b4f5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 3 Feb 2022 17:09:03 -0500 Subject: [PATCH 30/67] r/aws_network_acl_association: Tweak function names. --- internal/provider/provider.go | 2 +- .../service/ec2/network_acl_association.go | 21 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index ff3ca974dcd1..4e41958c3995 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1177,7 +1177,7 @@ func Provider() *schema.Provider { "aws_main_route_table_association": ec2.ResourceMainRouteTableAssociation(), "aws_nat_gateway": ec2.ResourceNATGateway(), "aws_network_acl": ec2.ResourceNetworkACL(), - "aws_network_acl_association": ec2.ResourceNetworkAclAssociation(), + "aws_network_acl_association": ec2.ResourceNetworkACLAssociation(), "aws_network_acl_rule": ec2.ResourceNetworkACLRule(), "aws_network_interface": ec2.ResourceNetworkInterface(), "aws_network_interface_attachment": ec2.ResourceNetworkInterfaceAttachment(), diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 93c06a1406f6..2086a7446693 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -14,20 +14,19 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -func ResourceNetworkAclAssociation() *schema.Resource { +func ResourceNetworkACLAssociation() *schema.Resource { return &schema.Resource{ - Create: ResourceNetworkAclAssociationCreate, - Read: ResourceNetworkAclAssociationRead, - Delete: ResourceNetworkAclAssociationDelete, + Create: resourceNetworkACLAssociationCreate, + Read: resourceNetworkACLAssociationRead, + Delete: resourceNetworkACLAssociationDelete, Schema: map[string]*schema.Schema{ - "subnet_id": { + "network_acl_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, - - "network_acl_id": { + "subnet_id": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -36,7 +35,7 @@ func ResourceNetworkAclAssociation() *schema.Resource { } } -func ResourceNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{}) error { +func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn naclId := d.Get("network_acl_id").(string) @@ -62,10 +61,10 @@ func ResourceNetworkAclAssociationCreate(d *schema.ResourceData, meta interface{ d.SetId(aws.StringValue(associationId)) log.Printf("[INFO] New Association ID: %s", d.Id()) - return ResourceNetworkAclAssociationRead(d, meta) + return resourceNetworkACLAssociationRead(d, meta) } -func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) error { +func resourceNetworkACLAssociationRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn // Inspect that the association exists @@ -93,7 +92,7 @@ func ResourceNetworkAclAssociationRead(d *schema.ResourceData, meta interface{}) return nil } -func ResourceNetworkAclAssociationDelete(d *schema.ResourceData, meta interface{}) error { +func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn subnetId := d.Get("subnet_id").(string) From 64c0324e314351bc80457422cb6e2978918aaf51 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 3 Feb 2022 17:14:00 -0500 Subject: [PATCH 31/67] Additional TODO. --- internal/service/ec2/find.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index 7c5ecde82f07..cd5e3e343d54 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -811,6 +811,8 @@ func FindNetworkACLEntry(conn *ec2.EC2, networkAclID string, egress bool, ruleNu } return nil, nil + + // TODO: Layer on top of FindNetworkACL and modify callers to handle NotFoundError. } func FindNetworkInterface(conn *ec2.EC2, input *ec2.DescribeNetworkInterfacesInput) (*ec2.NetworkInterface, error) { From 00dd498dc272e9f2c0dd1b1f13a5888793c09d31 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 3 Feb 2022 17:44:58 -0500 Subject: [PATCH 32/67] r/aws_network_acl_association: Tidy up. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_basic --- PASS: TestAccEC2NetworkACLAssociation_basic (36.75s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 43.628s --- internal/service/ec2/find.go | 44 +++++++ .../service/ec2/network_acl_association.go | 123 ++++++------------ .../ec2/network_acl_association_test.go | 9 +- 3 files changed, 89 insertions(+), 87 deletions(-) diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index cd5e3e343d54..77f5469b2478 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -762,6 +762,50 @@ func FindNetworkACLByID(conn *ec2.EC2, id string) (*ec2.NetworkAcl, error) { // TODO: Layer on top of FindNetworkACL and modify callers to handle NotFoundError. } +func FindNetworkACLAssociationByID(conn *ec2.EC2, associationID string) (*ec2.NetworkAclAssociation, error) { + input := &ec2.DescribeNetworkAclsInput{ + Filters: BuildAttributeFilterList(map[string]string{ + "association.association-id": associationID, + }), + } + + output, err := FindNetworkACL(conn, input) + + if err != nil { + return nil, err + } + + for _, v := range output.Associations { + if aws.StringValue(v.NetworkAclAssociationId) == associationID { + return v, nil + } + } + + return nil, &resource.NotFoundError{} +} + +func FindNetworkACLAssociationBySubnetID(conn *ec2.EC2, subnetID string) (*ec2.NetworkAclAssociation, error) { + input := &ec2.DescribeNetworkAclsInput{ + Filters: BuildAttributeFilterList(map[string]string{ + "association.subnet-id": subnetID, + }), + } + + output, err := FindNetworkACL(conn, input) + + if err != nil { + return nil, err + } + + for _, v := range output.Associations { + if aws.StringValue(v.SubnetId) == subnetID { + return v, nil + } + } + + return nil, &resource.NotFoundError{} +} + // FindNetworkACLEntry looks up a FindNetworkACLEntry by Network ACL ID, Egress, and Rule Number. When not found, returns nil and potentially an API error. func FindNetworkACLEntry(conn *ec2.EC2, networkAclID string, egress bool, ruleNumber int) (*ec2.NetworkAclEntry, error) { input := &ec2.DescribeNetworkAclsInput{ diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 2086a7446693..cb05fec9c9de 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -3,12 +3,9 @@ package ec2 import ( "fmt" "log" - "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -19,6 +16,9 @@ func ResourceNetworkACLAssociation() *schema.Resource { Create: resourceNetworkACLAssociationCreate, Read: resourceNetworkACLAssociationRead, Delete: resourceNetworkACLAssociationDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "network_acl_id": { @@ -38,28 +38,27 @@ func ResourceNetworkACLAssociation() *schema.Resource { func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - naclId := d.Get("network_acl_id").(string) - subnetId := d.Get("subnet_id").(string) + subnetID := d.Get("subnet_id").(string) + + association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) - association, errAssociation := findNetworkAclAssociation(subnetId, conn) - if errAssociation != nil { - return fmt.Errorf("Failed to find association for subnet %s: %s", subnetId, errAssociation) + if err != nil { + return fmt.Errorf("error reading Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) } - associationOpts := &ec2.ReplaceNetworkAclAssociationInput{ + input := &ec2.ReplaceNetworkAclAssociationInput{ AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(naclId), + NetworkAclId: aws.String(d.Get("network_acl_id").(string)), } - log.Printf("[DEBUG] Creating Network ACL association: %#v", associationOpts) - resp, err := conn.ReplaceNetworkAclAssociation(associationOpts) + log.Printf("[DEBUG] Creating Network ACL Association: %s", input) + output, err := conn.ReplaceNetworkAclAssociation(input) + if err != nil { - return fmt.Errorf("Error creating network acl association: %w", err) + return fmt.Errorf("error creating Network ACL Association: %w", err) } - associationId := resp.NewAssociationId - d.SetId(aws.StringValue(associationId)) - log.Printf("[INFO] New Association ID: %s", d.Id()) + d.SetId(aws.StringValue(output.NewAssociationId)) return resourceNetworkACLAssociationRead(d, meta) } @@ -67,27 +66,20 @@ func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{ func resourceNetworkACLAssociationRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - // Inspect that the association exists - subnetId := d.Get("subnet_id").(string) - association, err := findNetworkAclAssociation(subnetId, conn) + association, err := FindNetworkACLAssociationByID(conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Network ACL Association (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + if err != nil { - if tfresource.NotFound(err) { - log.Printf("[WARN] Unable to find association for subnet %s", subnetId) - d.SetId("") - return nil - } - if awsErr, ok := err.(awserr.Error); ok { - if awsErr != nil { - log.Printf("[WARN] Unable to find association for subnet %s", subnetId) - d.SetId("") - //nolint:nilerr // subnet likely doesn't exist so there is nothing more that we can do - return nil - } - } - return err + return fmt.Errorf("error reading Network ACL Association (%s): %w", d.Id(), err) } - d.Set("network_acl_id", aws.StringValue(association.NetworkAclId)) + d.Set("network_acl_id", association.NetworkAclId) + d.Set("subnet_id", association.SubnetId) return nil } @@ -95,66 +87,33 @@ func resourceNetworkACLAssociationRead(d *schema.ResourceData, meta interface{}) func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - subnetId := d.Get("subnet_id").(string) - - req := &ec2.DescribeNetworkAclsInput{} - req.Filters = BuildAttributeFilterList( - map[string]string{ - "association.subnet-id": subnetId, - }, - ) - - resp, err := conn.DescribeNetworkAcls(req) - if err != nil { - return err + input := &ec2.DescribeNetworkAclsInput{ + Filters: BuildAttributeFilterList(map[string]string{ + "association.association-id": d.Id(), + }), } - if len(resp.NetworkAcls) == 0 { - return fmt.Errorf("Unable to find Network ACL for subnet: %s", subnetId) - } + nacl, err := FindNetworkACL(conn, input) - nacl := resp.NetworkAcls[0] - var association *ec2.NetworkAclAssociation - if len(resp.NetworkAcls) > 0 { - for _, assoc := range nacl.Associations { - if aws.StringValue(assoc.SubnetId) == subnetId { - association = assoc - } - } + if err != nil { + return fmt.Errorf("error reading Network ACL for Association (%s): %w", d.Id(), err) } - defaultAcl, err := GetDefaultNetworkACL(*nacl.VpcId, conn) + vpcID := aws.StringValue(nacl.VpcId) + defaultNACL, err := FindVPCDefaultNetworkACL(conn, vpcID) if err != nil { - return fmt.Errorf("Failed to get default Network Acl : %s", err) - } - - associationOpts := ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: defaultAcl.NetworkAclId, + return fmt.Errorf("error reading EC2 VPC (%s) default NACL: %w", vpcID, err) } - log.Printf("[DEBUG] Replacing Network ACL association: %#v", associationOpts) - - err = resource.Retry(5*time.Minute, func() *resource.RetryError { - _, err = conn.ReplaceNetworkAclAssociation(&associationOpts) - if err != nil { - if awsErr, ok := err.(awserr.Error); ok { - if awsErr != nil { - return resource.RetryableError(awsErr) - } - } - return resource.NonRetryableError(err) - } - return nil + _, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: aws.String(d.Id()), + NetworkAclId: defaultNACL.NetworkAclId, }) - if tfresource.TimedOut(err) { - _, err = conn.ReplaceNetworkAclAssociation(&associationOpts) - } + if err != nil { - return err + return fmt.Errorf("error deleting Network ACL Association (%s): %w", d.Id(), err) } - d.SetId("") return nil } diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 5f9cb48f560b..1c19aac221ae 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -8,19 +8,18 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" ) -func TestAccNetworkAclAssociation_basic(t *testing.T) { - +func TestAccEC2NetworkACLAssociation_basic(t *testing.T) { var networkAcl ec2.NetworkAcl resourceName := "aws_network_acl.acl_a" - //lintignore:XAT001 resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), Providers: acctest.Providers, CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkAclAssoc, + Config: testAccNetworkACLAssociationConfig, Check: resource.ComposeAggregateTestCheckFunc( testAccCheckNetworkACLExists(resourceName, &networkAcl), testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.subnet_a"), @@ -35,7 +34,7 @@ func TestAccNetworkAclAssociation_basic(t *testing.T) { }) } -const testAccNetworkAclAssoc = ` +const testAccNetworkACLAssociationConfig = ` resource "aws_vpc" "test_vpc" { cidr_block = "10.1.0.0/16" tags = { From 0c0127c19bf452c0809e3d5ea16aa7819dd87112 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 09:44:31 -0500 Subject: [PATCH 33/67] r/aws_network_acl_association: Start improvement of acceptance tests. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_basic --- PASS: TestAccEC2NetworkACLAssociation_basic (34.96s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 38.706s --- .../ec2/network_acl_association_test.go | 154 ++++++++++++++++-- 1 file changed, 136 insertions(+), 18 deletions(-) diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 1c19aac221ae..986da2ee7fb0 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -1,28 +1,38 @@ package ec2_test import ( + "fmt" "testing" "github.com/aws/aws-sdk-go/service/ec2" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func TestAccEC2NetworkACLAssociation_basic(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_network_acl.acl_a" + var v ec2.NetworkAclAssociation + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_network_acl_association.test" + naclResourceName := "aws_network_acl.test" + subnetResourceName := "aws_subnet.test" resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), Providers: acctest.Providers, - CheckDestroy: testAccCheckNetworkACLDestroy, + CheckDestroy: testAccCheckNetworkACLAssociationDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLAssociationConfig, + Config: testAccNetworkACLAssociationConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.subnet_a"), + testAccCheckNetworkACLAssociationExists(resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, "network_acl_id", naclResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "subnet_id", subnetResourceName, "id"), ), }, { @@ -34,28 +44,136 @@ func TestAccEC2NetworkACLAssociation_basic(t *testing.T) { }) } -const testAccNetworkACLAssociationConfig = ` -resource "aws_vpc" "test_vpc" { +func testAccCheckNetworkACLAssociationDestroy(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_network_acl_association" { + continue + } + + _, err := tfec2.FindNetworkACLAssociationByID(conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("Network ACL Association %s still exists", rs.Primary.ID) + } + + return nil +} + +func testAccCheckNetworkACLAssociationExists(n string, v *ec2.NetworkAclAssociation) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No Network ACL Association ID is set") + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn + + output, err := tfec2.FindNetworkACLAssociationByID(conn, rs.Primary.ID) + + if err != nil { + return err + } + + *v = *output + + return nil + } +} + +func testAccNetworkACLAssociationConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" + tags = { - Name = "testAccAWSNetworkAclEsp" + Name = %[1]q } } -resource "aws_network_acl" "acl_a" { - vpc_id = aws_vpc.test_vpc.id + +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id + tags = { - Name = "terraform test" + Name = %[1]q } } -resource "aws_subnet" "subnet_a" { - vpc_id = aws_vpc.test_vpc.id + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "10.1.33.0/24" + tags = { - Name = "terraform test" + Name = %[1]q } } + resource "aws_network_acl_association" "test" { - network_acl_id = aws_network_acl.acl_a.id - subnet_id = aws_subnet.subnet_a.id + network_acl_id = aws_network_acl.test.id + subnet_id = aws_subnet.test.id +} +`, rName) +} + +func testAccNetworkACLAssociationTwoAssociationsConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test1" { + vpc_id = aws_vpc.test.id + + cidr_block = "10.1.33.0/24" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test2" { + vpc_id = aws_vpc.test.id + + cidr_block = "10.1.34.0/24" + + tags = { + Name = %[1]q + } +} + +resource "aws_network_acl_association" "test1" { + network_acl_id = aws_network_acl.test.id + subnet_id = aws_subnet.test1.id +} + +resource "aws_network_acl_association" "test2" { + network_acl_id = aws_network_acl.test.id + subnet_id = aws_subnet.test2.id +} +`, rName) } -` From 57ab970b640827862ea1ed47d6d3ab3aaa33371d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 09:55:39 -0500 Subject: [PATCH 34/67] r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_disappears'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_basic --- PASS: TestAccEC2NetworkACLAssociation_basic (35.16s) === RUN TestAccEC2NetworkACLAssociation_disappears --- PASS: TestAccEC2NetworkACLAssociation_disappears (28.86s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 67.928s --- .../ec2/network_acl_association_test.go | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 986da2ee7fb0..4ae0ba540f04 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -44,6 +44,29 @@ func TestAccEC2NetworkACLAssociation_basic(t *testing.T) { }) } +func TestAccEC2NetworkACLAssociation_disappears(t *testing.T) { + var v ec2.NetworkAclAssociation + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_network_acl_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckNetworkACLAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccNetworkACLAssociationConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLAssociationExists(resourceName, &v), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACLAssociation(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckNetworkACLAssociationDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn From a634db2093b46f13ad78f5eae34fc8686bc73e22 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 10:33:13 -0500 Subject: [PATCH 35/67] r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_twoAssociations'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_basic === PAUSE TestAccEC2NetworkACLAssociation_basic === RUN TestAccEC2NetworkACLAssociation_disappears === PAUSE TestAccEC2NetworkACLAssociation_disappears === RUN TestAccEC2NetworkACLAssociation_twoAssociations === PAUSE TestAccEC2NetworkACLAssociation_twoAssociations === CONT TestAccEC2NetworkACLAssociation_basic === CONT TestAccEC2NetworkACLAssociation_twoAssociations === CONT TestAccEC2NetworkACLAssociation_disappears --- PASS: TestAccEC2NetworkACLAssociation_disappears (36.54s) --- PASS: TestAccEC2NetworkACLAssociation_basic (40.31s) --- PASS: TestAccEC2NetworkACLAssociation_twoAssociations (44.56s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 53.139s --- .../ec2/network_acl_association_test.go | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 4ae0ba540f04..dde775b7b147 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -21,7 +21,7 @@ func TestAccEC2NetworkACLAssociation_basic(t *testing.T) { naclResourceName := "aws_network_acl.test" subnetResourceName := "aws_subnet.test" - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), Providers: acctest.Providers, @@ -49,7 +49,7 @@ func TestAccEC2NetworkACLAssociation_disappears(t *testing.T) { rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_network_acl_association.test" - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), Providers: acctest.Providers, @@ -67,6 +67,46 @@ func TestAccEC2NetworkACLAssociation_disappears(t *testing.T) { }) } +func TestAccEC2NetworkACLAssociation_twoAssociations(t *testing.T) { + var v1, v2 ec2.NetworkAclAssociation + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resource1Name := "aws_network_acl_association.test1" + resource2Name := "aws_network_acl_association.test2" + naclResourceName := "aws_network_acl.test" + subnet1ResourceName := "aws_subnet.test1" + subnet2ResourceName := "aws_subnet.test2" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckNetworkACLAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccNetworkACLAssociationTwoAssociationsConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLAssociationExists(resource1Name, &v1), + testAccCheckNetworkACLAssociationExists(resource1Name, &v2), + resource.TestCheckResourceAttrPair(resource1Name, "network_acl_id", naclResourceName, "id"), + resource.TestCheckResourceAttrPair(resource1Name, "subnet_id", subnet1ResourceName, "id"), + resource.TestCheckResourceAttrPair(resource2Name, "network_acl_id", naclResourceName, "id"), + resource.TestCheckResourceAttrPair(resource2Name, "subnet_id", subnet2ResourceName, "id"), + ), + }, + { + ResourceName: resource1Name, + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: resource2Name, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckNetworkACLAssociationDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn From 05999600d2c5b9b24a6c7e65301c5ee5b00be79f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 11:00:47 -0500 Subject: [PATCH 36/67] r/aws_network_acl: Alphabetize attributes. --- internal/service/ec2/network_acl.go | 188 ++++++++++------------------ 1 file changed, 64 insertions(+), 124 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 6a65d6c7589a..33afdd417d77 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -24,6 +24,62 @@ import ( ) func ResourceNetworkACL() *schema.Resource { + networkACLRuleSetSchema := &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + ConfigMode: schema.SchemaConfigModeAttr, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return strings.EqualFold(old, new) + }, + ValidateFunc: validation.StringInSlice(ec2.RuleAction_Values(), true), + }, + "cidr_block": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, + }, + "from_port": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IsPortNumberOrZero, + }, + "icmp_code": { + Type: schema.TypeInt, + Optional: true, + }, + "icmp_type": { + Type: schema.TypeInt, + Optional: true, + }, + "ipv6_cidr_block": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidIPv6CIDRNetworkAddress, + }, + "protocol": { + Type: schema.TypeString, + Required: true, + }, + "rule_no": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, 32766), + }, + "to_port": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IsPortNumberOrZero, + }, + }, + }, + Set: resourceNetworkACLEntryHash, + } return &schema.Resource{ Create: resourceNetworkACLCreate, @@ -39,10 +95,11 @@ func ResourceNetworkACL() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "vpc_id": { + "egress": networkACLRuleSetSchema, + "ingress": networkACLRuleSetSchema, + "owner_id": { Type: schema.TypeString, - Required: true, - ForceNew: true, + Computed: true, }, "subnet_ids": { Type: schema.TypeSet, @@ -50,130 +107,13 @@ func ResourceNetworkACL() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - "ingress": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - ConfigMode: schema.SchemaConfigModeAttr, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "from_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "to_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "rule_no": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 32766), - }, - "action": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - ValidateFunc: validation.StringInSlice([]string{ - ec2.RuleActionAllow, - ec2.RuleActionDeny, - }, true), - }, - "protocol": { - Type: schema.TypeString, - Required: true, - }, - "cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "ipv6_cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "icmp_type": { - Type: schema.TypeInt, - Optional: true, - }, - "icmp_code": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, - Set: resourceNetworkACLEntryHash, - }, - "egress": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - ConfigMode: schema.SchemaConfigModeAttr, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "from_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "to_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "rule_no": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 32766), - }, - "action": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - ValidateFunc: validation.StringInSlice([]string{ - ec2.RuleActionAllow, - ec2.RuleActionDeny, - }, true), - }, - "protocol": { - Type: schema.TypeString, - Required: true, - }, - "cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "ipv6_cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "icmp_type": { - Type: schema.TypeInt, - Optional: true, - }, - "icmp_code": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, - Set: resourceNetworkACLEntryHash, + "vpc_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, }, "tags": tftags.TagsSchema(), "tags_all": tftags.TagsSchemaComputed(), - "owner_id": { - Type: schema.TypeString, - Computed: true, - }, }, CustomizeDiff: verify.SetTagsDiff, From 711e7d2f46edd3b0f67f3be69b8eb2e5bdfeffb5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 11:23:16 -0500 Subject: [PATCH 37/67] r/aws_network_acl: Start to tidy up resource Create and Delete. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_tags === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_egressAndIngressRules === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges === CONT TestAccEC2NetworkACL_OnlyIngressRules_update --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (47.33s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_onlyEgressRules (47.40s) === CONT TestAccEC2NetworkACL_ipv6VPCRules --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (54.37s) === CONT TestAccEC2NetworkACL_espProtocol --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (80.95s) === CONT TestAccEC2NetworkACL_subnets --- PASS: TestAccEC2NetworkACL_tags (81.36s) === CONT TestAccEC2NetworkACL_subnetsDelete --- PASS: TestAccEC2NetworkACL_espProtocol (31.07s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (43.53s) === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (51.09s) === CONT TestAccEC2NetworkACL_subnetChange --- PASS: TestAccEC2NetworkACL_subnetsDelete (67.72s) === CONT TestAccEC2NetworkACL_ipv6Rules --- PASS: TestAccEC2NetworkACL_subnets (74.09s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_Egress_mode (84.18s) === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_Ingress_mode (85.73s) === CONT TestAccEC2NetworkACL_basic --- PASS: TestAccEC2NetworkACL_subnetChange (78.56s) --- PASS: TestAccEC2NetworkACL_disappears (41.75s) --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (30.58s) --- PASS: TestAccEC2NetworkACL_ipv6Rules (53.20s) --- PASS: TestAccEC2NetworkACL_basic (43.81s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 226.896s --- internal/service/ec2/network_acl.go | 102 ++++++++++++---------------- internal/service/ec2/wait.go | 2 + 2 files changed, 44 insertions(+), 60 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 33afdd417d77..33530066b197 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -6,7 +6,6 @@ import ( "log" "strconv" "strings" - "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" @@ -84,8 +83,8 @@ func ResourceNetworkACL() *schema.Resource { return &schema.Resource{ Create: resourceNetworkACLCreate, Read: resourceNetworkACLRead, - Delete: resourceNetworkACLDelete, Update: resourceNetworkACLUpdate, + Delete: resourceNetworkACLDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -121,29 +120,23 @@ func ResourceNetworkACL() *schema.Resource { } func resourceNetworkACLCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*conns.AWSClient).EC2Conn defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))) - // Create the Network Acl - createOpts := &ec2.CreateNetworkAclInput{ - VpcId: aws.String(d.Get("vpc_id").(string)), + input := &ec2.CreateNetworkAclInput{ TagSpecifications: ec2TagSpecificationsFromKeyValueTags(tags, ec2.ResourceTypeNetworkAcl), + VpcId: aws.String(d.Get("vpc_id").(string)), } - log.Printf("[DEBUG] Network Acl create config: %#v", createOpts) - resp, err := conn.CreateNetworkAcl(createOpts) + log.Printf("[DEBUG] Creating EC2 Network ACL: %s", input) + output, err := conn.CreateNetworkAcl(input) if err != nil { return fmt.Errorf("error creating EC2 Network ACL: %w", err) } - if resp == nil || resp.NetworkAcl == nil { - return fmt.Errorf("error creating EC2 Network ACL: empty response") - } - - d.SetId(aws.StringValue(resp.NetworkAcl.NetworkAclId)) + d.SetId(aws.StringValue(output.NetworkAcl.NetworkAclId)) if v, ok := d.GetOk("egress"); ok && v.(*schema.Set).Len() > 0 { err := updateNetworkAclEntries(d, "egress", conn) @@ -401,6 +394,42 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { return resourceNetworkACLRead(d, meta) } +func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).EC2Conn + + input := &ec2.DeleteNetworkAclInput{ + NetworkAclId: aws.String(d.Id()), + } + + log.Printf("[INFO] Deleting EC2 Network ACL: %s", d.Id()) + _, err := tfresource.RetryWhen(NetworkACLDeletedTimeout, + func() (interface{}, error) { + return conn.DeleteNetworkAcl(input) + }, + func(err error) (bool, error) { + if tfawserr.ErrCodeEquals(err, ErrCodeDependencyViolation) { + if err := cleanUpDependencyViolations(d, conn); err != nil { + return false, err + } + + return true, err + } + + return false, err + }, + ) + + if tfawserr.ErrCodeEquals(err, ErrCodeInvalidNetworkAclIDNotFound) { + return nil + } + + if err != nil { + return fmt.Errorf("error deleting EC2 Network ACL (%s): %w", d.Id(), err) + } + + return nil +} + func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2.EC2) error { if d.HasChange(entryType) { o, n := d.GetChange(entryType) @@ -507,53 +536,6 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2 return nil } -func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*conns.AWSClient).EC2Conn - - log.Printf("[INFO] Deleting Network Acl: %s", d.Id()) - input := &ec2.DeleteNetworkAclInput{ - NetworkAclId: aws.String(d.Id()), - } - err := resource.Retry(5*time.Minute, func() *resource.RetryError { - _, err := conn.DeleteNetworkAcl(input) - if err != nil { - if tfawserr.ErrMessageContains(err, "InvalidNetworkAclID.NotFound", "") { - return nil - } - if tfawserr.ErrMessageContains(err, "DependencyViolation", "") { - err = cleanUpDependencyViolations(d, conn) - if err != nil { - return resource.NonRetryableError(err) - } - return resource.RetryableError(fmt.Errorf("Dependencies found and cleaned up, retrying")) - } - - return resource.NonRetryableError(err) - - } - log.Printf("[Info] Deleted network ACL %s successfully", d.Id()) - return nil - }) - if tfresource.TimedOut(err) { - _, err = conn.DeleteNetworkAcl(input) - if err != nil && tfawserr.ErrMessageContains(err, "InvalidNetworkAclID.NotFound", "") { - return nil - } - err = cleanUpDependencyViolations(d, conn) - if err != nil { - // This seems excessive but is probably the best way to make sure it's actually deleted - _, err = conn.DeleteNetworkAcl(input) - if err != nil && tfawserr.ErrMessageContains(err, "InvalidNetworkAclID.NotFound", "") { - return nil - } - } - } - if err != nil { - return fmt.Errorf("Error destroying Network ACL (%s): %s", d.Id(), err) - } - return nil -} - func cleanUpDependencyViolations(d *schema.ResourceData, conn *ec2.EC2) error { // In case of dependency violation, we remove the association between subnet and network acl. // This means the subnet is attached to default acl of vpc. diff --git a/internal/service/ec2/wait.go b/internal/service/ec2/wait.go index e09605eb183e..1d09314bf10b 100644 --- a/internal/service/ec2/wait.go +++ b/internal/service/ec2/wait.go @@ -291,6 +291,8 @@ func WaitInstanceIAMInstanceProfileUpdated(conn *ec2.EC2, instanceID string, exp const ManagedPrefixListEntryCreateTimeout = 5 * time.Minute const ( + NetworkACLDeletedTimeout = 5 * time.Minute + NetworkACLPropagationTimeout = 2 * time.Minute NetworkACLEntryPropagationTimeout = 5 * time.Minute ) From 3c10b43aa0ee7dcfb64ef4abe82a5c7ebda1490e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 11:25:20 -0500 Subject: [PATCH 38/67] 'Network ACL Association' -> 'EC2 Network ACL Association'. --- internal/service/ec2/network_acl_association.go | 14 +++++++------- .../service/ec2/network_acl_association_test.go | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index cb05fec9c9de..e7d21045f1f6 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -43,7 +43,7 @@ func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{ association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) if err != nil { - return fmt.Errorf("error reading Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) + return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) } input := &ec2.ReplaceNetworkAclAssociationInput{ @@ -51,11 +51,11 @@ func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{ NetworkAclId: aws.String(d.Get("network_acl_id").(string)), } - log.Printf("[DEBUG] Creating Network ACL Association: %s", input) + log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) output, err := conn.ReplaceNetworkAclAssociation(input) if err != nil { - return fmt.Errorf("error creating Network ACL Association: %w", err) + return fmt.Errorf("error creating EC2 Network ACL Association: %w", err) } d.SetId(aws.StringValue(output.NewAssociationId)) @@ -69,13 +69,13 @@ func resourceNetworkACLAssociationRead(d *schema.ResourceData, meta interface{}) association, err := FindNetworkACLAssociationByID(conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { - log.Printf("[WARN] Network ACL Association (%s) not found, removing from state", d.Id()) + log.Printf("[WARN] EC2 Network ACL Association (%s) not found, removing from state", d.Id()) d.SetId("") return nil } if err != nil { - return fmt.Errorf("error reading Network ACL Association (%s): %w", d.Id(), err) + return fmt.Errorf("error reading EC2 Network ACL Association (%s): %w", d.Id(), err) } d.Set("network_acl_id", association.NetworkAclId) @@ -96,7 +96,7 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ nacl, err := FindNetworkACL(conn, input) if err != nil { - return fmt.Errorf("error reading Network ACL for Association (%s): %w", d.Id(), err) + return fmt.Errorf("error reading EC2 Network ACL for Association (%s): %w", d.Id(), err) } vpcID := aws.StringValue(nacl.VpcId) @@ -112,7 +112,7 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ }) if err != nil { - return fmt.Errorf("error deleting Network ACL Association (%s): %w", d.Id(), err) + return fmt.Errorf("error deleting EC2 Network ACL Association (%s): %w", d.Id(), err) } return nil diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index dde775b7b147..040caa2d8f4f 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -125,7 +125,7 @@ func testAccCheckNetworkACLAssociationDestroy(s *terraform.State) error { return err } - return fmt.Errorf("Network ACL Association %s still exists", rs.Primary.ID) + return fmt.Errorf("EC2 Network ACL Association %s still exists", rs.Primary.ID) } return nil @@ -139,7 +139,7 @@ func testAccCheckNetworkACLAssociationExists(n string, v *ec2.NetworkAclAssociat } if rs.Primary.ID == "" { - return fmt.Errorf("No Network ACL Association ID is set") + return fmt.Errorf("No EC2 Network ACL Association ID is set") } conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn From df6e264256c81e45a57817bc1c2472d31ab025d3 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 13:09:26 -0500 Subject: [PATCH 39/67] r/aws_network_acl: Tidy up resource Read. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_ipv6VPCRules === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (33.06s) === CONT TestAccEC2NetworkACL_ipv6Rules --- PASS: TestAccEC2NetworkACL_espProtocol (36.58s) === CONT TestAccEC2NetworkACL_subnetsDelete --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (49.92s) === CONT TestAccEC2NetworkACL_subnets --- PASS: TestAccEC2NetworkACL_onlyEgressRules (50.47s) === CONT TestAccEC2NetworkACL_subnetChange === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_basic (50.53s) --- PASS: TestAccEC2NetworkACL_ipv6Rules (50.79s) === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges --- PASS: TestAccEC2NetworkACL_subnetsDelete (71.50s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_update === CONT TestAccEC2NetworkACL_subnetChange network_acl_test.go:407: Step 3/3 error: Error running apply: exit status 1 Error: InvalidAssociationID.NotFound: The association ID 'aclassoc-065bf85a9bbddb537' does not exist status code: 400, request id: e4525095-c696-4054-8b2f-bcb054b8f517 with aws_network_acl.test, on terraform_plugin_test.tf line 30, in resource "aws_network_acl" "test": 30: resource "aws_network_acl" "test" { --- FAIL: TestAccEC2NetworkACL_subnetChange (63.72s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_subnets (74.38s) === CONT TestAccEC2NetworkACL_egressAndIngressRules --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (49.76s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_Ingress_mode (85.39s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (50.80s) === CONT TestAccEC2NetworkACL_tags --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (46.78s) --- PASS: TestAccEC2NetworkACL_disappears (44.03s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (75.51s) --- PASS: TestAccEC2NetworkACL_Egress_mode (83.47s) --- PASS: TestAccEC2NetworkACL_tags (75.46s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 248.257s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/find.go | 24 +--- internal/service/ec2/network_acl.go | 195 ++++++++++++++-------------- internal/service/ec2/wait.go | 4 +- 3 files changed, 104 insertions(+), 119 deletions(-) diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index 77f5469b2478..aac1cfb25aa0 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -729,37 +729,25 @@ func FindNetworkACLs(conn *ec2.EC2, input *ec2.DescribeNetworkAclsInput) ([]*ec2 return output, nil } -// FindNetworkACLByID looks up a NetworkAcl by ID. When not found, returns nil and potentially an API error. func FindNetworkACLByID(conn *ec2.EC2, id string) (*ec2.NetworkAcl, error) { input := &ec2.DescribeNetworkAclsInput{ NetworkAclIds: aws.StringSlice([]string{id}), } - output, err := conn.DescribeNetworkAcls(input) + output, err := FindNetworkACL(conn, input) if err != nil { return nil, err } - if output == nil { - return nil, nil - } - - for _, networkAcl := range output.NetworkAcls { - if networkAcl == nil { - continue - } - - if aws.StringValue(networkAcl.NetworkAclId) != id { - continue + // Eventual consistency check. + if aws.StringValue(output.NetworkAclId) != id { + return nil, &resource.NotFoundError{ + LastRequest: input, } - - return networkAcl, nil } - return nil, nil - - // TODO: Layer on top of FindNetworkACL and modify callers to handle NotFoundError. + return output, nil } func FindNetworkACLAssociationByID(conn *ec2.EC2, associationID string) (*ec2.NetworkAclAssociation, error) { diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 33530066b197..9a1982a1fe21 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -193,36 +192,12 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig - var networkAcl *ec2.NetworkAcl + outputRaw, err := tfresource.RetryWhenNewResourceNotFound(PropagationTimeout, func() (interface{}, error) { + return FindNetworkACLByID(conn, d.Id()) + }, d.IsNewResource()) - err := resource.Retry(NetworkACLPropagationTimeout, func() *resource.RetryError { - var err error - - networkAcl, err = FindNetworkACLByID(conn, d.Id()) - - if d.IsNewResource() && tfawserr.ErrCodeEquals(err, "InvalidNetworkAclID.NotFound") { - return resource.RetryableError(err) - } - - if err != nil { - return resource.NonRetryableError(err) - } - - if d.IsNewResource() && networkAcl == nil { - return resource.RetryableError(&resource.NotFoundError{ - LastError: fmt.Errorf("EC2 Network ACL (%s) not found", d.Id()), - }) - } - - return nil - }) - - if tfresource.TimedOut(err) { - networkAcl, err = FindNetworkACLByID(conn, d.Id()) - } - - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "InvalidNetworkAclID.NotFound") { - log.Printf("[WARN] EC2 Network ACL (%s) not found, removing from state", d.Id()) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] EC2 Network ACL %s not found, removing from state", d.Id()) d.SetId("") return nil } @@ -231,36 +206,51 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error reading EC2 Network ACL (%s): %w", d.Id(), err) } - if networkAcl == nil { - if d.IsNewResource() { - return fmt.Errorf("error reading EC2 Network ACL (%s): not found after creation", d.Id()) - } + networkAcl := outputRaw.(*ec2.NetworkAcl) - log.Printf("[WARN] EC2 Network ACL (%s) not found, removing from state", d.Id()) - d.SetId("") - return nil + ownerID := aws.StringValue(networkAcl.OwnerId) + arn := arn.ARN{ + Partition: meta.(*conns.AWSClient).Partition, + Service: ec2.ServiceName, + Region: meta.(*conns.AWSClient).Region, + AccountID: ownerID, + Resource: fmt.Sprintf("network-acl/%s", d.Id()), + }.String() + d.Set("arn", arn) + d.Set("owner_id", ownerID) + + var subnetIDs []string + for _, v := range networkAcl.Associations { + subnetIDs = append(subnetIDs, aws.StringValue(v.SubnetId)) } + d.Set("subnet_ids", subnetIDs) + + d.Set("vpc_id", networkAcl.VpcId) - var ingressEntries []*ec2.NetworkAclEntry var egressEntries []*ec2.NetworkAclEntry + var ingressEntries []*ec2.NetworkAclEntry // separate the ingress and egress rules - for _, e := range networkAcl.Entries { + for _, v := range networkAcl.Entries { // Skip the default rules added by AWS. They can be neither // configured or deleted by users. - if aws.Int64Value(e.RuleNumber) == defaultACLRuleNumberIPv4 || - aws.Int64Value(e.RuleNumber) == defaultACLRuleNumberIPv6 { + if v := aws.Int64Value(v.RuleNumber); v == defaultACLRuleNumberIPv4 || v == defaultACLRuleNumberIPv6 { continue } - if aws.BoolValue(e.Egress) { - egressEntries = append(egressEntries, e) + if aws.BoolValue(v.Egress) { + egressEntries = append(egressEntries, v) } else { - ingressEntries = append(ingressEntries, e) + ingressEntries = append(ingressEntries, v) } } - d.Set("vpc_id", networkAcl.VpcId) + if err := d.Set("egress", flattenNetworkAclEntries(egressEntries)); err != nil { + return fmt.Errorf("error setting egress: %w", err) + } + if err := d.Set("ingress", flattenNetworkAclEntries(ingressEntries)); err != nil { + return fmt.Errorf("error setting ingress: %w", err) + } tags := KeyValueTags(networkAcl.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig) @@ -273,33 +263,6 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error setting tags_all: %w", err) } - d.Set("owner_id", networkAcl.OwnerId) - - var subnetIds []*string - for _, a := range networkAcl.Associations { - subnetIds = append(subnetIds, a.SubnetId) - } - if err := d.Set("subnet_ids", flex.FlattenStringSet(subnetIds)); err != nil { - return err - } - - if err := d.Set("ingress", networkAclEntriesToMapList(ingressEntries)); err != nil { - return err - } - if err := d.Set("egress", networkAclEntriesToMapList(egressEntries)); err != nil { - return err - } - - arn := arn.ARN{ - Partition: meta.(*conns.AWSClient).Partition, - Service: ec2.ServiceName, - Region: meta.(*conns.AWSClient).Region, - AccountID: aws.StringValue(networkAcl.OwnerId), - Resource: fmt.Sprintf("network-acl/%s", d.Id()), - }.String() - - d.Set("arn", arn) - return nil } @@ -678,43 +641,79 @@ func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssoci } } -// networkAclEntriesToMapList turns ingress/egress rules read from AWS into a list -// of maps. -func networkAclEntriesToMapList(networkAcls []*ec2.NetworkAclEntry) []map[string]interface{} { - result := make([]map[string]interface{}, 0, len(networkAcls)) - for _, entry := range networkAcls { - acl := make(map[string]interface{}) - acl["rule_no"] = aws.Int64Value(entry.RuleNumber) - acl["action"] = aws.StringValue(entry.RuleAction) - if entry.CidrBlock != nil { - acl["cidr_block"] = aws.StringValue(entry.CidrBlock) +func flattenNetworkAclEntry(apiObject *ec2.NetworkAclEntry) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.RuleNumber; v != nil { + tfMap["rule_no"] = aws.Int64Value(v) + } + + if v := apiObject.RuleAction; v != nil { + tfMap["action"] = aws.StringValue(v) + } + + if v := apiObject.CidrBlock; v != nil { + tfMap["cidr_block"] = aws.StringValue(v) + } + + if v := apiObject.Ipv6CidrBlock; v != nil { + tfMap["ipv6_cidr_block"] = aws.StringValue(v) + } + + if apiObject := apiObject.PortRange; apiObject != nil { + if v := apiObject.From; v != nil { + tfMap["from_port"] = aws.Int64Value(v) } - if entry.Ipv6CidrBlock != nil { - acl["ipv6_cidr_block"] = aws.StringValue(entry.Ipv6CidrBlock) + + if v := apiObject.To; v != nil { + tfMap["to_port"] = aws.Int64Value(v) } + } + + if v := aws.StringValue(apiObject.Protocol); v != "" { // The AWS network ACL API only speaks protocol numbers, and // that's all we record. - if _, err := strconv.Atoi(aws.StringValue(entry.Protocol)); err != nil { + i, err := strconv.Atoi(v) + + if err != nil { // We're a protocol name. Look up the number. - acl["protocol"] = protocolIntegers()[aws.StringValue(entry.Protocol)] - } else { - // We're a protocol number. Pass through. - acl["protocol"] = aws.StringValue(entry.Protocol) + i = protocolIntegers()[v] } - acl["protocol"] = aws.StringValue(entry.Protocol) - if entry.PortRange != nil { - acl["from_port"] = aws.Int64Value(entry.PortRange.From) - acl["to_port"] = aws.Int64Value(entry.PortRange.To) + tfMap["protocol"] = strconv.Itoa(i) + } + + if apiObject := apiObject.IcmpTypeCode; apiObject != nil { + if v := apiObject.Code; v != nil { + tfMap["icmp_code"] = aws.Int64Value(v) } - if entry.IcmpTypeCode != nil { - acl["icmp_type"] = aws.Int64Value(entry.IcmpTypeCode.Type) - acl["icmp_code"] = aws.Int64Value(entry.IcmpTypeCode.Code) + if v := apiObject.Type; v != nil { + tfMap["icmp_type"] = aws.Int64Value(v) + } + } + + return tfMap +} + +func flattenNetworkAclEntries(apiObjects []*ec2.NetworkAclEntry) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var tfList []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue } - result = append(result, acl) + tfList = append(tfList, flattenNetworkAclEntry(apiObject)) } - return result + return tfList } diff --git a/internal/service/ec2/wait.go b/internal/service/ec2/wait.go index 1d09314bf10b..530a9e0b0f51 100644 --- a/internal/service/ec2/wait.go +++ b/internal/service/ec2/wait.go @@ -291,9 +291,7 @@ func WaitInstanceIAMInstanceProfileUpdated(conn *ec2.EC2, instanceID string, exp const ManagedPrefixListEntryCreateTimeout = 5 * time.Minute const ( - NetworkACLDeletedTimeout = 5 * time.Minute - - NetworkACLPropagationTimeout = 2 * time.Minute + NetworkACLDeletedTimeout = 5 * time.Minute NetworkACLEntryPropagationTimeout = 5 * time.Minute ) From 99574d2ced75ddc283873e1ebad6602fb18ffc24 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 14:01:51 -0500 Subject: [PATCH 40/67] Add 'networkACLAssociationCreate'. --- .../service/ec2/network_acl_association.go | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index e7d21045f1f6..7077ebef2dcf 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -38,27 +39,13 @@ func ResourceNetworkACLAssociation() *schema.Resource { func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - subnetID := d.Get("subnet_id").(string) - - association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) - - if err != nil { - return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) - } - - input := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(d.Get("network_acl_id").(string)), - } - - log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) - output, err := conn.ReplaceNetworkAclAssociation(input) + associationID, err := networkACLAssociationCreate(conn, d.Get("network_acl_id").(string), d.Get("subnet_id").(string)) if err != nil { - return fmt.Errorf("error creating EC2 Network ACL Association: %w", err) + return err } - d.SetId(aws.StringValue(output.NewAssociationId)) + d.SetId(associationID) return resourceNetworkACLAssociationRead(d, meta) } @@ -111,9 +98,35 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ NetworkAclId: defaultNACL.NetworkAclId, }) + if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { + return nil + } + if err != nil { return fmt.Errorf("error deleting EC2 Network ACL Association (%s): %w", d.Id(), err) } return nil } + +func networkACLAssociationCreate(conn *ec2.EC2, naclID, subnetID string) (string, error) { + association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) + + if err != nil { + return "", fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) + } + + input := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: aws.String(naclID), + } + + log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) + output, err := conn.ReplaceNetworkAclAssociation(input) + + if err != nil { + return "", fmt.Errorf("error creating EC2 Network ACL Association: %w", err) + } + + return aws.StringValue(output.NewAssociationId), nil +} From f44b7181b99de80cc21da6de0433e29c4d87fbcf Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 14:02:02 -0500 Subject: [PATCH 41/67] Revert "Add 'networkACLAssociationCreate'." This reverts commit 99574d2ced75ddc283873e1ebad6602fb18ffc24. --- .../service/ec2/network_acl_association.go | 47 +++++++------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 7077ebef2dcf..e7d21045f1f6 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -6,7 +6,6 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -39,13 +38,27 @@ func ResourceNetworkACLAssociation() *schema.Resource { func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - associationID, err := networkACLAssociationCreate(conn, d.Get("network_acl_id").(string), d.Get("subnet_id").(string)) + subnetID := d.Get("subnet_id").(string) + + association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) + + if err != nil { + return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) + } + + input := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: aws.String(d.Get("network_acl_id").(string)), + } + + log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) + output, err := conn.ReplaceNetworkAclAssociation(input) if err != nil { - return err + return fmt.Errorf("error creating EC2 Network ACL Association: %w", err) } - d.SetId(associationID) + d.SetId(aws.StringValue(output.NewAssociationId)) return resourceNetworkACLAssociationRead(d, meta) } @@ -98,35 +111,9 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ NetworkAclId: defaultNACL.NetworkAclId, }) - if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { - return nil - } - if err != nil { return fmt.Errorf("error deleting EC2 Network ACL Association (%s): %w", d.Id(), err) } return nil } - -func networkACLAssociationCreate(conn *ec2.EC2, naclID, subnetID string) (string, error) { - association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) - - if err != nil { - return "", fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) - } - - input := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(naclID), - } - - log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) - output, err := conn.ReplaceNetworkAclAssociation(input) - - if err != nil { - return "", fmt.Errorf("error creating EC2 Network ACL Association: %w", err) - } - - return aws.StringValue(output.NewAssociationId), nil -} From 4bdc6527cc964a4ab587c31ec8de21208bfd2cec Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 14:04:16 -0500 Subject: [PATCH 42/67] Revert "Revert "Add 'networkACLAssociationCreate'."" This reverts commit f44b7181b99de80cc21da6de0433e29c4d87fbcf. --- .../service/ec2/network_acl_association.go | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index e7d21045f1f6..7077ebef2dcf 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -38,27 +39,13 @@ func ResourceNetworkACLAssociation() *schema.Resource { func resourceNetworkACLAssociationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - subnetID := d.Get("subnet_id").(string) - - association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) - - if err != nil { - return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) - } - - input := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(d.Get("network_acl_id").(string)), - } - - log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) - output, err := conn.ReplaceNetworkAclAssociation(input) + associationID, err := networkACLAssociationCreate(conn, d.Get("network_acl_id").(string), d.Get("subnet_id").(string)) if err != nil { - return fmt.Errorf("error creating EC2 Network ACL Association: %w", err) + return err } - d.SetId(aws.StringValue(output.NewAssociationId)) + d.SetId(associationID) return resourceNetworkACLAssociationRead(d, meta) } @@ -111,9 +98,35 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ NetworkAclId: defaultNACL.NetworkAclId, }) + if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { + return nil + } + if err != nil { return fmt.Errorf("error deleting EC2 Network ACL Association (%s): %w", d.Id(), err) } return nil } + +func networkACLAssociationCreate(conn *ec2.EC2, naclID, subnetID string) (string, error) { + association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) + + if err != nil { + return "", fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) + } + + input := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: aws.String(naclID), + } + + log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) + output, err := conn.ReplaceNetworkAclAssociation(input) + + if err != nil { + return "", fmt.Errorf("error creating EC2 Network ACL Association: %w", err) + } + + return aws.StringValue(output.NewAssociationId), nil +} From e135839a974df60b51b05fc50c69182d844a289d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 16:04:18 -0500 Subject: [PATCH 43/67] r/aws_network_acl: Tidy up resource Create. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_ipv6Rules === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_ipv6VPCRules --- PASS: TestAccEC2NetworkACL_espProtocol (39.50s) === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (49.08s) === CONT TestAccEC2NetworkACL_egressAndIngressRules --- PASS: TestAccEC2NetworkACL_onlyEgressRules (52.89s) === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges --- PASS: TestAccEC2NetworkACL_basic (53.32s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_update --- PASS: TestAccEC2NetworkACL_ipv6Rules (59.69s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (29.60s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (44.27s) === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (47.83s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (52.47s) === CONT TestAccEC2NetworkACL_subnetChange --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (73.66s) === CONT TestAccEC2NetworkACL_subnets --- PASS: TestAccEC2NetworkACL_disappears (42.17s) === CONT TestAccEC2NetworkACL_tags --- PASS: TestAccEC2NetworkACL_Egress_mode (79.90s) === CONT TestAccEC2NetworkACL_subnetsDelete === CONT TestAccEC2NetworkACL_subnetChange network_acl_test.go:407: Step 3/3 error: Error running apply: exit status 1 Error: InvalidAssociationID.NotFound: The association ID 'aclassoc-00d0744685b58042d' does not exist status code: 400, request id: 5a3edd1f-2f2c-4ddb-8187-319307202b15 with aws_network_acl.test, on terraform_plugin_test.tf line 30, in resource "aws_network_acl" "test": 30: resource "aws_network_acl" "test" { --- FAIL: TestAccEC2NetworkACL_subnetChange (61.35s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (85.34s) --- PASS: TestAccEC2NetworkACL_subnets (72.26s) --- PASS: TestAccEC2NetworkACL_subnetsDelete (60.25s) --- PASS: TestAccEC2NetworkACL_tags (73.20s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 219.891s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/network_acl.go | 185 ++++++++++++++++++++++------ 1 file changed, 147 insertions(+), 38 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 9a1982a1fe21..a8d5b9ad2feb 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -138,48 +138,21 @@ func resourceNetworkACLCreate(d *schema.ResourceData, meta interface{}) error { d.SetId(aws.StringValue(output.NetworkAcl.NetworkAclId)) if v, ok := d.GetOk("egress"); ok && v.(*schema.Set).Len() > 0 { - err := updateNetworkAclEntries(d, "egress", conn) - - if err != nil { - return fmt.Errorf("error updating EC2 Network ACL (%s) Egress Entries: %w", d.Id(), err) + if err := createNetworkACLEntries(conn, d.Id(), v.(*schema.Set).List(), true); err != nil { + return err } } if v, ok := d.GetOk("ingress"); ok && v.(*schema.Set).Len() > 0 { - err := updateNetworkAclEntries(d, "ingress", conn) - - if err != nil { - return fmt.Errorf("error updating EC2 Network ACL (%s) Ingress Entries: %w", d.Id(), err) + if err := createNetworkACLEntries(conn, d.Id(), v.(*schema.Set).List(), false); err != nil { + return err } } if v, ok := d.GetOk("subnet_ids"); ok && v.(*schema.Set).Len() > 0 { - for _, subnetIDRaw := range v.(*schema.Set).List() { - subnetID, ok := subnetIDRaw.(string) - - if !ok { - continue - } - - association, err := findNetworkAclAssociation(subnetID, conn) - - if err != nil { - return fmt.Errorf("error finding existing EC2 Network ACL association for Subnet (%s): %w", subnetID, err) - } - - if association == nil { - return fmt.Errorf("error finding existing EC2 Network ACL association for Subnet (%s): empty response", subnetID) - } - - input := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(d.Id()), - } - - _, err = conn.ReplaceNetworkAclAssociation(input) - - if err != nil { - return fmt.Errorf("error replacing existing EC2 Network ACL association for Subnet (%s): %w", subnetID, err) + for _, v := range v.(*schema.Set).List() { + if _, err := networkACLAssociationCreate(conn, d.Id(), v.(string)); err != nil { + return err } } } @@ -229,8 +202,6 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { var egressEntries []*ec2.NetworkAclEntry var ingressEntries []*ec2.NetworkAclEntry - - // separate the ingress and egress rules for _, v := range networkAcl.Entries { // Skip the default rules added by AWS. They can be neither // configured or deleted by users. @@ -244,7 +215,6 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { ingressEntries = append(ingressEntries, v) } } - if err := d.Set("egress", flattenNetworkAclEntries(egressEntries)); err != nil { return fmt.Errorf("error setting egress: %w", err) } @@ -641,6 +611,139 @@ func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssoci } } +func createNetworkACLEntries(conn *ec2.EC2, naclID string, tfList []interface{}, egress bool) error { + naclEntries := expandNetworkAclEntries(tfList, egress) + + for _, naclEntry := range naclEntries { + if naclEntry == nil { + continue + } + + if aws.StringValue(naclEntry.Protocol) == "-1" { + // Protocol -1 rules don't store ports in AWS. Thus, they'll always + // hash differently when being read out of the API. Force the user + // to set from_port and to_port to 0 for these rules, to keep the + // hashing consistent. + if from, to := aws.Int64Value(naclEntry.PortRange.From), aws.Int64Value(naclEntry.PortRange.To); from != 0 || to != 0 { + return fmt.Errorf("to_port (%d) and from_port (%d) must both be 0 to use the the 'all' \"-1\" protocol!", to, from) + } + } + + input := &ec2.CreateNetworkAclEntryInput{ + CidrBlock: naclEntry.CidrBlock, + Egress: naclEntry.Egress, + IcmpTypeCode: naclEntry.IcmpTypeCode, + Ipv6CidrBlock: naclEntry.Ipv6CidrBlock, + NetworkAclId: aws.String(naclID), + PortRange: naclEntry.PortRange, + Protocol: naclEntry.Protocol, + RuleAction: naclEntry.RuleAction, + RuleNumber: naclEntry.RuleNumber, + } + + log.Printf("[INFO] Creating EC2 Network ACL Entry: %s", input) + _, err := conn.CreateNetworkAclEntry(input) + + if err != nil { + return fmt.Errorf("error creating EC2 Network ACL (%s) Entry: %w", naclID, err) + } + } + + return nil +} + +func expandNetworkAclEntry(tfMap map[string]interface{}, egress bool) *ec2.NetworkAclEntry { + if tfMap == nil { + return nil + } + + apiObject := &ec2.NetworkAclEntry{ + Egress: aws.Bool(egress), + PortRange: &ec2.PortRange{}, + } + + if v, ok := tfMap["rule_no"].(int); ok { + apiObject.RuleNumber = aws.Int64(int64(v)) + } + + if v, ok := tfMap["action"].(string); ok && v != "" { + apiObject.RuleAction = aws.String(v) + } + + if v, ok := tfMap["cidr_block"].(string); ok && v != "" { + apiObject.CidrBlock = aws.String(v) + } + + if v, ok := tfMap["ipv6_cidr_block"].(string); ok && v != "" { + apiObject.Ipv6CidrBlock = aws.String(v) + } + + if v, ok := tfMap["from_port"].(int); ok { + apiObject.PortRange.From = aws.Int64(int64(v)) + } + + if v, ok := tfMap["to_port"].(int); ok { + apiObject.PortRange.To = aws.Int64(int64(v)) + } + + if v, ok := tfMap["protocol"].(string); ok && v != "" { + i, err := strconv.Atoi(v) + + if err != nil { + // We're a protocol name. Look up the number. + i, ok = protocolIntegers()[v] + + if !ok { + log.Printf("[WARN] Unsupported protocol: %s", v) + return nil + } + } + + apiObject.Protocol = aws.String(strconv.Itoa(i)) + + // Specify additional required fields for ICMP. + if i == 1 || i == 58 { + apiObject.IcmpTypeCode = &ec2.IcmpTypeCode{} + + if v, ok := tfMap["icmp_code"].(int); ok { + apiObject.IcmpTypeCode.Code = aws.Int64(int64(v)) + } + + if v, ok := tfMap["icmp_type"].(int); ok { + apiObject.IcmpTypeCode.Type = aws.Int64(int64(v)) + } + } + } + + return apiObject +} + +func expandNetworkAclEntries(tfList []interface{}, egress bool) []*ec2.NetworkAclEntry { + if len(tfList) == 0 { + return nil + } + + var apiObjects []*ec2.NetworkAclEntry + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]interface{}) + + if !ok { + continue + } + + apiObject := expandNetworkAclEntry(tfMap, egress) + + if apiObject == nil { + continue + } + + apiObjects = append(apiObjects, apiObject) + } + + return apiObjects +} + func flattenNetworkAclEntry(apiObject *ec2.NetworkAclEntry) map[string]interface{} { if apiObject == nil { return nil @@ -681,7 +784,13 @@ func flattenNetworkAclEntry(apiObject *ec2.NetworkAclEntry) map[string]interface if err != nil { // We're a protocol name. Look up the number. - i = protocolIntegers()[v] + var ok bool + i, ok = protocolIntegers()[v] + + if !ok { + log.Printf("[WARN] Unsupported protocol: %s", v) + return nil + } } tfMap["protocol"] = strconv.Itoa(i) From 2c1df98afdc325584c4945c1ca9377e598faeae1 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 17:20:32 -0500 Subject: [PATCH 44/67] r/aws_network_acl: Tidy up resource Update. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_egressAndIngressRules === CONT TestAccEC2NetworkACL_ipv6Rules === CONT TestAccEC2NetworkACL_espProtocol --- PASS: TestAccEC2NetworkACL_espProtocol (31.14s) === CONT TestAccEC2NetworkACL_ipv6VPCRules --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (43.88s) === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_onlyEgressRules (43.98s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_basic (44.10s) === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_ipv6Rules (50.08s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (40.65s) === CONT TestAccEC2NetworkACL_subnets --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (28.83s) === CONT TestAccEC2NetworkACL_subnetsDelete --- PASS: TestAccEC2NetworkACL_disappears (37.26s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_update --- PASS: TestAccEC2NetworkACL_Ingress_mode (79.13s) === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges --- PASS: TestAccEC2NetworkACL_Egress_mode (79.59s) === CONT TestAccEC2NetworkACL_tags --- PASS: TestAccEC2NetworkACL_subnetsDelete (62.04s) === CONT TestAccEC2NetworkACL_subnetChange --- PASS: TestAccEC2NetworkACL_subnets (67.08s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (68.60s) --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (46.44s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (47.92s) === CONT TestAccEC2NetworkACL_subnetChange network_acl_test.go:407: Step 3/3 error: Error running apply: exit status 1 Error: error replacing EC2 Network ACL (acl-0665c4a892f397198) Association: InvalidAssociationID.NotFound: The association ID 'aclassoc-03bc9d49a1b598b1a' does not exist status code: 400, request id: fdbdab99-447d-41e5-b631-68a2cc36cbf7 with aws_network_acl.test, on terraform_plugin_test.tf line 30, in resource "aws_network_acl" "test": 30: resource "aws_network_acl" "test" { --- FAIL: TestAccEC2NetworkACL_subnetChange (58.16s) --- PASS: TestAccEC2NetworkACL_tags (70.67s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 198.042s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/network_acl.go | 159 +++++++++++++++++++--------- 1 file changed, 110 insertions(+), 49 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index a8d5b9ad2feb..aca4c1060045 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -240,87 +240,103 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn if d.HasChange("ingress") { - err := updateNetworkAclEntries(d, "ingress", conn) - if err != nil { + o, n := d.GetChange("ingress") + os, ns := o.(*schema.Set), n.(*schema.Set) + + if err := updateNetworkACLEntries(conn, d.Id(), os, ns, false); err != nil { return err } } if d.HasChange("egress") { - err := updateNetworkAclEntries(d, "egress", conn) - if err != nil { + o, n := d.GetChange("egress") + os, ns := o.(*schema.Set), n.(*schema.Set) + + if err := updateNetworkACLEntries(conn, d.Id(), os, ns, true); err != nil { return err } } if d.HasChange("subnet_ids") { o, n := d.GetChange("subnet_ids") - if o == nil { - o = new(schema.Set) - } - if n == nil { - n = new(schema.Set) - } + os, ns := o.(*schema.Set), n.(*schema.Set) + add, del := ns.Difference(os).List(), os.Difference(ns).List() - os := o.(*schema.Set) - ns := n.(*schema.Set) - - remove := os.Difference(ns).List() - add := ns.Difference(os).List() - - if len(remove) > 0 { + if len(del) > 0 { // A Network ACL is required for each subnet. In order to disassociate a // subnet from this ACL, we must associate it with the default ACL. - defaultAcl, err := GetDefaultNetworkACL(d.Get("vpc_id").(string), conn) + vpcID := d.Get("vpc_id").(string) + defaultNACL, err := FindVPCDefaultNetworkACL(conn, vpcID) + if err != nil { - return fmt.Errorf("Failed to find Default ACL for VPC %s", d.Get("vpc_id").(string)) + return fmt.Errorf("error reading EC2 VPC (%s) default NACL: %w", vpcID, err) } - for _, r := range remove { - association, err := findNetworkAclAssociation(r.(string), conn) + + for _, v := range del { + subnetID := v.(string) + + association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) + + if tfresource.NotFound(err) { + // Subnet has been deleted. + continue + } + if err != nil { - if tfresource.NotFound(err) { - // Subnet has been deleted. - continue - } - return fmt.Errorf("Failed to find acl association: acl %s with subnet %s: %s", d.Id(), r, err) + return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) } - log.Printf("[DEBUG] Replacing Network Acl Association (%s) with Default Network ACL ID (%s)", *association.NetworkAclAssociationId, *defaultAcl.NetworkAclId) - _, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ + + input := &ec2.ReplaceNetworkAclAssociationInput{ AssociationId: association.NetworkAclAssociationId, - NetworkAclId: defaultAcl.NetworkAclId, - }) - if err != nil { - if tfawserr.ErrMessageContains(err, "InvalidAssociationID.NotFound", "") { - continue - } - return fmt.Errorf("Error Replacing Default Network Acl Association: %s", err) + NetworkAclId: defaultNACL.NetworkAclId, } - } - } - if len(add) > 0 { - for _, a := range add { - association, err := findNetworkAclAssociation(a.(string), conn) - if err != nil { - return fmt.Errorf("Failed to find acl association: acl %s with subnet %s: %s", d.Id(), a, err) + log.Printf("[DEBUG] Replacing EC2 Network ACL Association: %s", input) + _, err = conn.ReplaceNetworkAclAssociation(input) + + if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { + continue } - _, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(d.Id()), - }) + if err != nil { - return err + return fmt.Errorf("error replacing EC2 Network ACL (%s) Association: %w", d.Id(), err) } } } + for _, v := range add { + subnetID := v.(string) + + association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) + + if tfresource.NotFound(err) { + // Subnet has been deleted. + continue + } + + if err != nil { + return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) + } + + input := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: aws.String(d.Id()), + } + + log.Printf("[DEBUG] Replacing EC2 Network ACL Association: %s", input) + _, err = conn.ReplaceNetworkAclAssociation(input) + + if err != nil { + return fmt.Errorf("error replacing EC2 Network ACL (%s) Association: %w", d.Id(), err) + } + } } - if d.HasChange("tags_all") && !d.IsNewResource() { + if d.HasChange("tags_all") { o, n := d.GetChange("tags_all") if err := UpdateTags(conn, d.Id(), o, n); err != nil { - return fmt.Errorf("error updating EC2 Network ACL (%s) tags: %s", d.Id(), err) + return fmt.Errorf("error updating EC2 Network ACL (%s) tags: %w", d.Id(), err) } } @@ -652,6 +668,51 @@ func createNetworkACLEntries(conn *ec2.EC2, naclID string, tfList []interface{}, return nil } +func deleteNetworkACLEntries(conn *ec2.EC2, naclID string, tfList []interface{}, egress bool) error { + naclEntries := expandNetworkAclEntries(tfList, egress) + + for _, naclEntry := range naclEntries { + if naclEntry == nil { + continue + } + + // AWS includes default rules with all network ACLs that can be + // neither modified nor destroyed. They have a custom rule + // number that is out of bounds for any other rule. If we + // encounter it, just continue. There's no work to be done. + if v := aws.Int64Value(naclEntry.RuleNumber); v == defaultACLRuleNumberIPv4 || v == defaultACLRuleNumberIPv6 { + continue + } + + input := &ec2.DeleteNetworkAclEntryInput{ + Egress: naclEntry.Egress, + NetworkAclId: aws.String(naclID), + RuleNumber: naclEntry.RuleNumber, + } + + log.Printf("[INFO] Deleting EC2 Network ACL Entry: %s", input) + _, err := conn.DeleteNetworkAclEntry(input) + + if err != nil { + return fmt.Errorf("error deleting EC2 Network ACL (%s) Entry: %w", naclID, err) + } + } + + return nil +} + +func updateNetworkACLEntries(conn *ec2.EC2, naclID string, os, ns *schema.Set, egress bool) error { + if err := deleteNetworkACLEntries(conn, naclID, os.Difference(ns).List(), egress); err != nil { + return err + } + + if err := createNetworkACLEntries(conn, naclID, ns.Difference(os).List(), egress); err != nil { + return err + } + + return nil +} + func expandNetworkAclEntry(tfMap map[string]interface{}, egress bool) *ec2.NetworkAclEntry { if tfMap == nil { return nil From 3e48a1bc24e616f4b92f8d09325378137e983d4d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 4 Feb 2022 17:57:24 -0500 Subject: [PATCH 45/67] r/aws_network_acl: Retry creation of new NACL/Subnet association. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges === CONT TestAccEC2NetworkACL_egressAndIngressRules --- PASS: TestAccEC2NetworkACL_espProtocol (31.58s) === CONT TestAccEC2NetworkACL_ipv6VPCRules --- PASS: TestAccEC2NetworkACL_basic (43.02s) === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_onlyEgressRules (43.14s) === CONT TestAccEC2NetworkACL_ipv6Rules --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (43.31s) === CONT TestAccEC2NetworkACL_subnetsDelete --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (48.39s) === CONT TestAccEC2NetworkACL_subnets --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (25.26s) === CONT TestAccEC2NetworkACL_subnetChange --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (37.02s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_ipv6Rules (62.57s) === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_disappears (53.21s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_subnets (92.36s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_update --- PASS: TestAccEC2NetworkACL_subnetsDelete (105.51s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_subnetChange (108.73s) === CONT TestAccEC2NetworkACL_tags --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (51.25s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (97.75s) --- PASS: TestAccEC2NetworkACL_Egress_mode (88.07s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (73.85s) --- PASS: TestAccEC2NetworkACL_tags (70.00s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 250.704s --- internal/service/ec2/network_acl.go | 12 +++++++----- internal/service/ec2/network_acl_association.go | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index aca4c1060045..2faf7e996d37 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -291,7 +291,7 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { NetworkAclId: defaultNACL.NetworkAclId, } - log.Printf("[DEBUG] Replacing EC2 Network ACL Association: %s", input) + log.Printf("[DEBUG] Deleting EC2 Network ACL Association: %s", input) _, err = conn.ReplaceNetworkAclAssociation(input) if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { @@ -299,7 +299,7 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { } if err != nil { - return fmt.Errorf("error replacing EC2 Network ACL (%s) Association: %w", d.Id(), err) + return fmt.Errorf("error deleting EC2 Network ACL (%s) Association: %w", d.Id(), err) } } } @@ -323,11 +323,13 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { NetworkAclId: aws.String(d.Id()), } - log.Printf("[DEBUG] Replacing EC2 Network ACL Association: %s", input) - _, err = conn.ReplaceNetworkAclAssociation(input) + log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) + _, err = tfresource.RetryWhenAWSErrCodeEquals(PropagationTimeout, func() (interface{}, error) { + return conn.ReplaceNetworkAclAssociation(input) + }, ErrCodeInvalidAssociationIDNotFound) if err != nil { - return fmt.Errorf("error replacing EC2 Network ACL (%s) Association: %w", d.Id(), err) + return fmt.Errorf("error creating EC2 Network ACL (%s) Association: %w", d.Id(), err) } } } diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 7077ebef2dcf..04ff3bdf717b 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -93,6 +93,7 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ return fmt.Errorf("error reading EC2 VPC (%s) default NACL: %w", vpcID, err) } + log.Printf("[DEBUG] Deleting EC2 Network ACL Association: %s", d.Id()) _, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ AssociationId: aws.String(d.Id()), NetworkAclId: defaultNACL.NetworkAclId, From d8a56492e8fe9218276e961d7ef2ad6d0b87ca84 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 5 Feb 2022 17:23:11 -0500 Subject: [PATCH 46/67] r/aws_network_acl: Add 'testAccNetworkACLConfig'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_ipv6VPCRules === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (29.77s) === CONT TestAccEC2NetworkACL_ipv6Rules --- PASS: TestAccEC2NetworkACL_basic (31.42s) === CONT TestAccEC2NetworkACL_subnetsDelete --- PASS: TestAccEC2NetworkACL_espProtocol (32.12s) === CONT TestAccEC2NetworkACL_subnets --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (42.75s) === CONT TestAccEC2NetworkACL_subnetChange --- PASS: TestAccEC2NetworkACL_onlyEgressRules (44.23s) === CONT TestAccEC2NetworkACL_egressAndIngressRules --- PASS: TestAccEC2NetworkACL_ipv6Rules (48.06s) === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (42.76s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_update --- PASS: TestAccEC2NetworkACL_subnetsDelete (62.57s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_subnets (68.12s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (50.67s) === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (51.89s) === CONT TestAccEC2NetworkACL_tags --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (73.21s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_Egress_mode (81.97s) --- PASS: TestAccEC2NetworkACL_disappears (26.53s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (77.51s) === CONT TestAccEC2NetworkACL_subnetChange network_acl_test.go:415: Step 3/3 error: Error running apply: exit status 1 Error: error creating EC2 Network ACL (acl-0fa1e1c4eab7e17ba) Association: InvalidAssociationID.NotFound: The association ID 'aclassoc-0659645c9e13b757c' does not exist status code: 400, request id: 8ae6299d-ef85-4ea0-a575-ebded9ecdb1b with aws_network_acl.test, on terraform_plugin_test.tf line 30, in resource "aws_network_acl" "test": 30: resource "aws_network_acl" "test" { --- PASS: TestAccEC2NetworkACL_tags (69.53s) --- FAIL: TestAccEC2NetworkACL_subnetChange (176.73s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 223.217s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/network_acl.go | 4 +- .../service/ec2/network_acl_association.go | 2 + internal/service/ec2/network_acl_test.go | 130 ++++++++++-------- 3 files changed, 74 insertions(+), 62 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 2faf7e996d37..493034bc88fa 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -105,13 +105,13 @@ func ResourceNetworkACL() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "tags": tftags.TagsSchema(), + "tags_all": tftags.TagsSchemaComputed(), "vpc_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "tags": tftags.TagsSchema(), - "tags_all": tftags.TagsSchemaComputed(), }, CustomizeDiff: verify.SetTagsDiff, diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 04ff3bdf717b..86cdf0062d10 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -110,6 +110,8 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ return nil } +// networkACLAssociationCreate creates an association between the specified NACL and subnet. +// The subnet's current association is replaced and the new association's ID is returned. func networkACLAssociationCreate(conn *ec2.EC2, naclID, subnetID string) (string, error) { association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) diff --git a/internal/service/ec2/network_acl_test.go b/internal/service/ec2/network_acl_test.go index 713a494e4214..f74f63bc3f92 100644 --- a/internal/service/ec2/network_acl_test.go +++ b/internal/service/ec2/network_acl_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -14,11 +13,14 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func TestAccEC2NetworkACL_basic(t *testing.T) { + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" - var networkAcl ec2.NetworkAcl + vpcResourceName := "aws_vpc.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -27,11 +29,16 @@ func TestAccEC2NetworkACL_basic(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLEgressNIngressConfig, + Config: testAccNetworkACLConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`network-acl/acl-.+`)), + resource.TestCheckResourceAttr(resourceName, "egress.#", "0"), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "0"), + acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrPair(resourceName, "vpc_id", vpcResourceName, "id"), ), }, { @@ -43,10 +50,33 @@ func TestAccEC2NetworkACL_basic(t *testing.T) { }) } +func TestAccEC2NetworkACL_disappears(t *testing.T) { + var v ec2.NetworkAcl + resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckNetworkACLDestroy, + Steps: []resource.TestStep{ + { + Config: testAccNetworkACLConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLExists(resourceName, &v), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACL(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccEC2NetworkACL_tags(t *testing.T) { + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var networkAcl ec2.NetworkAcl resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -57,7 +87,7 @@ func TestAccEC2NetworkACL_tags(t *testing.T) { { Config: testAccNetworkACLTags1Config(rName, "key1", "value1"), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), @@ -70,7 +100,7 @@ func TestAccEC2NetworkACL_tags(t *testing.T) { { Config: testAccNetworkACLTags2Config(rName, "key1", "value1updated", "key2", "value2"), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), @@ -79,7 +109,7 @@ func TestAccEC2NetworkACL_tags(t *testing.T) { { Config: testAccNetworkACLTags1Config(rName, "key2", "value2"), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), ), @@ -88,28 +118,6 @@ func TestAccEC2NetworkACL_tags(t *testing.T) { }) } -func TestAccEC2NetworkACL_disappears(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_network_acl.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), - Providers: acctest.Providers, - CheckDestroy: testAccCheckNetworkACLDestroy, - Steps: []resource.TestStep{ - { - Config: testAccNetworkACLEgressNIngressConfig, - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACL(), resourceName), - ), - ExpectNonEmptyPlan: true, - }, - }, - }) -} - func TestAccEC2NetworkACL_Egress_mode(t *testing.T) { var networkAcl1, networkAcl2, networkAcl3 ec2.NetworkAcl resourceName := "aws_network_acl.test" @@ -644,36 +652,27 @@ func testAccCheckNetworkACLDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn for _, rs := range s.RootModule().Resources { - if rs.Type != "aws_network" { + if rs.Type != "aws_network_acl" { continue } - // Retrieve the network acl - resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(rs.Primary.ID)}, - }) - if err == nil { - if len(resp.NetworkAcls) > 0 && *resp.NetworkAcls[0].NetworkAclId == rs.Primary.ID { - return fmt.Errorf("Network Acl (%s) still exists.", rs.Primary.ID) - } + _, err := tfec2.FindNetworkACLByID(conn, rs.Primary.ID) - return nil + if tfresource.NotFound(err) { + continue } - ec2err, ok := err.(awserr.Error) - if !ok { - return err - } - // Confirm error code is what we want - if ec2err.Code() != "InvalidNetworkAclID.NotFound" { + if err != nil { return err } + + return fmt.Errorf("EC2 Network ACL %s still exists", rs.Primary.ID) } return nil } -func testAccCheckNetworkACLExists(n string, networkAcl *ec2.NetworkAcl) resource.TestCheckFunc { +func testAccCheckNetworkACLExists(n string, v *ec2.NetworkAcl) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -681,23 +680,20 @@ func testAccCheckNetworkACLExists(n string, networkAcl *ec2.NetworkAcl) resource } if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set: %s", n) + return fmt.Errorf("No EC2 Network ACL ID is set: %s", n) } + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn - resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(rs.Primary.ID)}, - }) + output, err := tfec2.FindNetworkACLByID(conn, rs.Primary.ID) + if err != nil { return err } - if len(resp.NetworkAcls) > 0 && *resp.NetworkAcls[0].NetworkAclId == rs.Primary.ID { - *networkAcl = *resp.NetworkAcls[0] - return nil - } + *v = *output - return fmt.Errorf("Network Acls not found") + return nil } } @@ -787,6 +783,22 @@ func testAccCheckSubnetIsNotAssociatedWithAcl(acl string, subnet string) resourc } } +func testAccNetworkACLConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id +} +`, rName) +} + func testAccNetworkACLIPv6ICMPConfig(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { @@ -1527,8 +1539,7 @@ resource "aws_vpc" "test" { } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.test.id - ingress = [] + vpc_id = aws_vpc.test.id tags = { %[2]q = %[3]q @@ -1548,8 +1559,7 @@ resource "aws_vpc" "test" { } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.test.id - ingress = [] + vpc_id = aws_vpc.test.id tags = { %[2]q = %[3]q From 9ff42c7f41760cd5140853874a1c9cf38c129544 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 5 Feb 2022 17:31:57 -0500 Subject: [PATCH 47/67] r/aws_network_acl_association: Add 'networkACLAssociationDelete'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_basic === PAUSE TestAccEC2NetworkACLAssociation_basic === RUN TestAccEC2NetworkACLAssociation_disappears === PAUSE TestAccEC2NetworkACLAssociation_disappears === RUN TestAccEC2NetworkACLAssociation_twoAssociations === PAUSE TestAccEC2NetworkACLAssociation_twoAssociations === CONT TestAccEC2NetworkACLAssociation_basic === CONT TestAccEC2NetworkACLAssociation_twoAssociations === CONT TestAccEC2NetworkACLAssociation_disappears --- PASS: TestAccEC2NetworkACLAssociation_disappears (30.48s) --- PASS: TestAccEC2NetworkACLAssociation_basic (34.63s) --- PASS: TestAccEC2NetworkACLAssociation_twoAssociations (38.16s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 41.945s --- .../service/ec2/network_acl_association.go | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 86cdf0062d10..0941436032f0 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -93,18 +93,8 @@ func resourceNetworkACLAssociationDelete(d *schema.ResourceData, meta interface{ return fmt.Errorf("error reading EC2 VPC (%s) default NACL: %w", vpcID, err) } - log.Printf("[DEBUG] Deleting EC2 Network ACL Association: %s", d.Id()) - _, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: aws.String(d.Id()), - NetworkAclId: defaultNACL.NetworkAclId, - }) - - if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { - return nil - } - - if err != nil { - return fmt.Errorf("error deleting EC2 Network ACL Association (%s): %w", d.Id(), err) + if err := networkACLAssociationDelete(conn, d.Id(), aws.StringValue(defaultNACL.NetworkAclId)); err != nil { + return err } return nil @@ -133,3 +123,25 @@ func networkACLAssociationCreate(conn *ec2.EC2, naclID, subnetID string) (string return aws.StringValue(output.NewAssociationId), nil } + +// networkACLAssociationDelete deletes the specified association between a NACL and subnet. +// The subnet's current association is replaced by an association with the VPC's default NACL. +func networkACLAssociationDelete(conn *ec2.EC2, associationID, naclID string) error { + input := &ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: aws.String(associationID), + NetworkAclId: aws.String(naclID), + } + + log.Printf("[DEBUG] Deleting EC2 Network ACL Association: %s", associationID) + _, err := conn.ReplaceNetworkAclAssociation(input) + + if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { + return nil + } + + if err != nil { + return fmt.Errorf("error deleting EC2 Network ACL Association (%s): %w", associationID, err) + } + + return nil +} From 676548ad0705da1b067d313bf14e80e4074f4282 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 5 Feb 2022 17:47:08 -0500 Subject: [PATCH 48/67] r/aws_network_acl: Use 'networkACLAssociationCreate'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_basic === PAUSE TestAccEC2NetworkACLAssociation_basic === RUN TestAccEC2NetworkACLAssociation_disappears === PAUSE TestAccEC2NetworkACLAssociation_disappears === RUN TestAccEC2NetworkACLAssociation_twoAssociations === PAUSE TestAccEC2NetworkACLAssociation_twoAssociations === CONT TestAccEC2NetworkACLAssociation_basic === CONT TestAccEC2NetworkACLAssociation_twoAssociations === CONT TestAccEC2NetworkACLAssociation_disappears --- PASS: TestAccEC2NetworkACLAssociation_disappears (30.36s) --- PASS: TestAccEC2NetworkACLAssociation_basic (33.56s) --- PASS: TestAccEC2NetworkACLAssociation_twoAssociations (36.80s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 40.723s % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_ipv6Rules === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_ipv6VPCRules --- PASS: TestAccEC2NetworkACL_espProtocol (32.57s) === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_basic (32.63s) === CONT TestAccEC2NetworkACL_egressAndIngressRules --- PASS: TestAccEC2NetworkACL_onlyEgressRules (43.70s) === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (43.75s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_update --- PASS: TestAccEC2NetworkACL_ipv6Rules (48.96s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (25.73s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (39.96s) === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (46.75s) === CONT TestAccEC2NetworkACL_subnets --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (46.70s) === CONT TestAccEC2NetworkACL_subnetsDelete --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (68.76s) === CONT TestAccEC2NetworkACL_subnetChange --- PASS: TestAccEC2NetworkACL_Egress_mode (73.68s) === CONT TestAccEC2NetworkACL_tags --- PASS: TestAccEC2NetworkACL_Ingress_mode (74.53s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_subnetsDelete (60.17s) --- PASS: TestAccEC2NetworkACL_subnets (66.85s) --- PASS: TestAccEC2NetworkACL_disappears (24.82s) --- PASS: TestAccEC2NetworkACL_tags (68.30s) === CONT TestAccEC2NetworkACL_subnetChange network_acl_test.go:415: Step 3/3 error: Error running apply: exit status 1 Error: error creating EC2 Network ACL (acl-0cb6a49c8c276f9f0) Association: InvalidAssociationID.NotFound: The association ID 'aclassoc-03d931da2408feaa2' does not exist status code: 400, request id: 073b1ec7-c9ef-4d95-96f6-b6dd64bb30c1 with aws_network_acl.test, on terraform_plugin_test.tf line 30, in resource "aws_network_acl" "test": 30: resource "aws_network_acl" "test" { --- FAIL: TestAccEC2NetworkACL_subnetChange (176.20s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 292.226s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/network_acl.go | 36 +++---------------- .../service/ec2/network_acl_association.go | 8 +++-- 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 493034bc88fa..7a3b69e29f2b 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -286,28 +286,14 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) } - input := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: defaultNACL.NetworkAclId, - } - - log.Printf("[DEBUG] Deleting EC2 Network ACL Association: %s", input) - _, err = conn.ReplaceNetworkAclAssociation(input) - - if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAssociationIDNotFound) { - continue - } - - if err != nil { - return fmt.Errorf("error deleting EC2 Network ACL (%s) Association: %w", d.Id(), err) + if err := networkACLAssociationDelete(conn, aws.StringValue(association.NetworkAclAssociationId), aws.StringValue(defaultNACL.NetworkAclId)); err != nil { + return err } } } for _, v := range add { - subnetID := v.(string) - - association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) + _, err := networkACLAssociationCreate(conn, d.Id(), v.(string)) if tfresource.NotFound(err) { // Subnet has been deleted. @@ -315,21 +301,7 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { } if err != nil { - return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) - } - - input := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(d.Id()), - } - - log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) - _, err = tfresource.RetryWhenAWSErrCodeEquals(PropagationTimeout, func() (interface{}, error) { - return conn.ReplaceNetworkAclAssociation(input) - }, ErrCodeInvalidAssociationIDNotFound) - - if err != nil { - return fmt.Errorf("error creating EC2 Network ACL (%s) Association: %w", d.Id(), err) + return err } } } diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 0941436032f0..8afdfd571c3a 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -115,13 +115,15 @@ func networkACLAssociationCreate(conn *ec2.EC2, naclID, subnetID string) (string } log.Printf("[DEBUG] Creating EC2 Network ACL Association: %s", input) - output, err := conn.ReplaceNetworkAclAssociation(input) + outputRaw, err := tfresource.RetryWhenAWSErrCodeEquals(PropagationTimeout, func() (interface{}, error) { + return conn.ReplaceNetworkAclAssociation(input) + }, ErrCodeInvalidAssociationIDNotFound) if err != nil { - return "", fmt.Errorf("error creating EC2 Network ACL Association: %w", err) + return "", fmt.Errorf("error creating EC2 Network ACL (%s) Association: %w", naclID, err) } - return aws.StringValue(output.NewAssociationId), nil + return aws.StringValue(outputRaw.(*ec2.ReplaceNetworkAclAssociationOutput).NewAssociationId), nil } // networkACLAssociationDelete deletes the specified association between a NACL and subnet. From 310e66a604948983337ec5e45e2f1fae279ce47a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sun, 6 Feb 2022 17:46:25 -0500 Subject: [PATCH 49/67] r/aws_network_acl: Delete NACL associations before attempting NACL deletion. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ACCTEST_PARALLELISM=5 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 5 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_subnetsDelete === CONT TestAccEC2NetworkACL_subnets === CONT TestAccEC2NetworkACL_ipv6Rules --- PASS: TestAccEC2NetworkACL_basic (36.03s) === CONT TestAccEC2NetworkACL_espProtocol --- PASS: TestAccEC2NetworkACL_onlyEgressRules (47.80s) === CONT TestAccEC2NetworkACL_ipv6VPCRules --- PASS: TestAccEC2NetworkACL_ipv6Rules (54.02s) === CONT TestAccEC2NetworkACL_ipv6ICMPRules --- PASS: TestAccEC2NetworkACL_espProtocol (30.11s) === CONT TestAccEC2NetworkACL_egressAndIngressRules --- PASS: TestAccEC2NetworkACL_subnetsDelete (68.78s) === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges --- PASS: TestAccEC2NetworkACL_subnets (75.17s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_update --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (26.74s) === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (40.33s) === CONT TestAccEC2NetworkACL_subnetChange --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (40.71s) === CONT TestAccEC2NetworkACL_Egress_mode --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (47.23s) === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (47.33s) === CONT TestAccEC2NetworkACL_tags --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (70.44s) === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_subnetChange (72.74s) --- PASS: TestAccEC2NetworkACL_disappears (28.05s) --- PASS: TestAccEC2NetworkACL_Egress_mode (80.63s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (79.86s) --- PASS: TestAccEC2NetworkACL_tags (74.94s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 206.955s --- internal/service/ec2/default_network_acl.go | 28 ++++ internal/service/ec2/network_acl.go | 146 ++---------------- .../service/ec2/network_acl_association.go | 49 ++++++ internal/service/ec2/wait.go | 1 - 4 files changed, 90 insertions(+), 134 deletions(-) diff --git a/internal/service/ec2/default_network_acl.go b/internal/service/ec2/default_network_acl.go index a019ca9044c6..1e3309bdaff8 100644 --- a/internal/service/ec2/default_network_acl.go +++ b/internal/service/ec2/default_network_acl.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -328,3 +329,30 @@ func revokeAllNetworkACLEntries(netaclId string, meta interface{}) error { return nil } + +func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssociation *ec2.NetworkAclAssociation, err error) { + req := &ec2.DescribeNetworkAclsInput{} + req.Filters = BuildAttributeFilterList( + map[string]string{ + "association.subnet-id": subnetId, + }, + ) + resp, err := conn.DescribeNetworkAcls(req) + if err != nil { + return nil, err + } + + if len(resp.NetworkAcls) > 0 { + for _, association := range resp.NetworkAcls[0].Associations { + if aws.StringValue(association.SubnetId) == subnetId { + return association, nil + } + } + } + + return nil, &resource.NotFoundError{ + LastRequest: req, + LastResponse: resp, + Message: fmt.Sprintf("could not find association for subnet: %s ", subnetId), + } +} diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 7a3b69e29f2b..89ad57282e32 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -11,7 +11,6 @@ import ( "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -263,44 +262,13 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { add, del := ns.Difference(os).List(), os.Difference(ns).List() if len(del) > 0 { - // A Network ACL is required for each subnet. In order to disassociate a - // subnet from this ACL, we must associate it with the default ACL. - vpcID := d.Get("vpc_id").(string) - defaultNACL, err := FindVPCDefaultNetworkACL(conn, vpcID) - - if err != nil { - return fmt.Errorf("error reading EC2 VPC (%s) default NACL: %w", vpcID, err) - } - - for _, v := range del { - subnetID := v.(string) - - association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) - - if tfresource.NotFound(err) { - // Subnet has been deleted. - continue - } - - if err != nil { - return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) - } - - if err := networkACLAssociationDelete(conn, aws.StringValue(association.NetworkAclAssociationId), aws.StringValue(defaultNACL.NetworkAclId)); err != nil { - return err - } + if err := networkACLAssociationsDelete(conn, d.Get("vpc_id").(string), del); err != nil { + return err } } - for _, v := range add { - _, err := networkACLAssociationCreate(conn, d.Id(), v.(string)) - - if tfresource.NotFound(err) { - // Subnet has been deleted. - continue - } - - if err != nil { + if len(add) > 0 { + if err := networkACLAssociationsCreate(conn, d.Id(), add); err != nil { return err } } @@ -320,27 +288,20 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn + if v, ok := d.GetOk("subnet_ids"); ok && v.(*schema.Set).Len() > 0 { + if err := networkACLAssociationsDelete(conn, d.Get("vpc_id").(string), v.(*schema.Set).List()); err != nil { + return err + } + } + input := &ec2.DeleteNetworkAclInput{ NetworkAclId: aws.String(d.Id()), } log.Printf("[INFO] Deleting EC2 Network ACL: %s", d.Id()) - _, err := tfresource.RetryWhen(NetworkACLDeletedTimeout, - func() (interface{}, error) { - return conn.DeleteNetworkAcl(input) - }, - func(err error) (bool, error) { - if tfawserr.ErrCodeEquals(err, ErrCodeDependencyViolation) { - if err := cleanUpDependencyViolations(d, conn); err != nil { - return false, err - } - - return true, err - } - - return false, err - }, - ) + _, err := tfresource.RetryWhenAWSErrCodeEquals(PropagationTimeout, func() (interface{}, error) { + return conn.DeleteNetworkAcl(input) + }, ErrCodeDependencyViolation) if tfawserr.ErrCodeEquals(err, ErrCodeInvalidNetworkAclIDNotFound) { return nil @@ -459,60 +420,6 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2 return nil } -func cleanUpDependencyViolations(d *schema.ResourceData, conn *ec2.EC2) error { - // In case of dependency violation, we remove the association between subnet and network acl. - // This means the subnet is attached to default acl of vpc. - var associations []*ec2.NetworkAclAssociation - if v, ok := d.GetOk("subnet_ids"); ok { - ids := v.(*schema.Set).List() - for _, i := range ids { - a, err := findNetworkAclAssociation(i.(string), conn) - if err != nil { - if tfresource.NotFound(err) { - continue - } - return fmt.Errorf("Error finding network ACL association: %s", err) - } - associations = append(associations, a) - } - } - - log.Printf("[DEBUG] Replacing network associations for Network ACL (%s): %s", d.Id(), associations) - defaultAcl, err := GetDefaultNetworkACL(d.Get("vpc_id").(string), conn) - if err != nil { - return fmt.Errorf("Error getting default network ACL: %s", err) - } - - for _, a := range associations { - log.Printf("DEBUG] Replacing Network Acl Association (%s) with Default Network ACL ID (%s)", - aws.StringValue(a.NetworkAclAssociationId), aws.StringValue(defaultAcl.NetworkAclId)) - _, replaceErr := conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: a.NetworkAclAssociationId, - NetworkAclId: defaultAcl.NetworkAclId, - }) - if replaceErr != nil { - // It's possible that during an attempt to replace this - // association, the Subnet in question has already been moved to - // another ACL. This can happen if you're destroying a network acl - // and simultaneously re-associating it's subnet(s) with another - // ACL; Terraform may have already re-associated the subnet(s) by - // the time we attempt to destroy them, even between the time we - // list them and then try to destroy them. In this case, the - // association we're trying to replace will no longer exist and - // this call will fail. Here we trap that error and fail - // gracefully; the association we tried to replace gone, we trust - // someone else has taken ownership. - if tfawserr.ErrMessageContains(replaceErr, "InvalidAssociationID.NotFound", "") { - log.Printf("[WARN] Network Association (%s) no longer found; Network Association likely updated or removed externally, removing from state", aws.StringValue(a.NetworkAclAssociationId)) - continue - } - log.Printf("[ERR] Non retry-able error in replacing associations for Network ACL (%s): %s", d.Id(), replaceErr) - return fmt.Errorf("Error replacing network ACL associations: %s", err) - } - } - return nil -} - func resourceNetworkACLEntryHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) @@ -574,33 +481,6 @@ func GetDefaultNetworkACL(vpcId string, conn *ec2.EC2) (defaultAcl *ec2.NetworkA return resp.NetworkAcls[0], nil } -func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssociation *ec2.NetworkAclAssociation, err error) { - req := &ec2.DescribeNetworkAclsInput{} - req.Filters = BuildAttributeFilterList( - map[string]string{ - "association.subnet-id": subnetId, - }, - ) - resp, err := conn.DescribeNetworkAcls(req) - if err != nil { - return nil, err - } - - if len(resp.NetworkAcls) > 0 { - for _, association := range resp.NetworkAcls[0].Associations { - if aws.StringValue(association.SubnetId) == subnetId { - return association, nil - } - } - } - - return nil, &resource.NotFoundError{ - LastRequest: req, - LastResponse: resp, - Message: fmt.Sprintf("could not find association for subnet: %s ", subnetId), - } -} - func createNetworkACLEntries(conn *ec2.EC2, naclID string, tfList []interface{}, egress bool) error { naclEntries := expandNetworkAclEntries(tfList, egress) diff --git a/internal/service/ec2/network_acl_association.go b/internal/service/ec2/network_acl_association.go index 8afdfd571c3a..b890876f9d9f 100644 --- a/internal/service/ec2/network_acl_association.go +++ b/internal/service/ec2/network_acl_association.go @@ -126,6 +126,25 @@ func networkACLAssociationCreate(conn *ec2.EC2, naclID, subnetID string) (string return aws.StringValue(outputRaw.(*ec2.ReplaceNetworkAclAssociationOutput).NewAssociationId), nil } +// networkACLAssociationsCreate creates associations between the specified NACL and subnets. +func networkACLAssociationsCreate(conn *ec2.EC2, naclID string, subnetIDs []interface{}) error { + for _, v := range subnetIDs { + subnetID := v.(string) + _, err := networkACLAssociationCreate(conn, naclID, subnetID) + + if tfresource.NotFound(err) { + // Subnet has been deleted. + continue + } + + if err != nil { + return err + } + } + + return nil +} + // networkACLAssociationDelete deletes the specified association between a NACL and subnet. // The subnet's current association is replaced by an association with the VPC's default NACL. func networkACLAssociationDelete(conn *ec2.EC2, associationID, naclID string) error { @@ -147,3 +166,33 @@ func networkACLAssociationDelete(conn *ec2.EC2, associationID, naclID string) er return nil } + +// networkACLAssociationDelete deletes the specified NACL associations for the specified subnets. +// Each subnet's current association is replaced by an association with the specified VPC's default NACL. +func networkACLAssociationsDelete(conn *ec2.EC2, vpcID string, subnetIDs []interface{}) error { + defaultNACL, err := FindVPCDefaultNetworkACL(conn, vpcID) + + if err != nil { + return fmt.Errorf("error reading EC2 VPC (%s) default NACL: %w", vpcID, err) + } + + for _, v := range subnetIDs { + subnetID := v.(string) + association, err := FindNetworkACLAssociationBySubnetID(conn, subnetID) + + if tfresource.NotFound(err) { + // Subnet has been deleted. + continue + } + + if err != nil { + return fmt.Errorf("error reading EC2 Network ACL Association for EC2 Subnet (%s): %w", subnetID, err) + } + + if err := networkACLAssociationDelete(conn, aws.StringValue(association.NetworkAclAssociationId), aws.StringValue(defaultNACL.NetworkAclId)); err != nil { + return err + } + } + + return nil +} diff --git a/internal/service/ec2/wait.go b/internal/service/ec2/wait.go index 530a9e0b0f51..5db5542980c8 100644 --- a/internal/service/ec2/wait.go +++ b/internal/service/ec2/wait.go @@ -291,7 +291,6 @@ func WaitInstanceIAMInstanceProfileUpdated(conn *ec2.EC2, instanceID string, exp const ManagedPrefixListEntryCreateTimeout = 5 * time.Minute const ( - NetworkACLDeletedTimeout = 5 * time.Minute NetworkACLEntryPropagationTimeout = 5 * time.Minute ) From 228177dbebd34257b9510f706ae268040b0b7d94 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sun, 6 Feb 2022 18:05:09 -0500 Subject: [PATCH 50/67] r/aws_network_acl: Tidy up sweeper. --- internal/service/ec2/default_network_acl.go | 106 ++++++++++++++++ internal/service/ec2/network_acl.go | 127 +------------------- internal/service/ec2/sweep.go | 93 +++++--------- 3 files changed, 140 insertions(+), 186 deletions(-) diff --git a/internal/service/ec2/default_network_acl.go b/internal/service/ec2/default_network_acl.go index 1e3309bdaff8..57c0b663666f 100644 --- a/internal/service/ec2/default_network_acl.go +++ b/internal/service/ec2/default_network_acl.go @@ -356,3 +356,109 @@ func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssoci Message: fmt.Sprintf("could not find association for subnet: %s ", subnetId), } } + +func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2.EC2) error { + if d.HasChange(entryType) { + o, n := d.GetChange(entryType) + + if o == nil { + o = new(schema.Set) + } + if n == nil { + n = new(schema.Set) + } + + os := o.(*schema.Set) + ns := n.(*schema.Set) + + toBeDeleted, err := ExpandNetworkACLEntries(os.Difference(ns).List(), entryType) + if err != nil { + return err + } + for _, remove := range toBeDeleted { + // AWS includes default rules with all network ACLs that can be + // neither modified nor destroyed. They have a custom rule + // number that is out of bounds for any other rule. If we + // encounter it, just continue. There's no work to be done. + if aws.Int64Value(remove.RuleNumber) == defaultACLRuleNumberIPv4 || + aws.Int64Value(remove.RuleNumber) == defaultACLRuleNumberIPv6 { + continue + } + + // Delete old Acl + log.Printf("[DEBUG] Destroying Network ACL Entry number (%d)", int(aws.Int64Value(remove.RuleNumber))) + _, err := conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{ + NetworkAclId: aws.String(d.Id()), + RuleNumber: remove.RuleNumber, + Egress: remove.Egress, + }) + if err != nil { + return fmt.Errorf("Error deleting %s entry: %s", entryType, err) + } + } + + toBeCreated, err := ExpandNetworkACLEntries(ns.Difference(os).List(), entryType) + if err != nil { + return err + } + for _, add := range toBeCreated { + // Protocol -1 rules don't store ports in AWS. Thus, they'll always + // hash differently when being read out of the API. Force the user + // to set from_port and to_port to 0 for these rules, to keep the + // hashing consistent. + if aws.StringValue(add.Protocol) == "-1" { + to := aws.Int64Value(add.PortRange.To) + from := aws.Int64Value(add.PortRange.From) + expected := &ExpectedPortPair{ + to_port: 0, + from_port: 0, + } + if ok := ValidPorts(to, from, *expected); !ok { + return fmt.Errorf( + "to_port (%d) and from_port (%d) must both be 0 to use the the 'all' \"-1\" protocol!", + to, from) + } + } + + // AWS mutates the CIDR block into a network implied by the IP and + // mask provided. This results in hashing inconsistencies between + // the local config file and the state returned by the API. Error + // if the user provides a CIDR block with an inappropriate mask + if cidrBlock := aws.StringValue(add.CidrBlock); cidrBlock != "" { + if err := verify.ValidateIPv4CIDRBlock(cidrBlock); err != nil { + return err + } + } + if ipv6CidrBlock := aws.StringValue(add.Ipv6CidrBlock); ipv6CidrBlock != "" { + if err := verify.ValidateIPv6CIDRBlock(ipv6CidrBlock); err != nil { + return err + } + } + + createOpts := &ec2.CreateNetworkAclEntryInput{ + NetworkAclId: aws.String(d.Id()), + Egress: add.Egress, + PortRange: add.PortRange, + Protocol: add.Protocol, + RuleAction: add.RuleAction, + RuleNumber: add.RuleNumber, + IcmpTypeCode: add.IcmpTypeCode, + } + + if add.CidrBlock != nil && aws.StringValue(add.CidrBlock) != "" { + createOpts.CidrBlock = add.CidrBlock + } + + if add.Ipv6CidrBlock != nil && aws.StringValue(add.Ipv6CidrBlock) != "" { + createOpts.Ipv6CidrBlock = add.Ipv6CidrBlock + } + + // Add new Acl entry + _, connErr := conn.CreateNetworkAclEntry(createOpts) + if connErr != nil { + return fmt.Errorf("Error creating %s entry: %s", entryType, connErr) + } + } + } + return nil +} diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 89ad57282e32..ebba9dbf8383 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -62,6 +62,7 @@ func ResourceNetworkACL() *schema.Resource { "protocol": { Type: schema.TypeString, Required: true, + // TODO: Add ValidateFunc. }, "rule_no": { Type: schema.TypeInt, @@ -314,112 +315,6 @@ func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { return nil } -func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2.EC2) error { - if d.HasChange(entryType) { - o, n := d.GetChange(entryType) - - if o == nil { - o = new(schema.Set) - } - if n == nil { - n = new(schema.Set) - } - - os := o.(*schema.Set) - ns := n.(*schema.Set) - - toBeDeleted, err := ExpandNetworkACLEntries(os.Difference(ns).List(), entryType) - if err != nil { - return err - } - for _, remove := range toBeDeleted { - // AWS includes default rules with all network ACLs that can be - // neither modified nor destroyed. They have a custom rule - // number that is out of bounds for any other rule. If we - // encounter it, just continue. There's no work to be done. - if aws.Int64Value(remove.RuleNumber) == defaultACLRuleNumberIPv4 || - aws.Int64Value(remove.RuleNumber) == defaultACLRuleNumberIPv6 { - continue - } - - // Delete old Acl - log.Printf("[DEBUG] Destroying Network ACL Entry number (%d)", int(aws.Int64Value(remove.RuleNumber))) - _, err := conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{ - NetworkAclId: aws.String(d.Id()), - RuleNumber: remove.RuleNumber, - Egress: remove.Egress, - }) - if err != nil { - return fmt.Errorf("Error deleting %s entry: %s", entryType, err) - } - } - - toBeCreated, err := ExpandNetworkACLEntries(ns.Difference(os).List(), entryType) - if err != nil { - return err - } - for _, add := range toBeCreated { - // Protocol -1 rules don't store ports in AWS. Thus, they'll always - // hash differently when being read out of the API. Force the user - // to set from_port and to_port to 0 for these rules, to keep the - // hashing consistent. - if aws.StringValue(add.Protocol) == "-1" { - to := aws.Int64Value(add.PortRange.To) - from := aws.Int64Value(add.PortRange.From) - expected := &ExpectedPortPair{ - to_port: 0, - from_port: 0, - } - if ok := ValidPorts(to, from, *expected); !ok { - return fmt.Errorf( - "to_port (%d) and from_port (%d) must both be 0 to use the the 'all' \"-1\" protocol!", - to, from) - } - } - - // AWS mutates the CIDR block into a network implied by the IP and - // mask provided. This results in hashing inconsistencies between - // the local config file and the state returned by the API. Error - // if the user provides a CIDR block with an inappropriate mask - if cidrBlock := aws.StringValue(add.CidrBlock); cidrBlock != "" { - if err := verify.ValidateIPv4CIDRBlock(cidrBlock); err != nil { - return err - } - } - if ipv6CidrBlock := aws.StringValue(add.Ipv6CidrBlock); ipv6CidrBlock != "" { - if err := verify.ValidateIPv6CIDRBlock(ipv6CidrBlock); err != nil { - return err - } - } - - createOpts := &ec2.CreateNetworkAclEntryInput{ - NetworkAclId: aws.String(d.Id()), - Egress: add.Egress, - PortRange: add.PortRange, - Protocol: add.Protocol, - RuleAction: add.RuleAction, - RuleNumber: add.RuleNumber, - IcmpTypeCode: add.IcmpTypeCode, - } - - if add.CidrBlock != nil && aws.StringValue(add.CidrBlock) != "" { - createOpts.CidrBlock = add.CidrBlock - } - - if add.Ipv6CidrBlock != nil && aws.StringValue(add.Ipv6CidrBlock) != "" { - createOpts.Ipv6CidrBlock = add.Ipv6CidrBlock - } - - // Add new Acl entry - _, connErr := conn.CreateNetworkAclEntry(createOpts) - if connErr != nil { - return fmt.Errorf("Error creating %s entry: %s", entryType, connErr) - } - } - } - return nil -} - func resourceNetworkACLEntryHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) @@ -461,26 +356,6 @@ func resourceNetworkACLEntryHash(v interface{}) int { return create.StringHashcode(buf.String()) } -func GetDefaultNetworkACL(vpcId string, conn *ec2.EC2) (defaultAcl *ec2.NetworkAcl, err error) { - resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ - Filters: []*ec2.Filter{ - { - Name: aws.String("default"), - Values: []*string{aws.String("true")}, - }, - { - Name: aws.String("vpc-id"), - Values: []*string{aws.String(vpcId)}, - }, - }, - }) - - if err != nil { - return nil, err - } - return resp.NetworkAcls[0], nil -} - func createNetworkACLEntries(conn *ec2.EC2, naclID string, tfList []interface{}, egress bool) error { naclEntries := expandNetworkAclEntries(tfList, egress) diff --git a/internal/service/ec2/sweep.go b/internal/service/ec2/sweep.go index a76066b0aaf6..7d8f8da6a7bc 100644 --- a/internal/service/ec2/sweep.go +++ b/internal/service/ec2/sweep.go @@ -1075,78 +1075,51 @@ func sweepNetworkACLs(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } + input := &ec2.DescribeNetworkAclsInput{} conn := client.(*conns.AWSClient).EC2Conn + sweepResources := make([]*sweep.SweepResource, 0) - req := &ec2.DescribeNetworkAclsInput{} - resp, err := conn.DescribeNetworkAcls(req) - if err != nil { - if sweep.SkipSweepError(err) { - log.Printf("[WARN] Skipping EC2 Network ACL sweep for %s: %s", region, err) - return nil + err = conn.DescribeNetworkAclsPages(input, func(page *ec2.DescribeNetworkAclsOutput, lastPage bool) bool { + if page == nil { + return !lastPage } - return fmt.Errorf("Error describing Network ACLs: %s", err) - } - - if len(resp.NetworkAcls) == 0 { - log.Print("[DEBUG] No Network ACLs to sweep") - return nil - } - for _, nacl := range resp.NetworkAcls { - // Delete rules first - for _, entry := range nacl.Entries { - // These are the rule numbers for IPv4 and IPv6 "ALL traffic" rules which cannot be deleted - if aws.Int64Value(entry.RuleNumber) == 32767 || aws.Int64Value(entry.RuleNumber) == 32768 { - log.Printf("[DEBUG] Skipping Network ACL rule: %q / %d", *nacl.NetworkAclId, *entry.RuleNumber) + for _, v := range page.NetworkAcls { + if aws.BoolValue(v.IsDefault) { continue } - log.Printf("[INFO] Deleting Network ACL rule: %q / %d", *nacl.NetworkAclId, *entry.RuleNumber) - _, err := conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{ - NetworkAclId: nacl.NetworkAclId, - Egress: entry.Egress, - RuleNumber: entry.RuleNumber, - }) - if err != nil { - return fmt.Errorf( - "Error deleting Network ACL rule (%s / %d): %s", - *nacl.NetworkAclId, *entry.RuleNumber, err) - } - } + r := ResourceNetworkACL() + d := r.Data(nil) + d.SetId(aws.StringValue(v.NetworkAclId)) - // Disassociate subnets - log.Printf("[DEBUG] Found %d Network ACL associations for %q", len(nacl.Associations), *nacl.NetworkAclId) - for _, a := range nacl.Associations { - log.Printf("[DEBUG] Replacing subnet associations for Network ACL %q", *nacl.NetworkAclId) - defaultAcl, err := GetDefaultNetworkACL(*nacl.VpcId, conn) - if err != nil { - return fmt.Errorf("Failed to find default Network ACL for VPC %q", *nacl.VpcId) - } - _, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ - NetworkAclId: defaultAcl.NetworkAclId, - AssociationId: a.NetworkAclAssociationId, - }) - if err != nil { - return fmt.Errorf("Failed to replace subnet association for Network ACL %q: %s", - *nacl.NetworkAclId, err) + var subnetIDs []string + for _, v := range v.Associations { + subnetIDs = append(subnetIDs, aws.StringValue(v.SubnetId)) } - } + d.Set("subnet_ids", subnetIDs) - // Default Network ACLs will be deleted along with VPC - if *nacl.IsDefault { - log.Printf("[DEBUG] Skipping default Network ACL: %q", *nacl.NetworkAclId) - continue - } + d.Set("vpc_id", v.VpcId) - log.Printf("[INFO] Deleting Network ACL: %q", *nacl.NetworkAclId) - _, err := conn.DeleteNetworkAcl(&ec2.DeleteNetworkAclInput{ - NetworkAclId: nacl.NetworkAclId, - }) - if err != nil { - return fmt.Errorf( - "Error deleting Network ACL (%s): %s", - *nacl.NetworkAclId, err) + sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } + + return !lastPage + }) + + if sweep.SkipSweepError(err) { + log.Printf("[WARN] Skipping EC2 Network ACL sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing EC2 Network ACLs (%s): %w", region, err) + } + + err = sweep.SweepOrchestrator(sweepResources) + + if err != nil { + return fmt.Errorf("error sweeping EC2 Network ACLs (%s): %w", region, err) } return nil From c329fcb9c06f7391cf2b2611ed3d20ef6246211f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 08:56:09 -0500 Subject: [PATCH 51/67] r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_disappears_NACL' and 'TestAccEC2NetworkACLAssociation_disappears_Subnet'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_basic === PAUSE TestAccEC2NetworkACLAssociation_basic === RUN TestAccEC2NetworkACLAssociation_disappears === PAUSE TestAccEC2NetworkACLAssociation_disappears === RUN TestAccEC2NetworkACLAssociation_disappears_NACL === PAUSE TestAccEC2NetworkACLAssociation_disappears_NACL === RUN TestAccEC2NetworkACLAssociation_disappears_Subnet === PAUSE TestAccEC2NetworkACLAssociation_disappears_Subnet === RUN TestAccEC2NetworkACLAssociation_twoAssociations === PAUSE TestAccEC2NetworkACLAssociation_twoAssociations === CONT TestAccEC2NetworkACLAssociation_basic === CONT TestAccEC2NetworkACLAssociation_disappears_Subnet === CONT TestAccEC2NetworkACLAssociation_disappears === CONT TestAccEC2NetworkACLAssociation_disappears_NACL === CONT TestAccEC2NetworkACLAssociation_twoAssociations --- PASS: TestAccEC2NetworkACLAssociation_disappears_Subnet (38.06s) --- PASS: TestAccEC2NetworkACLAssociation_disappears (38.15s) --- PASS: TestAccEC2NetworkACLAssociation_disappears_NACL (38.68s) --- PASS: TestAccEC2NetworkACLAssociation_basic (42.49s) --- PASS: TestAccEC2NetworkACLAssociation_twoAssociations (46.83s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 53.854s --- internal/service/ec2/network_acl.go | 29 +++++++---- .../ec2/network_acl_association_test.go | 48 +++++++++++++++++++ website/docs/r/network_acl.html.markdown | 4 ++ .../docs/r/network_acl_association.markdown | 4 ++ 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index ebba9dbf8383..1d9678b3dd01 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -179,9 +179,9 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error reading EC2 Network ACL (%s): %w", d.Id(), err) } - networkAcl := outputRaw.(*ec2.NetworkAcl) + nacl := outputRaw.(*ec2.NetworkAcl) - ownerID := aws.StringValue(networkAcl.OwnerId) + ownerID := aws.StringValue(nacl.OwnerId) arn := arn.ARN{ Partition: meta.(*conns.AWSClient).Partition, Service: ec2.ServiceName, @@ -193,16 +193,16 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { d.Set("owner_id", ownerID) var subnetIDs []string - for _, v := range networkAcl.Associations { + for _, v := range nacl.Associations { subnetIDs = append(subnetIDs, aws.StringValue(v.SubnetId)) } d.Set("subnet_ids", subnetIDs) - d.Set("vpc_id", networkAcl.VpcId) + d.Set("vpc_id", nacl.VpcId) var egressEntries []*ec2.NetworkAclEntry var ingressEntries []*ec2.NetworkAclEntry - for _, v := range networkAcl.Entries { + for _, v := range nacl.Entries { // Skip the default rules added by AWS. They can be neither // configured or deleted by users. if v := aws.Int64Value(v.RuleNumber); v == defaultACLRuleNumberIPv4 || v == defaultACLRuleNumberIPv6 { @@ -222,7 +222,7 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error setting ingress: %w", err) } - tags := KeyValueTags(networkAcl.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig) + tags := KeyValueTags(nacl.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig) //lintignore:AWSR002 if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { @@ -289,8 +289,19 @@ func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - if v, ok := d.GetOk("subnet_ids"); ok && v.(*schema.Set).Len() > 0 { - if err := networkACLAssociationsDelete(conn, d.Get("vpc_id").(string), v.(*schema.Set).List()); err != nil { + // Delete all NACL/Subnet associations, even if they are managed via aws_network_acl_association resources. + nacl, err := FindNetworkACLByID(conn, d.Id()) + + if err != nil { + return fmt.Errorf("error reading EC2 Network ACL (%s): %w", d.Id(), err) + } + + var subnetIDs []interface{} + for _, v := range nacl.Associations { + subnetIDs = append(subnetIDs, aws.StringValue(v.SubnetId)) + } + if len(subnetIDs) > 0 { + if err := networkACLAssociationsDelete(conn, d.Get("vpc_id").(string), subnetIDs); err != nil { return err } } @@ -300,7 +311,7 @@ func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { } log.Printf("[INFO] Deleting EC2 Network ACL: %s", d.Id()) - _, err := tfresource.RetryWhenAWSErrCodeEquals(PropagationTimeout, func() (interface{}, error) { + _, err = tfresource.RetryWhenAWSErrCodeEquals(PropagationTimeout, func() (interface{}, error) { return conn.DeleteNetworkAcl(input) }, ErrCodeDependencyViolation) diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 040caa2d8f4f..6745feef7c71 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -67,6 +67,54 @@ func TestAccEC2NetworkACLAssociation_disappears(t *testing.T) { }) } +func TestAccEC2NetworkACLAssociation_disappears_NACL(t *testing.T) { + var v ec2.NetworkAclAssociation + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_network_acl_association.test" + naclResourceName := "aws_network_acl.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckNetworkACLAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccNetworkACLAssociationConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLAssociationExists(resourceName, &v), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACL(), naclResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccEC2NetworkACLAssociation_disappears_Subnet(t *testing.T) { + var v ec2.NetworkAclAssociation + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_network_acl_association.test" + subnetResourceName := "aws_subnet.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckNetworkACLAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccNetworkACLAssociationConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLAssociationExists(resourceName, &v), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceSubnet(), subnetResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccEC2NetworkACLAssociation_twoAssociations(t *testing.T) { var v1, v2 ec2.NetworkAclAssociation rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) diff --git a/website/docs/r/network_acl.html.markdown b/website/docs/r/network_acl.html.markdown index db83cc4727f0..fe88d0ca2fab 100644 --- a/website/docs/r/network_acl.html.markdown +++ b/website/docs/r/network_acl.html.markdown @@ -17,6 +17,10 @@ defined in-line. At this time you cannot use a Network ACL with in-line rules in conjunction with any Network ACL Rule resources. Doing so will cause a conflict of rule settings and will overwrite rules. +~> **NOTE on Network ACLs and Network ACL Associations:** Terraform provides both a standalone [network ACL association](network_acl_association.html) +resource and a network ACL resource with a `subnet_ids` attribute. Do not use the same subnet ID in both a network ACL +resource and a network ACL association resource. Doing so will cause a conflict of associations and will overwrite the association. + ## Example Usage ```terraform diff --git a/website/docs/r/network_acl_association.markdown b/website/docs/r/network_acl_association.markdown index a961624f060b..7c674e470fb0 100644 --- a/website/docs/r/network_acl_association.markdown +++ b/website/docs/r/network_acl_association.markdown @@ -10,6 +10,10 @@ description: |- Provides an network ACL association resource which allows you to associate your network ACL with any subnet(s). +~> **NOTE on Network ACLs and Network ACL Associations:** Terraform provides both a standalone network ACL association resource +and a [network ACL](network_acl.html) resource with a `subnet_ids` attribute. Do not use the same subnet ID in both a network ACL +resource and a network ACL association resource. Doing so will cause a conflict of associations and will overwrite the association. + ## Example Usage ```terraform From 93ac311188e26531508301fa3e4a04797de10b90 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 09:11:48 -0500 Subject: [PATCH 52/67] r/aws_network_acl: Prevent import of a default NACL. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_ipv6Rules === CONT TestAccEC2NetworkACL_Ingress_mode === CONT TestAccEC2NetworkACL_egressAndIngressRules === CONT TestAccEC2NetworkACL_disappears === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic === CONT TestAccEC2NetworkACL_subnetsDelete === CONT TestAccEC2NetworkACL_subnets === CONT TestAccEC2NetworkACL_subnetChange === CONT TestAccEC2NetworkACL_Egress_mode === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_ipv6VPCRules === CONT TestAccEC2NetworkACL_OnlyIngressRules_update === CONT TestAccEC2NetworkACL_ipv6ICMPRules === CONT TestAccEC2NetworkACL_tags === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges --- PASS: TestAccEC2NetworkACL_disappears (42.27s) --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (43.63s) --- PASS: TestAccEC2NetworkACL_basic (43.78s) --- PASS: TestAccEC2NetworkACL_espProtocol (46.83s) --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (58.18s) --- PASS: TestAccEC2NetworkACL_onlyEgressRules (58.35s) --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (58.35s) --- PASS: TestAccEC2NetworkACL_ipv6Rules (63.57s) --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (64.22s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (64.36s) --- PASS: TestAccEC2NetworkACL_subnetsDelete (79.00s) --- PASS: TestAccEC2NetworkACL_subnets (85.99s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (86.18s) --- PASS: TestAccEC2NetworkACL_subnetChange (91.53s) --- PASS: TestAccEC2NetworkACL_tags (92.37s) --- PASS: TestAccEC2NetworkACL_Egress_mode (99.65s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (99.96s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 104.400s --- internal/service/ec2/network_acl.go | 123 ++++++++++++++++------------ 1 file changed, 71 insertions(+), 52 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 1d9678b3dd01..ab338cc242ec 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -26,57 +26,8 @@ func ResourceNetworkACL() *schema.Resource { Optional: true, Computed: true, ConfigMode: schema.SchemaConfigModeAttr, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - ValidateFunc: validation.StringInSlice(ec2.RuleAction_Values(), true), - }, - "cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, - }, - "from_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "icmp_code": { - Type: schema.TypeInt, - Optional: true, - }, - "icmp_type": { - Type: schema.TypeInt, - Optional: true, - }, - "ipv6_cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: verify.ValidIPv6CIDRNetworkAddress, - }, - "protocol": { - Type: schema.TypeString, - Required: true, - // TODO: Add ValidateFunc. - }, - "rule_no": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 32766), - }, - "to_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - }, - }, - Set: resourceNetworkACLEntryHash, + Elem: networkACLRuleResource, + Set: resourceNetworkACLEntryHash, } return &schema.Resource{ @@ -84,8 +35,23 @@ func ResourceNetworkACL() *schema.Resource { Read: resourceNetworkACLRead, Update: resourceNetworkACLUpdate, Delete: resourceNetworkACLDelete, + Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + conn := meta.(*conns.AWSClient).EC2Conn + + nacl, err := FindNetworkACLByID(conn, d.Id()) + + if err != nil { + return nil, err + } + + if aws.BoolValue(nacl.IsDefault) { + return nil, fmt.Errorf("use the `aws_default_network_acl` resource instead") + } + + return []*schema.ResourceData{d}, nil + }, }, Schema: map[string]*schema.Schema{ @@ -118,6 +84,59 @@ func ResourceNetworkACL() *schema.Resource { } } +// NACL rule Resource definition. +// Used in aws_network_acl and aws_default_network_acl ingress and egress rule sets. +var networkACLRuleResource = &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return strings.EqualFold(old, new) + }, + ValidateFunc: validation.StringInSlice(ec2.RuleAction_Values(), true), + }, + "cidr_block": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, + }, + "from_port": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IsPortNumberOrZero, + }, + "icmp_code": { + Type: schema.TypeInt, + Optional: true, + }, + "icmp_type": { + Type: schema.TypeInt, + Optional: true, + }, + "ipv6_cidr_block": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidIPv6CIDRNetworkAddress, + }, + "protocol": { + Type: schema.TypeString, + Required: true, + // TODO: Add ValidateFunc. + }, + "rule_no": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, 32766), + }, + "to_port": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IsPortNumberOrZero, + }, + }, +} + func resourceNetworkACLCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig From 4ce03d932e08837805c436473475c4a738e13172 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 10:02:03 -0500 Subject: [PATCH 53/67] r/aws_network_acl: Tidy up acceptance tests. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_ipv6Rules === CONT TestAccEC2NetworkACL_subnetsDelete === CONT TestAccEC2NetworkACL_Ingress_mode === CONT TestAccEC2NetworkACL_tags === CONT TestAccEC2NetworkACL_subnets === CONT TestAccEC2NetworkACL_subnetChange === CONT TestAccEC2NetworkACL_egressAndIngressRules === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges === CONT TestAccEC2NetworkACL_OnlyIngressRules_update === CONT TestAccEC2NetworkACL_ipv6VPCRules === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic === CONT TestAccEC2NetworkACL_Egress_mode === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_ipv6ICMPRules === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_disappears (37.88s) --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (39.82s) --- PASS: TestAccEC2NetworkACL_basic (45.33s) --- PASS: TestAccEC2NetworkACL_espProtocol (45.79s) --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (57.17s) --- PASS: TestAccEC2NetworkACL_onlyEgressRules (57.82s) --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (58.57s) --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (60.57s) --- PASS: TestAccEC2NetworkACL_ipv6Rules (62.72s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (62.83s) --- PASS: TestAccEC2NetworkACL_subnets (81.70s) --- PASS: TestAccEC2NetworkACL_subnetsDelete (84.22s) --- PASS: TestAccEC2NetworkACL_tags (90.29s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (91.21s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (95.33s) --- PASS: TestAccEC2NetworkACL_Egress_mode (95.56s) === CONT TestAccEC2NetworkACL_subnetChange network_acl_test.go:409: Step 3/3 error: Error running apply: exit status 1 Error: error creating EC2 Network ACL (acl-0bd2b0339abb92b53) Association: InvalidAssociationID.NotFound: The association ID 'aclassoc-0e845a1f77a8f781e' does not exist status code: 400, request id: 69b4d9e6-0bcd-4ae6-8471-31164a1697b7 with aws_network_acl.test, on terraform_plugin_test.tf line 30, in resource "aws_network_acl" "test": 30: resource "aws_network_acl" "test" { --- FAIL: TestAccEC2NetworkACL_subnetChange (194.20s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 197.905s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/network_acl_test.go | 670 ++++++++++------------- 1 file changed, 296 insertions(+), 374 deletions(-) diff --git a/internal/service/ec2/network_acl_test.go b/internal/service/ec2/network_acl_test.go index f74f63bc3f92..30bf5d88a478 100644 --- a/internal/service/ec2/network_acl_test.go +++ b/internal/service/ec2/network_acl_test.go @@ -5,7 +5,6 @@ import ( "regexp" "testing" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -119,8 +118,9 @@ func TestAccEC2NetworkACL_tags(t *testing.T) { } func TestAccEC2NetworkACL_Egress_mode(t *testing.T) { - var networkAcl1, networkAcl2, networkAcl3 ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -129,10 +129,9 @@ func TestAccEC2NetworkACL_Egress_mode(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLEgressModeBlocksConfig(), + Config: testAccNetworkACLEgressModeBlocksConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl1), - testAccCheckNetworkACLEgressRuleLength(&networkAcl1, 2), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "egress.#", "2"), ), }, @@ -142,10 +141,9 @@ func TestAccEC2NetworkACL_Egress_mode(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLEgressModeNoBlocksConfig(), + Config: testAccNetworkACLEgressModeNoBlocksConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl2), - testAccCheckNetworkACLEgressRuleLength(&networkAcl2, 2), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "egress.#", "2"), ), }, @@ -155,10 +153,9 @@ func TestAccEC2NetworkACL_Egress_mode(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLEgressModeZeroedConfig(), + Config: testAccNetworkACLEgressModeZeroedConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl3), - testAccCheckNetworkACLEgressRuleLength(&networkAcl3, 0), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "egress.#", "0"), ), }, @@ -172,8 +169,9 @@ func TestAccEC2NetworkACL_Egress_mode(t *testing.T) { } func TestAccEC2NetworkACL_Ingress_mode(t *testing.T) { - var networkAcl1, networkAcl2, networkAcl3 ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -182,10 +180,9 @@ func TestAccEC2NetworkACL_Ingress_mode(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLIngressModeBlocksConfig(), + Config: testAccNetworkACLIngressModeBlocksConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl1), - testIngressRuleLength(&networkAcl1, 2), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "ingress.#", "2"), ), }, @@ -195,10 +192,9 @@ func TestAccEC2NetworkACL_Ingress_mode(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLIngressModeNoBlocksConfig(), + Config: testAccNetworkACLIngressModeNoBlocksConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl2), - testIngressRuleLength(&networkAcl2, 2), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "ingress.#", "2"), ), }, @@ -208,10 +204,9 @@ func TestAccEC2NetworkACL_Ingress_mode(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLIngressModeZeroedConfig(), + Config: testAccNetworkACLIngressModeZeroedConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl3), - testIngressRuleLength(&networkAcl3, 0), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "ingress.#", "0"), ), }, @@ -225,8 +220,9 @@ func TestAccEC2NetworkACL_Ingress_mode(t *testing.T) { } func TestAccEC2NetworkACL_egressAndIngressRules(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -235,9 +231,9 @@ func TestAccEC2NetworkACL_egressAndIngressRules(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLEgressNIngressConfig, + Config: testAccNetworkACLEgressNIngressConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "ingress.*", map[string]string{ "protocol": "6", "rule_no": "1", @@ -254,7 +250,6 @@ func TestAccEC2NetworkACL_egressAndIngressRules(t *testing.T) { "action": "allow", "cidr_block": "10.3.0.0/18", }), - acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), ), }, { @@ -267,8 +262,9 @@ func TestAccEC2NetworkACL_egressAndIngressRules(t *testing.T) { } func TestAccEC2NetworkACL_OnlyIngressRules_basic(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -277,9 +273,9 @@ func TestAccEC2NetworkACL_OnlyIngressRules_basic(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLIngressConfig, + Config: testAccNetworkACLIngressConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "ingress.*", map[string]string{ "protocol": "6", "rule_no": "2", @@ -288,7 +284,6 @@ func TestAccEC2NetworkACL_OnlyIngressRules_basic(t *testing.T) { "action": "deny", "cidr_block": "10.2.0.0/18", }), - acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), ), }, { @@ -301,8 +296,9 @@ func TestAccEC2NetworkACL_OnlyIngressRules_basic(t *testing.T) { } func TestAccEC2NetworkACL_OnlyIngressRules_update(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -311,10 +307,10 @@ func TestAccEC2NetworkACL_OnlyIngressRules_update(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLIngressConfig, + Config: testAccNetworkACLIngressConfig(resourceName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testIngressRuleLength(&networkAcl, 2), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "2"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "ingress.*", map[string]string{ "protocol": "6", "rule_no": "1", @@ -327,7 +323,6 @@ func TestAccEC2NetworkACL_OnlyIngressRules_update(t *testing.T) { "from_port": "443", "rule_no": "2", }), - acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), ), }, { @@ -336,10 +331,10 @@ func TestAccEC2NetworkACL_OnlyIngressRules_update(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLIngressChangeConfig, + Config: testAccNetworkACLIngressChangeConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testIngressRuleLength(&networkAcl, 1), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "ingress.*", map[string]string{ "protocol": "6", "rule_no": "1", @@ -348,7 +343,6 @@ func TestAccEC2NetworkACL_OnlyIngressRules_update(t *testing.T) { "action": "deny", "cidr_block": "10.2.0.0/18", }), - acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), ), }, }, @@ -356,8 +350,9 @@ func TestAccEC2NetworkACL_OnlyIngressRules_update(t *testing.T) { } func TestAccEC2NetworkACL_caseSensitivityNoChanges(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -366,9 +361,9 @@ func TestAccEC2NetworkACL_caseSensitivityNoChanges(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLCaseSensitiveConfig, + Config: testAccNetworkACLCaseSensitiveConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), ), }, { @@ -381,8 +376,9 @@ func TestAccEC2NetworkACL_caseSensitivityNoChanges(t *testing.T) { } func TestAccEC2NetworkACL_onlyEgressRules(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -391,12 +387,9 @@ func TestAccEC2NetworkACL_onlyEgressRules(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLEgressConfig, + Config: testAccNetworkACLEgressConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), - resource.TestCheckResourceAttr(resourceName, "tags.Name", "tf-acc-acl-egress"), - resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar"), + testAccCheckNetworkACLExists(resourceName, &v), ), }, { @@ -409,8 +402,9 @@ func TestAccEC2NetworkACL_onlyEgressRules(t *testing.T) { } func TestAccEC2NetworkACL_subnetChange(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -419,10 +413,11 @@ func TestAccEC2NetworkACL_subnetChange(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLSubnetConfig, + Config: testAccNetworkACLSubnetConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.old"), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), ), }, { @@ -431,11 +426,11 @@ func TestAccEC2NetworkACL_subnetChange(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLSubnetChangeConfig, + Config: testAccNetworkACLSubnetChangeConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testAccCheckSubnetIsNotAssociatedWithAcl(resourceName, "aws_subnet.old"), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.new"), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test2", "id"), ), }, }, @@ -444,18 +439,9 @@ func TestAccEC2NetworkACL_subnetChange(t *testing.T) { } func TestAccEC2NetworkACL_subnets(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" - - checkACLSubnets := func(acl *ec2.NetworkAcl, count int) resource.TestCheckFunc { - return func(*terraform.State) (err error) { - if count != len(acl.Associations) { - return fmt.Errorf("ACL association count does not match, expected %d, got %d", count, len(acl.Associations)) - } - - return nil - } - } + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -464,12 +450,12 @@ func TestAccEC2NetworkACL_subnets(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLSubnet_SubnetIDs, + Config: testAccNetworkACLSubnet_SubnetIDs(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.one"), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.two"), - checkACLSubnets(&networkAcl, 2), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test2", "id"), ), }, { @@ -478,13 +464,13 @@ func TestAccEC2NetworkACL_subnets(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLSubnet_SubnetIdsUpdate, + Config: testAccNetworkACLSubnet_SubnetIDsUpdate(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.one"), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.three"), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.four"), - checkACLSubnets(&networkAcl, 3), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "3"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test3", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test4", "id"), ), }, }, @@ -492,18 +478,9 @@ func TestAccEC2NetworkACL_subnets(t *testing.T) { } func TestAccEC2NetworkACL_subnetsDelete(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" - - checkACLSubnets := func(acl *ec2.NetworkAcl, count int) resource.TestCheckFunc { - return func(*terraform.State) (err error) { - if count != len(acl.Associations) { - return fmt.Errorf("ACL association count does not match, expected %d, got %d", count, len(acl.Associations)) - } - - return nil - } - } + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -512,12 +489,12 @@ func TestAccEC2NetworkACL_subnetsDelete(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLSubnet_SubnetIDs, + Config: testAccNetworkACLSubnet_SubnetIDs(resourceName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.one"), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.two"), - checkACLSubnets(&networkAcl, 2), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test2", "id"), ), }, { @@ -526,11 +503,11 @@ func TestAccEC2NetworkACL_subnetsDelete(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccNetworkACLSubnet_SubnetIdsDeleteOne, + Config: testAccNetworkACLSubnet_SubnetIDsDeleteOne(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - testAccCheckSubnetIsAssociatedWithAcl(resourceName, "aws_subnet.one"), - checkACLSubnets(&networkAcl, 1), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), ), }, }, @@ -538,8 +515,9 @@ func TestAccEC2NetworkACL_subnetsDelete(t *testing.T) { } func TestAccEC2NetworkACL_ipv6Rules(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -548,9 +526,9 @@ func TestAccEC2NetworkACL_ipv6Rules(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLIPv6Config, + Config: testAccNetworkACLIPv6Config(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), resource.TestCheckResourceAttr( resourceName, "ingress.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "ingress.*", map[string]string{ @@ -573,9 +551,9 @@ func TestAccEC2NetworkACL_ipv6Rules(t *testing.T) { } func TestAccEC2NetworkACL_ipv6ICMPRules(t *testing.T) { - var networkAcl ec2.NetworkAcl - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -586,7 +564,7 @@ func TestAccEC2NetworkACL_ipv6ICMPRules(t *testing.T) { { Config: testAccNetworkACLIPv6ICMPConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), ), }, }, @@ -594,8 +572,9 @@ func TestAccEC2NetworkACL_ipv6ICMPRules(t *testing.T) { } func TestAccEC2NetworkACL_ipv6VPCRules(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -604,11 +583,10 @@ func TestAccEC2NetworkACL_ipv6VPCRules(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLIPv6VPCConfig, + Config: testAccNetworkACLIPv6VPCConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - resource.TestCheckResourceAttr( - resourceName, "ingress.#", "1"), + testAccCheckNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "ingress.*", map[string]string{ "ipv6_cidr_block": "2600:1f16:d1e:9a00::/56", }), @@ -624,8 +602,9 @@ func TestAccEC2NetworkACL_ipv6VPCRules(t *testing.T) { } func TestAccEC2NetworkACL_espProtocol(t *testing.T) { - var networkAcl ec2.NetworkAcl + var v ec2.NetworkAcl resourceName := "aws_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -634,9 +613,9 @@ func TestAccEC2NetworkACL_espProtocol(t *testing.T) { CheckDestroy: testAccCheckNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLEsp, + Config: testAccNetworkACLEsp(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), + testAccCheckNetworkACLExists(resourceName, &v), ), }, { @@ -697,92 +676,6 @@ func testAccCheckNetworkACLExists(n string, v *ec2.NetworkAcl) resource.TestChec } } -func testAccCheckNetworkACLEgressRuleLength(networkAcl *ec2.NetworkAcl, length int) resource.TestCheckFunc { - return func(s *terraform.State) error { - var entries []*ec2.NetworkAclEntry - for _, entry := range networkAcl.Entries { - if aws.BoolValue(entry.Egress) { - entries = append(entries, entry) - } - } - // There is always a default rule (ALL Traffic ... DENY) - // so we have to increase the length by 1 - if len(entries) != length+1 { - return fmt.Errorf("Invalid number of ingress entries found; count = %d", len(entries)) - } - return nil - } -} - -func testIngressRuleLength(networkAcl *ec2.NetworkAcl, length int) resource.TestCheckFunc { - return func(s *terraform.State) error { - var ingressEntries []*ec2.NetworkAclEntry - for _, e := range networkAcl.Entries { - if !*e.Egress { - ingressEntries = append(ingressEntries, e) - } - } - // There is always a default rule (ALL Traffic ... DENY) - // so we have to increase the length by 1 - if len(ingressEntries) != length+1 { - return fmt.Errorf("Invalid number of ingress entries found; count = %d", len(ingressEntries)) - } - return nil - } -} - -func testAccCheckSubnetIsAssociatedWithAcl(acl string, sub string) resource.TestCheckFunc { - return func(s *terraform.State) error { - networkAcl := s.RootModule().Resources[acl] - subnet := s.RootModule().Resources[sub] - - conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn - resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(networkAcl.Primary.ID)}, - Filters: []*ec2.Filter{ - { - Name: aws.String("association.subnet-id"), - Values: []*string{aws.String(subnet.Primary.ID)}, - }, - }, - }) - if err != nil { - return err - } - if len(resp.NetworkAcls) > 0 { - return nil - } - - return fmt.Errorf("Network Acl %s is not associated with subnet %s", acl, sub) - } -} - -func testAccCheckSubnetIsNotAssociatedWithAcl(acl string, subnet string) resource.TestCheckFunc { - return func(s *terraform.State) error { - networkAcl := s.RootModule().Resources[acl] - subnet := s.RootModule().Resources[subnet] - - conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn - resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(networkAcl.Primary.ID)}, - Filters: []*ec2.Filter{ - { - Name: aws.String("association.subnet-id"), - Values: []*string{aws.String(subnet.Primary.ID)}, - }, - }, - }) - - if err != nil { - return err - } - if len(resp.NetworkAcls) > 0 { - return fmt.Errorf("Network Acl %s is still associated with subnet %s", acl, subnet) - } - return nil - } -} - func testAccNetworkACLConfig(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { @@ -805,7 +698,7 @@ resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = %q + Name = %[1]q } } @@ -824,33 +717,34 @@ resource "aws_network_acl" "test" { } tags = { - Name = %q + Name = %[1]q } } -`, rName, rName) +`, rName) } -const testAccNetworkACLIPv6Config = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLIPv6Config(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-ipv6" + Name = %[1]q } } -resource "aws_subnet" "blob" { +resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-ipv6" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id ingress { protocol = 6 @@ -861,26 +755,28 @@ resource "aws_network_acl" "test" { to_port = 22 } - subnet_ids = [aws_subnet.blob.id] + subnet_ids = [aws_subnet.test.id] tags = { - Name = "tf-acc-acl-ipv6" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLIPv6VPCConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLIPv6VPCConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true tags = { - Name = "terraform-testacc-network-acl-ipv6-vpc-rules" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id ingress { protocol = 6 @@ -892,32 +788,34 @@ resource "aws_network_acl" "test" { } tags = { - Name = "tf-acc-acl-ipv6" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLIngressConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLIngressConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-ingress" + Name = %[1]q } } -resource "aws_subnet" "blob" { +resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-ingress" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id ingress { protocol = 6 @@ -937,35 +835,37 @@ resource "aws_network_acl" "test" { to_port = 443 } - subnet_ids = [aws_subnet.blob.id] + subnet_ids = [aws_subnet.test.id] tags = { - Name = "tf-acc-acl-ingress" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLCaseSensitiveConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLCaseSensitiveConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-ingress" + Name = %[1]q } } -resource "aws_subnet" "blob" { +resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-ingress" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id ingress { protocol = 6 @@ -976,35 +876,37 @@ resource "aws_network_acl" "test" { to_port = 22 } - subnet_ids = [aws_subnet.blob.id] + subnet_ids = [aws_subnet.test.id] tags = { - Name = "tf-acc-acl-case-sensitive" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLIngressChangeConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLIngressChangeConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-ingress" + Name = %[1]q } } -resource "aws_subnet" "blob" { +resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-ingress" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id ingress { protocol = 6 @@ -1015,35 +917,37 @@ resource "aws_network_acl" "test" { to_port = 22 } - subnet_ids = [aws_subnet.blob.id] + subnet_ids = [aws_subnet.test.id] tags = { - Name = "tf-acc-acl-ingress" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLEgressConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLEgressConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.2.0.0/16" tags = { - Name = "terraform-testacc-network-acl-egress" + Name = %[1]q } } -resource "aws_subnet" "blob" { +resource "aws_subnet" "test" { cidr_block = "10.2.0.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-egress" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id egress { protocol = 6 @@ -1082,33 +986,34 @@ resource "aws_network_acl" "test" { } tags = { - foo = "bar" - Name = "tf-acc-acl-egress" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLEgressNIngressConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLEgressNIngressConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "terraform-testacc-network-acl-egress-and-ingress" + Name = %[1]q } } -resource "aws_subnet" "blob" { +resource "aws_subnet" "test" { cidr_block = "10.3.0.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-egress-and-ingress" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id egress { protocol = 6 @@ -1127,231 +1032,247 @@ resource "aws_network_acl" "test" { from_port = 80 to_port = 80 } + + tags = { + Name = %[1]q + } +} +`, rName) } -` -const testAccNetworkACLSubnetConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLSubnetConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-subnet-change" + Name = %[1]q } } -resource "aws_subnet" "old" { +resource "aws_subnet" "test1" { cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-subnet-change-old" + Name = %[1]q } } -resource "aws_subnet" "new" { +resource "aws_subnet" "test2" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-subnet-change-new" + Name = %[1]q } } -resource "aws_network_acl" "roll" { - vpc_id = aws_vpc.foo.id - subnet_ids = [aws_subnet.new.id] +resource "aws_network_acl" "test1" { + vpc_id = aws_vpc.test.id + subnet_ids = [aws_subnet.test2.id] tags = { - Name = "tf-acc-acl-subnet-change-roll" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id - subnet_ids = [aws_subnet.old.id] + vpc_id = aws_vpc.test.id + subnet_ids = [aws_subnet.test1.id] tags = { - Name = "tf-acc-acl-subnet-change-test" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLSubnetChangeConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLSubnetChangeConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-subnet-change" + Name = %[1]q } } -resource "aws_subnet" "old" { +resource "aws_subnet" "test1" { cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-subnet-change-old" + Name = %[1]q } } -resource "aws_subnet" "new" { +resource "aws_subnet" "test2" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id map_public_ip_on_launch = true tags = { - Name = "tf-acc-network-acl-subnet-change-new" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id - subnet_ids = [aws_subnet.new.id] + vpc_id = aws_vpc.test.id + subnet_ids = [aws_subnet.test2.id] tags = { - Name = "tf-acc-acl-subnet-change-test" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLSubnet_SubnetIDs = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLSubnet_SubnetIDs(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-subnet-ids" + Name = %[1]q } } -resource "aws_subnet" "one" { +resource "aws_subnet" "test1" { cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-network-acl-subnet-ids-one" + Name = %[1]q } } -resource "aws_subnet" "two" { +resource "aws_subnet" "test2" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-network-acl-subnet-ids-two" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id - subnet_ids = [aws_subnet.one.id, aws_subnet.two.id] + vpc_id = aws_vpc.test.id + subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] tags = { - Name = "tf-acc-acl-subnet-ids" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLSubnet_SubnetIdsUpdate = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLSubnet_SubnetIDsUpdate(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-subnet-ids" + Name = %[1]q } } -resource "aws_subnet" "one" { +resource "aws_subnet" "test1" { cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-network-acl-subnet-ids-one" + Name = %[1]q } } -resource "aws_subnet" "two" { +resource "aws_subnet" "test2" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-network-acl-subnet-ids-two" + Name = %[1]q } } -resource "aws_subnet" "three" { +resource "aws_subnet" "test3" { cidr_block = "10.1.222.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-network-acl-subnet-ids-three" + Name = %[1]q } } -resource "aws_subnet" "four" { +resource "aws_subnet" "test4" { cidr_block = "10.1.4.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-network-acl-subnet-ids-four" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id subnet_ids = [ - aws_subnet.one.id, - aws_subnet.three.id, - aws_subnet.four.id, + aws_subnet.test1.id, + aws_subnet.test3.id, + aws_subnet.test4.id, ] tags = { - Name = "tf-acc-acl-subnet-ids" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLSubnet_SubnetIdsDeleteOne = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLSubnet_SubnetIDsDeleteOne(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-subnet-ids" + Name = %[1]q } } -resource "aws_subnet" "one" { +resource "aws_subnet" "test1" { cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-network-acl-subnet-ids-one" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.foo.id - subnet_ids = [aws_subnet.one.id] + vpc_id = aws_vpc.test.id + subnet_ids = [aws_subnet.test1.id] tags = { - Name = "tf-acc-acl-subnet-ids" + Name = %[1]q } } -` +`, rName) +} -const testAccNetworkACLEsp = ` -resource "aws_vpc" "testvpc" { +func testAccNetworkACLEsp(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-network-acl-esp" + Name = %[1]q } } resource "aws_network_acl" "test" { - vpc_id = aws_vpc.testvpc.id + vpc_id = aws_vpc.test.id egress { protocol = "esp" @@ -1363,24 +1284,25 @@ resource "aws_network_acl" "test" { } tags = { - Name = "tf-acc-acl-esp" + Name = %[1]q } } -` +`, rName) +} -func testAccNetworkACLEgressModeBlocksConfig() string { - return ` +func testAccNetworkACLEgressModeBlocksConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-network-acl-egress-computed-attribute-mode" + Name = %[1]q } } resource "aws_network_acl" "test" { tags = { - Name = "terraform-testacc-network-acl-egress-computed-attribute-mode" + Name = %[1]q } vpc_id = aws_vpc.test.id @@ -1403,36 +1325,36 @@ resource "aws_network_acl" "test" { to_port = 0 } } -` +`, rName) } -func testAccNetworkACLEgressModeNoBlocksConfig() string { - return ` +func testAccNetworkACLEgressModeNoBlocksConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-network-acl-egress-computed-attribute-mode" + Name = %[1]q } } resource "aws_network_acl" "test" { tags = { - Name = "terraform-testacc-network-acl-egress-computed-attribute-mode" + Name = %[1]q } vpc_id = aws_vpc.test.id } -` +`, rName) } -func testAccNetworkACLEgressModeZeroedConfig() string { - return ` +func testAccNetworkACLEgressModeZeroedConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-network-acl-egress-computed-attribute-mode" + Name = %[1]q } } @@ -1440,27 +1362,27 @@ resource "aws_network_acl" "test" { egress = [] tags = { - Name = "terraform-testacc-network-acl-egress-computed-attribute-mode" + Name = %[1]q } vpc_id = aws_vpc.test.id } -` +`, rName) } -func testAccNetworkACLIngressModeBlocksConfig() string { - return ` +func testAccNetworkACLIngressModeBlocksConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-network-acl-ingress-computed-attribute-mode" + Name = %[1]q } } resource "aws_network_acl" "test" { tags = { - Name = "terraform-testacc-network-acl-ingress-computed-attribute-mode" + Name = %[1]q } vpc_id = aws_vpc.test.id @@ -1483,36 +1405,36 @@ resource "aws_network_acl" "test" { to_port = 0 } } -` +`, rName) } -func testAccNetworkACLIngressModeNoBlocksConfig() string { - return ` +func testAccNetworkACLIngressModeNoBlocksConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-network-acl-ingress-computed-attribute-mode" + Name = %[1]q } } resource "aws_network_acl" "test" { tags = { - Name = "terraform-testacc-network-acl-ingress-computed-attribute-mode" + Name = %[1]q } vpc_id = aws_vpc.test.id } -` +`, rName) } -func testAccNetworkACLIngressModeZeroedConfig() string { - return ` +func testAccNetworkACLIngressModeZeroedConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-network-acl-ingress-computed-attribute-mode" + Name = %[1]q } } @@ -1520,12 +1442,12 @@ resource "aws_network_acl" "test" { ingress = [] tags = { - Name = "terraform-testacc-network-acl-ingress-computed-attribute-mode" + Name = %[1]q } vpc_id = aws_vpc.test.id } -` +`, rName) } func testAccNetworkACLTags1Config(rName, tagKey1, tagValue1 string) string { From dc9c0d4223e35ec487abe866e5504c9e0103930c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 10:15:05 -0500 Subject: [PATCH 54/67] r/aws_network_acl: Validate 'protocol'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_ipv6Rules === CONT TestAccEC2NetworkACL_ipv6VPCRules === CONT TestAccEC2NetworkACL_disappears === CONT TestAccEC2NetworkACL_subnets === CONT TestAccEC2NetworkACL_subnetsDelete === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_ipv6ICMPRules === CONT TestAccEC2NetworkACL_egressAndIngressRules === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges === CONT TestAccEC2NetworkACL_OnlyIngressRules_update === CONT TestAccEC2NetworkACL_subnetChange === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic === CONT TestAccEC2NetworkACL_Egress_mode === CONT TestAccEC2NetworkACL_tags === CONT TestAccEC2NetworkACL_Ingress_mode --- PASS: TestAccEC2NetworkACL_disappears (41.13s) --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (42.72s) --- PASS: TestAccEC2NetworkACL_basic (45.84s) --- PASS: TestAccEC2NetworkACL_espProtocol (46.82s) --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (57.86s) --- PASS: TestAccEC2NetworkACL_onlyEgressRules (59.48s) --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (59.51s) --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (65.03s) --- PASS: TestAccEC2NetworkACL_ipv6Rules (65.04s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (65.33s) --- PASS: TestAccEC2NetworkACL_subnets (85.20s) --- PASS: TestAccEC2NetworkACL_subnetsDelete (85.79s) --- PASS: TestAccEC2NetworkACL_tags (91.47s) --- PASS: TestAccEC2NetworkACL_subnetChange (92.49s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (95.58s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (97.62s) --- PASS: TestAccEC2NetworkACL_Egress_mode (98.92s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 102.739s --- internal/service/ec2/network_acl.go | 49 ++++++++++++++++++----------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index ab338cc242ec..eab8b7fedd8c 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -122,7 +122,15 @@ var networkACLRuleResource = &schema.Resource{ "protocol": { Type: schema.TypeString, Required: true, - // TODO: Add ValidateFunc. + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + _, err := networkACLProtocolNumber(v.(string)) + + if err != nil { + errors = append(errors, fmt.Errorf("%q : %w", k, err)) + } + + return + }, }, "rule_no": { Type: schema.TypeInt, @@ -507,16 +515,11 @@ func expandNetworkAclEntry(tfMap map[string]interface{}, egress bool) *ec2.Netwo } if v, ok := tfMap["protocol"].(string); ok && v != "" { - i, err := strconv.Atoi(v) + i, err := networkACLProtocolNumber(v) if err != nil { - // We're a protocol name. Look up the number. - i, ok = protocolIntegers()[v] - - if !ok { - log.Printf("[WARN] Unsupported protocol: %s", v) - return nil - } + log.Printf("[WARN] %s", err) + return nil } apiObject.Protocol = aws.String(strconv.Itoa(i)) @@ -600,17 +603,11 @@ func flattenNetworkAclEntry(apiObject *ec2.NetworkAclEntry) map[string]interface if v := aws.StringValue(apiObject.Protocol); v != "" { // The AWS network ACL API only speaks protocol numbers, and // that's all we record. - i, err := strconv.Atoi(v) + i, err := networkACLProtocolNumber(v) if err != nil { - // We're a protocol name. Look up the number. - var ok bool - i, ok = protocolIntegers()[v] - - if !ok { - log.Printf("[WARN] Unsupported protocol: %s", v) - return nil - } + log.Printf("[WARN] %s", err) + return nil } tfMap["protocol"] = strconv.Itoa(i) @@ -646,3 +643,19 @@ func flattenNetworkAclEntries(apiObjects []*ec2.NetworkAclEntry) []interface{} { return tfList } + +func networkACLProtocolNumber(v string) (int, error) { + i, err := strconv.Atoi(v) + + if err != nil { + // Lookup number by name. + var ok bool + i, ok = protocolIntegers()[v] + + if !ok { + return 0, fmt.Errorf("unsupported NACL protocol: %s", v) + } + } + + return i, nil +} From b27edef7557b13ea4918c7dbc700079add37dc39 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 11:55:35 -0500 Subject: [PATCH 55/67] r/aws_network_acl: Add 'modifyNetworkACLAttributesOnCreate' and 'deleteNetworkAclEntries'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACL_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACL_' -timeout 180m === RUN TestAccEC2NetworkACL_basic === PAUSE TestAccEC2NetworkACL_basic === RUN TestAccEC2NetworkACL_disappears === PAUSE TestAccEC2NetworkACL_disappears === RUN TestAccEC2NetworkACL_tags === PAUSE TestAccEC2NetworkACL_tags === RUN TestAccEC2NetworkACL_Egress_mode === PAUSE TestAccEC2NetworkACL_Egress_mode === RUN TestAccEC2NetworkACL_Ingress_mode === PAUSE TestAccEC2NetworkACL_Ingress_mode === RUN TestAccEC2NetworkACL_egressAndIngressRules === PAUSE TestAccEC2NetworkACL_egressAndIngressRules === RUN TestAccEC2NetworkACL_OnlyIngressRules_basic === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_basic === RUN TestAccEC2NetworkACL_OnlyIngressRules_update === PAUSE TestAccEC2NetworkACL_OnlyIngressRules_update === RUN TestAccEC2NetworkACL_caseSensitivityNoChanges === PAUSE TestAccEC2NetworkACL_caseSensitivityNoChanges === RUN TestAccEC2NetworkACL_onlyEgressRules === PAUSE TestAccEC2NetworkACL_onlyEgressRules === RUN TestAccEC2NetworkACL_subnetChange === PAUSE TestAccEC2NetworkACL_subnetChange === RUN TestAccEC2NetworkACL_subnets === PAUSE TestAccEC2NetworkACL_subnets === RUN TestAccEC2NetworkACL_subnetsDelete === PAUSE TestAccEC2NetworkACL_subnetsDelete === RUN TestAccEC2NetworkACL_ipv6Rules === PAUSE TestAccEC2NetworkACL_ipv6Rules === RUN TestAccEC2NetworkACL_ipv6ICMPRules === PAUSE TestAccEC2NetworkACL_ipv6ICMPRules === RUN TestAccEC2NetworkACL_ipv6VPCRules === PAUSE TestAccEC2NetworkACL_ipv6VPCRules === RUN TestAccEC2NetworkACL_espProtocol === PAUSE TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_basic === CONT TestAccEC2NetworkACL_onlyEgressRules === CONT TestAccEC2NetworkACL_ipv6Rules === CONT TestAccEC2NetworkACL_Ingress_mode === CONT TestAccEC2NetworkACL_tags === CONT TestAccEC2NetworkACL_ipv6ICMPRules === CONT TestAccEC2NetworkACL_subnetsDelete === CONT TestAccEC2NetworkACL_subnets === CONT TestAccEC2NetworkACL_subnetChange === CONT TestAccEC2NetworkACL_egressAndIngressRules === CONT TestAccEC2NetworkACL_caseSensitivityNoChanges === CONT TestAccEC2NetworkACL_Egress_mode === CONT TestAccEC2NetworkACL_OnlyIngressRules_update === CONT TestAccEC2NetworkACL_OnlyIngressRules_basic === CONT TestAccEC2NetworkACL_ipv6VPCRules === CONT TestAccEC2NetworkACL_espProtocol === CONT TestAccEC2NetworkACL_disappears --- PASS: TestAccEC2NetworkACL_disappears (49.49s) --- PASS: TestAccEC2NetworkACL_ipv6ICMPRules (50.88s) --- PASS: TestAccEC2NetworkACL_basic (52.00s) --- PASS: TestAccEC2NetworkACL_espProtocol (53.85s) --- PASS: TestAccEC2NetworkACL_ipv6VPCRules (67.59s) --- PASS: TestAccEC2NetworkACL_egressAndIngressRules (67.96s) --- PASS: TestAccEC2NetworkACL_onlyEgressRules (68.02s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_basic (72.64s) --- PASS: TestAccEC2NetworkACL_caseSensitivityNoChanges (74.42s) --- PASS: TestAccEC2NetworkACL_ipv6Rules (74.45s) --- PASS: TestAccEC2NetworkACL_subnetsDelete (97.17s) --- PASS: TestAccEC2NetworkACL_subnets (97.74s) --- PASS: TestAccEC2NetworkACL_tags (105.77s) --- PASS: TestAccEC2NetworkACL_OnlyIngressRules_update (106.86s) --- PASS: TestAccEC2NetworkACL_Ingress_mode (113.66s) --- PASS: TestAccEC2NetworkACL_Egress_mode (113.83s) === CONT TestAccEC2NetworkACL_subnetChange network_acl_test.go:409: Step 3/3 error: Error running apply: exit status 1 Error: error creating EC2 Network ACL (acl-08bb876eefe45f372) Association: InvalidAssociationID.NotFound: The association ID 'aclassoc-05d9ca41251fb599a' does not exist status code: 400, request id: c3f6459f-442e-442c-b3c5-5d72e249ea20 with aws_network_acl.test, on terraform_plugin_test.tf line 30, in resource "aws_network_acl" "test": 30: resource "aws_network_acl" "test" { --- FAIL: TestAccEC2NetworkACL_subnetChange (208.10s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 214.359s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/network_acl.go | 52 ++++++++++++++++++----------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index eab8b7fedd8c..dcae2c93e927 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -54,6 +54,8 @@ func ResourceNetworkACL() *schema.Resource { }, }, + // Keep in sync with aws_default_network_acl's schema. + // See notes in default_network_acl.go. Schema: map[string]*schema.Schema{ "arn": { Type: schema.TypeString, @@ -164,24 +166,8 @@ func resourceNetworkACLCreate(d *schema.ResourceData, meta interface{}) error { d.SetId(aws.StringValue(output.NetworkAcl.NetworkAclId)) - if v, ok := d.GetOk("egress"); ok && v.(*schema.Set).Len() > 0 { - if err := createNetworkACLEntries(conn, d.Id(), v.(*schema.Set).List(), true); err != nil { - return err - } - } - - if v, ok := d.GetOk("ingress"); ok && v.(*schema.Set).Len() > 0 { - if err := createNetworkACLEntries(conn, d.Id(), v.(*schema.Set).List(), false); err != nil { - return err - } - } - - if v, ok := d.GetOk("subnet_ids"); ok && v.(*schema.Set).Len() > 0 { - for _, v := range v.(*schema.Set).List() { - if _, err := networkACLAssociationCreate(conn, d.Id(), v.(string)); err != nil { - return err - } - } + if err := modifyNetworkACLAttributesOnCreate(conn, d); err != nil { + return err } return resourceNetworkACLRead(d, meta) @@ -353,6 +339,32 @@ func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { return nil } +// modifyNetworkACLAttributesOnCreate sets NACL attributes on resource Create. +// Called after new NACL creation or existing default NACL adoption. +func modifyNetworkACLAttributesOnCreate(conn *ec2.EC2, d *schema.ResourceData) error { + if v, ok := d.GetOk("egress"); ok && v.(*schema.Set).Len() > 0 { + if err := createNetworkACLEntries(conn, d.Id(), v.(*schema.Set).List(), true); err != nil { + return err + } + } + + if v, ok := d.GetOk("ingress"); ok && v.(*schema.Set).Len() > 0 { + if err := createNetworkACLEntries(conn, d.Id(), v.(*schema.Set).List(), false); err != nil { + return err + } + } + + if v, ok := d.GetOk("subnet_ids"); ok && v.(*schema.Set).Len() > 0 { + for _, v := range v.(*schema.Set).List() { + if _, err := networkACLAssociationCreate(conn, d.Id(), v.(string)); err != nil { + return err + } + } + } + + return nil +} + func resourceNetworkACLEntryHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) @@ -436,8 +448,10 @@ func createNetworkACLEntries(conn *ec2.EC2, naclID string, tfList []interface{}, } func deleteNetworkACLEntries(conn *ec2.EC2, naclID string, tfList []interface{}, egress bool) error { - naclEntries := expandNetworkAclEntries(tfList, egress) + return deleteNetworkAclEntries(conn, naclID, expandNetworkAclEntries(tfList, egress)) +} +func deleteNetworkAclEntries(conn *ec2.EC2, naclID string, naclEntries []*ec2.NetworkAclEntry) error { for _, naclEntry := range naclEntries { if naclEntry == nil { continue From 0b6ab2eab8dae4777a798e7935dd4293053cab81 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 13:06:00 -0500 Subject: [PATCH 56/67] Tweak 'networkACLProtocolNumber'. --- internal/service/ec2/default_network_acl.go | 430 +++----------------- internal/service/ec2/network_acl.go | 109 +++-- 2 files changed, 124 insertions(+), 415 deletions(-) diff --git a/internal/service/ec2/default_network_acl.go b/internal/service/ec2/default_network_acl.go index 57c0b663666f..45295d961473 100644 --- a/internal/service/ec2/default_network_acl.go +++ b/internal/service/ec2/default_network_acl.go @@ -5,10 +5,7 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -24,33 +21,51 @@ const ( ) func ResourceDefaultNetworkACL() *schema.Resource { + networkACLRuleSetSchema := &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: networkACLRuleResource, + Set: resourceNetworkACLEntryHash, + } + return &schema.Resource{ Create: resourceDefaultNetworkACLCreate, - // We reuse aws_network_acl's read method, the operations are the same Read: resourceNetworkACLRead, - Delete: resourceDefaultNetworkACLDelete, Update: resourceDefaultNetworkACLUpdate, + Delete: resourceDefaultNetworkACLDelete, + Importer: &schema.ResourceImporter{ State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { d.Set("default_network_acl_id", d.Id()) + return []*schema.ResourceData{d}, nil }, }, + // Keep in sync with aws_network_acl's schema with the following changes: + // - egress and ingress are not Computed and don't have "Attributes as Blocks" processing mode set + // - subnet_ids is not Computed + // and additions: + // - default_network_acl_id Required/ForceNew Schema: map[string]*schema.Schema{ "arn": { Type: schema.TypeString, Computed: true, }, - "vpc_id": { - Type: schema.TypeString, - Computed: true, - }, "default_network_acl_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, + // We want explicit management of Rules here, so we do not allow them to be + // computed. Instead, an empty config will enforce just that; removal of the + // rules + "egress": networkACLRuleSetSchema, + "ingress": networkACLRuleSetSchema, + "owner_id": { + Type: schema.TypeString, + Computed: true, + }, // We want explicit management of Subnets here, so we do not allow them to be // computed. Instead, an empty config will enforce just that; removal of the // any Subnets that have been assigned to the Default Network ACL. Because we @@ -62,122 +77,9 @@ func ResourceDefaultNetworkACL() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - // We want explicit management of Rules here, so we do not allow them to be - // computed. Instead, an empty config will enforce just that; removal of the - // rules - "ingress": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "from_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "to_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "rule_no": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 32766), - }, - "action": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - ec2.RuleActionAllow, - ec2.RuleActionDeny, - }, true), - }, - "protocol": { - Type: schema.TypeString, - Required: true, - }, - "cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "ipv6_cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "icmp_type": { - Type: schema.TypeInt, - Optional: true, - }, - "icmp_code": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, - Set: resourceNetworkACLEntryHash, - }, - "egress": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "from_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "to_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IsPortNumberOrZero, - }, - "rule_no": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 32766), - }, - "action": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - ec2.RuleActionAllow, - ec2.RuleActionDeny, - }, true), - }, - "protocol": { - Type: schema.TypeString, - Required: true, - }, - "cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "ipv6_cidr_block": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsCIDR, - }, - "icmp_type": { - Type: schema.TypeInt, - Optional: true, - }, - "icmp_code": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, - Set: resourceNetworkACLEntryHash, - }, - "tags": tftags.TagsSchema(), "tags_all": tftags.TagsSchemaComputed(), - - "owner_id": { + "vpc_id": { Type: schema.TypeString, Computed: true, }, @@ -188,277 +90,65 @@ func ResourceDefaultNetworkACL() *schema.Resource { } func resourceDefaultNetworkACLCreate(d *schema.ResourceData, meta interface{}) error { - d.SetId(d.Get("default_network_acl_id").(string)) - - // revoke all default and pre-existing rules on the default network acl. - // In the UPDATE method, we'll apply only the rules in the configuration. - log.Printf("[DEBUG] Revoking default ingress and egress rules for Default Network ACL for %s", d.Id()) - err := revokeAllNetworkACLEntries(d.Id(), meta) - if err != nil { - return err - } - - return resourceDefaultNetworkACLUpdate(d, meta) -} - -func resourceDefaultNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - if d.HasChange("ingress") { - err := updateNetworkAclEntries(d, "ingress", conn) - if err != nil { - return err - } - } - - if d.HasChange("egress") { - err := updateNetworkAclEntries(d, "egress", conn) - if err != nil { - return err - } - } - - if d.HasChange("subnet_ids") { - o, n := d.GetChange("subnet_ids") - if o == nil { - o = new(schema.Set) - } - if n == nil { - n = new(schema.Set) - } - - os := o.(*schema.Set) - ns := n.(*schema.Set) - - remove := os.Difference(ns).List() - add := ns.Difference(os).List() + naclID := d.Get("default_network_acl_id").(string) + nacl, err := FindNetworkACLByID(conn, naclID) - if len(remove) > 0 { - // - // NO-OP - // - // Subnets *must* belong to a Network ACL. Subnets are not "removed" from - // Network ACLs, instead their association is replaced. In a normal - // Network ACL, any removal of a Subnet is done by replacing the - // Subnet/ACL association with an association between the Subnet and the - // Default Network ACL. Because we're managing the default here, we cannot - // do that, so we simply log a NO-OP. In order to remove the Subnet here, - // it must be destroyed, or assigned to different Network ACL. Those - // operations are not handled here - log.Printf("[WARN] Cannot remove subnets from the Default Network ACL. They must be re-assigned or destroyed") - } - - if len(add) > 0 { - for _, a := range add { - association, err := findNetworkAclAssociation(a.(string), conn) - if err != nil { - return fmt.Errorf("Failed to find acl association: acl %s with subnet %s: %s", d.Id(), a, err) - } - log.Printf("[DEBUG] Updating Network Association for Default Network ACL (%s) and Subnet (%s)", d.Id(), a.(string)) - _, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: aws.String(d.Id()), - }) - if err != nil { - return err - } - } - } + if err != nil { + return fmt.Errorf("error reading EC2 Network ACL (%s): %w", d.Id(), err) } - if d.HasChange("tags_all") { - o, n := d.GetChange("tags_all") - - if err := UpdateTags(conn, d.Id(), o, n); err != nil { - return fmt.Errorf("error updating EC2 Default Network ACL (%s) tags: %s", d.Id(), err) - } + if !aws.BoolValue(nacl.IsDefault) { + return fmt.Errorf("use the `aws_network_acl` resource instead") } - // Re-use the exiting Network ACL Resources READ method - return resourceNetworkACLRead(d, meta) -} - -func resourceDefaultNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { - log.Printf("[WARN] Cannot destroy Default Network ACL. Terraform will remove this resource from the state file, however resources may remain.") - return nil -} - -// revokeAllNetworkACLEntries revoke all ingress and egress rules that the Default -// Network ACL currently has -func revokeAllNetworkACLEntries(netaclId string, meta interface{}) error { - conn := meta.(*conns.AWSClient).EC2Conn - - resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(netaclId)}, - }) + d.SetId(naclID) - if err != nil { - log.Printf("[DEBUG] Error looking up Network ACL: %s", err) + // Revoke all default and pre-existing rules on the default network ACL. + if err := deleteNetworkAclEntries(conn, d.Id(), nacl.Entries); err != nil { return err } - if resp == nil { - return fmt.Errorf("Error looking up Default Network ACL Entries: No results") + if err := modifyNetworkACLAttributesOnCreate(conn, d); err != nil { + return err } - networkAcl := resp.NetworkAcls[0] - for _, e := range networkAcl.Entries { - // Skip the default rules added by AWS. They can be neither - // configured or deleted by users. See http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html#default-network-acl - if aws.Int64Value(e.RuleNumber) == defaultACLRuleNumberIPv4 || - aws.Int64Value(e.RuleNumber) == defaultACLRuleNumberIPv6 { - continue - } - - // track if this is an egress or ingress rule, for logging purposes - rt := "ingress" - if aws.BoolValue(e.Egress) { - rt = "egress" - } + // Configure tags. + defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig + ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig + newTags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))).IgnoreConfig(ignoreTagsConfig) + oldTags := KeyValueTags(nacl.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig) - log.Printf("[DEBUG] Destroying Network ACL (%s) Entry number (%d)", rt, int(*e.RuleNumber)) - _, err := conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{ - NetworkAclId: aws.String(netaclId), - RuleNumber: e.RuleNumber, - Egress: e.Egress, - }) - if err != nil { - return fmt.Errorf("Error deleting entry (%s): %s", e, err) + if !oldTags.Equal(newTags) { + if err := UpdateTags(conn, d.Id(), oldTags, newTags); err != nil { + return fmt.Errorf("error updating EC2 Default Network ACL (%s) tags: %w", d.Id(), err) } } - return nil + return resourceNetworkACLRead(d, meta) } -func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssociation *ec2.NetworkAclAssociation, err error) { - req := &ec2.DescribeNetworkAclsInput{} - req.Filters = BuildAttributeFilterList( - map[string]string{ - "association.subnet-id": subnetId, - }, - ) - resp, err := conn.DescribeNetworkAcls(req) - if err != nil { - return nil, err - } +func resourceDefaultNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).EC2Conn - if len(resp.NetworkAcls) > 0 { - for _, association := range resp.NetworkAcls[0].Associations { - if aws.StringValue(association.SubnetId) == subnetId { - return association, nil - } - } + // Subnets *must* belong to a Network ACL. Subnets are not "removed" from + // Network ACLs, instead their association is replaced. In a normal + // Network ACL, any removal of a Subnet is done by replacing the + // Subnet/ACL association with an association between the Subnet and the + // Default Network ACL. Because we're managing the default here, we cannot + // do that, so we simply log a NO-OP. In order to remove the Subnet here, + // it must be destroyed, or assigned to different Network ACL. Those + // operations are not handled here. + if err := modifyNetworkACLAttributesOnUpdate(conn, d, true); err != nil { + return err } - return nil, &resource.NotFoundError{ - LastRequest: req, - LastResponse: resp, - Message: fmt.Sprintf("could not find association for subnet: %s ", subnetId), - } + return resourceNetworkACLRead(d, meta) } -func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2.EC2) error { - if d.HasChange(entryType) { - o, n := d.GetChange(entryType) - - if o == nil { - o = new(schema.Set) - } - if n == nil { - n = new(schema.Set) - } - - os := o.(*schema.Set) - ns := n.(*schema.Set) - - toBeDeleted, err := ExpandNetworkACLEntries(os.Difference(ns).List(), entryType) - if err != nil { - return err - } - for _, remove := range toBeDeleted { - // AWS includes default rules with all network ACLs that can be - // neither modified nor destroyed. They have a custom rule - // number that is out of bounds for any other rule. If we - // encounter it, just continue. There's no work to be done. - if aws.Int64Value(remove.RuleNumber) == defaultACLRuleNumberIPv4 || - aws.Int64Value(remove.RuleNumber) == defaultACLRuleNumberIPv6 { - continue - } - - // Delete old Acl - log.Printf("[DEBUG] Destroying Network ACL Entry number (%d)", int(aws.Int64Value(remove.RuleNumber))) - _, err := conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{ - NetworkAclId: aws.String(d.Id()), - RuleNumber: remove.RuleNumber, - Egress: remove.Egress, - }) - if err != nil { - return fmt.Errorf("Error deleting %s entry: %s", entryType, err) - } - } - - toBeCreated, err := ExpandNetworkACLEntries(ns.Difference(os).List(), entryType) - if err != nil { - return err - } - for _, add := range toBeCreated { - // Protocol -1 rules don't store ports in AWS. Thus, they'll always - // hash differently when being read out of the API. Force the user - // to set from_port and to_port to 0 for these rules, to keep the - // hashing consistent. - if aws.StringValue(add.Protocol) == "-1" { - to := aws.Int64Value(add.PortRange.To) - from := aws.Int64Value(add.PortRange.From) - expected := &ExpectedPortPair{ - to_port: 0, - from_port: 0, - } - if ok := ValidPorts(to, from, *expected); !ok { - return fmt.Errorf( - "to_port (%d) and from_port (%d) must both be 0 to use the the 'all' \"-1\" protocol!", - to, from) - } - } - - // AWS mutates the CIDR block into a network implied by the IP and - // mask provided. This results in hashing inconsistencies between - // the local config file and the state returned by the API. Error - // if the user provides a CIDR block with an inappropriate mask - if cidrBlock := aws.StringValue(add.CidrBlock); cidrBlock != "" { - if err := verify.ValidateIPv4CIDRBlock(cidrBlock); err != nil { - return err - } - } - if ipv6CidrBlock := aws.StringValue(add.Ipv6CidrBlock); ipv6CidrBlock != "" { - if err := verify.ValidateIPv6CIDRBlock(ipv6CidrBlock); err != nil { - return err - } - } - - createOpts := &ec2.CreateNetworkAclEntryInput{ - NetworkAclId: aws.String(d.Id()), - Egress: add.Egress, - PortRange: add.PortRange, - Protocol: add.Protocol, - RuleAction: add.RuleAction, - RuleNumber: add.RuleNumber, - IcmpTypeCode: add.IcmpTypeCode, - } - - if add.CidrBlock != nil && aws.StringValue(add.CidrBlock) != "" { - createOpts.CidrBlock = add.CidrBlock - } - - if add.Ipv6CidrBlock != nil && aws.StringValue(add.Ipv6CidrBlock) != "" { - createOpts.Ipv6CidrBlock = add.Ipv6CidrBlock - } +func resourceDefaultNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { + log.Printf("[WARN] EC2 Default Network ACL (%s) not deleted, removing from state", d.Id()) - // Add new Acl entry - _, connErr := conn.CreateNetworkAclEntry(createOpts) - if connErr != nil { - return fmt.Errorf("Error creating %s entry: %s", entryType, connErr) - } - } - } return nil } diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index dcae2c93e927..64a0fb825ad6 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -252,48 +252,8 @@ func resourceNetworkACLRead(d *schema.ResourceData, meta interface{}) error { func resourceNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - if d.HasChange("ingress") { - o, n := d.GetChange("ingress") - os, ns := o.(*schema.Set), n.(*schema.Set) - - if err := updateNetworkACLEntries(conn, d.Id(), os, ns, false); err != nil { - return err - } - } - - if d.HasChange("egress") { - o, n := d.GetChange("egress") - os, ns := o.(*schema.Set), n.(*schema.Set) - - if err := updateNetworkACLEntries(conn, d.Id(), os, ns, true); err != nil { - return err - } - } - - if d.HasChange("subnet_ids") { - o, n := d.GetChange("subnet_ids") - os, ns := o.(*schema.Set), n.(*schema.Set) - add, del := ns.Difference(os).List(), os.Difference(ns).List() - - if len(del) > 0 { - if err := networkACLAssociationsDelete(conn, d.Get("vpc_id").(string), del); err != nil { - return err - } - } - - if len(add) > 0 { - if err := networkACLAssociationsCreate(conn, d.Id(), add); err != nil { - return err - } - } - } - - if d.HasChange("tags_all") { - o, n := d.GetChange("tags_all") - - if err := UpdateTags(conn, d.Id(), o, n); err != nil { - return fmt.Errorf("error updating EC2 Network ACL (%s) tags: %w", d.Id(), err) - } + if err := modifyNetworkACLAttributesOnUpdate(conn, d, true); err != nil { + return err } return resourceNetworkACLRead(d, meta) @@ -341,6 +301,7 @@ func resourceNetworkACLDelete(d *schema.ResourceData, meta interface{}) error { // modifyNetworkACLAttributesOnCreate sets NACL attributes on resource Create. // Called after new NACL creation or existing default NACL adoption. +// Tags are not configured. func modifyNetworkACLAttributesOnCreate(conn *ec2.EC2, d *schema.ResourceData) error { if v, ok := d.GetOk("egress"); ok && v.(*schema.Set).Len() > 0 { if err := createNetworkACLEntries(conn, d.Id(), v.(*schema.Set).List(), true); err != nil { @@ -365,6 +326,56 @@ func modifyNetworkACLAttributesOnCreate(conn *ec2.EC2, d *schema.ResourceData) e return nil } +// modifyNetworkACLAttributesOnUpdate sets NACL attributes on resource Update. +// Tags are configured. +func modifyNetworkACLAttributesOnUpdate(conn *ec2.EC2, d *schema.ResourceData, deleteEntries bool) error { + if d.HasChange("ingress") { + o, n := d.GetChange("ingress") + os, ns := o.(*schema.Set), n.(*schema.Set) + + if err := updateNetworkACLEntries(conn, d.Id(), os, ns, false, deleteEntries); err != nil { + return err + } + } + + if d.HasChange("egress") { + o, n := d.GetChange("egress") + os, ns := o.(*schema.Set), n.(*schema.Set) + + if err := updateNetworkACLEntries(conn, d.Id(), os, ns, true, deleteEntries); err != nil { + return err + } + } + + if d.HasChange("subnet_ids") { + o, n := d.GetChange("subnet_ids") + os, ns := o.(*schema.Set), n.(*schema.Set) + add, del := ns.Difference(os).List(), os.Difference(ns).List() + + if len(del) > 0 { + if err := networkACLAssociationsDelete(conn, d.Get("vpc_id").(string), del); err != nil { + return err + } + } + + if len(add) > 0 { + if err := networkACLAssociationsCreate(conn, d.Id(), add); err != nil { + return err + } + } + } + + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") + + if err := UpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating EC2 Network ACL (%s) tags: %w", d.Id(), err) + } + } + + return nil +} + func resourceNetworkACLEntryHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) @@ -482,9 +493,11 @@ func deleteNetworkAclEntries(conn *ec2.EC2, naclID string, naclEntries []*ec2.Ne return nil } -func updateNetworkACLEntries(conn *ec2.EC2, naclID string, os, ns *schema.Set, egress bool) error { - if err := deleteNetworkACLEntries(conn, naclID, os.Difference(ns).List(), egress); err != nil { - return err +func updateNetworkACLEntries(conn *ec2.EC2, naclID string, os, ns *schema.Set, egress bool, deleteEntries bool) error { + if deleteEntries { + if err := deleteNetworkACLEntries(conn, naclID, os.Difference(ns).List(), egress); err != nil { + return err + } } if err := createNetworkACLEntries(conn, naclID, ns.Difference(os).List(), egress); err != nil { @@ -669,6 +682,12 @@ func networkACLProtocolNumber(v string) (int, error) { if !ok { return 0, fmt.Errorf("unsupported NACL protocol: %s", v) } + } else { + _, ok := protocolStrings(protocolIntegers())[i] + + if !ok { + return 0, fmt.Errorf("unsupported NACL protocol: %d", i) + } } return i, nil From 6308f6a1b7100c498709e4f45ca5d912b85a81d3 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 13:16:50 -0500 Subject: [PATCH 57/67] r/aws_default_network_acl: All current acceptance tests passing. Acceptance test output: % make testacc TESTS=TestAccEC2DefaultNetworkACL_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2DefaultNetworkACL_' -timeout 180m === RUN TestAccEC2DefaultNetworkACL_basic === PAUSE TestAccEC2DefaultNetworkACL_basic === RUN TestAccEC2DefaultNetworkACL_basicIPv6VPC === PAUSE TestAccEC2DefaultNetworkACL_basicIPv6VPC === RUN TestAccEC2DefaultNetworkACL_Deny_ingress === PAUSE TestAccEC2DefaultNetworkACL_Deny_ingress === RUN TestAccEC2DefaultNetworkACL_withIPv6Ingress === PAUSE TestAccEC2DefaultNetworkACL_withIPv6Ingress === RUN TestAccEC2DefaultNetworkACL_subnetRemoval === PAUSE TestAccEC2DefaultNetworkACL_subnetRemoval === RUN TestAccEC2DefaultNetworkACL_subnetReassign === PAUSE TestAccEC2DefaultNetworkACL_subnetReassign === CONT TestAccEC2DefaultNetworkACL_basic === CONT TestAccEC2DefaultNetworkACL_withIPv6Ingress === CONT TestAccEC2DefaultNetworkACL_subnetRemoval === CONT TestAccEC2DefaultNetworkACL_Deny_ingress === CONT TestAccEC2DefaultNetworkACL_subnetReassign === CONT TestAccEC2DefaultNetworkACL_basicIPv6VPC --- PASS: TestAccEC2DefaultNetworkACL_basic (32.42s) --- PASS: TestAccEC2DefaultNetworkACL_Deny_ingress (33.61s) --- PASS: TestAccEC2DefaultNetworkACL_withIPv6Ingress (33.67s) --- PASS: TestAccEC2DefaultNetworkACL_basicIPv6VPC (45.46s) --- PASS: TestAccEC2DefaultNetworkACL_subnetRemoval (68.42s) --- PASS: TestAccEC2DefaultNetworkACL_subnetReassign (76.87s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 80.645s --- internal/service/ec2/default_network_acl.go | 2 +- internal/service/ec2/network_acl.go | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/internal/service/ec2/default_network_acl.go b/internal/service/ec2/default_network_acl.go index 45295d961473..8ef7d2445fbb 100644 --- a/internal/service/ec2/default_network_acl.go +++ b/internal/service/ec2/default_network_acl.go @@ -140,7 +140,7 @@ func resourceDefaultNetworkACLUpdate(d *schema.ResourceData, meta interface{}) e // do that, so we simply log a NO-OP. In order to remove the Subnet here, // it must be destroyed, or assigned to different Network ACL. Those // operations are not handled here. - if err := modifyNetworkACLAttributesOnUpdate(conn, d, true); err != nil { + if err := modifyNetworkACLAttributesOnUpdate(conn, d, false); err != nil { return err } diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 64a0fb825ad6..11fa4cdfec7d 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -328,12 +328,12 @@ func modifyNetworkACLAttributesOnCreate(conn *ec2.EC2, d *schema.ResourceData) e // modifyNetworkACLAttributesOnUpdate sets NACL attributes on resource Update. // Tags are configured. -func modifyNetworkACLAttributesOnUpdate(conn *ec2.EC2, d *schema.ResourceData, deleteEntries bool) error { +func modifyNetworkACLAttributesOnUpdate(conn *ec2.EC2, d *schema.ResourceData, deleteAssociations bool) error { if d.HasChange("ingress") { o, n := d.GetChange("ingress") os, ns := o.(*schema.Set), n.(*schema.Set) - if err := updateNetworkACLEntries(conn, d.Id(), os, ns, false, deleteEntries); err != nil { + if err := updateNetworkACLEntries(conn, d.Id(), os, ns, false); err != nil { return err } } @@ -342,7 +342,7 @@ func modifyNetworkACLAttributesOnUpdate(conn *ec2.EC2, d *schema.ResourceData, d o, n := d.GetChange("egress") os, ns := o.(*schema.Set), n.(*schema.Set) - if err := updateNetworkACLEntries(conn, d.Id(), os, ns, true, deleteEntries); err != nil { + if err := updateNetworkACLEntries(conn, d.Id(), os, ns, true); err != nil { return err } } @@ -352,7 +352,7 @@ func modifyNetworkACLAttributesOnUpdate(conn *ec2.EC2, d *schema.ResourceData, d os, ns := o.(*schema.Set), n.(*schema.Set) add, del := ns.Difference(os).List(), os.Difference(ns).List() - if len(del) > 0 { + if len(del) > 0 && deleteAssociations { if err := networkACLAssociationsDelete(conn, d.Get("vpc_id").(string), del); err != nil { return err } @@ -493,11 +493,9 @@ func deleteNetworkAclEntries(conn *ec2.EC2, naclID string, naclEntries []*ec2.Ne return nil } -func updateNetworkACLEntries(conn *ec2.EC2, naclID string, os, ns *schema.Set, egress bool, deleteEntries bool) error { - if deleteEntries { - if err := deleteNetworkACLEntries(conn, naclID, os.Difference(ns).List(), egress); err != nil { - return err - } +func updateNetworkACLEntries(conn *ec2.EC2, naclID string, os, ns *schema.Set, egress bool) error { + if err := deleteNetworkACLEntries(conn, naclID, os.Difference(ns).List(), egress); err != nil { + return err } if err := createNetworkACLEntries(conn, naclID, ns.Difference(os).List(), egress); err != nil { From 7fe0b7731064fe26f52e1208a6f629c79da7af9e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 14:52:20 -0500 Subject: [PATCH 58/67] r/aws_default_network_acl: Tidy up acceptance tests. Acceptance test output: % make testacc TESTS=TestAccEC2DefaultNetworkACL_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2DefaultNetworkACL_' -timeout 180m === RUN TestAccEC2DefaultNetworkACL_basic === PAUSE TestAccEC2DefaultNetworkACL_basic === RUN TestAccEC2DefaultNetworkACL_basicIPv6VPC === PAUSE TestAccEC2DefaultNetworkACL_basicIPv6VPC === RUN TestAccEC2DefaultNetworkACL_tags === PAUSE TestAccEC2DefaultNetworkACL_tags === RUN TestAccEC2DefaultNetworkACL_Deny_ingress === PAUSE TestAccEC2DefaultNetworkACL_Deny_ingress === RUN TestAccEC2DefaultNetworkACL_withIPv6Ingress === PAUSE TestAccEC2DefaultNetworkACL_withIPv6Ingress === RUN TestAccEC2DefaultNetworkACL_subnetRemoval === PAUSE TestAccEC2DefaultNetworkACL_subnetRemoval === RUN TestAccEC2DefaultNetworkACL_subnetReassign === PAUSE TestAccEC2DefaultNetworkACL_subnetReassign === CONT TestAccEC2DefaultNetworkACL_basic === CONT TestAccEC2DefaultNetworkACL_withIPv6Ingress === CONT TestAccEC2DefaultNetworkACL_Deny_ingress === CONT TestAccEC2DefaultNetworkACL_tags === CONT TestAccEC2DefaultNetworkACL_basicIPv6VPC === CONT TestAccEC2DefaultNetworkACL_subnetRemoval === CONT TestAccEC2DefaultNetworkACL_subnetReassign --- PASS: TestAccEC2DefaultNetworkACL_basic (36.95s) --- PASS: TestAccEC2DefaultNetworkACL_Deny_ingress (37.92s) --- PASS: TestAccEC2DefaultNetworkACL_withIPv6Ingress (37.99s) --- PASS: TestAccEC2DefaultNetworkACL_basicIPv6VPC (46.17s) --- PASS: TestAccEC2DefaultNetworkACL_subnetRemoval (66.14s) --- PASS: TestAccEC2DefaultNetworkACL_subnetReassign (72.55s) --- PASS: TestAccEC2DefaultNetworkACL_tags (78.94s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 82.958s --- .../service/ec2/default_network_acl_test.go | 448 +++++++++--------- 1 file changed, 234 insertions(+), 214 deletions(-) diff --git a/internal/service/ec2/default_network_acl_test.go b/internal/service/ec2/default_network_acl_test.go index 4c0b3bbda825..fbff0c869cd4 100644 --- a/internal/service/ec2/default_network_acl_test.go +++ b/internal/service/ec2/default_network_acl_test.go @@ -7,30 +7,19 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" ) -var defaultEgressAcl = &ec2.NetworkAclEntry{ - CidrBlock: aws.String("0.0.0.0/0"), - Egress: aws.Bool(true), - Protocol: aws.String("-1"), - RuleAction: aws.String("allow"), - RuleNumber: aws.Int64(100), -} -var ipv6IngressAcl = &ec2.NetworkAclEntry{ - Ipv6CidrBlock: aws.String("::/0"), - Egress: aws.Bool(false), - Protocol: aws.String("-1"), - RuleAction: aws.String("allow"), - RuleNumber: aws.Int64(101), -} - func TestAccEC2DefaultNetworkACL_basic(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_default_network_acl.default" + var v ec2.NetworkAcl + resourceName := "aws_default_network_acl.test" + vpcResourceName := "aws_vpc.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -39,12 +28,16 @@ func TestAccEC2DefaultNetworkACL_basic(t *testing.T) { CheckDestroy: testAccCheckDefaultNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccDefaultNetworkConfig_basic, + Config: testAccDefaultNetworkACLConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), + testAccCheckDefaultNetworkACLExists(resourceName, &v), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`network-acl/acl-.+`)), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{}, 0, 2), + resource.TestCheckResourceAttr(resourceName, "egress.#", "0"), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "0"), acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttrPair(resourceName, "vpc_id", vpcResourceName, "id"), ), }, { @@ -57,8 +50,37 @@ func TestAccEC2DefaultNetworkACL_basic(t *testing.T) { } func TestAccEC2DefaultNetworkACL_basicIPv6VPC(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_default_network_acl.default" + var v ec2.NetworkAcl + resourceName := "aws_default_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckDefaultNetworkACLDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDefaultNetworkACLIPv6Config(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "egress.#", "0"), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccEC2DefaultNetworkACL_tags(t *testing.T) { + var v ec2.NetworkAcl + resourceName := "aws_default_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -67,10 +89,11 @@ func TestAccEC2DefaultNetworkACL_basicIPv6VPC(t *testing.T) { CheckDestroy: testAccCheckDefaultNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccDefaultNetworkConfig_basicIPv6VPC, + Config: testAccDefaultNetworkACLTags1Config(rName, "key1", "value1"), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{}, 0, 4), + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), }, { @@ -78,16 +101,31 @@ func TestAccEC2DefaultNetworkACL_basicIPv6VPC(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccDefaultNetworkACLTags2Config(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccDefaultNetworkACLTags1Config(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, }, }) } func TestAccEC2DefaultNetworkACL_Deny_ingress(t *testing.T) { - // TestAccEC2DefaultNetworkACL_Deny_ingress will deny all Ingress rules, but - // not Egress. We then expect there to be 3 rules, 2 AWS defaults and 1 - // additional Egress. - var networkAcl ec2.NetworkAcl - resourceName := "aws_default_network_acl.default" + var v ec2.NetworkAcl + resourceName := "aws_default_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -96,10 +134,19 @@ func TestAccEC2DefaultNetworkACL_Deny_ingress(t *testing.T) { CheckDestroy: testAccCheckDefaultNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccDefaultNetworkConfig_deny_ingress, + Config: testAccDefaultNetworkACLDenyIngressConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{defaultEgressAcl}, 0, 2), + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "egress.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "egress.*", map[string]string{ + "protocol": "-1", + "rule_no": "100", + "from_port": "0", + "to_port": "0", + "action": "allow", + "cidr_block": "0.0.0.0/0", + }), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "0"), ), }, { @@ -112,8 +159,9 @@ func TestAccEC2DefaultNetworkACL_Deny_ingress(t *testing.T) { } func TestAccEC2DefaultNetworkACL_withIPv6Ingress(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_default_network_acl.default" + var v ec2.NetworkAcl + resourceName := "aws_default_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -122,10 +170,19 @@ func TestAccEC2DefaultNetworkACL_withIPv6Ingress(t *testing.T) { CheckDestroy: testAccCheckDefaultNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccDefaultNetworkConfig_includingIPv6Rule, + Config: testAccDefaultNetworkACLIncludingIPv6RuleConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{ipv6IngressAcl}, 0, 2), + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "egress.#", "0"), + resource.TestCheckResourceAttr(resourceName, "ingress.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "ingress.*", map[string]string{ + "protocol": "-1", + "rule_no": "101", + "from_port": "0", + "to_port": "0", + "action": "allow", + "ipv6_cidr_block": "::/0", + }), ), }, { @@ -138,8 +195,9 @@ func TestAccEC2DefaultNetworkACL_withIPv6Ingress(t *testing.T) { } func TestAccEC2DefaultNetworkACL_subnetRemoval(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_default_network_acl.default" + var v ec2.NetworkAcl + resourceName := "aws_default_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -148,10 +206,12 @@ func TestAccEC2DefaultNetworkACL_subnetRemoval(t *testing.T) { CheckDestroy: testAccCheckDefaultNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccDefaultNetworkConfig_Subnets, + Config: testAccDefaultNetworkACLSubnetsConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{}, 2, 2), + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test2", "id"), ), }, { @@ -159,15 +219,13 @@ func TestAccEC2DefaultNetworkACL_subnetRemoval(t *testing.T) { ImportState: true, ImportStateVerify: true, }, - // Here the Subnets have been removed from the Default Network ACL Config, // but have not been reassigned. The result is that the Subnets are still // there, and we have a non-empty plan { - Config: testAccDefaultNetworkConfig_Subnets_remove, + Config: testAccDefaultNetworkACLSubnetsRemoveConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{}, 2, 2), + testAccCheckDefaultNetworkACLExists(resourceName, &v), ), ExpectNonEmptyPlan: true, }, @@ -181,8 +239,9 @@ func TestAccEC2DefaultNetworkACL_subnetRemoval(t *testing.T) { } func TestAccEC2DefaultNetworkACL_subnetReassign(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_default_network_acl.default" + var v ec2.NetworkAcl + resourceName := "aws_default_network_acl.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -191,10 +250,12 @@ func TestAccEC2DefaultNetworkACL_subnetReassign(t *testing.T) { CheckDestroy: testAccCheckDefaultNetworkACLDestroy, Steps: []resource.TestStep{ { - Config: testAccDefaultNetworkConfig_Subnets, + Config: testAccDefaultNetworkACLSubnetsConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{}, 2, 2), + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test2", "id"), ), }, { @@ -202,7 +263,6 @@ func TestAccEC2DefaultNetworkACL_subnetReassign(t *testing.T) { ImportState: true, ImportStateVerify: true, }, - // Here we've reassigned the subnets to a different ACL. // Without any otherwise association between the `aws_network_acl` and // `aws_default_network_acl` resources, we cannot guarantee that the @@ -216,10 +276,10 @@ func TestAccEC2DefaultNetworkACL_subnetReassign(t *testing.T) { // update occurs first, and the former's READ will correctly read zero // subnets { - Config: testAccDefaultNetworkConfig_Subnets_move, + Config: testAccDefaultNetworkACLSubnetsMoveConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccGetDefaultNetworkACL(resourceName, &networkAcl), - testAccCheckDefaultACLAttributes(&networkAcl, []*ec2.NetworkAclEntry{}, 0, 2), + testAccCheckDefaultNetworkACLExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), ), }, { @@ -232,32 +292,11 @@ func TestAccEC2DefaultNetworkACL_subnetReassign(t *testing.T) { } func testAccCheckDefaultNetworkACLDestroy(s *terraform.State) error { - // We can't destroy this resource; it comes and goes with the VPC itself. + // The default NACL is not deleted. return nil } -func testAccCheckDefaultACLAttributes(acl *ec2.NetworkAcl, rules []*ec2.NetworkAclEntry, subnetCount int, hiddenRuleCount int) resource.TestCheckFunc { - return func(s *terraform.State) error { - - aclEntriesCount := len(acl.Entries) - ruleCount := len(rules) - - // Default ACL has hidden rules we can't do anything about - ruleCount = ruleCount + hiddenRuleCount - - if ruleCount != aclEntriesCount { - return fmt.Errorf("Expected (%d) Rules, got (%d)", ruleCount, aclEntriesCount) - } - - if len(acl.Associations) != subnetCount { - return fmt.Errorf("Expected (%d) Subnets, got (%d)", subnetCount, len(acl.Associations)) - } - - return nil - } -} - -func testAccGetDefaultNetworkACL(n string, networkAcl *ec2.NetworkAcl) resource.TestCheckFunc { +func testAccCheckDefaultNetworkACLExists(n string, v *ec2.NetworkAcl) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -265,252 +304,233 @@ func testAccGetDefaultNetworkACL(n string, networkAcl *ec2.NetworkAcl) resource. } if rs.Primary.ID == "" { - return fmt.Errorf("No Network ACL is set") + return fmt.Errorf("No EC2 Default Network ACL ID is set: %s", n) } + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn - resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(rs.Primary.ID)}, - }) + output, err := tfec2.FindNetworkACLByID(conn, rs.Primary.ID) + if err != nil { return err } - if len(resp.NetworkAcls) > 0 && - aws.StringValue(resp.NetworkAcls[0].NetworkAclId) == rs.Primary.ID { - *networkAcl = *resp.NetworkAcls[0] - return nil + if !aws.BoolValue(output.IsDefault) { + return fmt.Errorf("EC2 Network ACL %s is not a default NACL", rs.Primary.ID) } - return fmt.Errorf("Network Acls not found") + *v = *output + + return nil } } -const testAccDefaultNetworkConfig_basic = ` -resource "aws_vpc" "tftestvpc" { +func testAccDefaultNetworkACLConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-default-network-acl-basic" + Name = %[1]q } } -resource "aws_default_network_acl" "default" { - default_network_acl_id = aws_vpc.tftestvpc.default_network_acl_id - - tags = { - Name = "tf-acc-default-acl-basic" - } +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id +} +`, rName) } -` -const testAccDefaultNetworkConfig_includingIPv6Rule = ` -resource "aws_vpc" "tftestvpc" { +func testAccDefaultNetworkACLTags1Config(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-default-network-acl-including-ipv6-rule" + Name = %[1]q } } -resource "aws_default_network_acl" "default" { - default_network_acl_id = aws_vpc.tftestvpc.default_network_acl_id - - ingress { - protocol = -1 - rule_no = 101 - action = "allow" - ipv6_cidr_block = "::/0" - from_port = 0 - to_port = 0 - } +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id tags = { - Name = "tf-acc-default-acl-basic-including-ipv6-rule" + %[2]q = %[3]q } } -` +`, rName, tagKey1, tagValue1) +} -const testAccDefaultNetworkConfig_deny_ingress = ` -resource "aws_vpc" "tftestvpc" { +func testAccDefaultNetworkACLTags2Config(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-default-network-acl-deny-ingress" + Name = %[1]q } } -resource "aws_default_network_acl" "default" { - default_network_acl_id = aws_vpc.tftestvpc.default_network_acl_id - - egress { - protocol = -1 - rule_no = 100 - action = "allow" - cidr_block = "0.0.0.0/0" - from_port = 0 - to_port = 0 - } +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id tags = { - Name = "tf-acc-default-acl-deny-ingress" + %[2]q = %[3]q + %[4]q = %[5]q } } -` +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} -const testAccDefaultNetworkConfig_Subnets = ` -resource "aws_vpc" "foo" { +func testAccDefaultNetworkACLIncludingIPv6RuleConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-default-network-acl-subnets" + Name = %[1]q } } -resource "aws_subnet" "one" { - cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id - tags = { - Name = "tf-acc-default-network-acl-one" + ingress { + protocol = -1 + rule_no = 101 + action = "allow" + ipv6_cidr_block = "::/0" + from_port = 0 + to_port = 0 } } - -resource "aws_subnet" "two" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id - - tags = { - Name = "tf-acc-default-network-acl-two" - } +`, rName) } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id +func testAccDefaultNetworkACLDenyIngressConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" tags = { - Name = "tf-acc-default-acl-subnets" + Name = %[1]q } } -resource "aws_default_network_acl" "default" { - default_network_acl_id = aws_vpc.foo.default_network_acl_id - - subnet_ids = [aws_subnet.one.id, aws_subnet.two.id] +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id - tags = { - Name = "tf-acc-default-acl-subnets" + egress { + protocol = -1 + rule_no = 100 + action = "allow" + cidr_block = "0.0.0.0/0" + from_port = 0 + to_port = 0 } } -` +`, rName) +} -const testAccDefaultNetworkConfig_Subnets_remove = ` -resource "aws_vpc" "foo" { +func testAccDefaultNetworkACLSubnetsBaseConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-default-network-acl-subnets-remove" + Name = %[1]q } } -resource "aws_subnet" "one" { +resource "aws_subnet" "test1" { cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-default-network-acl-subnets-remove-one" + Name = %[1]q } } -resource "aws_subnet" "two" { +resource "aws_subnet" "test2" { cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-default-network-acl-subnets-remove-two" + Name = %[1]q } } - -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id - - tags = { - Name = "tf-acc-default-acl-subnets-remove" - } +`, rName) } -resource "aws_default_network_acl" "default" { - default_network_acl_id = aws_vpc.foo.default_network_acl_id +func testAccDefaultNetworkACLSubnetsConfig(rName string) string { + return acctest.ConfigCompose(testAccDefaultNetworkACLSubnetsBaseConfig(rName), fmt.Sprintf(` +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-default-acl-subnets-remove" + Name = %[1]q } } -` -const testAccDefaultNetworkConfig_Subnets_move = ` -resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id - tags = { - Name = "terraform-testacc-default-network-acl-subnets-move" - } + subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] +} +`, rName)) } -resource "aws_subnet" "one" { - cidr_block = "10.1.111.0/24" - vpc_id = aws_vpc.foo.id +func testAccDefaultNetworkACLSubnetsRemoveConfig(rName string) string { + return acctest.ConfigCompose(testAccDefaultNetworkACLSubnetsBaseConfig(rName), fmt.Sprintf(` +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-default-network-acl-subnets-move-one" + Name = %[1]q } } -resource "aws_subnet" "two" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.foo.id +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id - tags = { - Name = "tf-acc-default-network-acl-subnets-move-two" - } + depends_on = [aws_network_acl.test] +} +`, rName)) } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id +func testAccDefaultNetworkACLSubnetsMoveConfig(rName string) string { + return acctest.ConfigCompose(testAccDefaultNetworkACLSubnetsBaseConfig(rName), fmt.Sprintf(` +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id - subnet_ids = [aws_subnet.one.id, aws_subnet.two.id] + subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] tags = { - Name = "tf-acc-default-acl-subnets-move" + Name = %[1]q } } -resource "aws_default_network_acl" "default" { - default_network_acl_id = aws_vpc.foo.default_network_acl_id - - depends_on = [aws_network_acl.bar] +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id - tags = { - Name = "tf-acc-default-acl-subnets-move" - } + depends_on = [aws_network_acl.test] +} +`, rName)) } -` -const testAccDefaultNetworkConfig_basicIPv6VPC = ` -resource "aws_vpc" "tftestvpc" { +func testAccDefaultNetworkACLIPv6Config(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true tags = { - Name = "terraform-testacc-default-network-acl-basic-ipv6-vpc" + Name = %[1]q } } -resource "aws_default_network_acl" "default" { - default_network_acl_id = aws_vpc.tftestvpc.default_network_acl_id - - tags = { - Name = "tf-acc-default-acl-subnets-basic-ipv6-vpc" - } +resource "aws_default_network_acl" "test" { + default_network_acl_id = aws_vpc.test.default_network_acl_id +} +`, rName) } -` From 0bd6c95146f4cfee6324d807af72da7eff3e8ad5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 16:37:00 -0500 Subject: [PATCH 59/67] Add CHANGELOG entry. --- .changelog/18807.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/18807.txt diff --git a/.changelog/18807.txt b/.changelog/18807.txt new file mode 100644 index 000000000000..257fbffb64b3 --- /dev/null +++ b/.changelog/18807.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_network_acl_association +``` From a5fc988e16af693edd493dff99639aefb6ae0933 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 7 Feb 2022 17:17:21 -0500 Subject: [PATCH 60/67] r/aws_network_acl_rule: Tidy up. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLRule_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLRule_' -timeout 180m === RUN TestAccEC2NetworkACLRule_basic === PAUSE TestAccEC2NetworkACLRule_basic === RUN TestAccEC2NetworkACLRule_disappears === PAUSE TestAccEC2NetworkACLRule_disappears === RUN TestAccEC2NetworkACLRule_Disappears_networkACL === PAUSE TestAccEC2NetworkACLRule_Disappears_networkACL === RUN TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === PAUSE TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === RUN TestAccEC2NetworkACLRule_ipv6 === PAUSE TestAccEC2NetworkACLRule_ipv6 === RUN TestAccEC2NetworkACLRule_ipv6ICMP === PAUSE TestAccEC2NetworkACLRule_ipv6ICMP === RUN TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === PAUSE TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === RUN TestAccEC2NetworkACLRule_allProtocol === PAUSE TestAccEC2NetworkACLRule_allProtocol === RUN TestAccEC2NetworkACLRule_tcpProtocol === PAUSE TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_basic === CONT TestAccEC2NetworkACLRule_ipv6ICMP === CONT TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_allProtocol === CONT TestAccEC2NetworkACLRule_ipv6 === CONT TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === CONT TestAccEC2NetworkACLRule_Disappears_networkACL === CONT TestAccEC2NetworkACLRule_disappears === CONT TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === CONT TestAccEC2NetworkACLRule_allProtocol network_acl_rule_test.go:213: Step 1/2 error: After applying this test step, the plan was not empty. stdout: Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: -/+ destroy and then create replacement Terraform will perform the following actions: # aws_network_acl_rule.baz must be replaced -/+ resource "aws_network_acl_rule" "baz" { ~ from_port = 0 -> 22 # forces replacement - icmp_code = 0 -> null - icmp_type = 0 -> null ~ id = "nacl-2142537903" -> (known after apply) ~ to_port = 0 -> 22 # forces replacement # (6 unchanged attributes hidden) } Plan: 1 to add, 0 to change, 1 to destroy. --- FAIL: TestAccEC2NetworkACLRule_allProtocol (30.33s) === CONT TestAccEC2NetworkACLRule_ipv6 network_acl_rule_test.go:125: Failed state verification, resource with ID nacl-1741481141 not found === CONT TestAccEC2NetworkACLRule_basic network_acl_rule_test.go:22: Failed state verification, resource with ID nacl-2880102436 not found --- PASS: TestAccEC2NetworkACLRule_Disappears_networkACL (38.29s) --- PASS: TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber (40.48s) --- PASS: TestAccEC2NetworkACLRule_disappears (40.87s) --- PASS: TestAccEC2NetworkACLRule_ipv6ICMP (41.53s) --- FAIL: TestAccEC2NetworkACLRule_ipv6 (41.70s) --- FAIL: TestAccEC2NetworkACLRule_basic (43.98s) === CONT TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate network_acl_rule_test.go:179: Step 2/3 error: Error running apply: exit status 1 Error: Provider produced inconsistent final plan When expanding the plan for aws_network_acl_rule.test to include new values learned so far during apply, provider "registry.terraform.io/hashicorp/aws" produced an invalid new value for .ipv6_cidr_block: was cty.StringVal(""), but now cty.StringVal("2600:1f14:35a:af00::/56"). This is a bug in the provider, which should be reported in the provider's own issue tracker. --- PASS: TestAccEC2NetworkACLRule_tcpProtocol (61.55s) --- FAIL: TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate (62.64s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 66.490s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/errors.go | 1 + internal/service/ec2/find.go | 52 +-- internal/service/ec2/network_acl.go | 10 +- internal/service/ec2/network_acl_rule.go | 277 +++++++--------- internal/service/ec2/network_acl_rule_test.go | 295 +++++------------- 5 files changed, 221 insertions(+), 414 deletions(-) diff --git a/internal/service/ec2/errors.go b/internal/service/ec2/errors.go index a3459abd609d..5c3d862d1cdb 100644 --- a/internal/service/ec2/errors.go +++ b/internal/service/ec2/errors.go @@ -34,6 +34,7 @@ const ( ErrCodeInvalidInstanceIDNotFound = "InvalidInstanceID.NotFound" ErrCodeInvalidInternetGatewayIDNotFound = "InvalidInternetGatewayID.NotFound" ErrCodeInvalidKeyPairNotFound = "InvalidKeyPair.NotFound" + ErrCodeInvalidNetworkAclEntryNotFound = "InvalidNetworkAclEntry.NotFound" ErrCodeInvalidNetworkAclIDNotFound = "InvalidNetworkAclID.NotFound" ErrCodeInvalidNetworkInterfaceIDNotFound = "InvalidNetworkInterfaceID.NotFound" ErrCodeInvalidParameter = "InvalidParameter" diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index aac1cfb25aa0..c3235c14d7a6 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -2,6 +2,7 @@ package ec2 import ( "fmt" + "strconv" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" @@ -794,57 +795,28 @@ func FindNetworkACLAssociationBySubnetID(conn *ec2.EC2, subnetID string) (*ec2.N return nil, &resource.NotFoundError{} } -// FindNetworkACLEntry looks up a FindNetworkACLEntry by Network ACL ID, Egress, and Rule Number. When not found, returns nil and potentially an API error. -func FindNetworkACLEntry(conn *ec2.EC2, networkAclID string, egress bool, ruleNumber int) (*ec2.NetworkAclEntry, error) { +func FindNetworkACLEntry(conn *ec2.EC2, naclID string, egress bool, ruleNumber int) (*ec2.NetworkAclEntry, error) { input := &ec2.DescribeNetworkAclsInput{ - Filters: []*ec2.Filter{ - { - Name: aws.String("entry.egress"), - Values: aws.StringSlice([]string{fmt.Sprintf("%t", egress)}), - }, - { - Name: aws.String("entry.rule-number"), - Values: aws.StringSlice([]string{fmt.Sprintf("%d", ruleNumber)}), - }, - }, - NetworkAclIds: aws.StringSlice([]string{networkAclID}), + Filters: BuildAttributeFilterList(map[string]string{ + "entry.egress": strconv.FormatBool(egress), + "entry.rule-number": strconv.Itoa(ruleNumber), + }), + NetworkAclIds: aws.StringSlice([]string{naclID}), } - output, err := conn.DescribeNetworkAcls(input) + output, err := FindNetworkACL(conn, input) if err != nil { return nil, err } - if output == nil { - return nil, nil - } - - for _, networkAcl := range output.NetworkAcls { - if networkAcl == nil { - continue - } - - if aws.StringValue(networkAcl.NetworkAclId) != networkAclID { - continue - } - - for _, entry := range output.NetworkAcls[0].Entries { - if entry == nil { - continue - } - - if aws.BoolValue(entry.Egress) != egress || aws.Int64Value(entry.RuleNumber) != int64(ruleNumber) { - continue - } - - return entry, nil + for _, v := range output.Entries { + if aws.BoolValue(v.Egress) == egress && aws.Int64Value(v.RuleNumber) == int64(ruleNumber) { + return v, nil } } - return nil, nil - - // TODO: Layer on top of FindNetworkACL and modify callers to handle NotFoundError. + return nil, &resource.NotFoundError{} } func FindNetworkInterface(conn *ec2.EC2, input *ec2.DescribeNetworkInterfacesInput) (*ec2.NetworkInterface, error) { diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index 11fa4cdfec7d..f078959614cd 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -540,17 +540,17 @@ func expandNetworkAclEntry(tfMap map[string]interface{}, egress bool) *ec2.Netwo } if v, ok := tfMap["protocol"].(string); ok && v != "" { - i, err := networkACLProtocolNumber(v) + protocolNumber, err := networkACLProtocolNumber(v) if err != nil { log.Printf("[WARN] %s", err) return nil } - apiObject.Protocol = aws.String(strconv.Itoa(i)) + apiObject.Protocol = aws.String(strconv.Itoa(protocolNumber)) // Specify additional required fields for ICMP. - if i == 1 || i == 58 { + if protocolNumber == 1 || protocolNumber == 58 { apiObject.IcmpTypeCode = &ec2.IcmpTypeCode{} if v, ok := tfMap["icmp_code"].(int); ok { @@ -628,14 +628,14 @@ func flattenNetworkAclEntry(apiObject *ec2.NetworkAclEntry) map[string]interface if v := aws.StringValue(apiObject.Protocol); v != "" { // The AWS network ACL API only speaks protocol numbers, and // that's all we record. - i, err := networkACLProtocolNumber(v) + protocolNumber, err := networkACLProtocolNumber(v) if err != nil { log.Printf("[WARN] %s", err) return nil } - tfMap["protocol"] = strconv.Itoa(i) + tfMap["protocol"] = strconv.Itoa(protocolNumber) } if apiObject := apiObject.IcmpTypeCode; apiObject != nil { diff --git a/internal/service/ec2/network_acl_rule.go b/internal/service/ec2/network_acl_rule.go index 98139fe0829e..2f57739fbbc9 100644 --- a/internal/service/ec2/network_acl_rule.go +++ b/internal/service/ec2/network_acl_rule.go @@ -10,8 +10,8 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -22,6 +22,7 @@ func ResourceNetworkACLRule() *schema.Resource { Create: resourceNetworkACLRuleCreate, Read: resourceNetworkACLRuleRead, Delete: resourceNetworkACLRuleDelete, + Importer: &schema.ResourceImporter{ State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { idParts := strings.Split(d.Id(), ":") @@ -48,21 +49,43 @@ func ResourceNetworkACLRule() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "network_acl_id": { - Type: schema.TypeString, - Required: true, + "cidr_block": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ExactlyOneOf: []string{"cidr_block", "ipv6_cidr_block"}, + }, + "egress": { + Type: schema.TypeBool, + Optional: true, ForceNew: true, + Default: false, }, - "rule_number": { + "from_port": { Type: schema.TypeInt, - Required: true, + Optional: true, ForceNew: true, }, - "egress": { - Type: schema.TypeBool, + "icmp_code": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "icmp_type": { + Type: schema.TypeInt, Optional: true, ForceNew: true, - Default: false, + }, + "ipv6_cidr_block": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ExactlyOneOf: []string{"cidr_block", "ipv6_cidr_block"}, + }, + "network_acl_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, }, "protocol": { Type: schema.TypeString, @@ -79,27 +102,28 @@ func ResourceNetworkACLRule() *schema.Resource { return old == new }, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + _, err := networkACLProtocolNumber(v.(string)) + + if err != nil { + errors = append(errors, fmt.Errorf("%q : %w", k, err)) + } + + return + }, }, "rule_action": { Type: schema.TypeString, Required: true, ForceNew: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return strings.EqualFold(old, new) + }, + ValidateFunc: validation.StringInSlice(ec2.RuleAction_Values(), true), }, - "cidr_block": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ConflictsWith: []string{"ipv6_cidr_block"}, - }, - "ipv6_cidr_block": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ConflictsWith: []string{"cidr_block"}, - }, - "from_port": { + "rule_number": { Type: schema.TypeInt, - Optional: true, + Required: true, ForceNew: true, }, "to_port": { @@ -107,179 +131,120 @@ func ResourceNetworkACLRule() *schema.Resource { Optional: true, ForceNew: true, }, - "icmp_type": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: ValidICMPArgumentValue, - }, - "icmp_code": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: ValidICMPArgumentValue, - }, }, } } func resourceNetworkACLRuleCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - egress := d.Get("egress").(bool) - networkAclID := d.Get("network_acl_id").(string) - ruleNumber := d.Get("rule_number").(int) - protocol := d.Get("protocol").(string) - p, protocolErr := strconv.Atoi(protocol) - if protocolErr != nil { - var ok bool - p, ok = protocolIntegers()[protocol] - if !ok { - return fmt.Errorf("Invalid Protocol %s for rule %d", protocol, d.Get("rule_number").(int)) - } + protocolNumber, err := networkACLProtocolNumber(d.Get("protocol").(string)) + + if err != nil { + return err } - log.Printf("[INFO] Transformed Protocol %s into %d", protocol, p) - params := &ec2.CreateNetworkAclEntryInput{ - NetworkAclId: aws.String(networkAclID), + protocol := strconv.Itoa(protocolNumber) + egress := d.Get("egress").(bool) + naclID := d.Get("network_acl_id").(string) + ruleNumber := d.Get("rule_number").(int) + + input := &ec2.CreateNetworkAclEntryInput{ Egress: aws.Bool(egress), - RuleNumber: aws.Int64(int64(ruleNumber)), - Protocol: aws.String(strconv.Itoa(p)), - RuleAction: aws.String(d.Get("rule_action").(string)), + NetworkAclId: aws.String(naclID), PortRange: &ec2.PortRange{ From: aws.Int64(int64(d.Get("from_port").(int))), To: aws.Int64(int64(d.Get("to_port").(int))), }, + Protocol: aws.String(protocol), + RuleAction: aws.String(d.Get("rule_action").(string)), + RuleNumber: aws.Int64(int64(ruleNumber)), } - cidr, hasCidr := d.GetOk("cidr_block") - ipv6Cidr, hasIpv6Cidr := d.GetOk("ipv6_cidr_block") - - if !hasCidr && !hasIpv6Cidr { - return fmt.Errorf("Either `cidr_block` or `ipv6_cidr_block` must be defined") - } - - if hasCidr { - params.CidrBlock = aws.String(cidr.(string)) + if v, ok := d.GetOk("cidr_block"); ok { + input.CidrBlock = aws.String(v.(string)) } - if hasIpv6Cidr { - params.Ipv6CidrBlock = aws.String(ipv6Cidr.(string)) + if v, ok := d.GetOk("ipv6_cidr_block"); ok { + input.Ipv6CidrBlock = aws.String(v.(string)) } // Specify additional required fields for ICMP. For the list // of ICMP codes and types, see: https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml - if p == 1 || p == 58 { - params.IcmpTypeCode = &ec2.IcmpTypeCode{} - if v, ok := d.GetOk("icmp_type"); ok { - icmpType, err := strconv.Atoi(v.(string)) - if err != nil { - return fmt.Errorf("Unable to parse ICMP type %s for rule %d", v, ruleNumber) - } - params.IcmpTypeCode.Type = aws.Int64(int64(icmpType)) - log.Printf("[DEBUG] Got ICMP type %d for rule %d", icmpType, ruleNumber) - } - if v, ok := d.GetOk("icmp_code"); ok { - icmpCode, err := strconv.Atoi(v.(string)) - if err != nil { - return fmt.Errorf("Unable to parse ICMP code %s for rule %d", v, ruleNumber) - } - params.IcmpTypeCode.Code = aws.Int64(int64(icmpCode)) - log.Printf("[DEBUG] Got ICMP code %d for rule %d", icmpCode, ruleNumber) + if protocolNumber == 1 || protocolNumber == 58 { + input.IcmpTypeCode = &ec2.IcmpTypeCode{ + Code: aws.Int64(int64(d.Get("icmp_code").(int))), + Type: aws.Int64(int64(d.Get("icmp_type").(int))), } } - log.Printf("[INFO] Creating Network Acl Rule: %d (%t)", ruleNumber, egress) - _, err := conn.CreateNetworkAclEntry(params) + log.Printf("[DEBUG] Creating EC2 Network ACL Rule: %s", input) + _, err = conn.CreateNetworkAclEntry(input) if err != nil { - return fmt.Errorf("error creating Network ACL (%s) Egress (%t) Rule (%d): %w", networkAclID, egress, ruleNumber, err) + return fmt.Errorf("error creating EC2 Network ACL (%s) Rule (egress:%t)(%d): %w", naclID, egress, ruleNumber, err) } - d.SetId(networkAclIdRuleNumberEgressHash(networkAclID, ruleNumber, egress, d.Get("protocol").(string))) + d.SetId(networkAclIdRuleNumberEgressHash(naclID, ruleNumber, egress, protocol)) return resourceNetworkACLRuleRead(d, meta) } func resourceNetworkACLRuleRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn + egress := d.Get("egress").(bool) - networkAclID := d.Get("network_acl_id").(string) + naclID := d.Get("network_acl_id").(string) ruleNumber := d.Get("rule_number").(int) - var resp *ec2.NetworkAclEntry - - err := resource.Retry(NetworkACLEntryPropagationTimeout, func() *resource.RetryError { - var err error - - resp, err = FindNetworkACLEntry(conn, networkAclID, egress, ruleNumber) - - if d.IsNewResource() && tfawserr.ErrCodeEquals(err, "InvalidNetworkAclID.NotFound") { - return resource.RetryableError(err) - } - - if err != nil { - return resource.NonRetryableError(err) - } + outputRaw, err := tfresource.RetryWhenNewResourceNotFound(PropagationTimeout, func() (interface{}, error) { + return FindNetworkACLEntry(conn, naclID, egress, ruleNumber) + }, d.IsNewResource()) - if d.IsNewResource() && resp == nil { - return resource.RetryableError(&resource.NotFoundError{ - LastError: fmt.Errorf("EC2 Network ACL (%s) Egress (%t) Rule (%d) not found", networkAclID, egress, ruleNumber), - }) - } - - return nil - }) - - if tfresource.TimedOut(err) { - resp, err = FindNetworkACLEntry(conn, networkAclID, egress, ruleNumber) - } - - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "InvalidNetworkAclID.NotFound") { - log.Printf("[WARN] EC2 Network ACL (%s) not found, removing from state", networkAclID) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] EC2 Network ACL Rule %s not found, removing from state", d.Id()) d.SetId("") return nil } if err != nil { - return fmt.Errorf("error reading EC2 Network ACL (%s) Egress (%t) Rule (%d): %w", networkAclID, egress, ruleNumber, err) - } - - if resp == nil { - if d.IsNewResource() { - return fmt.Errorf("error reading EC2 Network ACL (%s) Egress (%t) Rule (%d): not found after creation", networkAclID, egress, ruleNumber) - } - - log.Printf("[WARN] EC2 Network ACL (%s) Egress (%t) Rule (%d) not found, removing from state", networkAclID, egress, ruleNumber) - d.SetId("") - return nil + return fmt.Errorf("error reading EC2 Network ACL Rule (%s): %w", d.Id(), err) } - d.Set("rule_number", resp.RuleNumber) - d.Set("cidr_block", resp.CidrBlock) - d.Set("ipv6_cidr_block", resp.Ipv6CidrBlock) - d.Set("egress", resp.Egress) - if resp.IcmpTypeCode != nil { - d.Set("icmp_code", strconv.FormatInt(aws.Int64Value(resp.IcmpTypeCode.Code), 10)) - d.Set("icmp_type", strconv.FormatInt(aws.Int64Value(resp.IcmpTypeCode.Type), 10)) + naclEntry := outputRaw.(*ec2.NetworkAclEntry) + + d.Set("cidr_block", naclEntry.CidrBlock) + d.Set("egress", naclEntry.Egress) + d.Set("ipv6_cidr_block", naclEntry.Ipv6CidrBlock) + if naclEntry.IcmpTypeCode != nil { + d.Set("icmp_code", naclEntry.IcmpTypeCode.Code) + d.Set("icmp_type", naclEntry.IcmpTypeCode.Type) + } else { + d.Set("icmp_code", nil) + d.Set("icmp_type", nil) } - if resp.PortRange != nil { - d.Set("from_port", resp.PortRange.From) - d.Set("to_port", resp.PortRange.To) + if naclEntry.PortRange != nil { + d.Set("from_port", naclEntry.PortRange.From) + d.Set("to_port", naclEntry.PortRange.To) + } else { + d.Set("from_port", nil) + d.Set("to_port", nil) } + d.Set("rule_action", naclEntry.RuleAction) + d.Set("rule_number", naclEntry.RuleNumber) - d.Set("rule_action", resp.RuleAction) + if v := aws.StringValue(naclEntry.Protocol); v != "" { + // The AWS network ACL API only speaks protocol numbers, and + // that's all we record. + protocolNumber, err := networkACLProtocolNumber(v) - p, protocolErr := strconv.Atoi(*resp.Protocol) - log.Printf("[INFO] Converting the protocol %v", p) - if protocolErr == nil { - var ok bool - protocol, ok := protocolStrings(protocolIntegers())[p] - if !ok { - return fmt.Errorf("Invalid Protocol %s for rule %d", *resp.Protocol, d.Get("rule_number").(int)) + if err != nil { + return err } - log.Printf("[INFO] Transformed Protocol %s back into %s", *resp.Protocol, protocol) - d.Set("protocol", protocol) + + d.Set("protocol", strconv.Itoa(protocolNumber)) + } else { + d.Set("protocol", nil) } return nil @@ -288,16 +253,19 @@ func resourceNetworkACLRuleRead(d *schema.ResourceData, meta interface{}) error func resourceNetworkACLRuleDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - params := &ec2.DeleteNetworkAclEntryInput{ + log.Printf("[INFO] Deleting EC2 Network ACL Rule: %s", d.Id()) + _, err := conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{ + Egress: aws.Bool(d.Get("egress").(bool)), NetworkAclId: aws.String(d.Get("network_acl_id").(string)), RuleNumber: aws.Int64(int64(d.Get("rule_number").(int))), - Egress: aws.Bool(d.Get("egress").(bool)), + }) + + if tfawserr.ErrCodeEquals(err, ErrCodeInvalidNetworkAclEntryNotFound) { + return nil } - log.Printf("[INFO] Deleting Network Acl Rule: %s", d.Id()) - _, err := conn.DeleteNetworkAclEntry(params) if err != nil { - return fmt.Errorf("Error Deleting Network Acl Rule: %s", err.Error()) + return fmt.Errorf("error deleting EC2 Network ACL Rule (%s): %w", d.Id(), err) } return nil @@ -311,12 +279,3 @@ func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egres buf.WriteString(fmt.Sprintf("%s-", protocol)) return fmt.Sprintf("nacl-%d", create.StringHashcode(buf.String())) } - -func ValidICMPArgumentValue(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - _, err := strconv.Atoi(value) - if len(value) == 0 || err != nil { - errors = append(errors, fmt.Errorf("%q must be an integer value: %q", k, value)) - } - return -} diff --git a/internal/service/ec2/network_acl_rule_test.go b/internal/service/ec2/network_acl_rule_test.go index 21feb838ea07..4d6fb1d61fab 100644 --- a/internal/service/ec2/network_acl_rule_test.go +++ b/internal/service/ec2/network_acl_rule_test.go @@ -6,8 +6,6 @@ import ( "strconv" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -15,9 +13,12 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func TestAccEC2NetworkACLRule_basic(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), @@ -25,29 +26,17 @@ func TestAccEC2NetworkACLRule_basic(t *testing.T) { CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleBasicConfig, + Config: testAccNetworkACLRuleConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.baz"), - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.qux"), - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.wibble"), + testAccCheckNetworkACLRuleExists("aws_network_acl_rule.test1"), + testAccCheckNetworkACLRuleExists("aws_network_acl_rule.test2"), + testAccCheckNetworkACLRuleExists("aws_network_acl_rule.test3"), ), }, { - ResourceName: "aws_network_acl_rule.baz", - ImportState: true, - ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc("aws_network_acl_rule.baz", "tcp"), - ImportStateVerify: true, - }, - { - ResourceName: "aws_network_acl_rule.qux", + ResourceName: "aws_network_acl_rule.test1", ImportState: true, - ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc("aws_network_acl_rule.qux", "icmp"), - ImportStateVerify: true, - }, - { - ResourceName: "aws_network_acl_rule.wibble", - ImportState: true, - ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc("aws_network_acl_rule.wibble", "icmp"), + ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc("aws_network_acl_rule.test1", "tcp"), ImportStateVerify: true, }, }, @@ -55,6 +44,9 @@ func TestAccEC2NetworkACLRule_basic(t *testing.T) { } func TestAccEC2NetworkACLRule_disappears(t *testing.T) { + resourceName := "aws_network_acl_rule.test1" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), @@ -62,10 +54,10 @@ func TestAccEC2NetworkACLRule_disappears(t *testing.T) { CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleBasicConfig, + Config: testAccNetworkACLRuleConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.baz"), - testAccCheckNetworkACLRuleDelete("aws_network_acl_rule.baz"), + testAccCheckNetworkACLRuleExists(resourceName), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACLRule(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -73,7 +65,10 @@ func TestAccEC2NetworkACLRule_disappears(t *testing.T) { }) } -func TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber(t *testing.T) { +func TestAccEC2NetworkACLRule_Disappears_networkACL(t *testing.T) { + resourceName := "aws_network_acl_rule.test1" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), @@ -81,10 +76,10 @@ func TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber(t *testing.T) { CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleIngressEgressSameNumberMissing, + Config: testAccNetworkACLRuleConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.baz"), - testAccCheckNetworkACLRuleDelete("aws_network_acl_rule.baz"), + testAccCheckNetworkACLRuleExists(resourceName), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACL(), "aws_network_acl.test"), ), ExpectNonEmptyPlan: true, }, @@ -92,9 +87,9 @@ func TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber(t *testing.T) { }) } -func TestAccEC2NetworkACLRule_Disappears_networkACL(t *testing.T) { - var networkAcl ec2.NetworkAcl - resourceName := "aws_network_acl.bar" +func TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber(t *testing.T) { + resourceName := "aws_network_acl_rule.test1" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -103,10 +98,10 @@ func TestAccEC2NetworkACLRule_Disappears_networkACL(t *testing.T) { CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleBasicConfig, + Config: testAccNetworkACLRuleIngressEgressSameNumberMissingConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLExists(resourceName, &networkAcl), - acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACL(), resourceName), + testAccCheckNetworkACLRuleExists(resourceName), + acctest.CheckResourceDisappears(acctest.Provider, tfec2.ResourceNetworkACLRule(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -114,21 +109,6 @@ func TestAccEC2NetworkACLRule_Disappears_networkACL(t *testing.T) { }) } -func TestAccEC2NetworkACLRule_missingParam(t *testing.T) { - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), - Providers: acctest.Providers, - CheckDestroy: testAccCheckNetworkACLRuleDestroy, - Steps: []resource.TestStep{ - { - Config: testAccNetworkACLRuleMissingParam, - ExpectError: regexp.MustCompile("Either `cidr_block` or `ipv6_cidr_block` must be defined"), - }, - }, - }) -} - func TestAccEC2NetworkACLRule_ipv6(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -255,85 +235,39 @@ func TestAccEC2NetworkACLRule_tcpProtocol(t *testing.T) { }) } -func TestNetworkACLRule_validateICMPArgumentValue(t *testing.T) { - type testCases struct { - Value string - ErrCount int - } - - invalidCases := []testCases{ - { - Value: "", - ErrCount: 1, - }, - { - Value: "not-a-number", - ErrCount: 1, - }, - { - Value: "1.0", - ErrCount: 1, - }, - } +func testAccCheckNetworkACLRuleDestroy(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn - for _, tc := range invalidCases { - _, errors := tfec2.ValidICMPArgumentValue(tc.Value, "icmp_type") - if len(errors) != tc.ErrCount { - t.Fatalf("Expected %q to trigger a validation error.", tc.Value) + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_network_acl_rule" { + continue } - } - validCases := []testCases{ - { - Value: "0", - ErrCount: 0, - }, - { - Value: "-1", - ErrCount: 0, - }, - { - Value: "1", - ErrCount: 0, - }, - } + egress, err := strconv.ParseBool(rs.Primary.Attributes["egress"]) - for _, tc := range validCases { - _, errors := tfec2.ValidICMPArgumentValue(tc.Value, "icmp_type") - if len(errors) != tc.ErrCount { - t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) + if err != nil { + return err } - } -} + naclID := rs.Primary.Attributes["network_acl_id"] -func testAccCheckNetworkACLRuleDestroy(s *terraform.State) error { - for _, rs := range s.RootModule().Resources { - conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn - if rs.Type != "aws_network_acl_rule" { - continue - } + ruleNumber, err := strconv.Atoi(rs.Primary.Attributes["rule_number"]) - req := &ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(rs.Primary.ID)}, - } - resp, err := conn.DescribeNetworkAcls(req) - if err == nil { - if len(resp.NetworkAcls) > 0 && *resp.NetworkAcls[0].NetworkAclId == rs.Primary.ID { - networkAcl := resp.NetworkAcls[0] - if networkAcl.Entries != nil { - return fmt.Errorf("Network ACL Entries still exist") - } - } + if err != nil { + return err } - ec2err, ok := err.(awserr.Error) - if !ok { - return err + _, err = tfec2.FindNetworkACLEntry(conn, naclID, egress, ruleNumber) + + if tfresource.NotFound(err) { + continue } - if ec2err.Code() != "InvalidNetworkAclID.NotFound" { + + if err != nil { return err } + + return fmt.Errorf("EC2 Network ACL Rule %s still exists", rs.Primary.ID) } return nil @@ -348,89 +282,53 @@ func testAccCheckNetworkACLRuleExists(n string) resource.TestCheckFunc { } if rs.Primary.ID == "" { - return fmt.Errorf("No Network ACL Rule Id is set") + return fmt.Errorf("No EC2 Network ACL Rule ID is set: %s", n) } - req := &ec2.DescribeNetworkAclsInput{ - NetworkAclIds: []*string{aws.String(rs.Primary.Attributes["network_acl_id"])}, - } - resp, err := conn.DescribeNetworkAcls(req) - if err != nil { - return err - } - if len(resp.NetworkAcls) != 1 { - return fmt.Errorf("Network ACL not found") - } egress, err := strconv.ParseBool(rs.Primary.Attributes["egress"]) + if err != nil { return err } - ruleNo, err := strconv.ParseInt(rs.Primary.Attributes["rule_number"], 10, 64) - if err != nil { - return err - } - for _, e := range resp.NetworkAcls[0].Entries { - if *e.RuleNumber == ruleNo && *e.Egress == egress { - return nil - } - } - return fmt.Errorf("Entry not found: %s", resp.NetworkAcls[0]) - } -} -func testAccCheckNetworkACLRuleDelete(n string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } + naclID := rs.Primary.Attributes["network_acl_id"] - if rs.Primary.ID == "" { - return fmt.Errorf("No Network ACL Rule Id is set") - } + ruleNumber, err := strconv.Atoi(rs.Primary.Attributes["rule_number"]) - egress, err := strconv.ParseBool(rs.Primary.Attributes["egress"]) - if err != nil { - return err - } - ruleNo, err := strconv.ParseInt(rs.Primary.Attributes["rule_number"], 10, 64) if err != nil { return err } - conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn - _, err = conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{ - NetworkAclId: aws.String(rs.Primary.Attributes["network_acl_id"]), - RuleNumber: aws.Int64(ruleNo), - Egress: aws.Bool(egress), - }) + _, err = tfec2.FindNetworkACLEntry(conn, naclID, egress, ruleNumber) + if err != nil { - return fmt.Errorf("Error deleting Network ACL Rule (%s) in testAccCheckNetworkACLRuleDelete: %s", rs.Primary.ID, err) + return err } return nil } } -const testAccNetworkACLRuleBasicConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLRuleConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "terraform-testacc-network-acl-rule-basic" + Name = %[1]q } } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-acl-rule-basic" + Name = %[1]q } } -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test1" { + network_acl_id = aws_network_acl.test.id rule_number = 200 egress = false protocol = "tcp" @@ -440,8 +338,8 @@ resource "aws_network_acl_rule" "baz" { to_port = 22 } -resource "aws_network_acl_rule" "qux" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test2" { + network_acl_id = aws_network_acl.test.id rule_number = 300 protocol = "icmp" rule_action = "allow" @@ -450,8 +348,8 @@ resource "aws_network_acl_rule" "qux" { icmp_code = -1 } -resource "aws_network_acl_rule" "wibble" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test3" { + network_acl_id = aws_network_acl.test.id rule_number = 400 protocol = "icmp" rule_action = "allow" @@ -459,36 +357,9 @@ resource "aws_network_acl_rule" "wibble" { icmp_type = -1 icmp_code = -1 } -` - -const testAccNetworkACLRuleMissingParam = ` -resource "aws_vpc" "foo" { - cidr_block = "10.3.0.0/16" - - tags = { - Name = "terraform-testacc-network-acl-rule-missing-param" - } +`, rName) } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id - - tags = { - Name = "tf-acc-acl-rule-missing-param" - } -} - -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id - rule_number = 200 - egress = false - protocol = "tcp" - rule_action = "allow" - from_port = 22 - to_port = 22 -} -` - const testAccNetworkACLRuleAllProtocolNoRealUpdateConfig = ` resource "aws_vpc" "foo" { cidr_block = "10.3.0.0/16" @@ -622,25 +493,26 @@ resource "aws_network_acl_rule" "baz" { } ` -const testAccNetworkACLRuleIngressEgressSameNumberMissing = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLRuleIngressEgressSameNumberMissingConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "terraform-testacc-network-acl-rule-ingress-egress-same-number-missing" + Name = %[1]q } } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-acl-rule-basic" + Name = %[1]q } } -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test1" { + network_acl_id = aws_network_acl.test.id rule_number = 100 egress = false protocol = "tcp" @@ -650,8 +522,8 @@ resource "aws_network_acl_rule" "baz" { to_port = 22 } -resource "aws_network_acl_rule" "qux" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test2" { + network_acl_id = aws_network_acl.test.id rule_number = 100 egress = true protocol = "tcp" @@ -660,7 +532,8 @@ resource "aws_network_acl_rule" "qux" { from_port = 22 to_port = 22 } -` +`, rName) +} func testAccNetworkACLRuleIPv6ICMPConfig(rName string) string { return fmt.Sprintf(` @@ -747,8 +620,9 @@ func testAccNetworkACLRuleImportStateIdFunc(resourceName, resourceProtocol strin return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[resourceName] if !ok { - return "", fmt.Errorf("not found: %s", resourceName) + 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"] @@ -757,6 +631,7 @@ func testAccNetworkACLRuleImportStateIdFunc(resourceName, resourceProtocol strin protocol = resourceProtocol } egress := rs.Primary.Attributes["egress"] + return fmt.Sprintf("%s:%s:%s:%s", networkAclId, ruleNumber, protocol, egress), nil } } From 987e576579ce1606a10a9557a68551ad7c9ceffa Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Feb 2022 08:58:56 -0500 Subject: [PATCH 61/67] r/aws_network_acl_rule: Tidy up acceptance tests. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLRule_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLRule_' -timeout 180m === RUN TestAccEC2NetworkACLRule_basic === PAUSE TestAccEC2NetworkACLRule_basic === RUN TestAccEC2NetworkACLRule_disappears === PAUSE TestAccEC2NetworkACLRule_disappears === RUN TestAccEC2NetworkACLRule_Disappears_networkACL === PAUSE TestAccEC2NetworkACLRule_Disappears_networkACL === RUN TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === PAUSE TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === RUN TestAccEC2NetworkACLRule_ipv6 === PAUSE TestAccEC2NetworkACLRule_ipv6 === RUN TestAccEC2NetworkACLRule_ipv6ICMP === PAUSE TestAccEC2NetworkACLRule_ipv6ICMP === RUN TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === PAUSE TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === RUN TestAccEC2NetworkACLRule_allProtocol === PAUSE TestAccEC2NetworkACLRule_allProtocol === RUN TestAccEC2NetworkACLRule_tcpProtocol === PAUSE TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_basic === CONT TestAccEC2NetworkACLRule_ipv6ICMP === CONT TestAccEC2NetworkACLRule_ipv6 === CONT TestAccEC2NetworkACLRule_Disappears_networkACL === CONT TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === CONT TestAccEC2NetworkACLRule_disappears === CONT TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === CONT TestAccEC2NetworkACLRule_allProtocol === CONT TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate network_acl_rule_test.go:239: Step 1/3 error: Check failed: Check 2/4 error: Not found: aws_network_acl_rule.test === CONT TestAccEC2NetworkACLRule_allProtocol network_acl_rule_test.go:277: Step 1/2 error: Check failed: 2 errors occurred: * Check 4/11 error: aws_network_acl_rule.test: Attribute 'from_port' expected "22", got "0" * Check 11/11 error: aws_network_acl_rule.test: Attribute 'to_port' expected "22", got "0" --- FAIL: TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate (24.54s) --- FAIL: TestAccEC2NetworkACLRule_allProtocol (26.51s) === CONT TestAccEC2NetworkACLRule_ipv6 network_acl_rule_test.go:164: Failed state verification, resource with ID nacl-4107606206 not found === CONT TestAccEC2NetworkACLRule_basic network_acl_rule_test.go:25: Failed state verification, resource with ID nacl-996638004 not found --- PASS: TestAccEC2NetworkACLRule_Disappears_networkACL (37.50s) --- PASS: TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber (39.23s) --- PASS: TestAccEC2NetworkACLRule_disappears (39.81s) --- PASS: TestAccEC2NetworkACLRule_ipv6ICMP (42.25s) --- FAIL: TestAccEC2NetworkACLRule_ipv6 (42.27s) --- FAIL: TestAccEC2NetworkACLRule_basic (43.06s) --- PASS: TestAccEC2NetworkACLRule_tcpProtocol (55.81s) FAIL FAIL github.com/hashicorp/terraform-provider-aws/internal/service/ec2 59.862s FAIL make: *** [testacc] Error 1 --- internal/service/ec2/network_acl_rule_test.go | 293 +++++++++++++----- 1 file changed, 209 insertions(+), 84 deletions(-) diff --git a/internal/service/ec2/network_acl_rule_test.go b/internal/service/ec2/network_acl_rule_test.go index 4d6fb1d61fab..717d4b7bb01f 100644 --- a/internal/service/ec2/network_acl_rule_test.go +++ b/internal/service/ec2/network_acl_rule_test.go @@ -17,6 +17,9 @@ import ( ) func TestAccEC2NetworkACLRule_basic(t *testing.T) { + resource1Name := "aws_network_acl_rule.test1" + resource2Name := "aws_network_acl_rule.test2" + resource3Name := "aws_network_acl_rule.test3" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ @@ -27,16 +30,61 @@ func TestAccEC2NetworkACLRule_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccNetworkACLRuleConfig(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.test1"), - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.test2"), - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.test3"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLRuleExists(resource1Name), + testAccCheckNetworkACLRuleExists(resource2Name), + testAccCheckNetworkACLRuleExists(resource3Name), + + resource.TestCheckResourceAttr(resource1Name, "cidr_block", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resource1Name, "egress", "false"), + resource.TestCheckResourceAttr(resource1Name, "from_port", "22"), + resource.TestCheckResourceAttr(resource1Name, "icmp_code", "0"), + resource.TestCheckResourceAttr(resource1Name, "icmp_type", "0"), + resource.TestCheckResourceAttr(resource1Name, "ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resource1Name, "protocol", "6"), + resource.TestCheckResourceAttr(resource1Name, "rule_action", "allow"), + resource.TestCheckResourceAttr(resource1Name, "rule_number", "200"), + resource.TestCheckResourceAttr(resource1Name, "to_port", "22"), + + resource.TestCheckResourceAttr(resource2Name, "cidr_block", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resource2Name, "egress", "false"), + resource.TestCheckResourceAttr(resource2Name, "from_port", "0"), + resource.TestCheckResourceAttr(resource2Name, "icmp_code", "-1"), + resource.TestCheckResourceAttr(resource2Name, "icmp_type", "0"), + resource.TestCheckResourceAttr(resource2Name, "ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resource2Name, "protocol", "1"), + resource.TestCheckResourceAttr(resource2Name, "rule_action", "allow"), + resource.TestCheckResourceAttr(resource2Name, "rule_number", "300"), + resource.TestCheckResourceAttr(resource2Name, "to_port", "0"), + + resource.TestCheckResourceAttr(resource3Name, "cidr_block", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resource3Name, "egress", "false"), + resource.TestCheckResourceAttr(resource3Name, "from_port", "0"), + resource.TestCheckResourceAttr(resource3Name, "icmp_code", "-1"), + resource.TestCheckResourceAttr(resource3Name, "icmp_type", "-1"), + resource.TestCheckResourceAttr(resource3Name, "ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resource3Name, "protocol", "1"), + resource.TestCheckResourceAttr(resource3Name, "rule_action", "allow"), + resource.TestCheckResourceAttr(resource3Name, "rule_number", "400"), + resource.TestCheckResourceAttr(resource3Name, "to_port", "0"), ), }, { - ResourceName: "aws_network_acl_rule.test1", + ResourceName: resource1Name, + ImportState: true, + ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc(resource1Name, "tcp"), + ImportStateVerify: true, + }, + { + ResourceName: resource2Name, + ImportState: true, + ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc(resource2Name, "icmp"), + ImportStateVerify: true, + }, + { + ResourceName: resource3Name, ImportState: true, - ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc("aws_network_acl_rule.test1", "tcp"), + ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc(resource3Name, "icmp"), ImportStateVerify: true, }, }, @@ -110,6 +158,9 @@ func TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber(t *testing.T) { } func TestAccEC2NetworkACLRule_ipv6(t *testing.T) { + resourceName := "aws_network_acl_rule.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), @@ -117,15 +168,25 @@ func TestAccEC2NetworkACLRule_ipv6(t *testing.T) { CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleIPv6Config, - Check: resource.ComposeTestCheckFunc( - testAccCheckNetworkACLRuleExists("aws_network_acl_rule.baz"), + Config: testAccNetworkACLRuleIPv6Config(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLRuleExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "egress", "false"), + resource.TestCheckResourceAttr(resourceName, "from_port", "22"), + resource.TestCheckResourceAttr(resourceName, "icmp_code", "0"), + resource.TestCheckResourceAttr(resourceName, "icmp_type", "0"), + resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", "::/0"), + resource.TestCheckResourceAttr(resourceName, "protocol", "6"), + resource.TestCheckResourceAttr(resourceName, "rule_action", "allow"), + resource.TestCheckResourceAttr(resourceName, "rule_number", "150"), + resource.TestCheckResourceAttr(resourceName, "to_port", "22"), ), }, { - ResourceName: "aws_network_acl_rule.baz", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc("aws_network_acl_rule.baz", "tcp"), + ImportStateIdFunc: testAccNetworkACLRuleImportStateIdFunc(resourceName, "tcp"), ImportStateVerify: true, }, }, @@ -146,6 +207,16 @@ func TestAccEC2NetworkACLRule_ipv6ICMP(t *testing.T) { Config: testAccNetworkACLRuleIPv6ICMPConfig(rName), Check: resource.ComposeTestCheckFunc( testAccCheckNetworkACLRuleExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "egress", "false"), + resource.TestCheckResourceAttr(resourceName, "from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "icmp_code", "-1"), + resource.TestCheckResourceAttr(resourceName, "icmp_type", "-1"), + resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", "::/0"), + resource.TestCheckResourceAttr(resourceName, "protocol", "58"), + resource.TestCheckResourceAttr(resourceName, "rule_action", "allow"), + resource.TestCheckResourceAttr(resourceName, "rule_number", "150"), + resource.TestCheckResourceAttr(resourceName, "to_port", "0"), ), }, { @@ -160,7 +231,8 @@ func TestAccEC2NetworkACLRule_ipv6ICMP(t *testing.T) { // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/6710 func TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate(t *testing.T) { - var vpc ec2.Vpc + var v ec2.Vpc + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) vpcResourceName := "aws_vpc.test" resourceName := "aws_network_acl_rule.test" @@ -171,20 +243,21 @@ func TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate(t *testi CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleIPv6VPCNotAssignGeneratedIpv6CIDRBlockUpdateConfig(), + Config: testAccNetworkACLRuleIPv6VPCNotAssignGeneratedIpv6CIDRBlockUpdateConfig(rName), Check: resource.ComposeTestCheckFunc( - acctest.CheckVPCExists(vpcResourceName, &vpc), + acctest.CheckVPCExists(vpcResourceName, &v), + testAccCheckNetworkACLRuleExists(resourceName), resource.TestCheckResourceAttr(vpcResourceName, "assign_generated_ipv6_cidr_block", "false"), resource.TestCheckResourceAttr(vpcResourceName, "ipv6_cidr_block", ""), ), }, { - Config: testAccNetworkACLRuleIPv6VPCAssignGeneratedIpv6CIDRBlockUpdateConfig(), + Config: testAccNetworkACLRuleIPv6VPCAssignGeneratedIpv6CIDRBlockUpdateConfig(rName), Check: resource.ComposeTestCheckFunc( - acctest.CheckVPCExists(vpcResourceName, &vpc), + acctest.CheckVPCExists(vpcResourceName, &v), + testAccCheckNetworkACLRuleExists(resourceName), resource.TestCheckResourceAttr(vpcResourceName, "assign_generated_ipv6_cidr_block", "true"), resource.TestMatchResourceAttr(vpcResourceName, "ipv6_cidr_block", regexp.MustCompile(`/56$`)), - testAccCheckNetworkACLRuleExists(resourceName), ), }, { @@ -198,6 +271,9 @@ func TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate(t *testi } func TestAccEC2NetworkACLRule_allProtocol(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_network_acl_rule.test" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), @@ -205,18 +281,33 @@ func TestAccEC2NetworkACLRule_allProtocol(t *testing.T) { CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleAllProtocolConfig, - ExpectNonEmptyPlan: false, + Config: testAccNetworkACLRuleAllProtocolConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLRuleExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "cidr_block", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "egress", "false"), + resource.TestCheckResourceAttr(resourceName, "from_port", "22"), + resource.TestCheckResourceAttr(resourceName, "icmp_code", "0"), + resource.TestCheckResourceAttr(resourceName, "icmp_type", "0"), + resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "protocol", "-1"), + resource.TestCheckResourceAttr(resourceName, "rule_action", "allow"), + resource.TestCheckResourceAttr(resourceName, "rule_number", "150"), + resource.TestCheckResourceAttr(resourceName, "to_port", "22"), + ), }, { - Config: testAccNetworkACLRuleAllProtocolNoRealUpdateConfig, - ExpectNonEmptyPlan: false, + Config: testAccNetworkACLRuleAllProtocolNoRealUpdateConfig(rName), + PlanOnly: true, }, }, }) } func TestAccEC2NetworkACLRule_tcpProtocol(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_network_acl_rule.test" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), @@ -224,12 +315,24 @@ func TestAccEC2NetworkACLRule_tcpProtocol(t *testing.T) { CheckDestroy: testAccCheckNetworkACLRuleDestroy, Steps: []resource.TestStep{ { - Config: testAccNetworkACLRuleTCPProtocolConfig, - ExpectNonEmptyPlan: false, + Config: testAccNetworkACLRuleTCPProtocolConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLRuleExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "cidr_block", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "egress", "true"), + resource.TestCheckResourceAttr(resourceName, "from_port", "22"), + resource.TestCheckResourceAttr(resourceName, "icmp_code", "0"), + resource.TestCheckResourceAttr(resourceName, "icmp_type", "0"), + resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "protocol", "6"), + resource.TestCheckResourceAttr(resourceName, "rule_action", "deny"), + resource.TestCheckResourceAttr(resourceName, "rule_number", "150"), + resource.TestCheckResourceAttr(resourceName, "to_port", "22"), + ), }, { - Config: testAccNetworkACLRuleTCPProtocolNoRealUpdateConfig, - ExpectNonEmptyPlan: false, + Config: testAccNetworkACLRuleTCPProtocolNoRealUpdateConfig(rName), + PlanOnly: true, }, }, }) @@ -360,25 +463,26 @@ resource "aws_network_acl_rule" "test3" { `, rName) } -const testAccNetworkACLRuleAllProtocolNoRealUpdateConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLRuleAllProtocolNoRealUpdateConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "terraform-testacc-network-acl-rule-all-proto-no-real-upd" + Name = %[1]q } } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-acl-rule-no-real-update" + Name = %[1]q } } -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test" { + network_acl_id = aws_network_acl.test.id rule_number = 150 egress = false protocol = "all" @@ -387,50 +491,60 @@ resource "aws_network_acl_rule" "baz" { from_port = 22 to_port = 22 } -` +`, rName) +} -const testAccNetworkACLRuleTCPProtocolNoRealUpdateConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLRuleTCPProtocolNoRealUpdateConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "testAccNetworkACLRuleTCPProtocolNoRealUpdateConfig" + Name = %[1]q } } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id + +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id + +resource "aws_network_acl_rule" "test" { + network_acl_id = aws_network_acl.test.id rule_number = 150 - egress = false + egress = true protocol = "tcp" - rule_action = "allow" + rule_action = "deny" cidr_block = "0.0.0.0/0" from_port = 22 to_port = 22 } -` +`, rName) +} -const testAccNetworkACLRuleAllProtocolConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLRuleAllProtocolConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "terraform-testacc-network-acl-rule-proto" + Name = %[1]q } } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-acl-rule-all-protocol" + Name = %[1]q } } -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test" { + network_acl_id = aws_network_acl.test.id rule_number = 150 egress = false protocol = "-1" @@ -439,50 +553,60 @@ resource "aws_network_acl_rule" "baz" { from_port = 22 to_port = 22 } -` +`, rName) +} -const testAccNetworkACLRuleTCPProtocolConfig = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLRuleTCPProtocolConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "testAccNetworkACLRuleTCPProtocolConfig" + Name = %[1]q } } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id + +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id + +resource "aws_network_acl_rule" "test" { + network_acl_id = aws_network_acl.test.id rule_number = 150 - egress = false + egress = true protocol = "6" - rule_action = "allow" + rule_action = "deny" cidr_block = "0.0.0.0/0" from_port = 22 to_port = 22 } -` +`, rName) +} -const testAccNetworkACLRuleIPv6Config = ` -resource "aws_vpc" "foo" { +func testAccNetworkACLRuleIPv6Config(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = "terraform-testacc-network-acl-rule-ipv6" + Name = %[1]q } } -resource "aws_network_acl" "bar" { - vpc_id = aws_vpc.foo.id +resource "aws_network_acl" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-acl-rule-ipv6" + Name = %[1]q } } -resource "aws_network_acl_rule" "baz" { - network_acl_id = aws_network_acl.bar.id +resource "aws_network_acl_rule" "test" { + network_acl_id = aws_network_acl.test.id rule_number = 150 egress = false protocol = "tcp" @@ -491,7 +615,8 @@ resource "aws_network_acl_rule" "baz" { from_port = 22 to_port = 22 } -` +`, rName) +} func testAccNetworkACLRuleIngressEgressSameNumberMissingConfig(rName string) string { return fmt.Sprintf(` @@ -541,7 +666,7 @@ resource "aws_vpc" "test" { cidr_block = "10.3.0.0/16" tags = { - Name = %q + Name = %[1]q } } @@ -549,7 +674,7 @@ resource "aws_network_acl" "test" { vpc_id = aws_vpc.test.id tags = { - Name = %q + Name = %[1]q } } @@ -565,14 +690,14 @@ resource "aws_network_acl_rule" "test" { `, rName, rName) } -func testAccNetworkACLRuleIPv6VPCAssignGeneratedIpv6CIDRBlockUpdateConfig() string { - return ` +func testAccNetworkACLRuleIPv6VPCAssignGeneratedIpv6CIDRBlockUpdateConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { assign_generated_ipv6_cidr_block = true cidr_block = "10.3.0.0/16" tags = { - Name = "tf-acc-test-network-acl-rule-ipv6-enabled" + Name = %[1]q } } @@ -580,7 +705,7 @@ resource "aws_network_acl" "test" { vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-test-network-acl-rule-ipv6-enabled" + Name = %[1]q } } @@ -593,17 +718,17 @@ resource "aws_network_acl_rule" "test" { rule_number = 150 to_port = 22 } -` +`, rName) } -func testAccNetworkACLRuleIPv6VPCNotAssignGeneratedIpv6CIDRBlockUpdateConfig() string { - return ` +func testAccNetworkACLRuleIPv6VPCNotAssignGeneratedIpv6CIDRBlockUpdateConfig(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { assign_generated_ipv6_cidr_block = false cidr_block = "10.3.0.0/16" tags = { - Name = "tf-acc-test-network-acl-rule-ipv6-not-enabled" + Name = %[1]q } } @@ -611,9 +736,9 @@ resource "aws_network_acl" "test" { vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-test-network-acl-rule-ipv6-not-enabled" + Name = %[1]q } -}` +}`, rName) } func testAccNetworkACLRuleImportStateIdFunc(resourceName, resourceProtocol string) resource.ImportStateIdFunc { From 3e0c6d7711054da563cd3a6611e2948341af2852 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Feb 2022 11:30:00 -0500 Subject: [PATCH 62/67] r/aws_vpc: Restore resourceVPCCustomizeDiff functionality from #6721 mistakenly removed in #22420. --- internal/service/ec2/vpc.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/internal/service/ec2/vpc.go b/internal/service/ec2/vpc.go index 3036e72f1243..c3c4cd57f03d 100644 --- a/internal/service/ec2/vpc.go +++ b/internal/service/ec2/vpc.go @@ -491,6 +491,15 @@ func resourceVPCImport(d *schema.ResourceData, meta interface{}) ([]*schema.Reso } func resourceVPCCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v interface{}) error { + if diff.HasChange("assign_generated_ipv6_cidr_block") { + if err := diff.SetNewComputed("ipv6_association_id"); err != nil { + return fmt.Errorf("error setting ipv6_association_id to computed: %s", err) + } + if err := diff.SetNewComputed("ipv6_cidr_block"); err != nil { + return fmt.Errorf("error setting ipv6_cidr_block to computed: %s", err) + } + } + if diff.HasChange("instance_tenancy") { old, new := diff.GetChange("instance_tenancy") if old.(string) != ec2.TenancyDedicated || new.(string) != ec2.TenancyDefault { From 67115bc410320d3a3f5ad4ec9aee5133eac26b69 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Feb 2022 11:45:52 -0500 Subject: [PATCH 63/67] r/aws_network_acl_rule: All acceptance tests passing. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLRule_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLRule_' -timeout 180m === RUN TestAccEC2NetworkACLRule_basic === PAUSE TestAccEC2NetworkACLRule_basic === RUN TestAccEC2NetworkACLRule_disappears === PAUSE TestAccEC2NetworkACLRule_disappears === RUN TestAccEC2NetworkACLRule_Disappears_networkACL === PAUSE TestAccEC2NetworkACLRule_Disappears_networkACL === RUN TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === PAUSE TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === RUN TestAccEC2NetworkACLRule_ipv6 === PAUSE TestAccEC2NetworkACLRule_ipv6 === RUN TestAccEC2NetworkACLRule_ipv6ICMP === PAUSE TestAccEC2NetworkACLRule_ipv6ICMP === RUN TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === PAUSE TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === RUN TestAccEC2NetworkACLRule_allProtocol === PAUSE TestAccEC2NetworkACLRule_allProtocol === RUN TestAccEC2NetworkACLRule_tcpProtocol === PAUSE TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_basic === CONT TestAccEC2NetworkACLRule_ipv6ICMP === CONT TestAccEC2NetworkACLRule_disappears === CONT TestAccEC2NetworkACLRule_allProtocol === CONT TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === CONT TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === CONT TestAccEC2NetworkACLRule_ipv6 === CONT TestAccEC2NetworkACLRule_Disappears_networkACL --- PASS: TestAccEC2NetworkACLRule_Disappears_networkACL (35.83s) --- PASS: TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber (37.73s) --- PASS: TestAccEC2NetworkACLRule_disappears (38.16s) --- PASS: TestAccEC2NetworkACLRule_ipv6 (38.73s) --- PASS: TestAccEC2NetworkACLRule_ipv6ICMP (40.09s) --- PASS: TestAccEC2NetworkACLRule_basic (46.70s) --- PASS: TestAccEC2NetworkACLRule_tcpProtocol (55.74s) --- PASS: TestAccEC2NetworkACLRule_allProtocol (56.43s) --- PASS: TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate (75.92s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 80.354s --- internal/service/ec2/find.go | 2 +- internal/service/ec2/network_acl_rule.go | 74 ++++++++++--------- internal/service/ec2/network_acl_rule_test.go | 26 ++----- 3 files changed, 46 insertions(+), 56 deletions(-) diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index c3235c14d7a6..52002fb3eea1 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -795,7 +795,7 @@ func FindNetworkACLAssociationBySubnetID(conn *ec2.EC2, subnetID string) (*ec2.N return nil, &resource.NotFoundError{} } -func FindNetworkACLEntry(conn *ec2.EC2, naclID string, egress bool, ruleNumber int) (*ec2.NetworkAclEntry, error) { +func FindNetworkACLEntryByThreePartKey(conn *ec2.EC2, naclID string, egress bool, ruleNumber int) (*ec2.NetworkAclEntry, error) { input := &ec2.DescribeNetworkAclsInput{ Filters: BuildAttributeFilterList(map[string]string{ "entry.egress": strconv.FormatBool(egress), diff --git a/internal/service/ec2/network_acl_rule.go b/internal/service/ec2/network_acl_rule.go index 2f57739fbbc9..f593c1c04d8f 100644 --- a/internal/service/ec2/network_acl_rule.go +++ b/internal/service/ec2/network_acl_rule.go @@ -24,28 +24,7 @@ func ResourceNetworkACLRule() *schema.Resource { Delete: resourceNetworkACLRuleDelete, 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 := idParts[2] - 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.SetId(networkAclIdRuleNumberEgressHash(networkAclID, ruleNumber, egress, protocol)) - return []*schema.ResourceData{d}, nil - }, + State: resourceNetworkACLRuleImport, }, Schema: map[string]*schema.Schema{ @@ -138,13 +117,13 @@ func ResourceNetworkACLRule() *schema.Resource { func resourceNetworkACLRuleCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).EC2Conn - protocolNumber, err := networkACLProtocolNumber(d.Get("protocol").(string)) + protocol := d.Get("protocol").(string) + protocolNumber, err := networkACLProtocolNumber(protocol) if err != nil { return err } - protocol := strconv.Itoa(protocolNumber) egress := d.Get("egress").(bool) naclID := d.Get("network_acl_id").(string) ruleNumber := d.Get("rule_number").(int) @@ -156,7 +135,7 @@ func resourceNetworkACLRuleCreate(d *schema.ResourceData, meta interface{}) erro From: aws.Int64(int64(d.Get("from_port").(int))), To: aws.Int64(int64(d.Get("to_port").(int))), }, - Protocol: aws.String(protocol), + Protocol: aws.String(strconv.Itoa(protocolNumber)), RuleAction: aws.String(d.Get("rule_action").(string)), RuleNumber: aws.Int64(int64(ruleNumber)), } @@ -185,7 +164,7 @@ func resourceNetworkACLRuleCreate(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("error creating EC2 Network ACL (%s) Rule (egress:%t)(%d): %w", naclID, egress, ruleNumber, err) } - d.SetId(networkAclIdRuleNumberEgressHash(naclID, ruleNumber, egress, protocol)) + d.SetId(NetworkACLRuleCreateResourceID(naclID, ruleNumber, egress, protocol)) return resourceNetworkACLRuleRead(d, meta) } @@ -198,7 +177,7 @@ func resourceNetworkACLRuleRead(d *schema.ResourceData, meta interface{}) error ruleNumber := d.Get("rule_number").(int) outputRaw, err := tfresource.RetryWhenNewResourceNotFound(PropagationTimeout, func() (interface{}, error) { - return FindNetworkACLEntry(conn, naclID, egress, ruleNumber) + return FindNetworkACLEntryByThreePartKey(conn, naclID, egress, ruleNumber) }, d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { @@ -219,16 +198,10 @@ func resourceNetworkACLRuleRead(d *schema.ResourceData, meta interface{}) error if naclEntry.IcmpTypeCode != nil { d.Set("icmp_code", naclEntry.IcmpTypeCode.Code) d.Set("icmp_type", naclEntry.IcmpTypeCode.Type) - } else { - d.Set("icmp_code", nil) - d.Set("icmp_type", nil) } if naclEntry.PortRange != nil { d.Set("from_port", naclEntry.PortRange.From) d.Set("to_port", naclEntry.PortRange.To) - } else { - d.Set("from_port", nil) - d.Set("to_port", nil) } d.Set("rule_action", naclEntry.RuleAction) d.Set("rule_number", naclEntry.RuleNumber) @@ -271,9 +244,40 @@ func resourceNetworkACLRuleDelete(d *schema.ResourceData, meta interface{}) erro return nil } -func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egress bool, protocol string) string { +func resourceNetworkACLRuleImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), NetworkACLRuleImportIDSeparator) + + if len(parts) != 4 || parts[0] == "" || parts[1] == "" || parts[2] == "" || parts[3] == "" { + return nil, fmt.Errorf("unexpected format of ID (%[1]s), expected NETWORK_ACL_ID%[2]sRULE_NUMBER%[2]sPROTOCOL%[2]sEGRESS", d.Id(), NetworkACLRuleImportIDSeparator) + } + + naclID := parts[0] + ruleNumber, err := strconv.Atoi(parts[1]) + + if err != nil { + return nil, err + } + + protocol := parts[2] + egress, err := strconv.ParseBool(parts[3]) + + if err != nil { + return nil, err + } + + d.SetId(NetworkACLRuleCreateResourceID(naclID, ruleNumber, egress, protocol)) + d.Set("egress", egress) + d.Set("network_acl_id", naclID) + d.Set("rule_number", ruleNumber) + + return []*schema.ResourceData{d}, nil +} + +const NetworkACLRuleImportIDSeparator = ":" + +func NetworkACLRuleCreateResourceID(naclID string, ruleNumber int, egress bool, protocol string) string { var buf bytes.Buffer - buf.WriteString(fmt.Sprintf("%s-", networkAclId)) + buf.WriteString(fmt.Sprintf("%s-", naclID)) buf.WriteString(fmt.Sprintf("%d-", ruleNumber)) buf.WriteString(fmt.Sprintf("%t-", egress)) buf.WriteString(fmt.Sprintf("%s-", protocol)) diff --git a/internal/service/ec2/network_acl_rule_test.go b/internal/service/ec2/network_acl_rule_test.go index 717d4b7bb01f..c361379a863d 100644 --- a/internal/service/ec2/network_acl_rule_test.go +++ b/internal/service/ec2/network_acl_rule_test.go @@ -4,6 +4,7 @@ import ( "fmt" "regexp" "strconv" + "strings" "testing" "github.com/aws/aws-sdk-go/service/ec2" @@ -38,8 +39,6 @@ func TestAccEC2NetworkACLRule_basic(t *testing.T) { resource.TestCheckResourceAttr(resource1Name, "cidr_block", "0.0.0.0/0"), resource.TestCheckResourceAttr(resource1Name, "egress", "false"), resource.TestCheckResourceAttr(resource1Name, "from_port", "22"), - resource.TestCheckResourceAttr(resource1Name, "icmp_code", "0"), - resource.TestCheckResourceAttr(resource1Name, "icmp_type", "0"), resource.TestCheckResourceAttr(resource1Name, "ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resource1Name, "protocol", "6"), resource.TestCheckResourceAttr(resource1Name, "rule_action", "allow"), @@ -48,25 +47,21 @@ func TestAccEC2NetworkACLRule_basic(t *testing.T) { resource.TestCheckResourceAttr(resource2Name, "cidr_block", "0.0.0.0/0"), resource.TestCheckResourceAttr(resource2Name, "egress", "false"), - resource.TestCheckResourceAttr(resource2Name, "from_port", "0"), resource.TestCheckResourceAttr(resource2Name, "icmp_code", "-1"), resource.TestCheckResourceAttr(resource2Name, "icmp_type", "0"), resource.TestCheckResourceAttr(resource2Name, "ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resource2Name, "protocol", "1"), resource.TestCheckResourceAttr(resource2Name, "rule_action", "allow"), resource.TestCheckResourceAttr(resource2Name, "rule_number", "300"), - resource.TestCheckResourceAttr(resource2Name, "to_port", "0"), resource.TestCheckResourceAttr(resource3Name, "cidr_block", "0.0.0.0/0"), resource.TestCheckResourceAttr(resource3Name, "egress", "false"), - resource.TestCheckResourceAttr(resource3Name, "from_port", "0"), resource.TestCheckResourceAttr(resource3Name, "icmp_code", "-1"), resource.TestCheckResourceAttr(resource3Name, "icmp_type", "-1"), resource.TestCheckResourceAttr(resource3Name, "ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resource3Name, "protocol", "1"), resource.TestCheckResourceAttr(resource3Name, "rule_action", "allow"), resource.TestCheckResourceAttr(resource3Name, "rule_number", "400"), - resource.TestCheckResourceAttr(resource3Name, "to_port", "0"), ), }, { @@ -174,8 +169,6 @@ func TestAccEC2NetworkACLRule_ipv6(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "egress", "false"), resource.TestCheckResourceAttr(resourceName, "from_port", "22"), - resource.TestCheckResourceAttr(resourceName, "icmp_code", "0"), - resource.TestCheckResourceAttr(resourceName, "icmp_type", "0"), resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", "::/0"), resource.TestCheckResourceAttr(resourceName, "protocol", "6"), resource.TestCheckResourceAttr(resourceName, "rule_action", "allow"), @@ -205,18 +198,16 @@ func TestAccEC2NetworkACLRule_ipv6ICMP(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccNetworkACLRuleIPv6ICMPConfig(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckNetworkACLRuleExists(resourceName), resource.TestCheckResourceAttr(resourceName, "cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "egress", "false"), - resource.TestCheckResourceAttr(resourceName, "from_port", "0"), resource.TestCheckResourceAttr(resourceName, "icmp_code", "-1"), resource.TestCheckResourceAttr(resourceName, "icmp_type", "-1"), resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", "::/0"), resource.TestCheckResourceAttr(resourceName, "protocol", "58"), resource.TestCheckResourceAttr(resourceName, "rule_action", "allow"), resource.TestCheckResourceAttr(resourceName, "rule_number", "150"), - resource.TestCheckResourceAttr(resourceName, "to_port", "0"), ), }, { @@ -246,7 +237,6 @@ func TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate(t *testi Config: testAccNetworkACLRuleIPv6VPCNotAssignGeneratedIpv6CIDRBlockUpdateConfig(rName), Check: resource.ComposeTestCheckFunc( acctest.CheckVPCExists(vpcResourceName, &v), - testAccCheckNetworkACLRuleExists(resourceName), resource.TestCheckResourceAttr(vpcResourceName, "assign_generated_ipv6_cidr_block", "false"), resource.TestCheckResourceAttr(vpcResourceName, "ipv6_cidr_block", ""), ), @@ -287,8 +277,6 @@ func TestAccEC2NetworkACLRule_allProtocol(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "cidr_block", "0.0.0.0/0"), resource.TestCheckResourceAttr(resourceName, "egress", "false"), resource.TestCheckResourceAttr(resourceName, "from_port", "22"), - resource.TestCheckResourceAttr(resourceName, "icmp_code", "0"), - resource.TestCheckResourceAttr(resourceName, "icmp_type", "0"), resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "protocol", "-1"), resource.TestCheckResourceAttr(resourceName, "rule_action", "allow"), @@ -321,8 +309,6 @@ func TestAccEC2NetworkACLRule_tcpProtocol(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "cidr_block", "0.0.0.0/0"), resource.TestCheckResourceAttr(resourceName, "egress", "true"), resource.TestCheckResourceAttr(resourceName, "from_port", "22"), - resource.TestCheckResourceAttr(resourceName, "icmp_code", "0"), - resource.TestCheckResourceAttr(resourceName, "icmp_type", "0"), resource.TestCheckResourceAttr(resourceName, "ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "protocol", "6"), resource.TestCheckResourceAttr(resourceName, "rule_action", "deny"), @@ -360,7 +346,7 @@ func testAccCheckNetworkACLRuleDestroy(s *terraform.State) error { return err } - _, err = tfec2.FindNetworkACLEntry(conn, naclID, egress, ruleNumber) + _, err = tfec2.FindNetworkACLEntryByThreePartKey(conn, naclID, egress, ruleNumber) if tfresource.NotFound(err) { continue @@ -402,7 +388,7 @@ func testAccCheckNetworkACLRuleExists(n string) resource.TestCheckFunc { return err } - _, err = tfec2.FindNetworkACLEntry(conn, naclID, egress, ruleNumber) + _, err = tfec2.FindNetworkACLEntryByThreePartKey(conn, naclID, egress, ruleNumber) if err != nil { return err @@ -748,7 +734,7 @@ func testAccNetworkACLRuleImportStateIdFunc(resourceName, resourceProtocol strin return "", fmt.Errorf("Not found: %s", resourceName) } - networkAclId := rs.Primary.Attributes["network_acl_id"] + naclID := 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 @@ -757,6 +743,6 @@ func testAccNetworkACLRuleImportStateIdFunc(resourceName, resourceProtocol strin } egress := rs.Primary.Attributes["egress"] - return fmt.Sprintf("%s:%s:%s:%s", networkAclId, ruleNumber, protocol, egress), nil + return strings.Join([]string{naclID, ruleNumber, protocol, egress}, tfec2.NetworkACLRuleImportIDSeparator), nil } } From d093e3fb91fc018879e74aa362f00ee960926345 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Feb 2022 12:24:26 -0500 Subject: [PATCH 64/67] r/aws_network_acl_rule: Replace 'protocolNumbers()' etc. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLRule_ PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLRule_' -timeout 180m === RUN TestAccEC2NetworkACLRule_basic === PAUSE TestAccEC2NetworkACLRule_basic === RUN TestAccEC2NetworkACLRule_disappears === PAUSE TestAccEC2NetworkACLRule_disappears === RUN TestAccEC2NetworkACLRule_Disappears_networkACL === PAUSE TestAccEC2NetworkACLRule_Disappears_networkACL === RUN TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === PAUSE TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === RUN TestAccEC2NetworkACLRule_ipv6 === PAUSE TestAccEC2NetworkACLRule_ipv6 === RUN TestAccEC2NetworkACLRule_ipv6ICMP === PAUSE TestAccEC2NetworkACLRule_ipv6ICMP === RUN TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === PAUSE TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate === RUN TestAccEC2NetworkACLRule_allProtocol === PAUSE TestAccEC2NetworkACLRule_allProtocol === RUN TestAccEC2NetworkACLRule_tcpProtocol === PAUSE TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_basic === CONT TestAccEC2NetworkACLRule_ipv6ICMP === CONT TestAccEC2NetworkACLRule_allProtocol === CONT TestAccEC2NetworkACLRule_tcpProtocol === CONT TestAccEC2NetworkACLRule_ipv6 === CONT TestAccEC2NetworkACLRule_disappears === CONT TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber === CONT TestAccEC2NetworkACLRule_Disappears_networkACL === CONT TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate --- PASS: TestAccEC2NetworkACLRule_Disappears_networkACL (59.76s) --- PASS: TestAccEC2NetworkACLRule_Disappears_ingressEgressSameNumber (61.75s) --- PASS: TestAccEC2NetworkACLRule_disappears (62.08s) --- PASS: TestAccEC2NetworkACLRule_ipv6 (66.11s) --- PASS: TestAccEC2NetworkACLRule_ipv6ICMP (66.55s) --- PASS: TestAccEC2NetworkACLRule_basic (76.44s) --- PASS: TestAccEC2NetworkACLRule_allProtocol (81.80s) --- PASS: TestAccEC2NetworkACLRule_tcpProtocol (83.37s) --- PASS: TestAccEC2NetworkACLRule_ipv6VPCAssignGeneratedIPv6CIDRBlockUpdate (102.12s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 113.589s --- internal/service/ec2/default_network_acl.go | 2 +- internal/service/ec2/network_acl.go | 208 ++++++++++++++-- internal/service/ec2/network_acl_entry.go | 234 ------------------ .../service/ec2/network_acl_entry_test.go | 100 -------- internal/service/ec2/network_acl_rule.go | 9 +- 5 files changed, 186 insertions(+), 367 deletions(-) delete mode 100644 internal/service/ec2/network_acl_entry.go delete mode 100644 internal/service/ec2/network_acl_entry_test.go diff --git a/internal/service/ec2/default_network_acl.go b/internal/service/ec2/default_network_acl.go index 8ef7d2445fbb..fa0c554240da 100644 --- a/internal/service/ec2/default_network_acl.go +++ b/internal/service/ec2/default_network_acl.go @@ -25,7 +25,7 @@ func ResourceDefaultNetworkACL() *schema.Resource { Type: schema.TypeSet, Optional: true, Elem: networkACLRuleResource, - Set: resourceNetworkACLEntryHash, + Set: networkACLRuleHash, } return &schema.Resource{ diff --git a/internal/service/ec2/network_acl.go b/internal/service/ec2/network_acl.go index f078959614cd..2a1d253d5286 100644 --- a/internal/service/ec2/network_acl.go +++ b/internal/service/ec2/network_acl.go @@ -27,7 +27,7 @@ func ResourceNetworkACL() *schema.Resource { Computed: true, ConfigMode: schema.SchemaConfigModeAttr, Elem: networkACLRuleResource, - Set: resourceNetworkACLEntryHash, + Set: networkACLRuleHash, } return &schema.Resource{ @@ -376,41 +376,30 @@ func modifyNetworkACLAttributesOnUpdate(conn *ec2.EC2, d *schema.ResourceData, d return nil } -func resourceNetworkACLEntryHash(v interface{}) int { +func networkACLRuleHash(v interface{}) int { var buf bytes.Buffer - m := v.(map[string]interface{}) - buf.WriteString(fmt.Sprintf("%d-", m["from_port"].(int))) - buf.WriteString(fmt.Sprintf("%d-", m["to_port"].(int))) - buf.WriteString(fmt.Sprintf("%d-", m["rule_no"].(int))) - buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["action"].(string)))) + + tfMap := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%d-", tfMap["from_port"].(int))) + buf.WriteString(fmt.Sprintf("%d-", tfMap["to_port"].(int))) + buf.WriteString(fmt.Sprintf("%d-", tfMap["rule_no"].(int))) + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(tfMap["action"].(string)))) // The AWS network ACL API only speaks protocol numbers, and that's // all we store. Never hash a protocol name. - protocol := m["protocol"].(string) - if _, err := strconv.Atoi(m["protocol"].(string)); err != nil { - // We're a protocol name. Look up the number. - buf.WriteString(fmt.Sprintf("%d-", protocolIntegers()[protocol])) - } else { - // We're a protocol number. Pass the value through. - buf.WriteString(fmt.Sprintf("%s-", protocol)) - } - - if v, ok := m["cidr_block"]; ok { - buf.WriteString(fmt.Sprintf("%s-", v.(string))) - } + protocolNumber, _ := networkACLProtocolNumber(tfMap["protocol"].(string)) + buf.WriteString(fmt.Sprintf("%d-", protocolNumber)) - if v, ok := m["ipv6_cidr_block"]; ok { + if v, ok := tfMap["cidr_block"]; ok { buf.WriteString(fmt.Sprintf("%s-", v.(string))) } - - if v, ok := m["ssl_certificate_id"]; ok { + if v, ok := tfMap["ipv6_cidr_block"]; ok { buf.WriteString(fmt.Sprintf("%s-", v.(string))) } - - if v, ok := m["icmp_type"]; ok { + if v, ok := tfMap["icmp_type"]; ok { buf.WriteString(fmt.Sprintf("%d-", v.(int))) } - if v, ok := m["icmp_code"]; ok { + if v, ok := tfMap["icmp_code"]; ok { buf.WriteString(fmt.Sprintf("%d-", v.(int))) } @@ -675,13 +664,13 @@ func networkACLProtocolNumber(v string) (int, error) { if err != nil { // Lookup number by name. var ok bool - i, ok = protocolIntegers()[v] + i, ok = ianaProtocolAToI[v] if !ok { return 0, fmt.Errorf("unsupported NACL protocol: %s", v) } } else { - _, ok := protocolStrings(protocolIntegers())[i] + _, ok := ianaProtocolIToA[i] if !ok { return 0, fmt.Errorf("unsupported NACL protocol: %d", i) @@ -690,3 +679,168 @@ func networkACLProtocolNumber(v string) (int, error) { return i, nil } + +type ianaProtocolAToIType map[string]int +type ianaProtocolIToAType map[int]string + +func (m ianaProtocolAToIType) invert() ianaProtocolIToAType { + output := make(map[int]string, len(m)) + + for k, v := range m { + output[v] = k + } + + return output +} + +var ( + ianaProtocolAToI = ianaProtocolAToIType(map[string]int{ + // Defined at https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml. + "all": -1, + "hopopt": 0, + "icmp": 1, + "igmp": 2, + "ggp": 3, + "ipv4": 4, + "st": 5, + "tcp": 6, + "cbt": 7, + "egp": 8, + "igp": 9, + "bbn-rcc-mon": 10, + "nvp-ii": 11, + "pup": 12, + "argus": 13, + "emcon": 14, + "xnet": 15, + "chaos": 16, + "udp": 17, + "mux": 18, + "dcn-meas": 19, + "hmp": 20, + "prm": 21, + "xns-idp": 22, + "trunk-1": 23, + "trunk-2": 24, + "leaf-1": 25, + "leaf-2": 26, + "rdp": 27, + "irtp": 28, + "iso-tp4": 29, + "netblt": 30, + "mfe-nsp": 31, + "merit-inp": 32, + "dccp": 33, + "3pc": 34, + "idpr": 35, + "xtp": 36, + "ddp": 37, + "idpr-cmtp": 38, + "tp++": 39, + "il": 40, + "ipv6": 41, + "sdrp": 42, + "ipv6-route": 43, + "ipv6-frag": 44, + "idrp": 45, + "rsvp": 46, + "gre": 47, + "dsr": 48, + "bna": 49, + "esp": 50, + "ah": 51, + "i-nlsp": 52, + "swipe": 53, + "narp": 54, + "mobile": 55, + "tlsp": 56, + "ipv6-icmp": 58, + "ipv6-nonxt": 59, + "ipv6-opts": 60, + "61": 61, + "cftp": 62, + "63": 63, + "sat-expak": 64, + "kryptolan": 65, + "rvd": 66, + "ippc": 67, + "68": 68, + "sat-mon": 69, + "visa": 70, + "ipcv": 71, + "cpnx": 72, + "cphb": 73, + "wsn": 74, + "pvp": 75, + "br-sat-mon": 76, + "sun-nd": 77, + "wb-mon": 78, + "wb-expak": 79, + "iso-ip": 80, + "vmtp": 81, + "secure-vmtp": 82, + "vines": 83, + "ttp": 84, + "nsfnet-igp": 85, + "dgp": 86, + "tcf": 87, + "eigrp": 88, + "ospfigp": 89, + "sprite-rpc": 90, + "larp": 91, + "mtp": 92, + "ax.25": 93, + "ipip": 94, + "micp": 95, + "scc-sp": 96, + "etherip": 97, + "encap": 98, + "99": 99, + "gmtp": 100, + "ifmp": 101, + "pnni": 102, + "pim": 103, + "aris": 104, + "scps": 105, + "qnx": 106, + "a/n": 107, + "ipcomp": 108, + "snp": 109, + "compaq-peer": 110, + "ipx-in-ip": 111, + "vrrp": 112, + "pgm": 113, + "114": 114, + "l2tp": 115, + "dd": 116, + "iatp": 117, + "stp": 118, + "srp": 119, + "uti": 120, + "smp": 121, + "sm": 122, + "ptp": 123, + "isis-over-ipv4": 124, + "fire": 125, + "crtp": 126, + "crudp": 127, + "sscopmce": 128, + "iplt": 129, + "sps": 130, + "pipe": 131, + "sctp": 132, + "fc": 133, + "rsvp-e2e-ignore": 134, + "mobility-header": 135, + "udplite": 136, + "mpls-in-ip": 137, + "manet": 138, + "hip": 139, + "shim6": 140, + "wesp": 141, + "rohc": 142, + "253": 253, + "254": 254, + }) + ianaProtocolIToA = ianaProtocolAToI.invert() +) diff --git a/internal/service/ec2/network_acl_entry.go b/internal/service/ec2/network_acl_entry.go deleted file mode 100644 index ecfc5cc731c5..000000000000 --- a/internal/service/ec2/network_acl_entry.go +++ /dev/null @@ -1,234 +0,0 @@ -package ec2 - -import ( - "fmt" - "strconv" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" -) - -func ExpandNetworkACLEntries(configured []interface{}, entryType string) ([]*ec2.NetworkAclEntry, error) { - entries := make([]*ec2.NetworkAclEntry, 0, len(configured)) - for _, eRaw := range configured { - data := eRaw.(map[string]interface{}) - protocol := data["protocol"].(string) - p, err := strconv.Atoi(protocol) - if err != nil { - var ok bool - p, ok = protocolIntegers()[protocol] - if !ok { - return nil, fmt.Errorf("Invalid Protocol %s for rule %#v", protocol, data) - } - } - - e := &ec2.NetworkAclEntry{ - Protocol: aws.String(strconv.Itoa(p)), - PortRange: &ec2.PortRange{ - From: aws.Int64(int64(data["from_port"].(int))), - To: aws.Int64(int64(data["to_port"].(int))), - }, - Egress: aws.Bool(entryType == "egress"), - RuleAction: aws.String(data["action"].(string)), - RuleNumber: aws.Int64(int64(data["rule_no"].(int))), - } - - if v, ok := data["ipv6_cidr_block"]; ok { - e.Ipv6CidrBlock = aws.String(v.(string)) - } - - if v, ok := data["cidr_block"]; ok { - e.CidrBlock = aws.String(v.(string)) - } - - // Specify additional required fields for ICMP - if p == 1 || p == 58 { - e.IcmpTypeCode = &ec2.IcmpTypeCode{} - if v, ok := data["icmp_code"]; ok { - e.IcmpTypeCode.Code = aws.Int64(int64(v.(int))) - } - if v, ok := data["icmp_type"]; ok { - e.IcmpTypeCode.Type = aws.Int64(int64(v.(int))) - } - } - - entries = append(entries, e) - } - return entries, nil -} - -func protocolStrings(protocolIntegers map[string]int) map[int]string { - protocolStrings := make(map[int]string, len(protocolIntegers)) - for k, v := range protocolIntegers { - protocolStrings[v] = k - } - - return protocolStrings -} - -func protocolIntegers() map[string]int { - return map[string]int{ - // defined at https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml - "all": -1, - "hopopt": 0, - "icmp": 1, - "igmp": 2, - "ggp": 3, - "ipv4": 4, - "st": 5, - "tcp": 6, - "cbt": 7, - "egp": 8, - "igp": 9, - "bbn-rcc-mon": 10, - "nvp-ii": 11, - "pup": 12, - "argus": 13, - "emcon": 14, - "xnet": 15, - "chaos": 16, - "udp": 17, - "mux": 18, - "dcn-meas": 19, - "hmp": 20, - "prm": 21, - "xns-idp": 22, - "trunk-1": 23, - "trunk-2": 24, - "leaf-1": 25, - "leaf-2": 26, - "rdp": 27, - "irtp": 28, - "iso-tp4": 29, - "netblt": 30, - "mfe-nsp": 31, - "merit-inp": 32, - "dccp": 33, - "3pc": 34, - "idpr": 35, - "xtp": 36, - "ddp": 37, - "idpr-cmtp": 38, - "tp++": 39, - "il": 40, - "ipv6": 41, - "sdrp": 42, - "ipv6-route": 43, - "ipv6-frag": 44, - "idrp": 45, - "rsvp": 46, - "gre": 47, - "dsr": 48, - "bna": 49, - "esp": 50, - "ah": 51, - "i-nlsp": 52, - "swipe": 53, - "narp": 54, - "mobile": 55, - "tlsp": 56, - "ipv6-icmp": 58, - "ipv6-nonxt": 59, - "ipv6-opts": 60, - "61": 61, - "cftp": 62, - "63": 63, - "sat-expak": 64, - "kryptolan": 65, - "rvd": 66, - "ippc": 67, - "68": 68, - "sat-mon": 69, - "visa": 70, - "ipcv": 71, - "cpnx": 72, - "cphb": 73, - "wsn": 74, - "pvp": 75, - "br-sat-mon": 76, - "sun-nd": 77, - "wb-mon": 78, - "wb-expak": 79, - "iso-ip": 80, - "vmtp": 81, - "secure-vmtp": 82, - "vines": 83, - "ttp": 84, - "nsfnet-igp": 85, - "dgp": 86, - "tcf": 87, - "eigrp": 88, - "ospfigp": 89, - "sprite-rpc": 90, - "larp": 91, - "mtp": 92, - "ax.25": 93, - "ipip": 94, - "micp": 95, - "scc-sp": 96, - "etherip": 97, - "encap": 98, - "99": 99, - "gmtp": 100, - "ifmp": 101, - "pnni": 102, - "pim": 103, - "aris": 104, - "scps": 105, - "qnx": 106, - "a/n": 107, - "ipcomp": 108, - "snp": 109, - "compaq-peer": 110, - "ipx-in-ip": 111, - "vrrp": 112, - "pgm": 113, - "114": 114, - "l2tp": 115, - "dd": 116, - "iatp": 117, - "stp": 118, - "srp": 119, - "uti": 120, - "smp": 121, - "sm": 122, - "ptp": 123, - "isis-over-ipv4": 124, - "fire": 125, - "crtp": 126, - "crudp": 127, - "sscopmce": 128, - "iplt": 129, - "sps": 130, - "pipe": 131, - "sctp": 132, - "fc": 133, - "rsvp-e2e-ignore": 134, - "mobility-header": 135, - "udplite": 136, - "mpls-in-ip": 137, - "manet": 138, - "hip": 139, - "shim6": 140, - "wesp": 141, - "rohc": 142, - "253": 253, - "254": 254, - } -} - -// ExpectedPortPair stores a pair of ports we expect to see together. -type ExpectedPortPair struct { - to_port int64 - from_port int64 -} - -// ValidPorts ensures the ports and protocol match expected -// values. -func ValidPorts(to int64, from int64, expected ExpectedPortPair) bool { - if to != expected.to_port || from != expected.from_port { - return false - } - - return true -} diff --git a/internal/service/ec2/network_acl_entry_test.go b/internal/service/ec2/network_acl_entry_test.go deleted file mode 100644 index f0bdc8b8e0fa..000000000000 --- a/internal/service/ec2/network_acl_entry_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package ec2 - -import ( - "reflect" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" -) - -func Test_expandNetworkACLEntry(t *testing.T) { - input := []interface{}{ - map[string]interface{}{ - "protocol": "tcp", - "from_port": 22, - "to_port": 22, - "cidr_block": "0.0.0.0/0", - "action": "deny", - "rule_no": 1, - }, - map[string]interface{}{ - "protocol": "tcp", - "from_port": 443, - "to_port": 443, - "cidr_block": "0.0.0.0/0", - "action": "deny", - "rule_no": 2, - }, - map[string]interface{}{ - "protocol": "-1", - "from_port": 443, - "to_port": 443, - "cidr_block": "0.0.0.0/0", - "action": "deny", - "rule_no": 2, - }, - } - expanded, _ := ExpandNetworkACLEntries(input, "egress") - - expected := []*ec2.NetworkAclEntry{ - { - Protocol: aws.String("6"), - PortRange: &ec2.PortRange{ - From: aws.Int64(22), - To: aws.Int64(22), - }, - RuleAction: aws.String("deny"), - RuleNumber: aws.Int64(1), - CidrBlock: aws.String("0.0.0.0/0"), - Egress: aws.Bool(true), - }, - { - Protocol: aws.String("6"), - PortRange: &ec2.PortRange{ - From: aws.Int64(443), - To: aws.Int64(443), - }, - RuleAction: aws.String("deny"), - RuleNumber: aws.Int64(2), - CidrBlock: aws.String("0.0.0.0/0"), - Egress: aws.Bool(true), - }, - { - Protocol: aws.String("-1"), - PortRange: &ec2.PortRange{ - From: aws.Int64(443), - To: aws.Int64(443), - }, - RuleAction: aws.String("deny"), - RuleNumber: aws.Int64(2), - CidrBlock: aws.String("0.0.0.0/0"), - Egress: aws.Bool(true), - }, - } - - if !reflect.DeepEqual(expanded, expected) { - t.Fatalf( - "Got:\n\n%#v\n\nExpected:\n\n%#v\n", - expanded, - expected) - } - -} - -func Test_validatePorts(t *testing.T) { - for _, ts := range []struct { - to int64 - from int64 - expected *ExpectedPortPair - wanted bool - }{ - {0, 0, &ExpectedPortPair{0, 0}, true}, - {0, 1, &ExpectedPortPair{0, 0}, false}, - } { - got := ValidPorts(ts.to, ts.from, *ts.expected) - if got != ts.wanted { - t.Fatalf("Got: %t; Expected: %t\n", got, ts.wanted) - } - } -} diff --git a/internal/service/ec2/network_acl_rule.go b/internal/service/ec2/network_acl_rule.go index f593c1c04d8f..504ba92bb848 100644 --- a/internal/service/ec2/network_acl_rule.go +++ b/internal/service/ec2/network_acl_rule.go @@ -71,12 +71,11 @@ func ResourceNetworkACLRule() *schema.Resource { Required: true, ForceNew: true, DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - pi := protocolIntegers() - if val, ok := pi[old]; ok { - old = strconv.Itoa(val) + if v, ok := ianaProtocolAToI[old]; ok { + old = strconv.Itoa(v) } - if val, ok := pi[new]; ok { - new = strconv.Itoa(val) + if v, ok := ianaProtocolAToI[new]; ok { + new = strconv.Itoa(v) } return old == new From 7a038cf6b4dbc24b140083f345920c93bae836a0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Feb 2022 13:30:51 -0500 Subject: [PATCH 65/67] r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_associateWithDefaultNACL'. Acceptance test output: % make testacc TESTS=TestAccEC2NetworkACLAssociation_associateWithDefaultNACL PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 20 -run='TestAccEC2NetworkACLAssociation_associateWithDefaultNACL' -timeout 180m === RUN TestAccEC2NetworkACLAssociation_associateWithDefaultNACL === PAUSE TestAccEC2NetworkACLAssociation_associateWithDefaultNACL === CONT TestAccEC2NetworkACLAssociation_associateWithDefaultNACL --- PASS: TestAccEC2NetworkACLAssociation_associateWithDefaultNACL (38.09s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 42.008s --- .../ec2/network_acl_association_test.go | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index 6745feef7c71..d662fa99e784 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -155,6 +155,33 @@ func TestAccEC2NetworkACLAssociation_twoAssociations(t *testing.T) { }) } +func TestAccEC2NetworkACLAssociation_associateWithDefaultNACL(t *testing.T) { + var v ec2.NetworkAclAssociation + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_network_acl_association.test" + subnetResourceName := "aws_subnet.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckNetworkACLAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccNetworkACLAssociationDefaultNACLConfig(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckNetworkACLAssociationExists(resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, "subnet_id", subnetResourceName, "id"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} func testAccCheckNetworkACLAssociationDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn @@ -288,3 +315,30 @@ resource "aws_network_acl_association" "test2" { } `, rName) } + +func testAccNetworkACLAssociationDefaultNACLConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + + cidr_block = "10.1.33.0/24" + + tags = { + Name = %[1]q + } +} + +resource "aws_network_acl_association" "test" { + network_acl_id = aws_vpc.test.default_network_acl_id + subnet_id = aws_subnet.test.id +} +`, rName) +} From f372d7d6fa9f1384de2688242ef3897aea6fa6ed Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Feb 2022 13:38:00 -0500 Subject: [PATCH 66/67] Correct documentation page file name. --- ...association.markdown => network_acl_association.html.markdown} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename website/docs/r/{network_acl_association.markdown => network_acl_association.html.markdown} (100%) diff --git a/website/docs/r/network_acl_association.markdown b/website/docs/r/network_acl_association.html.markdown similarity index 100% rename from website/docs/r/network_acl_association.markdown rename to website/docs/r/network_acl_association.html.markdown From f2aee7c6e31d25cce23990501d84c86c857cea8e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Feb 2022 13:39:39 -0500 Subject: [PATCH 67/67] Fix terrafmt errors. --- internal/service/ec2/network_acl_association_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/ec2/network_acl_association_test.go b/internal/service/ec2/network_acl_association_test.go index d662fa99e784..53b5d0562571 100644 --- a/internal/service/ec2/network_acl_association_test.go +++ b/internal/service/ec2/network_acl_association_test.go @@ -250,7 +250,7 @@ resource "aws_network_acl" "test" { } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id cidr_block = "10.1.33.0/24" @@ -285,7 +285,7 @@ resource "aws_network_acl" "test" { } resource "aws_subnet" "test1" { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id cidr_block = "10.1.33.0/24" @@ -295,7 +295,7 @@ resource "aws_subnet" "test1" { } resource "aws_subnet" "test2" { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id cidr_block = "10.1.34.0/24" @@ -327,7 +327,7 @@ resource "aws_vpc" "test" { } resource "aws_subnet" "test" { - vpc_id = aws_vpc.test.id + vpc_id = aws_vpc.test.id cidr_block = "10.1.33.0/24"