diff --git a/.changelog/27433.txt b/.changelog/27433.txt new file mode 100644 index 00000000000..e5d9a944070 --- /dev/null +++ b/.changelog/27433.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_sesv2_email_identity_feedback_attributes +``` diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 17ad1fd5efe..cbe563e2147 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -2059,10 +2059,11 @@ func New(_ context.Context) (*schema.Provider, error) { "aws_ses_receipt_rule_set": ses.ResourceReceiptRuleSet(), "aws_ses_template": ses.ResourceTemplate(), - "aws_sesv2_configuration_set": sesv2.ResourceConfigurationSet(), - "aws_sesv2_dedicated_ip_assignment": sesv2.ResourceDedicatedIPAssignment(), - "aws_sesv2_dedicated_ip_pool": sesv2.ResourceDedicatedIPPool(), - "aws_sesv2_email_identity": sesv2.ResourceEmailIdentity(), + "aws_sesv2_configuration_set": sesv2.ResourceConfigurationSet(), + "aws_sesv2_dedicated_ip_assignment": sesv2.ResourceDedicatedIPAssignment(), + "aws_sesv2_dedicated_ip_pool": sesv2.ResourceDedicatedIPPool(), + "aws_sesv2_email_identity": sesv2.ResourceEmailIdentity(), + "aws_sesv2_email_identity_feedback_attributes": sesv2.ResourceEmailIdentityFeedbackAttributes(), "aws_sfn_activity": sfn.ResourceActivity(), "aws_sfn_state_machine": sfn.ResourceStateMachine(), diff --git a/internal/service/sesv2/email_identity_feedback_attributes.go b/internal/service/sesv2/email_identity_feedback_attributes.go new file mode 100644 index 00000000000..3342ef81fac --- /dev/null +++ b/internal/service/sesv2/email_identity_feedback_attributes.go @@ -0,0 +1,138 @@ +package sesv2 + +import ( + "context" + "errors" + "log" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/sesv2" + "github.com/aws/aws-sdk-go-v2/service/sesv2/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func ResourceEmailIdentityFeedbackAttributes() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceEmailIdentityFeedbackAttributesCreate, + ReadWithoutTimeout: resourceEmailIdentityFeedbackAttributesRead, + UpdateWithoutTimeout: resourceEmailIdentityFeedbackAttributesUpdate, + DeleteWithoutTimeout: resourceEmailIdentityFeedbackAttributesDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "email_forwarding_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "email_identity": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +const ( + ResNameEmailIdentityFeedbackAttributes = "Email Identity Feedback Attributes" +) + +func resourceEmailIdentityFeedbackAttributesCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).SESV2Conn + + in := &sesv2.PutEmailIdentityFeedbackAttributesInput{ + EmailIdentity: aws.String(d.Get("email_identity").(string)), + EmailForwardingEnabled: d.Get("email_forwarding_enabled").(bool), + } + + out, err := conn.PutEmailIdentityFeedbackAttributes(ctx, in) + if err != nil { + return create.DiagError(names.SESV2, create.ErrActionCreating, ResNameEmailIdentityFeedbackAttributes, d.Get("name").(string), err) + } + + if out == nil { + return create.DiagError(names.SESV2, create.ErrActionCreating, ResNameEmailIdentityFeedbackAttributes, d.Get("name").(string), errors.New("empty output")) + } + + d.SetId(d.Get("email_identity").(string)) + + return resourceEmailIdentityFeedbackAttributesRead(ctx, d, meta) +} + +func resourceEmailIdentityFeedbackAttributesRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).SESV2Conn + + out, err := FindEmailIdentityByID(ctx, conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] SESV2 EmailIdentityFeedbackAttributes (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return create.DiagError(names.SESV2, create.ErrActionReading, ResNameEmailIdentityFeedbackAttributes, d.Id(), err) + } + + d.Set("email_identity", d.Id()) + d.Set("email_forwarding_enabled", out.FeedbackForwardingStatus) + + return nil +} + +func resourceEmailIdentityFeedbackAttributesUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).SESV2Conn + + update := false + + in := &sesv2.PutEmailIdentityFeedbackAttributesInput{ + EmailIdentity: aws.String(d.Id()), + } + + if d.HasChanges("email_forwarding_enabled") { + in.EmailForwardingEnabled = d.Get("email_forwarding_enabled").(bool) + update = true + } + + if !update { + return nil + } + + log.Printf("[DEBUG] Updating SESV2 EmailIdentityFeedbackAttributes (%s): %#v", d.Id(), in) + _, err := conn.PutEmailIdentityFeedbackAttributes(ctx, in) + if err != nil { + return create.DiagError(names.SESV2, create.ErrActionUpdating, ResNameEmailIdentityFeedbackAttributes, d.Id(), err) + } + + return resourceEmailIdentityFeedbackAttributesRead(ctx, d, meta) +} + +func resourceEmailIdentityFeedbackAttributesDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).SESV2Conn + + log.Printf("[INFO] Deleting SESV2 EmailIdentityFeedbackAttributes %s", d.Id()) + + _, err := conn.PutEmailIdentityFeedbackAttributes(ctx, &sesv2.PutEmailIdentityFeedbackAttributesInput{ + EmailIdentity: aws.String(d.Id()), + }) + + if err != nil { + var nfe *types.NotFoundException + if errors.As(err, &nfe) { + return nil + } + + return create.DiagError(names.SESV2, create.ErrActionDeleting, ResNameEmailIdentityFeedbackAttributes, d.Id(), err) + } + + return nil +} diff --git a/internal/service/sesv2/email_identity_feedback_attributes_test.go b/internal/service/sesv2/email_identity_feedback_attributes_test.go new file mode 100644 index 00000000000..3b90ed538a5 --- /dev/null +++ b/internal/service/sesv2/email_identity_feedback_attributes_test.go @@ -0,0 +1,174 @@ +package sesv2_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "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" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfsesv2 "github.com/hashicorp/terraform-provider-aws/internal/service/sesv2" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccSESV2EmailIdentityFeedbackAttributes_basic(t *testing.T) { + rName := acctest.RandomEmailAddress(acctest.RandomDomainName()) + resourceName := "aws_sesv2_email_identity_feedback_attributes.test" + emailIdentityName := "aws_sesv2_email_identity.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEmailIdentityDestroy, + Steps: []resource.TestStep{ + { + Config: testAccEmailIdentityFeedbackAttributesConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEmailIdentityFeedbackAttributesExist(emailIdentityName, false), + resource.TestCheckResourceAttrPair(resourceName, "email_identity", emailIdentityName, "email_identity"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSESV2EmailIdentityFeedbackAttributes_disappears(t *testing.T) { + rName := acctest.RandomEmailAddress(acctest.RandomDomainName()) + resourceName := "aws_sesv2_email_identity_feedback_attributes.test" + emailIdentityName := "aws_sesv2_email_identity.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEmailIdentityDestroy, + Steps: []resource.TestStep{ + { + Config: testAccEmailIdentityFeedbackAttributesConfig_emailForwardingEnabled(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckEmailIdentityFeedbackAttributesExist(emailIdentityName, true), + acctest.CheckResourceDisappears(acctest.Provider, tfsesv2.ResourceEmailIdentityFeedbackAttributes(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccSESV2EmailIdentityFeedbackAttributes_disappears_emailIdentity(t *testing.T) { + rName := acctest.RandomEmailAddress(acctest.RandomDomainName()) + emailIdentityName := "aws_sesv2_email_identity.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEmailIdentityDestroy, + Steps: []resource.TestStep{ + { + Config: testAccEmailIdentityFeedbackAttributesConfig_emailForwardingEnabled(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckEmailIdentityFeedbackAttributesExist(emailIdentityName, true), + acctest.CheckResourceDisappears(acctest.Provider, tfsesv2.ResourceEmailIdentity(), emailIdentityName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccSESV2EmailIdentityFeedbackAttributes_emailForwardingEnabled(t *testing.T) { + rName := acctest.RandomEmailAddress(acctest.RandomDomainName()) + resourceName := "aws_sesv2_email_identity_feedback_attributes.test" + emailIdentityName := "aws_sesv2_email_identity.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEmailIdentityDestroy, + Steps: []resource.TestStep{ + { + Config: testAccEmailIdentityFeedbackAttributesConfig_emailForwardingEnabled(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckEmailIdentityFeedbackAttributesExist(emailIdentityName, true), + resource.TestCheckResourceAttr(resourceName, "email_forwarding_enabled", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccEmailIdentityFeedbackAttributesConfig_emailForwardingEnabled(rName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckEmailIdentityFeedbackAttributesExist(emailIdentityName, false), + resource.TestCheckResourceAttr(resourceName, "email_forwarding_enabled", "false"), + ), + }, + }, + }) +} + +// testAccCheckEmailIdentityFeedbackAttributesExist verifies that both the email identity exists, +// and that the email forwarding enabled setting is correct +func testAccCheckEmailIdentityFeedbackAttributesExist(name string, emailForwardingEnabled bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.SESV2, create.ErrActionCheckingExistence, tfsesv2.ResNameEmailIdentity, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.SESV2, create.ErrActionCheckingExistence, tfsesv2.ResNameEmailIdentity, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).SESV2Conn + + out, err := tfsesv2.FindEmailIdentityByID(context.Background(), conn, rs.Primary.ID) + if err != nil { + return create.Error(names.SESV2, create.ErrActionCheckingExistence, tfsesv2.ResNameEmailIdentity, rs.Primary.ID, err) + } + if out == nil || out.FeedbackForwardingStatus != emailForwardingEnabled { + return create.Error(names.SESV2, create.ErrActionCheckingExistence, tfsesv2.ResNameEmailIdentityFeedbackAttributes, rs.Primary.ID, err) + } + + return nil + } +} + +func testAccEmailIdentityFeedbackAttributesConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_sesv2_email_identity" "test" { + email_identity = %[1]q +} + +resource "aws_sesv2_email_identity_feedback_attributes" "test" { + email_identity = aws_sesv2_email_identity.test.email_identity +} +`, rName) +} + +func testAccEmailIdentityFeedbackAttributesConfig_emailForwardingEnabled(rName string, emailForwardingEnabled bool) string { + return fmt.Sprintf(` +resource "aws_sesv2_email_identity" "test" { + email_identity = %[1]q +} + +resource "aws_sesv2_email_identity_feedback_attributes" "test" { + email_identity = aws_sesv2_email_identity.test.email_identity + email_forwarding_enabled = %[2]t +} +`, rName, emailForwardingEnabled) +} diff --git a/website/docs/r/sesv2_email_identity_feedback_attributes.html.markdown b/website/docs/r/sesv2_email_identity_feedback_attributes.html.markdown new file mode 100644 index 00000000000..07ba966f4f4 --- /dev/null +++ b/website/docs/r/sesv2_email_identity_feedback_attributes.html.markdown @@ -0,0 +1,45 @@ +--- +subcategory: "SESv2 (Simple Email V2)" +layout: "aws" +page_title: "AWS: aws_sesv2_email_identity_feedback_attributes" +description: |- + Terraform resource for managing an AWS SESv2 (Simple Email V2) Email Identity Feedback Attributes. +--- + +# Resource: aws_sesv2_email_identity_feedback_attributes + +Terraform resource for managing an AWS SESv2 (Simple Email V2) Email Identity Feedback Attributes. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_sesv2_email_identity" "example" { + email_identity = "example.com" +} + +resource "aws_sesv2_email_identity_feedback_attributes" "example" { + email_identity = aws_sesv2_email_identity.example.email_identity + email_forwarding_enabled = true +} +``` + +## Argument Reference + +The following arguments are supported: + +* `email_identity` - (Required) The email identity. +* `email_forwarding_enabled` - (Optional) Sets the feedback forwarding configuration for the identity. + +## Attributes Reference + +No additional attributes are exported. + +## Import + +SESv2 (Simple Email V2) Email Identity Feedback Attributes can be imported using the `email_identity`, e.g., + +``` +$ terraform import aws_sesv2_email_identity_feedback_attributes.example example.com +```