diff --git a/.changelog/36331.txt b/.changelog/36331.txt new file mode 100644 index 00000000000..7ea756883d8 --- /dev/null +++ b/.changelog/36331.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_keyspaces_keyspace: Add `replication_specification` argument +``` \ No newline at end of file diff --git a/internal/service/keyspaces/keyspace.go b/internal/service/keyspaces/keyspace.go index 28018c77ef0..722d3105a08 100644 --- a/internal/service/keyspaces/keyspace.go +++ b/internal/service/keyspaces/keyspace.go @@ -17,8 +17,10 @@ import ( "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/flex" 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" @@ -59,6 +61,34 @@ func resourceKeyspace() *schema.Resource { "The name can have up to 48 characters. It must begin with an alpha-numeric character and can only contain alpha-numeric characters and underscores.", ), }, + "replication_specification": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "replication_strategy": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[types.Rs](), + }, + "region_list": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + MaxItems: 6, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: verify.ValidRegionName, + }, + }, + }, + }, + }, names.AttrTags: tftags.TagsSchema(), names.AttrTagsAll: tftags.TagsSchemaComputed(), }, @@ -67,7 +97,6 @@ func resourceKeyspace() *schema.Resource { func resourceKeyspaceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KeyspacesClient(ctx) name := d.Get(names.AttrName).(string) @@ -76,6 +105,17 @@ func resourceKeyspaceCreate(ctx context.Context, d *schema.ResourceData, meta in Tags: getTagsIn(ctx), } + if v, ok := d.GetOk("replication_specification"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + tfMap := v.([]interface{})[0].(map[string]interface{}) + input.ReplicationSpecification = &types.ReplicationSpecification{ + ReplicationStrategy: types.Rs(tfMap["replication_strategy"].(string)), + } + + if v, ok := tfMap["region_list"].(*schema.Set); ok && v.Len() > 0 { + input.ReplicationSpecification.RegionList = flex.ExpandStringValueSet(v) + } + } + _, err := conn.CreateKeyspace(ctx, input) if err != nil { @@ -97,7 +137,6 @@ func resourceKeyspaceCreate(ctx context.Context, d *schema.ResourceData, meta in func resourceKeyspaceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KeyspacesClient(ctx) keyspace, err := findKeyspaceByName(ctx, conn, d.Id()) @@ -114,6 +153,10 @@ func resourceKeyspaceRead(ctx context.Context, d *schema.ResourceData, meta inte d.Set(names.AttrARN, keyspace.ResourceArn) d.Set(names.AttrName, keyspace.KeyspaceName) + d.Set("replication_specification", []interface{}{map[string]interface{}{ + "region_list": keyspace.ReplicationRegions, + "replication_strategy": keyspace.ReplicationStrategy, + }}) return diags } @@ -125,7 +168,6 @@ func resourceKeyspaceUpdate(ctx context.Context, d *schema.ResourceData, meta in func resourceKeyspaceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KeyspacesClient(ctx) log.Printf("[DEBUG] Deleting Keyspaces Keyspace: (%s)", d.Id()) diff --git a/internal/service/keyspaces/keyspace_test.go b/internal/service/keyspaces/keyspace_test.go index bca2aeebcbc..3ad4f54626f 100644 --- a/internal/service/keyspaces/keyspace_test.go +++ b/internal/service/keyspaces/keyspace_test.go @@ -8,6 +8,7 @@ import ( "fmt" "testing" + "github.com/aws/aws-sdk-go-v2/service/keyspaces/types" "github.com/hashicorp/aws-sdk-go-base/v2/endpoints" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -52,6 +53,44 @@ func TestAccKeyspacesKeyspace_basic(t *testing.T) { }) } +func TestAccKeyspacesKeyspace_replicationSpecificationMulti(t *testing.T) { + ctx := acctest.Context(t) + rName := "tf_acc_test_" + sdkacctest.RandString(20) + resourceName := "aws_keyspaces_keyspace.test" + region1 := acctest.Region() + region2 := acctest.AlternateRegion() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, names.KeyspacesServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckKeyspaceDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccKeyspaceConfig_replicationSpecification(rName, string(types.RsSingleRegion)), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKeyspaceExists(ctx, resourceName), + acctest.CheckResourceAttrRegionalARN(resourceName, "arn", "cassandra", "/keyspace/"+rName+"/"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "replication_specification.0.replication_strategy", string(types.RsSingleRegion)), + ), + }, + { + Config: testAccKeyspaceConfig_multiReplicationSpecification(rName, string(types.RsMultiRegion), region1, region2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKeyspaceExists(ctx, resourceName), + acctest.CheckResourceAttrRegionalARN(resourceName, "arn", "cassandra", "/keyspace/"+rName+"/"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "replication_specification.0.replication_strategy", string(types.RsMultiRegion)), + resource.TestCheckResourceAttr(resourceName, "replication_specification.0.region_list.#", "2"), + ), + }, + }, + }) +} + func TestAccKeyspacesKeyspace_disappears(t *testing.T) { ctx := acctest.Context(t) rName := "tf_acc_test_" + sdkacctest.RandString(20) @@ -197,3 +236,28 @@ resource "aws_keyspaces_keyspace" "test" { } `, rName, tag1Key, tag1Value, tag2Key, tag2Value) } + +func testAccKeyspaceConfig_replicationSpecification(rName, rSpecification string) string { + return fmt.Sprintf(` +resource "aws_keyspaces_keyspace" "test" { + name = %[1]q + + replication_specification { + replication_strategy = %[2]q + } +} +`, rName, rSpecification) +} + +func testAccKeyspaceConfig_multiReplicationSpecification(rName, rSpecification, region1, region2 string) string { + return fmt.Sprintf(` +resource "aws_keyspaces_keyspace" "test" { + name = %[1]q + + replication_specification { + replication_strategy = %[2]q + region_list = [%[3]q, %[4]q] + } +} +`, rName, rSpecification, region1, region2) +} diff --git a/internal/service/keyspaces/table.go b/internal/service/keyspaces/table.go index d80e3ff4871..4f7463d8954 100644 --- a/internal/service/keyspaces/table.go +++ b/internal/service/keyspaces/table.go @@ -305,7 +305,6 @@ func resourceTable() *schema.Resource { func resourceTableCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KeyspacesClient(ctx) keyspaceName := d.Get("keyspace_name").(string) @@ -366,11 +365,9 @@ func resourceTableCreate(ctx context.Context, d *schema.ResourceData, meta inter func resourceTableRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KeyspacesClient(ctx) keyspaceName, tableName, err := tableParseResourceID(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -446,11 +443,9 @@ func resourceTableRead(ctx context.Context, d *schema.ResourceData, meta interfa func resourceTableUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KeyspacesClient(ctx) keyspaceName, tableName, err := tableParseResourceID(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -618,11 +613,9 @@ func resourceTableUpdate(ctx context.Context, d *schema.ResourceData, meta inter func resourceTableDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).KeyspacesClient(ctx) keyspaceName, tableName, err := tableParseResourceID(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } diff --git a/website/docs/r/keyspaces_keyspace.html.markdown b/website/docs/r/keyspaces_keyspace.html.markdown index 50eb56b9da5..6ee3399a733 100644 --- a/website/docs/r/keyspaces_keyspace.html.markdown +++ b/website/docs/r/keyspaces_keyspace.html.markdown @@ -28,6 +28,9 @@ The following arguments are required: The following arguments are optional: +* `replication_specification` - (Optional) The replication specification of the keyspace. + * `region_list` - (Optional) Replication regions. If `replication_strategy` is `MULTI_REGION`, `region_list` requires the current Region and at least one additional AWS Region where the keyspace is going to be replicated in. + * `replication_strategy` - (Required) Replication strategy. Valid values: `SINGLE_REGION` and `MULTI_REGION`. * `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ## Attribute Reference