Skip to content

Commit

Permalink
Merge pull request #32247 from hashicorp/f-opensearchserverless_acces…
Browse files Browse the repository at this point in the history
…s_collection_ds

[data source]: aws_opensearchserverless_collection
  • Loading branch information
johnsonaj authored Jun 28, 2023
2 parents 5c5ab41 + a6c7598 commit 7990b87
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 0 deletions.
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)
}

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
4 changes: 4 additions & 0 deletions internal/service/opensearchserverless/service_package_gen.go

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

Loading

0 comments on commit 7990b87

Please sign in to comment.