Skip to content

Commit

Permalink
Merge pull request #27278 from hashicorp/f-aws_sesv2_dedicated_ip_pool
Browse files Browse the repository at this point in the history
New Resource `aws_sesv2_dedicated_ip_pool`
  • Loading branch information
jar-b authored Oct 18, 2022
2 parents 7f77cc5 + 54413d2 commit 55ad27d
Show file tree
Hide file tree
Showing 10 changed files with 665 additions and 2 deletions.
7 changes: 7 additions & 0 deletions .changelog/27278.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:new-resource
aws_sesv2_dedicated_ip_pool
```

```release-note:new-data-source
aws_sesv2_dedicated_ip_pool
```
3 changes: 3 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,8 @@ func New(_ context.Context) (*schema.Provider, error) {
"aws_ses_domain_identity": ses.DataSourceDomainIdentity(),
"aws_ses_email_identity": ses.DataSourceEmailIdentity(),

"aws_sesv2_dedicated_ip_pool": sesv2.DataSourceDedicatedIPPool(),

"aws_db_cluster_snapshot": rds.DataSourceClusterSnapshot(),
"aws_db_event_categories": rds.DataSourceEventCategories(),
"aws_db_instance": rds.DataSourceInstance(),
Expand Down Expand Up @@ -2051,6 +2053,7 @@ func New(_ context.Context) (*schema.Provider, error) {
"aws_ses_template": ses.ResourceTemplate(),

"aws_sesv2_configuration_set": sesv2.ResourceConfigurationSet(),
"aws_sesv2_dedicated_ip_pool": sesv2.ResourceDedicatedIPPool(),

"aws_sfn_activity": sfn.ResourceActivity(),
"aws_sfn_state_machine": sfn.ResourceStateMachine(),
Expand Down
1 change: 0 additions & 1 deletion internal/service/sesv2/configuration_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ func resourceConfigurationSetUpdate(ctx context.Context, d *schema.ResourceData,
}

if d.HasChanges("reputation_options") {
log.Printf("[DEBUG] has change kurwa")
in := &sesv2.PutConfigurationSetReputationOptionsInput{
ConfigurationSetName: aws.String(d.Id()),
}
Expand Down
187 changes: 187 additions & 0 deletions internal/service/sesv2/dedicated_ip_pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package sesv2

import (
"context"
"errors"
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/arn"
"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/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/create"
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"
"github.com/hashicorp/terraform-provider-aws/names"
)

func ResourceDedicatedIPPool() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceDedicatedIPPoolCreate,
ReadWithoutTimeout: resourceDedicatedIPPoolRead,
UpdateWithoutTimeout: resourceDedicatedIPPoolUpdate,
DeleteWithoutTimeout: resourceDedicatedIPPoolDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Update: schema.DefaultTimeout(30 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"pool_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},

CustomizeDiff: verify.SetTagsDiff,
}
}

const (
ResNameDedicatedIPPool = "Dedicated IP Pool"
)

func resourceDedicatedIPPoolCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).SESV2Conn

in := &sesv2.CreateDedicatedIpPoolInput{
PoolName: aws.String(d.Get("pool_name").(string)),
}

defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))
if len(tags) > 0 {
in.Tags = Tags(tags.IgnoreAWS())
}

out, err := conn.CreateDedicatedIpPool(ctx, in)
if err != nil {
return create.DiagError(names.SESV2, create.ErrActionCreating, ResNameDedicatedIPPool, d.Get("pool_name").(string), err)
}
if out == nil {
return create.DiagError(names.SESV2, create.ErrActionCreating, ResNameDedicatedIPPool, d.Get("pool_name").(string), errors.New("empty output"))
}

d.SetId(d.Get("pool_name").(string))
return resourceDedicatedIPPoolRead(ctx, d, meta)
}

func resourceDedicatedIPPoolRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).SESV2Conn

_, err := FindDedicatedIPPoolByID(ctx, conn, d.Id())
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] SESV2 DedicatedIPPool (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}
if err != nil {
return create.DiagError(names.SESV2, create.ErrActionReading, ResNameDedicatedIPPool, d.Id(), err)
}
d.Set("pool_name", d.Id())

poolNameARN := arn.ARN{
Partition: meta.(*conns.AWSClient).Partition,
Service: "ses",
Region: meta.(*conns.AWSClient).Region,
AccountID: meta.(*conns.AWSClient).AccountID,
Resource: fmt.Sprintf("dedicated-ip-pool/%s", d.Id()),
}.String()
d.Set("arn", poolNameARN)

tags, err := ListTags(ctx, conn, d.Get("arn").(string))
if err != nil {
return create.DiagError(names.SESV2, create.ErrActionReading, ResNameDedicatedIPPool, d.Id(), err)
}

defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig
tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return create.DiagError(names.SESV2, create.ErrActionSetting, ResNameDedicatedIPPool, d.Id(), err)
}

if err := d.Set("tags_all", tags.Map()); err != nil {
return create.DiagError(names.SESV2, create.ErrActionSetting, ResNameDedicatedIPPool, d.Id(), err)
}

return nil
}

func resourceDedicatedIPPoolUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).SESV2Conn

if d.HasChanges("tags_all") {
o, n := d.GetChange("tags_all")

if err := UpdateTags(ctx, conn, d.Get("arn").(string), o, n); err != nil {
return create.DiagError(names.SESV2, create.ErrActionUpdating, ResNameDedicatedIPPool, d.Id(), err)
}
}

return resourceDedicatedIPPoolRead(ctx, d, meta)
}

func resourceDedicatedIPPoolDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).SESV2Conn

log.Printf("[INFO] Deleting SESV2 DedicatedIPPool %s", d.Id())
_, err := conn.DeleteDedicatedIpPool(ctx, &sesv2.DeleteDedicatedIpPoolInput{
PoolName: 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, ResNameDedicatedIPPool, d.Id(), err)
}

return nil
}

func FindDedicatedIPPoolByID(ctx context.Context, conn *sesv2.Client, id string) (*sesv2.GetDedicatedIpsOutput, error) {
in := &sesv2.GetDedicatedIpsInput{
PoolName: aws.String(id),
}
out, err := conn.GetDedicatedIps(ctx, in)
if err != nil {
var nfe *types.NotFoundException
if errors.As(err, &nfe) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: in,
}
}

return nil, err
}

if out == nil {
return nil, tfresource.NewEmptyResultError(in)
}

return out, nil
}
115 changes: 115 additions & 0 deletions internal/service/sesv2/dedicated_ip_pool_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package sesv2

import (
"context"
"fmt"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/arn"
"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"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/names"
)

func DataSourceDedicatedIPPool() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceDedicatedIPPoolRead,

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"dedicated_ips": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ip": {
Type: schema.TypeString,
Computed: true,
},
"warmup_percentage": {
Type: schema.TypeInt,
Computed: true,
},
"warmup_status": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"pool_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tags": tftags.TagsSchemaComputed(),
},
}
}

const (
DSNameDedicatedIPPool = "Dedicated IP Pool Data Source"
)

func dataSourceDedicatedIPPoolRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).SESV2Conn
poolName := d.Get("pool_name").(string)

out, err := FindDedicatedIPPoolByID(ctx, conn, poolName)
if err != nil {
return create.DiagError(names.SESV2, create.ErrActionReading, DSNameDedicatedIPPool, poolName, err)
}
d.SetId(poolName)

poolNameARN := arn.ARN{
Partition: meta.(*conns.AWSClient).Partition,
Service: "ses",
Region: meta.(*conns.AWSClient).Region,
AccountID: meta.(*conns.AWSClient).AccountID,
Resource: fmt.Sprintf("dedicated-ip-pool/%s", d.Id()),
}.String()
d.Set("arn", poolNameARN)

d.Set("dedicated_ips", flattenDedicatedIPs(out.DedicatedIps))

tags, err := ListTags(ctx, conn, d.Get("arn").(string))
if err != nil {
return create.DiagError(names.SESV2, create.ErrActionReading, DSNameDedicatedIPPool, d.Id(), err)
}

defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig
tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return create.DiagError(names.SESV2, create.ErrActionSetting, DSNameDedicatedIPPool, d.Id(), err)
}

return nil
}

func flattenDedicatedIPs(apiObjects []types.DedicatedIp) []interface{} {
if len(apiObjects) == 0 {
return nil
}

var dedicatedIps []interface{}
for _, apiObject := range apiObjects {
ip := map[string]interface{}{
"ip": aws.ToString(apiObject.Ip),
"warmup_percentage": apiObject.WarmupPercentage,
"warmup_status": string(apiObject.WarmupStatus),
}

dedicatedIps = append(dedicatedIps, ip)
}

return dedicatedIps
}
50 changes: 50 additions & 0 deletions internal/service/sesv2/dedicated_ip_pool_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package sesv2_test

import (
"fmt"
"regexp"
"testing"

sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/names"
)

func TestAccSESV2DedicatedIPPoolDataSource_basic(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceName := "data.aws_sesv2_dedicated_ip_pool.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(t)
testAccPreCheck(t)
},
ErrorCheck: acctest.ErrorCheck(t, names.SESV2EndpointID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckDedicatedIPPoolDestroy,
Steps: []resource.TestStep{
{
Config: testAccDedicatedIPPoolDataSourceConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDedicatedIPPoolExists(dataSourceName),
resource.TestCheckResourceAttr(dataSourceName, "pool_name", rName),
acctest.MatchResourceAttrRegionalARN(dataSourceName, "arn", "ses", regexp.MustCompile(`dedicated-ip-pool/.+`)),
),
},
},
})
}

func testAccDedicatedIPPoolDataSourceConfig_basic(poolName string) string {
return fmt.Sprintf(`
resource "aws_sesv2_dedicated_ip_pool" "test" {
pool_name = %[1]q
}
data "aws_sesv2_dedicated_ip_pool" "test" {
depends_on = [aws_sesv2_dedicated_ip_pool.test]
pool_name = %[1]q
}
`, poolName, poolName)
}
Loading

0 comments on commit 55ad27d

Please sign in to comment.