From d0eeb39cd712c33322d799e483a16b08642df624 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Thu, 14 Mar 2019 17:30:26 -0400 Subject: [PATCH] resource/aws_ses_domain_mail_from: Prevent crash with deleted SES Domain Identity (#7883) Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/7862 Output from acceptance testing before code update: ``` === CONT TestAccAWSSESDomainMailFrom_disappears_Identity panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x3e051ac] goroutine 415 [running]: github.com/terraform-providers/terraform-provider-aws/aws.resourceAwsSesDomainMailFromRead(0xc0009825b0, 0x4a444a0, 0xc0004cec00, 0xc0009825b0, 0x0) /Users/bflad/src/github.com/terraform-providers/terraform-provider-aws/aws/resource_aws_ses_domain_mail_from.go:87 +0x37c ``` Output from acceptance testing: ``` --- PASS: TestAccAWSSESDomainIdentity_disappears (9.03s) --- PASS: TestAccAWSSESDomainMailFrom_disappears_Identity (10.38s) --- PASS: TestAccAWSSESDomainMailFrom_disappears (13.55s) --- PASS: TestAccAWSSESDomainMailFrom_behaviorOnMxFailure (21.04s) --- PASS: TestAccAWSSESDomainMailFrom_basic (21.11s) ``` --- aws/resource_aws_ses_domain_identity_test.go | 36 +++++++++++ aws/resource_aws_ses_domain_mail_from.go | 24 ++++--- aws/resource_aws_ses_domain_mail_from_test.go | 63 +++++++++++++++++++ 3 files changed, 114 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_ses_domain_identity_test.go b/aws/resource_aws_ses_domain_identity_test.go index d22ca76065b5..4b7abc2677bb 100644 --- a/aws/resource_aws_ses_domain_identity_test.go +++ b/aws/resource_aws_ses_domain_identity_test.go @@ -34,6 +34,28 @@ func TestAccAWSSESDomainIdentity_basic(t *testing.T) { }) } +func TestAccAWSSESDomainIdentity_disappears(t *testing.T) { + domain := fmt.Sprintf( + "%s.terraformtesting.com", + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsSESDomainIdentityDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsSESDomainIdentityConfig(domain), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsSESDomainIdentityExists("aws_ses_domain_identity.test"), + testAccCheckAwsSESDomainIdentityDisappears(domain), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccAWSSESDomainIdentity_trailingPeriod(t *testing.T) { domain := fmt.Sprintf( "%s.terraformtesting.com.", @@ -116,6 +138,20 @@ func testAccCheckAwsSESDomainIdentityExists(n string) resource.TestCheckFunc { } } +func testAccCheckAwsSESDomainIdentityDisappears(identity string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).sesConn + + input := &ses.DeleteIdentityInput{ + Identity: aws.String(identity), + } + + _, err := conn.DeleteIdentity(input) + + return err + } +} + func testAccCheckAwsSESDomainIdentityArn(n string, domain string) resource.TestCheckFunc { return func(s *terraform.State) error { rs := s.RootModule().Resources[n] diff --git a/aws/resource_aws_ses_domain_mail_from.go b/aws/resource_aws_ses_domain_mail_from.go index c7361a607607..3174702039c4 100644 --- a/aws/resource_aws_ses_domain_mail_from.go +++ b/aws/resource_aws_ses_domain_mail_from.go @@ -73,21 +73,27 @@ func resourceAwsSesDomainMailFromRead(d *schema.ResourceData, meta interface{}) } out, err := conn.GetIdentityMailFromDomainAttributes(readOpts) + if err != nil { - log.Printf("error fetching MAIL FROM domain attributes for %s: %s", domainName, err) - return err + return fmt.Errorf("error fetching SES MAIL FROM domain attributes for %s: %s", domainName, err) } - d.Set("domain", domainName) + if out == nil { + return fmt.Errorf("error fetching SES MAIL FROM domain attributes for %s: empty response", domainName) + } - if v, ok := out.MailFromDomainAttributes[domainName]; ok { - d.Set("behavior_on_mx_failure", v.BehaviorOnMXFailure) - d.Set("mail_from_domain", v.MailFromDomain) - } else { - d.Set("behavior_on_mx_failure", v.BehaviorOnMXFailure) - d.Set("mail_from_domain", "") + attributes, ok := out.MailFromDomainAttributes[domainName] + + if !ok { + log.Printf("[WARN] SES Domain Identity (%s) not found, removing from state", domainName) + d.SetId("") + return nil } + d.Set("behavior_on_mx_failure", attributes.BehaviorOnMXFailure) + d.Set("domain", domainName) + d.Set("mail_from_domain", attributes.MailFromDomain) + return nil } diff --git a/aws/resource_aws_ses_domain_mail_from_test.go b/aws/resource_aws_ses_domain_mail_from_test.go index d421a97b34d9..1e72f1723530 100644 --- a/aws/resource_aws_ses_domain_mail_from_test.go +++ b/aws/resource_aws_ses_domain_mail_from_test.go @@ -51,6 +51,54 @@ func TestAccAWSSESDomainMailFrom_basic(t *testing.T) { }) } +func TestAccAWSSESDomainMailFrom_disappears(t *testing.T) { + domain := fmt.Sprintf( + "%s.terraformtesting.com", + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + mailFromDomain := fmt.Sprintf("bounce.%s", domain) + resourceName := "aws_ses_domain_mail_from.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckSESDomainMailFromDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsSESDomainMailFromConfig(domain, mailFromDomain), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsSESDomainMailFromExists(resourceName), + testAccCheckAwsSESDomainMailFromDisappears(domain), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAWSSESDomainMailFrom_disappears_Identity(t *testing.T) { + domain := fmt.Sprintf( + "%s.terraformtesting.com", + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + mailFromDomain := fmt.Sprintf("bounce.%s", domain) + resourceName := "aws_ses_domain_mail_from.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckSESDomainMailFromDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsSESDomainMailFromConfig(domain, mailFromDomain), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsSESDomainMailFromExists(resourceName), + testAccCheckAwsSESDomainIdentityDisappears(domain), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccAWSSESDomainMailFrom_behaviorOnMxFailure(t *testing.T) { domain := fmt.Sprintf( "%s.terraformtesting.com", @@ -142,6 +190,21 @@ func testAccCheckSESDomainMailFromDestroy(s *terraform.State) error { return nil } +func testAccCheckAwsSESDomainMailFromDisappears(identity string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).sesConn + + input := &ses.SetIdentityMailFromDomainInput{ + Identity: aws.String(identity), + MailFromDomain: nil, + } + + _, err := conn.SetIdentityMailFromDomain(input) + + return err + } +} + func testAccAwsSESDomainMailFromConfig(domain, mailFromDomain string) string { return fmt.Sprintf(` resource "aws_ses_domain_identity" "test" {