Skip to content

Commit

Permalink
Merge pull request #36568 from mattburgess/appsync-awssdkv2-migration
Browse files Browse the repository at this point in the history
appsync: Migrate to AWS SDK v2
  • Loading branch information
ewbankkit authored Jun 20, 2024
2 parents c41769d + baa3ebf commit 72576b8
Show file tree
Hide file tree
Showing 40 changed files with 3,261 additions and 3,032 deletions.
3 changes: 3 additions & 0 deletions .changelog/36568.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_appsync_api_key: Add `api_key_id` attribute
```
393 changes: 197 additions & 196 deletions go.mod

Large diffs are not rendered by default.

786 changes: 394 additions & 392 deletions go.sum

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions internal/conns/awsclient_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions internal/sdkv2/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package sdkv2

import (
"strings"
)

// ToUpperSchemaStateFunc converts a string value to uppercase before storing it in state.
func ToUpperSchemaStateFunc(v interface{}) string {
return strings.ToUpper(v.(string))
}
23 changes: 23 additions & 0 deletions internal/sdkv2/state_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package sdkv2

import (
"testing"

"github.com/google/go-cmp/cmp"
)

func TestToUpperSchemaStateFunc(t *testing.T) {
t.Parallel()

var input interface{} = "in-state"
want := "IN-STATE"

got := ToUpperSchemaStateFunc(input)

if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("unexpected diff (+want, -got): %s", diff)
}
}
205 changes: 147 additions & 58 deletions internal/service/appsync/api_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,42 @@ package appsync
import (
"context"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/appsync"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/appsync"
awstypes "github.com/aws/aws-sdk-go-v2/service/appsync/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-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/enum"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @SDKResource("aws_appsync_api_cache")
func ResourceAPICache() *schema.Resource {
// @SDKResource("aws_appsync_api_cache", name="API Cache")
func resourceAPICache() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceAPICacheCreate,
ReadWithoutTimeout: resourceAPICacheRead,
UpdateWithoutTimeout: resourceAPICacheUpdate,
DeleteWithoutTimeout: resourceAPICacheDelete,

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

Schema: map[string]*schema.Schema{
"api_id": {
Type: schema.TypeString,
Required: true,
},
"api_caching_behavior": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(appsync.ApiCachingBehavior_Values(), false),
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: enum.Validate[awstypes.ApiCachingBehavior](),
},
names.AttrType: {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(appsync.ApiCacheType_Values(), false),
},
"ttl": {
Type: schema.TypeInt,
"api_id": {
Type: schema.TypeString,
Required: true,
},
"at_rest_encryption_enabled": {
Expand All @@ -59,120 +54,214 @@ func ResourceAPICache() *schema.Resource {
Optional: true,
ForceNew: true,
},
"ttl": {
Type: schema.TypeInt,
Required: true,
},
names.AttrType: {
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: enum.Validate[awstypes.ApiCacheType](),
},
},
}
}

func resourceAPICacheCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).AppSyncConn(ctx)
conn := meta.(*conns.AWSClient).AppSyncClient(ctx)

apiID := d.Get("api_id").(string)

params := &appsync.CreateApiCacheInput{
input := &appsync.CreateApiCacheInput{
ApiCachingBehavior: awstypes.ApiCachingBehavior(d.Get("api_caching_behavior").(string)),
ApiId: aws.String(apiID),
Type: aws.String(d.Get(names.AttrType).(string)),
ApiCachingBehavior: aws.String(d.Get("api_caching_behavior").(string)),
Ttl: aws.Int64(int64(d.Get("ttl").(int))),
Ttl: int64(d.Get("ttl").(int)),
Type: awstypes.ApiCacheType(d.Get(names.AttrType).(string)),
}

if v, ok := d.GetOk("at_rest_encryption_enabled"); ok {
params.AtRestEncryptionEnabled = aws.Bool(v.(bool))
input.AtRestEncryptionEnabled = v.(bool)
}

if v, ok := d.GetOk("transit_encryption_enabled"); ok {
params.TransitEncryptionEnabled = aws.Bool(v.(bool))
input.TransitEncryptionEnabled = v.(bool)
}

_, err := conn.CreateApiCacheWithContext(ctx, params)
_, err := conn.CreateApiCache(ctx, input)

if err != nil {
return sdkdiag.AppendErrorf(diags, "creating Appsync API Cache: %s", err)
return sdkdiag.AppendErrorf(diags, "creating Appsync API Cache (%s): %s", apiID, err)
}

d.SetId(apiID)

if err := waitAPICacheAvailable(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for Appsync API Cache (%s) availability: %s", d.Id(), err)
if _, err := waitAPICacheAvailable(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for Appsync API Cache (%s) create: %s", d.Id(), err)
}

return append(diags, resourceAPICacheRead(ctx, d, meta)...)
}

func resourceAPICacheRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).AppSyncConn(ctx)
conn := meta.(*conns.AWSClient).AppSyncClient(ctx)

cache, err := findAPICacheByID(ctx, conn, d.Id())

cache, err := FindAPICacheByID(ctx, conn, d.Id())
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] AppSync API Cache (%s) not found, removing from state", d.Id())
d.SetId("")
return diags
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "getting Appsync API Cache %q: %s", d.Id(), err)
return sdkdiag.AppendErrorf(diags, "reading Appsync API Cache (%s): %s", d.Id(), err)
}

d.Set("api_id", d.Id())
d.Set(names.AttrType, cache.Type)
d.Set("api_caching_behavior", cache.ApiCachingBehavior)
d.Set("ttl", cache.Ttl)
d.Set("api_id", d.Id())
d.Set("at_rest_encryption_enabled", cache.AtRestEncryptionEnabled)
d.Set("transit_encryption_enabled", cache.TransitEncryptionEnabled)
d.Set("ttl", cache.Ttl)
d.Set(names.AttrType, cache.Type)

return diags
}

func resourceAPICacheUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).AppSyncConn(ctx)
conn := meta.(*conns.AWSClient).AppSyncClient(ctx)

params := &appsync.UpdateApiCacheInput{
input := &appsync.UpdateApiCacheInput{
ApiId: aws.String(d.Id()),
}

if d.HasChange(names.AttrType) {
params.Type = aws.String(d.Get(names.AttrType).(string))
}

if d.HasChange("api_caching_behavior") {
params.ApiCachingBehavior = aws.String(d.Get("api_caching_behavior").(string))
input.ApiCachingBehavior = awstypes.ApiCachingBehavior(d.Get("api_caching_behavior").(string))
}

if d.HasChange("ttl") {
params.Ttl = aws.Int64(int64(d.Get("ttl").(int)))
input.Ttl = int64(d.Get("ttl").(int))
}

if d.HasChange(names.AttrType) {
input.Type = awstypes.ApiCacheType(d.Get(names.AttrType).(string))
}

_, err := conn.UpdateApiCacheWithContext(ctx, params)
_, err := conn.UpdateApiCache(ctx, input)

if err != nil {
return sdkdiag.AppendErrorf(diags, "updating Appsync API Cache %q: %s", d.Id(), err)
}

if err := waitAPICacheAvailable(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for Appsync API Cache (%s) availability: %s", d.Id(), err)
if _, err := waitAPICacheAvailable(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for Appsync API Cache (%s) update: %s", d.Id(), err)
}

return append(diags, resourceAPICacheRead(ctx, d, meta)...)
}

func resourceAPICacheDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).AppSyncConn(ctx)
conn := meta.(*conns.AWSClient).AppSyncClient(ctx)

input := &appsync.DeleteApiCacheInput{
log.Printf("[INFO] Deleting Appsync API Cache: %s", d.Id())
_, err := conn.DeleteApiCache(ctx, &appsync.DeleteApiCacheInput{
ApiId: aws.String(d.Id()),
})

if errs.IsA[*awstypes.NotFoundException](err) {
return diags
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "deleting Appsync API Cache (%s): %s", d.Id(), err)
}

if _, err := waitAPICacheDeleted(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for Appsync API Cache (%s) delete: %s", d.Id(), err)
}

return diags
}

func findAPICacheByID(ctx context.Context, conn *appsync.Client, id string) (*awstypes.ApiCache, error) {
input := &appsync.GetApiCacheInput{
ApiId: aws.String(id),
}
_, err := conn.DeleteApiCacheWithContext(ctx, input)

output, err := conn.GetApiCache(ctx, input)

if errs.IsA[*awstypes.NotFoundException](err) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
if tfawserr.ErrCodeEquals(err, appsync.ErrCodeNotFoundException) {
return diags
return nil, err
}

if output == nil || output.ApiCache == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.ApiCache, nil
}

func statusAPICache(ctx context.Context, conn *appsync.Client, name string) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := findAPICacheByID(ctx, conn, name)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}
return sdkdiag.AppendErrorf(diags, "deleting Appsync API Cache: %s", err)

return output, string(output.Status), nil
}
}

if err := waitAPICacheDeleted(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for Appsync API Cache (%s) to be deleted: %s", d.Id(), err)
func waitAPICacheAvailable(ctx context.Context, conn *appsync.Client, id string) (*awstypes.ApiCache, error) { //nolint:unparam
const (
timeout = 60 * time.Minute
)
stateConf := &retry.StateChangeConf{
Pending: enum.Slice(awstypes.ApiCacheStatusCreating, awstypes.ApiCacheStatusModifying),
Target: enum.Slice(awstypes.ApiCacheStatusAvailable),
Refresh: statusAPICache(ctx, conn, id),
Timeout: timeout,
}

return diags
outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*awstypes.ApiCache); ok {
return output, err
}

return nil, err
}

func waitAPICacheDeleted(ctx context.Context, conn *appsync.Client, id string) (*awstypes.ApiCache, error) {
const (
timeout = 60 * time.Minute
)
stateConf := &retry.StateChangeConf{
Pending: enum.Slice(awstypes.ApiCacheStatusDeleting),
Target: []string{},
Refresh: statusAPICache(ctx, conn, id),
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*awstypes.ApiCache); ok {
return output, err
}

return nil, err
}
Loading

0 comments on commit 72576b8

Please sign in to comment.