diff --git a/.changelog/33705.txt b/.changelog/33705.txt new file mode 100644 index 00000000000..e609ecc53e6 --- /dev/null +++ b/.changelog/33705.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_sesv2_account_vdm_attributes +``` \ No newline at end of file diff --git a/internal/service/sesv2/account_vdm_attributes.go b/internal/service/sesv2/account_vdm_attributes.go new file mode 100644 index 00000000000..f994cbf8fd2 --- /dev/null +++ b/internal/service/sesv2/account_vdm_attributes.go @@ -0,0 +1,239 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package sesv2 + +import ( + "context" + "errors" + "log" + + "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/retry" + "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/enum" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @SDKResource("aws_sesv2_account_vdm_attributes", name="Account VDM Attributes") +func ResourceAccountVDMAttributes() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceAccountVDMAttributesUpdate, + ReadWithoutTimeout: resourceAccountVDMAttributesRead, + UpdateWithoutTimeout: resourceAccountVDMAttributesUpdate, + DeleteWithoutTimeout: resourceAccountVDMAttributesDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "dashboard_attributes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "engagement_metrics": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[types.FeatureStatus](), + }, + }, + }, + }, + "guardian_attributes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "optimized_shared_delivery": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[types.FeatureStatus](), + }, + }, + }, + }, + "vdm_enabled": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[types.FeatureStatus](), + }, + }, + } +} + +const ( + ResNameAccountVDMAttributes = "Account VDM Attributes" +) + +func resourceAccountVDMAttributesUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).SESV2Client(ctx) + + in := &sesv2.PutAccountVdmAttributesInput{ + VdmAttributes: &types.VdmAttributes{ + VdmEnabled: types.FeatureStatus(d.Get("vdm_enabled").(string)), + }, + } + + if v, ok := d.GetOk("dashboard_attributes"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.VdmAttributes.DashboardAttributes = expandDashboardAttributes(v.([]interface{})[0].(map[string]interface{})) + } + + if v, ok := d.GetOk("guardian_attributes"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + in.VdmAttributes.GuardianAttributes = expandGuardianAttributes(v.([]interface{})[0].(map[string]interface{})) + } + + out, err := conn.PutAccountVdmAttributes(ctx, in) + if err != nil { + return create.DiagError(names.SESV2, create.ErrActionCreating, ResNameAccountVDMAttributes, "", err) + } + + if out == nil { + return create.DiagError(names.SESV2, create.ErrActionCreating, ResNameAccountVDMAttributes, "", errors.New("empty output")) + } + + if d.IsNewResource() { + d.SetId("ses-account-vdm-attributes") + } + + return resourceAccountVDMAttributesRead(ctx, d, meta) +} + +func resourceAccountVDMAttributesRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).SESV2Client(ctx) + + out, err := FindAccountVDMAttributes(ctx, conn) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] SESV2 AccountVDMAttributes (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return create.DiagError(names.SESV2, create.ErrActionReading, ResNameAccountVDMAttributes, d.Id(), err) + } + + if out.DashboardAttributes != nil { + if err := d.Set("dashboard_attributes", []interface{}{flattenDashboardAttributes(out.DashboardAttributes)}); err != nil { + return create.DiagError(names.SESV2, create.ErrActionSetting, ResNameAccountVDMAttributes, d.Id(), err) + } + } + + if out.GuardianAttributes != nil { + if err := d.Set("guardian_attributes", []interface{}{flattenGuardianAttributes(out.GuardianAttributes)}); err != nil { + return create.DiagError(names.SESV2, create.ErrActionSetting, ResNameAccountVDMAttributes, d.Id(), err) + } + } + + d.Set("vdm_enabled", out.VdmEnabled) + + return nil +} + +func resourceAccountVDMAttributesDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).SESV2Client(ctx) + + log.Printf("[INFO] Deleting SESV2 AccountVDMAttributes %s", d.Id()) + + _, err := conn.PutAccountVdmAttributes(ctx, &sesv2.PutAccountVdmAttributesInput{ + VdmAttributes: &types.VdmAttributes{ + VdmEnabled: "DISABLED", + }, + }) + + if err != nil { + var nfe *types.NotFoundException + if errors.As(err, &nfe) { + return nil + } + + return create.DiagError(names.SESV2, create.ErrActionDeleting, ResNameAccountVDMAttributes, d.Id(), err) + } + + return nil +} + +func FindAccountVDMAttributes(ctx context.Context, conn *sesv2.Client) (*types.VdmAttributes, error) { + in := &sesv2.GetAccountInput{} + out, err := conn.GetAccount(ctx, in) + if err != nil { + var nfe *types.NotFoundException + if errors.As(err, &nfe) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + return nil, err + } + + if out == nil || out.VdmAttributes == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out.VdmAttributes, nil +} + +func expandDashboardAttributes(tfMap map[string]interface{}) *types.DashboardAttributes { + if tfMap == nil { + return nil + } + + a := &types.DashboardAttributes{} + + if v, ok := tfMap["engagement_metrics"].(string); ok && v != "" { + a.EngagementMetrics = types.FeatureStatus(v) + } + + return a +} + +func expandGuardianAttributes(tfMap map[string]interface{}) *types.GuardianAttributes { + if tfMap == nil { + return nil + } + + a := &types.GuardianAttributes{} + + if v, ok := tfMap["optimized_shared_delivery"].(string); ok && v != "" { + a.OptimizedSharedDelivery = types.FeatureStatus(v) + } + + return a +} + +func flattenDashboardAttributes(apiObject *types.DashboardAttributes) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{ + "engagement_metrics": string(apiObject.EngagementMetrics), + } + + return m +} + +func flattenGuardianAttributes(apiObject *types.GuardianAttributes) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{ + "optimized_shared_delivery": string(apiObject.OptimizedSharedDelivery), + } + + return m +} diff --git a/internal/service/sesv2/account_vdm_attributes_test.go b/internal/service/sesv2/account_vdm_attributes_test.go new file mode 100644 index 00000000000..ca4d2e1c1fb --- /dev/null +++ b/internal/service/sesv2/account_vdm_attributes_test.go @@ -0,0 +1,202 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package sesv2_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/sesv2/types" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/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 TestAccSESV2AccountVDMAttributes_serial(t *testing.T) { + t.Parallel() + + testCases := map[string]func(t *testing.T){ + "basic": testAccAccountVDMAttributes_basic, + "disappears": testAccAccountVDMAttributes_disappears, + "engagementMetrics": testAccAccountVDMAttributes_engagementMetrics, + "optimizedSharedDelivery": testAccAccountVDMAttributes_optimizedSharedDelivery, + } + + acctest.RunSerialTests1Level(t, testCases, 0) +} + +func testAccAccountVDMAttributes_basic(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_sesv2_account_vdm_attributes.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckAccountVDMAttributesDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccAccountVDMAttributesConfig_basic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "vdm_enabled", string(types.FeatureStatusEnabled)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccAccountVDMAttributes_disappears(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_sesv2_account_vdm_attributes.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckAccountVDMAttributesDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccAccountVDMAttributesConfig_basic(), + Check: resource.ComposeTestCheckFunc( + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsesv2.ResourceAccountVDMAttributes(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccAccountVDMAttributes_engagementMetrics(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_sesv2_account_vdm_attributes.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckAccountVDMAttributesDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccAccountVDMAttributesConfig_engagementMetrics(string(types.FeatureStatusEnabled)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "dashboard_attributes.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dashboard_attributes.0.engagement_metrics", string(types.FeatureStatusEnabled)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAccountVDMAttributesConfig_engagementMetrics(string(types.FeatureStatusDisabled)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "dashboard_attributes.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dashboard_attributes.0.engagement_metrics", string(types.FeatureStatusDisabled)), + ), + }, + }, + }) +} + +func testAccAccountVDMAttributes_optimizedSharedDelivery(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_sesv2_account_vdm_attributes.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckAccountVDMAttributesDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccAccountVDMAttributesConfig_optimizedSharedDelivery(string(types.FeatureStatusEnabled)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "guardian_attributes.#", "1"), + resource.TestCheckResourceAttr(resourceName, "guardian_attributes.0.optimized_shared_delivery", string(types.FeatureStatusEnabled)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAccountVDMAttributesConfig_optimizedSharedDelivery(string(types.FeatureStatusDisabled)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "guardian_attributes.#", "1"), + resource.TestCheckResourceAttr(resourceName, "guardian_attributes.0.optimized_shared_delivery", string(types.FeatureStatusDisabled)), + ), + }, + }, + }) +} + +func testAccCheckAccountVDMAttributesDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).SESV2Client(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_sesv2_account_vdm_attributes" { + continue + } + + out, err := tfsesv2.FindAccountVDMAttributes(ctx, conn) + if err != nil { + return err + } + + if out.VdmEnabled == types.FeatureStatusDisabled { + return nil + } + + return create.Error(names.SESV2, create.ErrActionCheckingDestroyed, tfsesv2.ResNameAccountVDMAttributes, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccAccountVDMAttributesConfig_basic() string { + return ` +resource "aws_sesv2_account_vdm_attributes" "test" { + vdm_enabled = "ENABLED" +} +` +} + +func testAccAccountVDMAttributesConfig_engagementMetrics(engagementMetrics string) string { + return fmt.Sprintf(` +resource "aws_sesv2_account_vdm_attributes" "test" { + vdm_enabled = "ENABLED" + + dashboard_attributes { + engagement_metrics = %[1]q + } +} +`, engagementMetrics) +} + +func testAccAccountVDMAttributesConfig_optimizedSharedDelivery(optimizedSharedDelivery string) string { + return fmt.Sprintf(` +resource "aws_sesv2_account_vdm_attributes" "test" { + vdm_enabled = "ENABLED" + + guardian_attributes { + optimized_shared_delivery = %[1]q + } +} +`, optimizedSharedDelivery) +} diff --git a/internal/service/sesv2/service_package_gen.go b/internal/service/sesv2/service_package_gen.go index 69a64d5ed1b..8bd83b3cbf8 100644 --- a/internal/service/sesv2/service_package_gen.go +++ b/internal/service/sesv2/service_package_gen.go @@ -48,6 +48,11 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ + { + Factory: ResourceAccountVDMAttributes, + TypeName: "aws_sesv2_account_vdm_attributes", + Name: "Account VDM Attributes", + }, { Factory: ResourceConfigurationSet, TypeName: "aws_sesv2_configuration_set", diff --git a/website/docs/r/sesv2_account_vdm_attributes.html.markdown b/website/docs/r/sesv2_account_vdm_attributes.html.markdown new file mode 100644 index 00000000000..0c56181596e --- /dev/null +++ b/website/docs/r/sesv2_account_vdm_attributes.html.markdown @@ -0,0 +1,69 @@ +--- +subcategory: "SESv2 (Simple Email V2)" +layout: "aws" +page_title: "AWS: aws_sesv2_account_vdm_attributes" +description: |- + Terraform resource for managing an AWS SESv2 (Simple Email V2) Account VDM Attributes. +--- + +# Resource: aws_sesv2_account_vdm_attributes + +Terraform resource for managing an AWS SESv2 (Simple Email V2) Account VDM Attributes. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_sesv2_account_vdm_attributes" "example" { + vdm_enabled = "ENABLED" + + dashboard_attributes { + engagement_metrics = "ENABLED" + } + + guardian_attributes { + optimized_shared_delivery = "ENABLED" + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `vdm_enabled` - (Required) Specifies the status of your VDM configuration. Valid values: `ENABLED`, `DISABLED`. + +The following arguments are optional: + +* `dashboard_attributes` - (Optional) Specifies additional settings for your VDM configuration as applicable to the Dashboard. +* `guardian_attributes` - (Optional) Specifies additional settings for your VDM configuration as applicable to the Guardian. + +### dashboard_attributes + +* `engagement_metrics` - (Optional) Specifies the status of your VDM engagement metrics collection. Valid values: `ENABLED`, `DISABLED`. + +### guardian_attributes + +* `optimized_shared_delivery` - (Optional) Specifies the status of your VDM optimized shared delivery. Valid values: `ENABLED`, `DISABLED`. + +## Attribute Reference + +This data source exports no additional attributes. + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SESv2 (Simple Email V2) Account VDM Attributes using the word `ses-account-vdm-attributes`. For example: + +```terraform +import { + to = aws_sesv2_account_vdm_attributes.example + id = "ses-account-vdm-attributes" +} +``` + +Using `terraform import`, import SESv2 (Simple Email V2) Account VDM Attributes using the word `ses-account-vdm-attributes`. For example: + +```console +% terraform import aws_sesv2_account_vdm_attributes.example ses-account-vdm-attributes +```