Skip to content

Commit

Permalink
Merge pull request #40224 from atkretsch/f-memorydb_valkey
Browse files Browse the repository at this point in the history
Add Valkey engine support for memorydb resources
  • Loading branch information
ewbankkit authored Nov 26, 2024
2 parents bf676bb + bb13c9c commit c93f7bc
Show file tree
Hide file tree
Showing 66 changed files with 1,647 additions and 1,641 deletions.
15 changes: 15 additions & 0 deletions .changelog/40224.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```release-note:enhancement
resource/aws_memorydb_cluster: Add `engine` argument
```

```release-note:enhancement
resource/aws_memorydb_snapshot: Add `cluster_configuration.engine` attribute
```

```release-note:enhancement
data-source/aws_memorydb_cluster: Add `engine` attribute
```

```release-note:enhancement
data-source/aws_memorydb_snapshot: Add `cluster_configuration.engine` attribute
```
2 changes: 1 addition & 1 deletion .teamcity/components/generated/services_all.kt
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ val services = mapOf(
"mediapackage" to ServiceSpec("Elemental MediaPackage"),
"mediapackagev2" to ServiceSpec("Elemental MediaPackage Version 2"),
"mediastore" to ServiceSpec("Elemental MediaStore"),
"memorydb" to ServiceSpec("MemoryDB for Redis"),
"memorydb" to ServiceSpec("MemoryDB"),
"mq" to ServiceSpec("MQ", vpcLock = true),
"mwaa" to ServiceSpec("MWAA (Managed Workflows for Apache Airflow)", vpcLock = true),
"neptune" to ServiceSpec("Neptune"),
Expand Down
2 changes: 1 addition & 1 deletion internal/generate/checknames/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func checkDocFile(dir, name string, prefixes []DocPrefix) error {
sc := scanner.Text()
sc = strings.TrimSuffix(strings.TrimPrefix(sc, "subcategory: \""), "\"")
if hf != sc {
return fmt.Errorf("file (%s) subcategory (%s) doesn't match file name prefix, expecting %s", name, sc, hf)
return fmt.Errorf("file (%s) subcategory (%s) doesn't match HumanFriendly, expecting %s", name, sc, hf)
}
case 2:
continue
Expand Down
179 changes: 137 additions & 42 deletions internal/service/memorydb/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ package memorydb
import (
"context"
"log"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/memorydb"
awstypes "github.com/aws/aws-sdk-go-v2/service/memorydb/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"
"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"
Expand Down Expand Up @@ -81,7 +83,6 @@ func resourceACL() *schema.Resource {

func resourceACLCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics

conn := meta.(*conns.AWSClient).MemoryDBClient(ctx)

name := create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string))
Expand All @@ -94,25 +95,48 @@ func resourceACLCreate(ctx context.Context, d *schema.ResourceData, meta interfa
input.UserNames = flex.ExpandStringValueSet(v.(*schema.Set))
}

log.Printf("[DEBUG] Creating MemoryDB ACL: %+v", input)
_, err := conn.CreateACL(ctx, input)

if err != nil {
return sdkdiag.AppendErrorf(diags, "creating MemoryDB ACL (%s): %s", name, err)
}

if err := waitACLActive(ctx, conn, name); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for MemoryDB ACL (%s) to be created: %s", name, err)
}

d.SetId(name)

if _, err := waitACLActive(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for MemoryDB ACL (%s) create: %s", d.Id(), err)
}

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

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

acl, err := findACLByName(ctx, conn, d.Id())

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] MemoryDB ACL (%s) not found, removing from state", d.Id())
d.SetId("")
return diags
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "reading MemoryDB ACL (%s): %s", d.Id(), err)
}

d.Set(names.AttrARN, acl.ARN)
d.Set("minimum_engine_version", acl.MinimumEngineVersion)
d.Set(names.AttrName, acl.Name)
d.Set(names.AttrNamePrefix, create.NamePrefixFromName(aws.ToString(acl.Name)))
d.Set("user_names", acl.UserNames)

return diags
}

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

if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) {
Expand All @@ -121,9 +145,9 @@ func resourceACLUpdate(ctx context.Context, d *schema.ResourceData, meta interfa
}

o, n := d.GetChange("user_names")
oldSet, newSet := o.(*schema.Set), n.(*schema.Set)
os, ns := o.(*schema.Set), n.(*schema.Set)

if toAdd := newSet.Difference(oldSet); toAdd.Len() > 0 {
if toAdd := ns.Difference(os); toAdd.Len() > 0 {
input.UserNamesToAdd = flex.ExpandStringValueSet(toAdd)
}

Expand All @@ -134,17 +158,18 @@ func resourceACLUpdate(ctx context.Context, d *schema.ResourceData, meta interfa
// InvalidParameterValueException. To work around this, filter out any
// users that have been reported as no longer being in the group.

initialState, err := FindACLByName(ctx, conn, d.Id())
initialState, err := findACLByName(ctx, conn, d.Id())

if err != nil {
return sdkdiag.AppendErrorf(diags, "getting MemoryDB ACL (%s) current state: %s", d.Id(), err)
return sdkdiag.AppendErrorf(diags, "reading MemoryDB ACL (%s): %s", d.Id(), err)
}

initialUserNames := map[string]struct{}{}
for _, userName := range initialState.UserNames {
initialUserNames[userName] = struct{}{}
}

for _, v := range oldSet.Difference(newSet).List() {
for _, v := range os.Difference(ns).List() {
userNameToRemove := v.(string)
_, userNameStillPresent := initialUserNames[userNameToRemove]

Expand All @@ -154,69 +179,139 @@ func resourceACLUpdate(ctx context.Context, d *schema.ResourceData, meta interfa
}

if len(input.UserNamesToAdd) > 0 || len(input.UserNamesToRemove) > 0 {
log.Printf("[DEBUG] Updating MemoryDB ACL (%s)", d.Id())

_, err := conn.UpdateACL(ctx, input)

if err != nil {
return sdkdiag.AppendErrorf(diags, "updating MemoryDB ACL (%s): %s", d.Id(), err)
}

if err := waitACLActive(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for MemoryDB ACL (%s) to be modified: %s", d.Id(), err)
if _, err := waitACLActive(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for MemoryDB ACL (%s) update: %s", d.Id(), err)
}
}
}

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

func resourceACLRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
func resourceACLDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics

conn := meta.(*conns.AWSClient).MemoryDBClient(ctx)

acl, err := FindACLByName(ctx, conn, d.Id())
log.Printf("[DEBUG] Deleting MemoryDB ACL: (%s)", d.Id())
_, err := conn.DeleteACL(ctx, &memorydb.DeleteACLInput{
ACLName: aws.String(d.Id()),
})

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] MemoryDB ACL (%s) not found, removing from state", d.Id())
d.SetId("")
if errs.IsA[*awstypes.ACLNotFoundFault](err) {
return diags
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "reading MemoryDB ACL (%s): %s", d.Id(), err)
return sdkdiag.AppendErrorf(diags, "deleting MemoryDB ACL (%s): %s", d.Id(), err)
}

d.Set(names.AttrARN, acl.ARN)
d.Set("minimum_engine_version", acl.MinimumEngineVersion)
d.Set(names.AttrName, acl.Name)
d.Set(names.AttrNamePrefix, create.NamePrefixFromName(aws.ToString(acl.Name)))
d.Set("user_names", flex.FlattenStringValueSet(acl.UserNames))
if _, err := waitACLDeleted(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for MemoryDB ACL (%s) delete: %s", d.Id(), err)
}

return diags
}

func resourceACLDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
func findACLByName(ctx context.Context, conn *memorydb.Client, name string) (*awstypes.ACL, error) {
input := &memorydb.DescribeACLsInput{
ACLName: aws.String(name),
}

conn := meta.(*conns.AWSClient).MemoryDBClient(ctx)
return findACL(ctx, conn, input)
}

log.Printf("[DEBUG] Deleting MemoryDB ACL: (%s)", d.Id())
_, err := conn.DeleteACL(ctx, &memorydb.DeleteACLInput{
ACLName: aws.String(d.Id()),
})
func findACL(ctx context.Context, conn *memorydb.Client, input *memorydb.DescribeACLsInput) (*awstypes.ACL, error) {
output, err := findACLs(ctx, conn, input)

if errs.IsA[*awstypes.ACLNotFoundFault](err) {
return diags
if err != nil {
return nil, err
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "deleting MemoryDB ACL (%s): %s", d.Id(), err)
return tfresource.AssertSingleValueResult(output)
}

func findACLs(ctx context.Context, conn *memorydb.Client, input *memorydb.DescribeACLsInput) ([]awstypes.ACL, error) {
var output []awstypes.ACL

pages := memorydb.NewDescribeACLsPaginator(conn, input)
for pages.HasMorePages() {
page, err := pages.NextPage(ctx)

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

if err != nil {
return nil, err
}

output = append(output, page.ACLs...)
}

if err := waitACLDeleted(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for MemoryDB ACL (%s) to be deleted: %s", d.Id(), err)
return output, nil
}

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

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

if err != nil {
return nil, "", err
}

return output, aws.ToString(output.Status), nil
}
}

return diags
func waitACLActive(ctx context.Context, conn *memorydb.Client, name string) (*awstypes.ACL, error) { //nolint:unparam
const (
timeout = 5 * time.Minute
)
stateConf := &retry.StateChangeConf{
Pending: []string{aclStatusCreating, aclStatusModifying},
Target: []string{aclStatusActive},
Refresh: statusACL(ctx, conn, name),
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

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

return nil, err
}

func waitACLDeleted(ctx context.Context, conn *memorydb.Client, name string) (*awstypes.ACL, error) {
const (
timeout = 5 * time.Minute
)
stateConf := &retry.StateChangeConf{
Pending: []string{aclStatusDeleting},
Target: []string{},
Refresh: statusACL(ctx, conn, name),
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

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

return nil, err
}
20 changes: 3 additions & 17 deletions internal/service/memorydb/acl_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @SDKDataSource("aws_memorydb_acl", name="ACL")
// @Tags(identifierAttribute="arn")
func dataSourceACL() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceACLRead,
Expand Down Expand Up @@ -47,34 +47,20 @@ func dataSourceACL() *schema.Resource {

func dataSourceACLRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics

conn := meta.(*conns.AWSClient).MemoryDBClient(ctx)
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig(ctx)

name := d.Get(names.AttrName).(string)

acl, err := FindACLByName(ctx, conn, name)
acl, err := findACLByName(ctx, conn, name)

if err != nil {
return sdkdiag.AppendFromErr(diags, tfresource.SingularDataSourceFindError("MemoryDB ACL", err))
}

d.SetId(aws.ToString(acl.Name))

d.Set(names.AttrARN, acl.ARN)
d.Set("minimum_engine_version", acl.MinimumEngineVersion)
d.Set(names.AttrName, acl.Name)
d.Set("user_names", flex.FlattenStringValueSet(acl.UserNames))

tags, err := listTags(ctx, conn, d.Get(names.AttrARN).(string))

if err != nil {
return sdkdiag.AppendErrorf(diags, "listing tags for MemoryDB ACL (%s): %s", d.Id(), err)
}

if err := d.Set(names.AttrTags, tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return sdkdiag.AppendErrorf(diags, "setting tags: %s", err)
}
d.Set("user_names", acl.UserNames)

return diags
}
4 changes: 0 additions & 4 deletions internal/service/memorydb/acl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,6 @@ func testAccCheckACLExists(ctx context.Context, n string) resource.TestCheckFunc
return fmt.Errorf("Not found: %s", n)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No MemoryDB ACL ID is set")
}

conn := acctest.Provider.Meta().(*conns.AWSClient).MemoryDBClient(ctx)

_, err := tfmemorydb.FindACLByName(ctx, conn, rs.Primary.Attributes[names.AttrName])
Expand Down
Loading

0 comments on commit c93f7bc

Please sign in to comment.