diff --git a/.changelog/40764.txt b/.changelog/40764.txt new file mode 100644 index 00000000000..d362b3f62c7 --- /dev/null +++ b/.changelog/40764.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_elasticache_user: Add `VALKEY` as supported value for 'engine' argument +``` + +```release-note:enhancement +resource/aws_elasticache_user_group: Add `VALKEY` as supported value for 'engine' argument +``` \ No newline at end of file diff --git a/internal/service/elasticache/user.go b/internal/service/elasticache/user.go index 315999095d2..87398d98965 100644 --- a/internal/service/elasticache/user.go +++ b/internal/service/elasticache/user.go @@ -6,7 +6,6 @@ package elasticache import ( "context" "log" - "strings" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -21,6 +20,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" + "github.com/hashicorp/terraform-provider-aws/internal/sdkv2" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -88,13 +88,10 @@ func resourceUser() *schema.Resource { }, }, names.AttrEngine: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"REDIS"}, false), - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"REDIS", "VALKEY"}, false), + DiffSuppressFunc: sdkv2.SuppressEquivalentStringCaseInsensitive, }, "no_password_required": { Type: schema.TypeBool, @@ -245,6 +242,10 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf } } + if d.HasChange(names.AttrEngine) { + input.Engine = aws.String(d.Get(names.AttrEngine).(string)) + } + if d.HasChange("no_password_required") { input.NoPasswordRequired = aws.Bool(d.Get("no_password_required").(bool)) } diff --git a/internal/service/elasticache/user_group.go b/internal/service/elasticache/user_group.go index 49d1b72c4f9..dc74c76ee64 100644 --- a/internal/service/elasticache/user_group.go +++ b/internal/service/elasticache/user_group.go @@ -6,7 +6,6 @@ package elasticache import ( "context" "log" - "strings" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -20,6 +19,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" + "github.com/hashicorp/terraform-provider-aws/internal/sdkv2" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -48,13 +48,10 @@ func resourceUserGroup() *schema.Resource { Computed: true, }, names.AttrEngine: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"REDIS"}, false), - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"REDIS", "VALKEY"}, false), + DiffSuppressFunc: sdkv2.SuppressEquivalentStringCaseInsensitive, }, names.AttrTags: tftags.TagsSchema(), names.AttrTagsAll: tftags.TagsSchemaComputed(), @@ -157,10 +154,13 @@ func resourceUserGroupUpdate(ctx context.Context, d *schema.ResourceData, meta i UserGroupId: aws.String(d.Get("user_group_id").(string)), } + if d.HasChange(names.AttrEngine) { + input.Engine = aws.String(d.Get(names.AttrEngine).(string)) + } + if d.HasChange("user_ids") { o, n := d.GetChange("user_ids") - del := o.(*schema.Set).Difference(n.(*schema.Set)) - add := n.(*schema.Set).Difference(o.(*schema.Set)) + add, del := n.(*schema.Set).Difference(o.(*schema.Set)), o.(*schema.Set).Difference(n.(*schema.Set)) if add.Len() > 0 { input.UserIdsToAdd = flex.ExpandStringValueSet(add) diff --git a/internal/service/elasticache/user_group_test.go b/internal/service/elasticache/user_group_test.go index a316c31aaa2..31957ce2e9f 100644 --- a/internal/service/elasticache/user_group_test.go +++ b/internal/service/elasticache/user_group_test.go @@ -88,6 +88,24 @@ func TestAccElastiCacheUserGroup_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrEngine, "redis"), ), }, + { + Config: testAccUserGroupConfig_engineValkey(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserGroupExists(ctx, resourceName, &userGroup), + resource.TestCheckResourceAttr(resourceName, "user_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "user_group_id", rName), + resource.TestCheckResourceAttr(resourceName, names.AttrEngine, "valkey"), + ), + }, + { + Config: testAccUserGroupConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserGroupExists(ctx, resourceName, &userGroup), + resource.TestCheckResourceAttr(resourceName, "user_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "user_group_id", rName), + resource.TestCheckResourceAttr(resourceName, names.AttrEngine, "redis"), + ), + }, }, }) } @@ -190,10 +208,6 @@ func testAccCheckUserGroupExists(ctx context.Context, n string, v *awstypes.User return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No ElastiCache User Group ID is set") - } - conn := acctest.Provider.Meta().(*conns.AWSClient).ElastiCacheClient(ctx) output, err := tfelasticache.FindUserGroupByID(ctx, conn, rs.Primary.ID) @@ -260,6 +274,24 @@ resource "aws_elasticache_user_group" "test" { `, rName)) } +func testAccUserGroupConfig_engineValkey(rName string) string { + return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` +resource "aws_elasticache_user" "test1" { + user_id = "%[1]s-1" + user_name = "default" + access_string = "on ~app::* -@all +@read +@hash +@bitmap +@geo -setbit -bitfield -hset -hsetnx -hmset -hincrby -hincrbyfloat -hdel -bitop -geoadd -georadius -georadiusbymember" + engine = "REDIS" + passwords = ["password123456789"] +} + +resource "aws_elasticache_user_group" "test" { + user_group_id = %[1]q + engine = "VALKEY" + user_ids = [aws_elasticache_user.test1.user_id] +} +`, rName)) +} + func testAccUserGroupConfig_tags1(rName, tagKey1, tagValue1 string) string { return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` resource "aws_elasticache_user" "test1" { diff --git a/internal/service/elasticache/user_test.go b/internal/service/elasticache/user_test.go index 726dcb513eb..d27d5b56a55 100644 --- a/internal/service/elasticache/user_test.go +++ b/internal/service/elasticache/user_test.go @@ -56,7 +56,7 @@ func TestAccElastiCacheUser_basic(t *testing.T) { }) } -func TestAccElastiCacheUser_password_auth_mode(t *testing.T) { +func TestAccElastiCacheUser_passwordAuthMode(t *testing.T) { ctx := acctest.Context(t) var user awstypes.User rName := sdkacctest.RandomWithPrefix("tf-acc") @@ -95,7 +95,7 @@ func TestAccElastiCacheUser_password_auth_mode(t *testing.T) { }) } -func TestAccElastiCacheUser_iam_auth_mode(t *testing.T) { +func TestAccElastiCacheUser_iamAuthMode(t *testing.T) { ctx := acctest.Context(t) var user awstypes.User rName := sdkacctest.RandomWithPrefix("tf-acc") @@ -167,7 +167,46 @@ func TestAccElastiCacheUser_update(t *testing.T) { }) } -func TestAccElastiCacheUser_update_password_auth_mode(t *testing.T) { +func TestAccElastiCacheUser_updateEngine(t *testing.T) { + ctx := acctest.Context(t) + var user awstypes.User + rName := sdkacctest.RandomWithPrefix("tf-acc") + resourceName := "aws_elasticache_user.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ElastiCacheServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckUserDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccUserConfigWithEngine(rName, "VALKEY"), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserExists(ctx, resourceName, &user), + resource.TestCheckResourceAttr(resourceName, names.AttrEngine, "valkey"), + ), + }, + { + Config: testAccUserConfigWithEngine(rName, "REDIS"), + Check: resource.ComposeTestCheckFunc( + testAccCheckUserExists(ctx, resourceName, &user), + resource.TestCheckResourceAttr(resourceName, names.AttrEngine, "redis"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "no_password_required", + "passwords", + }, + }, + }, + }) +} + +func TestAccElastiCacheUser_updatePasswordAuthMode(t *testing.T) { ctx := acctest.Context(t) var user awstypes.User rName := sdkacctest.RandomWithPrefix("tf-acc") @@ -381,10 +420,6 @@ func testAccCheckUserExists(ctx context.Context, n string, v *awstypes.User) res return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No ElastiCache User ID is set") - } - conn := acctest.Provider.Meta().(*conns.AWSClient).ElastiCacheClient(ctx) output, err := tfelasticache.FindUserByID(ctx, conn, rs.Primary.ID) @@ -467,6 +502,18 @@ resource "aws_elasticache_user" "test" { `, rName) } +func testAccUserConfigWithEngine(rName, engine string) string { + return fmt.Sprintf(` +resource "aws_elasticache_user" "test" { + user_id = %[1]q + user_name = "username1" + access_string = "on ~* +@all" + engine = %[2]q + passwords = ["password123456789"] +} +`, rName, engine) +} + func testAccUserConfigWithPasswordAuthMode_twoPasswords(rName string, password1 string, password2 string) string { return fmt.Sprintf(` resource "aws_elasticache_user" "test" { diff --git a/website/docs/r/elasticache_user.html.markdown b/website/docs/r/elasticache_user.html.markdown index e41676ebafd..96d63d6bd36 100644 --- a/website/docs/r/elasticache_user.html.markdown +++ b/website/docs/r/elasticache_user.html.markdown @@ -57,7 +57,7 @@ resource "aws_elasticache_user" "test" { The following arguments are required: * `access_string` - (Required) Access permissions string used for this user. See [Specifying Permissions Using an Access String](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Clusters.RBAC.html#Access-string) for more details. -* `engine` - (Required) The current supported value is `REDIS`. +* `engine` - (Required) The current supported values are `REDIS`, `VALKEY`. * `user_id` - (Required) The ID of the user. * `user_name` - (Required) The username of the user. diff --git a/website/docs/r/elasticache_user_group.html.markdown b/website/docs/r/elasticache_user_group.html.markdown index 3a94928644a..ca2deb929ba 100644 --- a/website/docs/r/elasticache_user_group.html.markdown +++ b/website/docs/r/elasticache_user_group.html.markdown @@ -32,7 +32,7 @@ resource "aws_elasticache_user_group" "test" { The following arguments are required: -* `engine` - (Required) The current supported value is `REDIS`. +* `engine` - (Required) The current supported value are `REDIS`, `VALKEY`. * `user_group_id` - (Required) The ID of the user group. The following arguments are optional: