Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[data source]: aws_opensearchserverless_collection #32247

Merged
merged 10 commits into from
Jun 28, 2023
3 changes: 3 additions & 0 deletions .changelog/32247.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_opensearchserverless_collection
```
170 changes: 170 additions & 0 deletions internal/service/opensearchserverless/collection_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package opensearchserverless

import (
"context"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
awstypes "github.com/aws/aws-sdk-go-v2/service/opensearchserverless/types"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-provider-aws/internal/create"
"github.com/hashicorp/terraform-provider-aws/internal/framework"
"github.com/hashicorp/terraform-provider-aws/internal/framework/flex"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @FrameworkDataSource(name="Collection")
func newDataSourceCollection(context.Context) (datasource.DataSourceWithConfigure, error) {
return &dataSourceCollection{}, nil
}

const (
DSNameCollection = "Collection Data Source"
)

type dataSourceCollection struct {
framework.DataSourceWithConfigure
}

func (d *dataSourceCollection) Metadata(_ context.Context, _ datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name
resp.TypeName = "aws_opensearchserverless_collection"
}

func (d *dataSourceCollection) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"arn": framework.ARNAttributeComputedOnly(),
"collection_endpoint": schema.StringAttribute{
Computed: true,
},
"created_date": schema.StringAttribute{
Computed: true,
},
"dashboard_endpoint": schema.StringAttribute{
Computed: true,
},
"description": schema.StringAttribute{
Computed: true,
},
"id": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(
path.MatchRelative().AtParent().AtName("name"),
),
stringvalidator.ExactlyOneOf(
path.MatchRelative().AtParent().AtName("name"),
),
},
},
"kms_key_arn": schema.StringAttribute{
Computed: true,
},
"last_modified_date": schema.StringAttribute{
Computed: true,
},
"name": schema.StringAttribute{
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(
path.MatchRelative().AtParent().AtName("id"),
),
},
},
names.AttrTags: tftags.TagsAttributeComputedOnly(),
"type": schema.StringAttribute{
Computed: true,
},
},
}
}
func (d *dataSourceCollection) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
conn := d.Meta().OpenSearchServerlessClient(ctx)

var data dataSourceCollectionData
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

var out *awstypes.CollectionDetail

if !data.ID.IsNull() && !data.ID.IsUnknown() {
output, err := FindCollectionByID(ctx, conn, data.ID.ValueString())
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.OpenSearchServerless, create.ErrActionReading, DSNameCollection, data.ID.String(), err),
err.Error(),
)
return
}

out = output
}

if !data.Name.IsNull() && !data.Name.IsUnknown() {
output, err := FindCollectionByName(ctx, conn, data.Name.ValueString())
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.OpenSearchServerless, create.ErrActionReading, DSNameCollection, data.ID.String(), err),
err.Error(),
)
return
}

out = output
}

data.ARN = flex.StringToFramework(ctx, out.Arn)
data.CollectionEndpoint = flex.StringToFramework(ctx, out.CollectionEndpoint)
data.DashboardEndpoint = flex.StringToFramework(ctx, out.DashboardEndpoint)
data.Description = flex.StringToFramework(ctx, out.Description)
data.ID = flex.StringToFramework(ctx, out.Id)
data.KmsKeyARN = flex.StringToFramework(ctx, out.KmsKeyArn)
data.Name = flex.StringToFramework(ctx, out.Name)
data.Type = flex.StringValueToFramework(ctx, out.Type)

createdDate := time.UnixMilli(aws.ToInt64(out.CreatedDate))
data.CreatedDate = flex.StringValueToFramework(ctx, createdDate.Format(time.RFC3339))

lastModifiedDate := time.UnixMilli(aws.ToInt64(out.LastModifiedDate))
data.LastModifiedDate = flex.StringValueToFramework(ctx, lastModifiedDate.Format(time.RFC3339))

ignoreTagsConfig := d.Meta().IgnoreTagsConfig
tags, err := listTags(ctx, conn, aws.ToString(out.Arn))

if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.OpenSearchServerless, create.ErrActionReading, DSNameCollection, data.ID.String(), err),
err.Error(),
)
return
}

tags = tags.IgnoreConfig(ignoreTagsConfig)
data.Tags = flex.FlattenFrameworkStringValueMapLegacy(ctx, tags.Map())

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

type dataSourceCollectionData struct {
ARN types.String `tfsdk:"arn"`
CollectionEndpoint types.String `tfsdk:"collection_endpoint"`
CreatedDate types.String `tfsdk:"created_date"`
DashboardEndpoint types.String `tfsdk:"dashboard_endpoint"`
Description types.String `tfsdk:"description"`
ID types.String `tfsdk:"id"`
KmsKeyARN types.String `tfsdk:"kms_key_arn"`
LastModifiedDate types.String `tfsdk:"last_modified_date"`
Name types.String `tfsdk:"name"`
Tags types.Map `tfsdk:"tags"`
Type types.String `tfsdk:"type"`
}
135 changes: 135 additions & 0 deletions internal/service/opensearchserverless/collection_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package opensearchserverless_test

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go-v2/service/opensearchserverless/types"
sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/names"
)

func TestAccOpenSearchServerlessCollectionDataSource_basic(t *testing.T) {
ctx := acctest.Context(t)
if testing.Short() {
t.Skip("skipping long-running test in short mode")
}

var collection types.CollectionDetail
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceName := "data.aws_opensearchserverless_collection.test"
resourceName := "aws_opensearchserverless_collection.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, names.OpenSearchServerlessEndpointID)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.OpenSearchServerlessEndpointID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckCollectionDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccCollectionDataSourceConfig_basic(rName, "encryption"),
Check: resource.ComposeTestCheckFunc(
testAccCheckCollectionExists(ctx, dataSourceName, &collection),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"),
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "collection_endpoint", resourceName, "collection_endpoint"),
resource.TestCheckResourceAttrPair(dataSourceName, "dashboard_endpoint", resourceName, "dashboard_endpoint"),
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
resource.TestCheckResourceAttrPair(dataSourceName, "kms_key_arn", resourceName, "kms_key_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "type", resourceName, "type"),
),
},
},
})
}

func TestAccOpenSearchServerlessCollectionDataSource_name(t *testing.T) {
ctx := acctest.Context(t)
if testing.Short() {
t.Skip("skipping long-running test in short mode")
}

var collection types.CollectionDetail
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceName := "data.aws_opensearchserverless_collection.test"
resourceName := "aws_opensearchserverless_collection.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, names.OpenSearchServerlessEndpointID)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.OpenSearchServerlessEndpointID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckCollectionDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccCollectionDataSourceConfig_name(rName, "encryption"),
Check: resource.ComposeTestCheckFunc(
testAccCheckCollectionExists(ctx, dataSourceName, &collection),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"),
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "collection_endpoint", resourceName, "collection_endpoint"),
resource.TestCheckResourceAttrPair(dataSourceName, "dashboard_endpoint", resourceName, "dashboard_endpoint"),
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
resource.TestCheckResourceAttrPair(dataSourceName, "kms_key_arn", resourceName, "kms_key_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "type", resourceName, "type"),
),
},
},
})
}

func testAccCollectionDataSourceBaseConfig(rName, policyType string) string {
return fmt.Sprintf(`
resource "aws_opensearchserverless_security_policy" "test" {
name = %[1]q
type = %[2]q
policy = jsonencode({
Rules = [
{
Resource = [
"collection/%[1]s"
],
ResourceType = "collection"
}
],
AWSOwnedKey = true
})
}

resource "aws_opensearchserverless_collection" "test" {
name = %[1]q
depends_on = [aws_opensearchserverless_security_policy.test]
}
`, rName, policyType)
}

func testAccCollectionDataSourceConfig_basic(rName, policyType string) string {
return acctest.ConfigCompose(
testAccCollectionDataSourceBaseConfig(rName, policyType),
`
data "aws_opensearchserverless_collection" "test" {
id = aws_opensearchserverless_collection.test.id
}
`)
}

func testAccCollectionDataSourceConfig_name(rName, policyType string) string {
return acctest.ConfigCompose(
testAccCollectionDataSourceBaseConfig(rName, policyType),
`
data "aws_opensearchserverless_collection" "test" {
name = aws_opensearchserverless_collection.test.name
}
`)
}
28 changes: 28 additions & 0 deletions internal/service/opensearchserverless/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@ func FindCollectionByID(ctx context.Context, conn *opensearchserverless.Client,
return &out.CollectionDetails[0], nil
}

func FindCollectionByName(ctx context.Context, conn *opensearchserverless.Client, name string) (*types.CollectionDetail, error) {
in := &opensearchserverless.BatchGetCollectionInput{
Names: []string{name},
}
out, err := conn.BatchGetCollection(ctx, in)
if err != nil {
var nfe *types.ResourceNotFoundException
if errors.As(err, &nfe) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: in,
}
}

return nil, err
}

if out == nil || out.CollectionDetails == nil || len(out.CollectionDetails) == 0 {
return nil, tfresource.NewEmptyResultError(in)
}
johnsonaj marked this conversation as resolved.
Show resolved Hide resolved

if len(out.CollectionDetails) > 1 {
return nil, tfresource.NewTooManyResultsError(len(out.CollectionDetails), in)
}

return &out.CollectionDetails[0], nil
}

func FindSecurityConfigByID(ctx context.Context, conn *opensearchserverless.Client, id string) (*types.SecurityConfigDetail, error) {
in := &opensearchserverless.GetSecurityConfigInput{
Id: aws.String(id),
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading