Skip to content

Commit 6ce3239

Browse files
authored
Merge pull request #45470 from tabito-hara/f-aws_s3vectors_idnex-add_metatdata_configuration
[Enhancement] aws_s3vectors_index: Add `metadata_configuration` and `encryption_configuration` blocks
2 parents 9a81542 + 6630a6d commit 6ce3239

File tree

4 files changed

+299
-9
lines changed

4 files changed

+299
-9
lines changed

.changelog/45470.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
resource/aws_s3vectors_index: Add `metadata_configuration` block
3+
```
4+
5+
```release-note:enhancement
6+
resource/aws_s3vectors_index: Add `encryption_configuration` block
7+
```

internal/service/s3vectors/index.go

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ import (
1111
"github.com/aws/aws-sdk-go-v2/service/s3vectors"
1212
awstypes "github.com/aws/aws-sdk-go-v2/service/s3vectors/types"
1313
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
14+
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
15+
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
1416
"github.com/hashicorp/terraform-plugin-framework/resource"
1517
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
1618
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int32planmodifier"
19+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
1720
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
21+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier"
1822
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
23+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1924
"github.com/hashicorp/terraform-plugin-framework/types"
2025
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
2126
"github.com/hashicorp/terraform-provider-aws/internal/errs"
@@ -74,6 +79,10 @@ func (r *indexResource) Schema(ctx context.Context, request resource.SchemaReque
7479
stringplanmodifier.RequiresReplace(),
7580
},
7681
},
82+
names.AttrEncryptionConfiguration: framework.ResourceOptionalComputedListOfObjectsAttribute[indexEncryptionConfigurationModel](ctx, 1, nil,
83+
listplanmodifier.UseStateForUnknown(),
84+
listplanmodifier.RequiresReplace(),
85+
),
7786
"index_arn": schema.StringAttribute{
7887
Computed: true,
7988
PlanModifiers: []planmodifier.String{
@@ -95,6 +104,31 @@ func (r *indexResource) Schema(ctx context.Context, request resource.SchemaReque
95104
},
96105
},
97106
},
107+
Blocks: map[string]schema.Block{
108+
"metadata_configuration": schema.ListNestedBlock{
109+
CustomType: fwtypes.NewListNestedObjectTypeOf[indexMetadataConfigurationModel](ctx),
110+
PlanModifiers: []planmodifier.List{
111+
listplanmodifier.RequiresReplace(),
112+
},
113+
Validators: []validator.List{
114+
listvalidator.SizeAtMost(1),
115+
},
116+
NestedObject: schema.NestedBlockObject{
117+
Attributes: map[string]schema.Attribute{
118+
"non_filterable_metadata_keys": schema.SetAttribute{
119+
Required: true,
120+
ElementType: types.StringType,
121+
PlanModifiers: []planmodifier.Set{
122+
setplanmodifier.RequiresReplace(),
123+
},
124+
Validators: []validator.Set{
125+
setvalidator.SizeBetween(1, 10),
126+
},
127+
},
128+
},
129+
},
130+
},
131+
},
98132
}
99133
}
100134

@@ -248,13 +282,24 @@ func findIndex(ctx context.Context, conn *s3vectors.Client, input *s3vectors.Get
248282

249283
type indexResourceModel struct {
250284
framework.WithRegionModel
251-
CreationTime timetypes.RFC3339 `tfsdk:"creation_time"`
252-
DataType fwtypes.StringEnum[awstypes.DataType] `tfsdk:"data_type"`
253-
Dimension types.Int32 `tfsdk:"dimension"`
254-
DistanceMetric fwtypes.StringEnum[awstypes.DistanceMetric] `tfsdk:"distance_metric"`
255-
IndexARN types.String `tfsdk:"index_arn"`
256-
IndexName types.String `tfsdk:"index_name"`
257-
Tags tftags.Map `tfsdk:"tags"`
258-
TagsAll tftags.Map `tfsdk:"tags_all"`
259-
VectorBucketName types.String `tfsdk:"vector_bucket_name"`
285+
CreationTime timetypes.RFC3339 `tfsdk:"creation_time"`
286+
DataType fwtypes.StringEnum[awstypes.DataType] `tfsdk:"data_type"`
287+
Dimension types.Int32 `tfsdk:"dimension"`
288+
DistanceMetric fwtypes.StringEnum[awstypes.DistanceMetric] `tfsdk:"distance_metric"`
289+
EncryptionConfiguration fwtypes.ListNestedObjectValueOf[indexEncryptionConfigurationModel] `tfsdk:"encryption_configuration"`
290+
IndexARN types.String `tfsdk:"index_arn"`
291+
IndexName types.String `tfsdk:"index_name"`
292+
MetadataConfiguration fwtypes.ListNestedObjectValueOf[indexMetadataConfigurationModel] `tfsdk:"metadata_configuration"`
293+
Tags tftags.Map `tfsdk:"tags"`
294+
TagsAll tftags.Map `tfsdk:"tags_all"`
295+
VectorBucketName types.String `tfsdk:"vector_bucket_name"`
296+
}
297+
298+
type indexEncryptionConfigurationModel struct {
299+
KMSKeyARN fwtypes.ARN `tfsdk:"kms_key_arn"`
300+
SseType fwtypes.StringEnum[awstypes.SseType] `tfsdk:"sse_type"`
301+
}
302+
303+
type indexMetadataConfigurationModel struct {
304+
NonFilterableMetadataKeys fwtypes.SetOfString `tfsdk:"non_filterable_metadata_keys"`
260305
}

internal/service/s3vectors/index_test.go

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package s3vectors_test
66
import (
77
"context"
88
"fmt"
9+
"strings"
910
"testing"
1011

1112
"github.com/YakDriver/regexache"
@@ -79,6 +80,132 @@ func TestAccS3VectorsIndex_basic(t *testing.T) {
7980
})
8081
}
8182

83+
func TestAccS3VectorsIndex_encryptionConfigurationAES256(t *testing.T) {
84+
ctx := acctest.Context(t)
85+
var v awstypes.Index
86+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
87+
resourceName := "aws_s3vectors_index.test"
88+
89+
resource.ParallelTest(t, resource.TestCase{
90+
PreCheck: func() {
91+
acctest.PreCheck(ctx, t)
92+
testAccPreCheck(ctx, t)
93+
},
94+
ErrorCheck: acctest.ErrorCheck(t, names.S3VectorsServiceID),
95+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
96+
CheckDestroy: testAccCheckIndexDestroy(ctx),
97+
Steps: []resource.TestStep{
98+
{
99+
Config: testAccIndexConfig_encryptionConfigurationAES256(rName),
100+
Check: resource.ComposeAggregateTestCheckFunc(
101+
testAccCheckIndexExists(ctx, resourceName, &v),
102+
),
103+
ConfigPlanChecks: resource.ConfigPlanChecks{
104+
PreApply: []plancheck.PlanCheck{
105+
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
106+
},
107+
},
108+
ConfigStateChecks: []statecheck.StateCheck{
109+
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrEncryptionConfiguration).AtSliceIndex(0).AtMapKey("sse_type"), tfknownvalue.StringExact(awstypes.SseTypeAes256)),
110+
},
111+
},
112+
{
113+
ResourceName: resourceName,
114+
ImportState: true,
115+
ImportStateIdFunc: acctest.AttrImportStateIdFunc(resourceName, "index_arn"),
116+
ImportStateVerify: true,
117+
ImportStateVerifyIdentifierAttribute: "index_arn",
118+
},
119+
},
120+
})
121+
}
122+
123+
func TestAccS3VectorsIndex_encryptionConfigurationCMK(t *testing.T) {
124+
ctx := acctest.Context(t)
125+
var v awstypes.Index
126+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
127+
resourceName := "aws_s3vectors_index.test"
128+
129+
resource.ParallelTest(t, resource.TestCase{
130+
PreCheck: func() {
131+
acctest.PreCheck(ctx, t)
132+
testAccPreCheck(ctx, t)
133+
},
134+
ErrorCheck: acctest.ErrorCheck(t, names.S3VectorsServiceID),
135+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
136+
CheckDestroy: testAccCheckIndexDestroy(ctx),
137+
Steps: []resource.TestStep{
138+
{
139+
Config: testAccIndexConfig_encryptionConfigurationCMK(rName),
140+
Check: resource.ComposeAggregateTestCheckFunc(
141+
testAccCheckIndexExists(ctx, resourceName, &v),
142+
),
143+
ConfigPlanChecks: resource.ConfigPlanChecks{
144+
PreApply: []plancheck.PlanCheck{
145+
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
146+
},
147+
},
148+
ConfigStateChecks: []statecheck.StateCheck{
149+
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrEncryptionConfiguration).AtSliceIndex(0).AtMapKey("sse_type"), tfknownvalue.StringExact(awstypes.SseTypeAwsKms)),
150+
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrEncryptionConfiguration).AtSliceIndex(0).AtMapKey(names.AttrKMSKeyARN), knownvalue.NotNull()),
151+
},
152+
},
153+
{
154+
ResourceName: resourceName,
155+
ImportState: true,
156+
ImportStateIdFunc: acctest.AttrImportStateIdFunc(resourceName, "index_arn"),
157+
ImportStateVerify: true,
158+
ImportStateVerifyIdentifierAttribute: "index_arn",
159+
},
160+
},
161+
})
162+
}
163+
164+
func TestAccS3VectorsIndex_metadataConfiguration(t *testing.T) {
165+
ctx := acctest.Context(t)
166+
var v awstypes.Index
167+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
168+
resourceName := "aws_s3vectors_index.test"
169+
170+
resource.ParallelTest(t, resource.TestCase{
171+
PreCheck: func() {
172+
acctest.PreCheck(ctx, t)
173+
testAccPreCheck(ctx, t)
174+
},
175+
ErrorCheck: acctest.ErrorCheck(t, names.S3VectorsServiceID),
176+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
177+
CheckDestroy: testAccCheckIndexDestroy(ctx),
178+
Steps: []resource.TestStep{
179+
{
180+
Config: testAccIndexConfig_metadataConfiguration(rName, []string{acctest.CtKey1, acctest.CtKey2}),
181+
Check: resource.ComposeAggregateTestCheckFunc(
182+
testAccCheckIndexExists(ctx, resourceName, &v),
183+
),
184+
ConfigPlanChecks: resource.ConfigPlanChecks{
185+
PreApply: []plancheck.PlanCheck{
186+
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
187+
},
188+
},
189+
ConfigStateChecks: []statecheck.StateCheck{
190+
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("metadata_configuration").AtSliceIndex(0).AtMapKey("non_filterable_metadata_keys"), knownvalue.SetExact(
191+
[]knownvalue.Check{
192+
knownvalue.StringExact(acctest.CtKey1),
193+
knownvalue.StringExact(acctest.CtKey2),
194+
},
195+
)),
196+
},
197+
},
198+
{
199+
ResourceName: resourceName,
200+
ImportState: true,
201+
ImportStateIdFunc: acctest.AttrImportStateIdFunc(resourceName, "index_arn"),
202+
ImportStateVerify: true,
203+
ImportStateVerifyIdentifierAttribute: "index_arn",
204+
},
205+
},
206+
})
207+
}
208+
82209
func TestAccS3VectorsIndex_disappears(t *testing.T) {
83210
ctx := acctest.Context(t)
84211
var v awstypes.Index
@@ -229,3 +356,99 @@ resource "aws_s3vectors_index" "test" {
229356
}
230357
`, rName)
231358
}
359+
360+
func testAccIndexConfig_encryptionConfigurationAES256(rName string) string {
361+
return fmt.Sprintf(`
362+
resource "aws_s3vectors_vector_bucket" "test" {
363+
vector_bucket_name = "%[1]s-bucket"
364+
force_destroy = true
365+
}
366+
367+
resource "aws_s3vectors_index" "test" {
368+
index_name = %[1]q
369+
vector_bucket_name = aws_s3vectors_vector_bucket.test.vector_bucket_name
370+
371+
data_type = "float32"
372+
dimension = 2
373+
distance_metric = "euclidean"
374+
375+
encryption_configuration {
376+
sse_type = "AES256"
377+
}
378+
}
379+
`, rName)
380+
}
381+
382+
func testAccIndexConfig_encryptionConfigurationCMK(rName string) string {
383+
return fmt.Sprintf(`
384+
data "aws_caller_identity" "current" {}
385+
data "aws_partition" "current" {}
386+
387+
data "aws_iam_policy_document" "kms_key_policy" {
388+
statement {
389+
effect = "Allow"
390+
principals {
391+
type = "Service"
392+
identifiers = ["indexing.s3vectors.amazonaws.com"]
393+
}
394+
actions = ["kms:Decrypt"]
395+
resources = ["*"]
396+
}
397+
statement {
398+
effect = "Allow"
399+
principals {
400+
type = "AWS"
401+
identifiers = ["arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:root"]
402+
}
403+
actions = ["kms:*"]
404+
resources = ["*"]
405+
}
406+
}
407+
408+
resource "aws_kms_key" "test" {
409+
deletion_window_in_days = 7
410+
policy = data.aws_iam_policy_document.kms_key_policy.json
411+
}
412+
413+
resource "aws_s3vectors_vector_bucket" "test" {
414+
vector_bucket_name = "%[1]s-bucket"
415+
force_destroy = true
416+
}
417+
418+
resource "aws_s3vectors_index" "test" {
419+
index_name = %[1]q
420+
vector_bucket_name = aws_s3vectors_vector_bucket.test.vector_bucket_name
421+
422+
data_type = "float32"
423+
dimension = 2
424+
distance_metric = "euclidean"
425+
426+
encryption_configuration {
427+
kms_key_arn = aws_kms_key.test.arn
428+
sse_type = "aws:kms"
429+
}
430+
}
431+
`, rName)
432+
}
433+
434+
func testAccIndexConfig_metadataConfiguration(rName string, keys []string) string {
435+
return fmt.Sprintf(`
436+
resource "aws_s3vectors_vector_bucket" "test" {
437+
vector_bucket_name = "%[1]s-bucket"
438+
force_destroy = true
439+
}
440+
441+
resource "aws_s3vectors_index" "test" {
442+
index_name = %[1]q
443+
vector_bucket_name = aws_s3vectors_vector_bucket.test.vector_bucket_name
444+
445+
data_type = "float32"
446+
dimension = 2
447+
distance_metric = "euclidean"
448+
449+
metadata_configuration {
450+
non_filterable_metadata_keys = ["%[2]s"]
451+
}
452+
}
453+
`, rName, strings.Join(keys, `", "`))
454+
}

website/docs/r/s3vectors_index.html.markdown

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,23 @@ The following arguments are required:
3838
The following arguments are optional:
3939

4040
* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference).
41+
* `encryption_configuration` - (Optional, Forces new resource) Block for encryption configuration for the vector index. See [`encyption_configuration` block](#encyption_configuration-block) below.
42+
* `metadata_configuration` - (Optional, Forces new resource) Block for metadata configuration for the vector index. See [`metadata_configuration` block](#metadata_configuration-block) below.
4143
* `tags` - (Optional) Key-value map of resource tags. 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.
4244

45+
### `encyption_configuration` block
46+
47+
The `encryption_configuration` block supports the following attributes:
48+
49+
* `kms_key_id` - (Optional, Forces new resource) AWS Key Management Service (KMS) customer managed key ID to use for the encryption configuration. This parameter is allowed if and only if `sse_type` is set to `aws:kms`.
50+
* `sse_type` - (Optional, Forces new resource) Type of encryption to use. Valid values: `AES256`, `aws:kms`. Defaults to `AES256`.
51+
52+
### `metadata_configuration` block
53+
54+
The `metadata_configuration` block supports the following attributes:
55+
56+
* `non_filterable_metadata_keys` - (Required, Forces new resource) List of non-filterable metadata keys.
57+
4358
## Attribute Reference
4459

4560
This resource exports the following attributes in addition to the arguments above:

0 commit comments

Comments
 (0)