Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/45468.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_bedrockagent_knowledge_base: Add storage_configuration.s3_vectors_configuration block
```
1 change: 1 addition & 0 deletions internal/service/bedrockagent/bedrockagent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func TestAccBedrockAgent_serial(t *testing.T) {
"OpenSearchBasic": testAccKnowledgeBase_OpenSearch_basic,
"OpenSearchUpdate": testAccKnowledgeBase_OpenSearch_update,
"OpenSearchSupplementalDataStorage": testAccKnowledgeBase_OpenSearch_supplementalDataStorage,
"S3Vectors": testAccKnowledgeBase_S3Vectors,
},
"DataSource": {
acctest.CtBasic: testAccDataSource_basic,
Expand Down
56 changes: 56 additions & 0 deletions internal/service/bedrockagent/knowledge_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
Expand Down Expand Up @@ -496,6 +498,53 @@ func (r *knowledgeBaseResource) Schema(ctx context.Context, request resource.Sch
},
},
},
"s3_vectors_configuration": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[s3VectorsConfigurationModel](ctx),
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
PlanModifiers: []planmodifier.List{
listplanmodifier.RequiresReplace(),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"index_arn": schema.StringAttribute{
CustomType: fwtypes.ARNType,
Optional: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Validators: []validator.String{
stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("index_name"), path.MatchRelative().AtParent().AtName("vector_bucket_arn")),
},
},
"index_name": schema.StringAttribute{
Optional: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Validators: []validator.String{
stringvalidator.AlsoRequires(path.MatchRelative().AtParent().AtName("vector_bucket_arn")),
stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("index_arn")),
},
},
"vector_bucket_arn": schema.StringAttribute{
CustomType: fwtypes.ARNType,
Optional: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Validators: []validator.String{
stringvalidator.AlsoRequires(path.MatchRelative().AtParent().AtName("index_name")),
stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("index_arn")),
},
},
},
Validators: []validator.Object{
objectvalidator.AtLeastOneOf(path.MatchRelative().AtName("index_arn"), path.MatchRelative().AtName("index_name")),
},
},
},
},
},
},
Expand Down Expand Up @@ -840,6 +889,7 @@ type storageConfigurationModel struct {
PineconeConfiguration fwtypes.ListNestedObjectValueOf[pineconeConfigurationModel] `tfsdk:"pinecone_configuration"`
RDSConfiguration fwtypes.ListNestedObjectValueOf[rdsConfigurationModel] `tfsdk:"rds_configuration"`
RedisEnterpriseCloudConfiguration fwtypes.ListNestedObjectValueOf[redisEnterpriseCloudConfigurationModel] `tfsdk:"redis_enterprise_cloud_configuration"`
S3VectorsConfiguration fwtypes.ListNestedObjectValueOf[s3VectorsConfigurationModel] `tfsdk:"s3_vectors_configuration"`
Type types.String `tfsdk:"type"`
}

Expand Down Expand Up @@ -895,3 +945,9 @@ type redisEnterpriseCloudFieldMappingModel struct {
TextField types.String `tfsdk:"text_field"`
VectorField types.String `tfsdk:"vector_field"`
}

type s3VectorsConfigurationModel struct {
IndexARN fwtypes.ARN `tfsdk:"index_arn"`
IndexName types.String `tfsdk:"index_name"`
VectorBucketARN fwtypes.ARN `tfsdk:"vector_bucket_arn"`
}
198 changes: 198 additions & 0 deletions internal/service/bedrockagent/knowledge_base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,69 @@ func testAccKnowledgeBase_OpenSearch_supplementalDataStorage(t *testing.T) {
})
}

func testAccKnowledgeBase_S3Vectors(t *testing.T) {
ctx := acctest.Context(t)

var knowledgebase types.KnowledgeBase
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_bedrockagent_knowledge_base.test"
foundationModel := "amazon.titan-embed-text-v2:0"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.BedrockAgentServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckKnowledgeBaseDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccKnowledgeBaseConfig_S3VectorsByIndexARN(rName, foundationModel),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate),
},
},
Check: resource.ComposeTestCheckFunc(
testAccCheckKnowledgeBaseExists(ctx, resourceName, &knowledgebase),
resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, "aws_iam_role.test", names.AttrARN),
resource.TestCheckResourceAttr(resourceName, "knowledge_base_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "knowledge_base_configuration.0.vector_knowledge_base_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "knowledge_base_configuration.0.type", "VECTOR"),
resource.TestCheckResourceAttr(resourceName, "storage_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "storage_configuration.0.type", "S3_VECTORS"),
resource.TestCheckResourceAttr(resourceName, "storage_configuration.0.s3_vectors_configuration.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "storage_configuration.0.s3_vectors_configuration.0.index_arn", "aws_s3vectors_index.test", "index_arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccKnowledgeBaseConfig_S3VectorsByIndexName(rName, foundationModel),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionDestroyBeforeCreate),
},
},
Check: resource.ComposeTestCheckFunc(
testAccCheckKnowledgeBaseExists(ctx, resourceName, &knowledgebase),
resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, "aws_iam_role.test", names.AttrARN),
resource.TestCheckResourceAttr(resourceName, "knowledge_base_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "knowledge_base_configuration.0.vector_knowledge_base_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "knowledge_base_configuration.0.type", "VECTOR"),
resource.TestCheckResourceAttr(resourceName, "storage_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "storage_configuration.0.type", "S3_VECTORS"),
resource.TestCheckResourceAttr(resourceName, "storage_configuration.0.s3_vectors_configuration.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "storage_configuration.0.s3_vectors_configuration.0.index_name", "aws_s3vectors_index.test", "index_name"),
),
},
},
})
}

func testAccCheckKnowledgeBaseDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).BedrockAgentClient(ctx)
Expand Down Expand Up @@ -946,3 +1009,138 @@ resource "aws_bedrockagent_knowledge_base" "test" {
}
`, rName, model))
}

func testAccKnowledgeBaseConfig_S3VectorsBase(rName string) string {
return fmt.Sprintf(`
data "aws_region" "current" {}
data "aws_partition" "current" {}

data "aws_iam_policy_document" "assume_role_bedrock" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["bedrock.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}

data "aws_iam_policy_document" "bedrock" {
statement {
effect = "Allow"
actions = ["bedrock:InvokeModel"]
resources = ["*"]
}
statement {
effect = "Allow"
actions = ["s3:ListBucket", "s3:GetObject"]
resources = ["*"]
}
statement {
effect = "Allow"
actions = [
"s3vectors:GetIndex",
"s3vectors:QueryVectors",
"s3vectors:PutVectors",
"s3vectors:GetVectors",
"s3vectors:DeleteVectors"
]
resources = ["*"]
}
}

resource "aws_iam_role" "test" {
assume_role_policy = data.aws_iam_policy_document.assume_role_bedrock.json
name = %[1]q
}

resource "aws_iam_role_policy" "test" {
role = aws_iam_role.test.name
policy = data.aws_iam_policy_document.bedrock.json
}

resource "aws_s3vectors_vector_bucket" "test" {
vector_bucket_name = %[1]q
force_destroy = true
}

resource "aws_s3vectors_index" "test" {
index_name = %[1]q
vector_bucket_name = aws_s3vectors_vector_bucket.test.vector_bucket_name

data_type = "float32"
dimension = 256
distance_metric = "euclidean"
}
`, rName)
}

func testAccKnowledgeBaseConfig_S3VectorsByIndexARN(rName, model string) string {
return acctest.ConfigCompose(
testAccKnowledgeBaseConfig_S3VectorsBase(rName),
fmt.Sprintf(`
resource "aws_bedrockagent_knowledge_base" "test" {
depends_on = [
aws_iam_role_policy.test,
]
name = %[1]q
role_arn = aws_iam_role.test.arn

knowledge_base_configuration {
vector_knowledge_base_configuration {
embedding_model_arn = "arn:${data.aws_partition.current.partition}:bedrock:${data.aws_region.current.region}::foundation-model/%[2]s"
embedding_model_configuration {
bedrock_embedding_model_configuration {
dimensions = 256
embedding_data_type = "FLOAT32"
}
}
}
type = "VECTOR"
}

storage_configuration {
type = "S3_VECTORS"
s3_vectors_configuration {
index_arn = aws_s3vectors_index.test.index_arn
}
}
}
`, rName, model))
}

func testAccKnowledgeBaseConfig_S3VectorsByIndexName(rName, model string) string {
return acctest.ConfigCompose(
testAccKnowledgeBaseConfig_S3VectorsBase(rName),
fmt.Sprintf(`
resource "aws_bedrockagent_knowledge_base" "test" {
depends_on = [
aws_iam_role_policy.test,
]
name = %[1]q
role_arn = aws_iam_role.test.arn

knowledge_base_configuration {
vector_knowledge_base_configuration {
embedding_model_arn = "arn:${data.aws_partition.current.partition}:bedrock:${data.aws_region.current.region}::foundation-model/%[2]s"
embedding_model_configuration {
bedrock_embedding_model_configuration {
dimensions = 256
embedding_data_type = "FLOAT32"
}
}
}
type = "VECTOR"
}

storage_configuration {
type = "S3_VECTORS"
s3_vectors_configuration {
index_name = aws_s3vectors_index.test.index_name
vector_bucket_arn = aws_s3vectors_vector_bucket.test.vector_bucket_arn
}
}
}
`, rName, model))
}
54 changes: 53 additions & 1 deletion website/docs/r/bedrockagent_knowledge_base.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,48 @@ resource "aws_bedrockagent_knowledge_base" "example" {
}
```

### S3 Vectors Configuration

```terraform
resource "aws_s3vectors_vector_bucket" "example" {
vector_bucket_name = "example-bucket"
}

resource "aws_s3vectors_index" "example" {
index_name = "example-index"
vector_bucket_name = aws_s3vectors_vector_bucket.example.vector_bucket_name

data_type = "float32"
dimension = 256
distance_metric = "euclidean"
}

resource "aws_bedrockagent_knowledge_base" "example" {
name = "example-s3vectors-kb"
role_arn = aws_iam_role.example.arn

knowledge_base_configuration {
vector_knowledge_base_configuration {
embedding_model_arn = "arn:aws:bedrock:us-west-2::foundation-model/amazon.titan-embed-text-v2:0"
embedding_model_configuration {
bedrock_embedding_model_configuration {
dimensions = 256
embedding_data_type = "FLOAT32"
}
}
}
type = "VECTOR"
}

storage_configuration {
type = "S3_VECTORS"
s3_vectors_configuration {
index_arn = aws_s3vectors_index.example.index_arn
}
}
}
```

## Argument Reference

The following arguments are required:
Expand Down Expand Up @@ -149,11 +191,12 @@ The `s3_location` configuration block supports the following arguments:

The `storage_configuration` configuration block supports the following arguments:

* `type` - (Required) Vector store service in which the knowledge base is stored. Valid Values: `OPENSEARCH_SERVERLESS`, `PINECONE`, `REDIS_ENTERPRISE_CLOUD`, `RDS`.
* `type` - (Required) Vector store service in which the knowledge base is stored. Valid Values: `OPENSEARCH_SERVERLESS`, `PINECONE`, `REDIS_ENTERPRISE_CLOUD`, `RDS`, `S3_VECTORS`.
* `opensearch_serverless_configuration` - (Optional) The storage configuration of the knowledge base in Amazon OpenSearch Service. See [`opensearch_serverless_configuration` block](#opensearch_serverless_configuration-block) for details.
* `pinecone_configuration` - (Optional) The storage configuration of the knowledge base in Pinecone. See [`pinecone_configuration` block](#pinecone_configuration-block) for details.
* `rds_configuration` - (Optional) Details about the storage configuration of the knowledge base in Amazon RDS. For more information, see [Create a vector index in Amazon RDS](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-setup.html). See [`rds_configuration` block](#rds_configuration-block) for details.
* `redis_enterprise_cloud_configuration` - (Optional) The storage configuration of the knowledge base in Redis Enterprise Cloud. See [`redis_enterprise_cloud_configuration` block](#redis_enterprise_cloud_configuration-block) for details.
* `s3_vectors_configuration` - (Optional) The storage configuration of the knowledge base in Amazon S3 Vectors. See [`s3_vectors_configuration` block](#s3_vectors_configuration-block) for details.

### `opensearch_serverless_configuration` block

Expand Down Expand Up @@ -204,6 +247,15 @@ The `redis_enterprise_cloud_configuration` configuration block supports the foll
* `vector_field` - (Required) Name of the field in which Amazon Bedrock stores the vector embeddings for your data sources.
* `vector_index_name` - (Required) Name of the vector index.

### `s3_vectors_configuration` block

The `s3_vectors_configuration` configuration block supports the following arguments.
Either `index_arn`, or both `index_name` and `vector_bucket_arn` must be specified.

* `index_arn` - (Optional) ARN of the S3 Vectors index. Conflicts with `index_name` and `vector_bucket_arn`.
* `index_name` - (Optional) Name of the S3 Vectors index. Must be specified with `vector_bucket_arn`. Conflicts with `index_arn`.
* `vector_bucket_arn` - (Optional) ARN of the S3 Vectors vector bucket. Must be specified with `index_name`. Conflicts with `index_arn`.

## Attribute Reference

This resource exports the following attributes in addition to the arguments above:
Expand Down
Loading