From eeb04b674e065756c8fc2778b483c5305ae3a4fb Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sat, 22 Feb 2020 19:51:48 +0200 Subject: [PATCH] add tagging support to ec2 traffic mirror filter + add disappearing test case + read after create --- aws/resource_aws_ec2_traffic_mirror_filter.go | 53 ++++++-- ...urce_aws_ec2_traffic_mirror_filter_test.go | 121 +++++++++++++++++- .../r/ec2_traffic_mirror_filter.html.markdown | 4 +- 3 files changed, 162 insertions(+), 16 deletions(-) diff --git a/aws/resource_aws_ec2_traffic_mirror_filter.go b/aws/resource_aws_ec2_traffic_mirror_filter.go index f64163cc5661..ad1fc33333e6 100644 --- a/aws/resource_aws_ec2_traffic_mirror_filter.go +++ b/aws/resource_aws_ec2_traffic_mirror_filter.go @@ -4,16 +4,16 @@ import ( "fmt" "log" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsEc2TrafficMirrorFilter() *schema.Resource { return &schema.Resource{ - Create: resourceAwsEc2TrafficMirrorinFilterCreate, + Create: resourceAwsEc2TrafficMirrorFilterCreate, Read: resourceAwsEc2TrafficMirrorFilterRead, Update: resourceAwsEc2TrafficMirrorFilterUpdate, Delete: resourceAwsEc2TrafficMirrorFilterDelete, @@ -36,11 +36,12 @@ func resourceAwsEc2TrafficMirrorFilter() *schema.Resource { }, false), }, }, + "tags": tagsSchema(), }, } } -func resourceAwsEc2TrafficMirrorinFilterCreate(d *schema.ResourceData, meta interface{}) error { +func resourceAwsEc2TrafficMirrorFilterCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn input := &ec2.CreateTrafficMirrorFilterInput{} @@ -49,6 +50,10 @@ func resourceAwsEc2TrafficMirrorinFilterCreate(d *schema.ResourceData, meta inte input.Description = aws.String(description.(string)) } + if v, ok := d.GetOk("tags"); ok { + input.TagSpecifications = ec2TagSpecificationsFromMap(v.(map[string]interface{}), ec2.ResourceTypeTrafficMirrorFilter) + } + out, err := conn.CreateTrafficMirrorFilter(input) if err != nil { return fmt.Errorf("Error while creating traffic filter %s", err) @@ -56,7 +61,20 @@ func resourceAwsEc2TrafficMirrorinFilterCreate(d *schema.ResourceData, meta inte d.SetId(*out.TrafficMirrorFilter.TrafficMirrorFilterId) - return resourceAwsEc2TrafficMirrorFilterUpdate(d, meta) + if v, ok := d.GetOk("network_services"); ok { + input := &ec2.ModifyTrafficMirrorFilterNetworkServicesInput{ + TrafficMirrorFilterId: aws.String(d.Id()), + AddNetworkServices: expandStringSet(v.(*schema.Set)), + } + + _, err := conn.ModifyTrafficMirrorFilterNetworkServices(input) + if err != nil { + return fmt.Errorf("error modifying EC2 Traffic Mirror Filter (%s) network services: %w", d.Id(), err) + } + + } + + return resourceAwsEc2TrafficMirrorFilterRead(d, meta) } func resourceAwsEc2TrafficMirrorFilterUpdate(d *schema.ResourceData, meta interface{}) error { @@ -84,6 +102,14 @@ func resourceAwsEc2TrafficMirrorFilterUpdate(d *schema.ResourceData, meta interf } } + if d.HasChange("tags") { + o, n := d.GetChange("tags") + + if err := keyvaluetags.Ec2UpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating EC2 Traffic Mirror Filter (%s) tags: %s", d.Id(), err) + } + } + return resourceAwsEc2TrafficMirrorFilterRead(d, meta) } @@ -95,6 +121,13 @@ func resourceAwsEc2TrafficMirrorFilterRead(d *schema.ResourceData, meta interfac } out, err := conn.DescribeTrafficMirrorFilters(input) + + if isAWSErr(err, "InvalidTrafficMirrorFilterId.NotFound", "") { + log.Printf("[WARN] EC2 Traffic Mirror Filter (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + if err != nil { return fmt.Errorf("Error describing traffic mirror filter %v: %v", d.Id(), err) } @@ -105,10 +138,14 @@ func resourceAwsEc2TrafficMirrorFilterRead(d *schema.ResourceData, meta interfac return nil } - d.SetId(*out.TrafficMirrorFilters[0].TrafficMirrorFilterId) - d.Set("description", out.TrafficMirrorFilters[0].Description) + trafficMirrorFilter := out.TrafficMirrorFilters[0] + d.Set("description", trafficMirrorFilter.Description) + + if err := d.Set("tags", keyvaluetags.Ec2KeyValueTags(trafficMirrorFilter.Tags).IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } - if err := d.Set("network_services", aws.StringValueSlice(out.TrafficMirrorFilters[0].NetworkServices)); err != nil { + if err := d.Set("network_services", aws.StringValueSlice(trafficMirrorFilter.NetworkServices)); err != nil { return fmt.Errorf("error setting network_services for filter %v: %s", d.Id(), err) } diff --git a/aws/resource_aws_ec2_traffic_mirror_filter_test.go b/aws/resource_aws_ec2_traffic_mirror_filter_test.go index bf7604ced6d4..260adfcc857a 100644 --- a/aws/resource_aws_ec2_traffic_mirror_filter_test.go +++ b/aws/resource_aws_ec2_traffic_mirror_filter_test.go @@ -12,7 +12,8 @@ import ( ) func TestAccAWSEc2TrafficMirrorFilter_basic(t *testing.T) { - resourceName := "aws_ec2_traffic_mirror_filter.filter" + var v ec2.TrafficMirrorFilter + resourceName := "aws_ec2_traffic_mirror_filter.test" description := "test filter" resource.ParallelTest(t, resource.TestCase{ @@ -27,16 +28,17 @@ func TestAccAWSEc2TrafficMirrorFilter_basic(t *testing.T) { { Config: testAccTrafficMirrorFilterConfig(description), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName), + testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "description", description), resource.TestCheckResourceAttr(resourceName, "network_services.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, // Test Disable DNS service { Config: testAccTrafficMirrorFilterConfigWithoutDNS(description), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName), + testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName, &v), resource.TestCheckNoResourceAttr(resourceName, "network_services"), ), }, @@ -44,7 +46,7 @@ func TestAccAWSEc2TrafficMirrorFilter_basic(t *testing.T) { { Config: testAccTrafficMirrorFilterConfig(description), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName), + testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "description", description), resource.TestCheckResourceAttr(resourceName, "network_services.#", "1"), ), @@ -58,7 +60,78 @@ func TestAccAWSEc2TrafficMirrorFilter_basic(t *testing.T) { }) } -func testAccCheckAWSEc2TrafficMirrorFilterExists(name string) resource.TestCheckFunc { +func TestAccAWSEc2TrafficMirrorFilter_tags(t *testing.T) { + var v ec2.TrafficMirrorFilter + resourceName := "aws_ec2_traffic_mirror_filter.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckAWSEc2TrafficMirrorFilter(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEc2TrafficMirrorFilterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTrafficMirrorFilterConfigTags1("key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccTrafficMirrorFilterConfigTags2("key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccTrafficMirrorFilterConfigTags1("key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + +func TestAccAWSEc2TrafficMirrorFilter_disappears(t *testing.T) { + var v ec2.TrafficMirrorFilter + resourceName := "aws_ec2_traffic_mirror_filter.test" + description := "test filter" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckAWSEc2TrafficMirrorFilter(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEc2TrafficMirrorFilterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTrafficMirrorFilterConfig(description), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEc2TrafficMirrorFilterExists(resourceName, &v), + testAccCheckAWSEc2TrafficMirrorFilterDisappears(&v), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckAWSEc2TrafficMirrorFilterExists(name string, traffic *ec2.TrafficMirrorFilter) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] if !ok { @@ -83,13 +156,26 @@ func testAccCheckAWSEc2TrafficMirrorFilterExists(name string) resource.TestCheck return fmt.Errorf("Traffic mirror filter %s not found", rs.Primary.ID) } + *traffic = *out.TrafficMirrorFilters[0] + return nil } } +func testAccCheckAWSEc2TrafficMirrorFilterDisappears(traffic *ec2.TrafficMirrorFilter) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).ec2conn + _, err := conn.DeleteTrafficMirrorFilter(&ec2.DeleteTrafficMirrorFilterInput{ + TrafficMirrorFilterId: traffic.TrafficMirrorFilterId, + }) + + return err + } +} + func testAccTrafficMirrorFilterConfig(description string) string { return fmt.Sprintf(` -resource "aws_ec2_traffic_mirror_filter" "filter" { +resource "aws_ec2_traffic_mirror_filter" "test" { description = "%s" network_services = ["amazon-dns"] @@ -99,12 +185,33 @@ resource "aws_ec2_traffic_mirror_filter" "filter" { func testAccTrafficMirrorFilterConfigWithoutDNS(description string) string { return fmt.Sprintf(` -resource "aws_ec2_traffic_mirror_filter" "filter" { +resource "aws_ec2_traffic_mirror_filter" "test" { description = "%s" } `, description) } +func testAccTrafficMirrorFilterConfigTags1(tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_ec2_traffic_mirror_filter" "test" { + tags = { + %[1]q = %[2]q + } +} +`, tagKey1, tagValue1) +} + +func testAccTrafficMirrorFilterConfigTags2(tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_ec2_traffic_mirror_filter" "test" { + tags = { + %[1]q = %[2]q + %[3]q = %[4]q + } +} +`, tagKey1, tagValue1, tagKey2, tagValue2) +} + func testAccPreCheckAWSEc2TrafficMirrorFilter(t *testing.T) { conn := testAccProvider.Meta().(*AWSClient).ec2conn diff --git a/website/docs/r/ec2_traffic_mirror_filter.html.markdown b/website/docs/r/ec2_traffic_mirror_filter.html.markdown index 93dcf6433ac3..55ab7cf7b804 100644 --- a/website/docs/r/ec2_traffic_mirror_filter.html.markdown +++ b/website/docs/r/ec2_traffic_mirror_filter.html.markdown @@ -27,7 +27,9 @@ resource "aws_ec2_traffic_mirror_filter" "foo" { The following arguments are supported: * `description` - (Optional, Forces new resource) A description of the filter. -* `network_services` - (Optional) List of amazon network services that should be mirrored. Valid values: amazon-dns +* `network_services` - (Optional) List of amazon network services that should be mirrored. Valid values: `amazon-dns`. +* `tags` - (Optional) Key-value mapping of resource tags. + ## Attributes Reference