diff --git a/.changelog/35937.txt b/.changelog/35937.txt new file mode 100644 index 000000000000..a5902bc9aa85 --- /dev/null +++ b/.changelog/35937.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +aws_redshift_data_shares +``` diff --git a/internal/service/redshift/data_shares_data_source.go b/internal/service/redshift/data_shares_data_source.go new file mode 100644 index 000000000000..8fd8ac10e8f2 --- /dev/null +++ b/internal/service/redshift/data_shares_data_source.go @@ -0,0 +1,107 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package redshift + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/service/redshift" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "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" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkDataSource(name="Data Shares") +func newDataSourceDataShares(context.Context) (datasource.DataSourceWithConfigure, error) { + return &dataSourceDataShares{}, nil +} + +const ( + DSNameDataShares = "Data Shares Data Source" +) + +type dataSourceDataShares struct { + framework.DataSourceWithConfigure +} + +func (d *dataSourceDataShares) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name + resp.TypeName = "aws_redshift_data_shares" +} + +func (d *dataSourceDataShares) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": framework.IDAttribute(), + }, + Blocks: map[string]schema.Block{ + "data_shares": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[dataSharesData](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "data_share_arn": schema.StringAttribute{ + Computed: true, + }, + "managed_by": schema.StringAttribute{ + Computed: true, + }, + "producer_arn": schema.StringAttribute{ + Computed: true, + }, + }, + }, + }, + }, + } +} +func (d *dataSourceDataShares) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().RedshiftClient(ctx) + + var data dataSourceDataSharesData + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + data.ID = types.StringValue(d.Meta().Region) + + paginator := redshift.NewDescribeDataSharesPaginator(conn, &redshift.DescribeDataSharesInput{}) + + var out redshift.DescribeDataSharesOutput + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Redshift, create.ErrActionReading, DSNameDataShares, data.ID.String(), err), + err.Error(), + ) + return + } + + if page != nil && len(page.DataShares) > 0 { + out.DataShares = append(out.DataShares, page.DataShares...) + } + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +type dataSourceDataSharesData struct { + DataShares fwtypes.ListNestedObjectValueOf[dataSharesData] `tfsdk:"data_shares"` + ID types.String `tfsdk:"id"` +} + +type dataSharesData struct { + DataShareARN types.String `tfsdk:"data_share_arn"` + ManagedBy types.String `tfsdk:"managed_by"` + ProducerARN types.String `tfsdk:"producer_arn"` +} diff --git a/internal/service/redshift/data_shares_data_source_test.go b/internal/service/redshift/data_shares_data_source_test.go new file mode 100644 index 000000000000..1a8b139ed1b6 --- /dev/null +++ b/internal/service/redshift/data_shares_data_source_test.go @@ -0,0 +1,88 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package redshift_test + +import ( + "fmt" + "regexp" + "testing" + + "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go/service/redshift" + 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" +) + +func TestAccRedshiftDataSharesDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_redshift_data_shares.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, redshift.EndpointsID) + }, + ErrorCheck: acctest.ErrorCheck(t, redshift.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccDataSharesDataSourceConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "data_shares.#"), + resource.TestMatchTypeSetElemNestedAttrs(dataSourceName, "data_shares.*", map[string]*regexp.Regexp{ + "data_share_arn": regexache.MustCompile(`datashare:+.`), + "producer_arn": regexache.MustCompile(`namespace/+.`), + }), + ), + }, + }, + }) +} + +func testAccDataSharesDataSourceConfig_basic(rName string) string { + return acctest.ConfigCompose( + fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +resource "aws_redshiftserverless_namespace" "test" { + namespace_name = %[1]q + db_name = "test" +} + +resource "aws_redshiftserverless_workgroup" "test" { + namespace_name = aws_redshiftserverless_namespace.test.namespace_name + workgroup_name = %[1]q +} + +resource "aws_redshiftdata_statement" "test_create" { + workgroup_name = aws_redshiftserverless_workgroup.test.workgroup_name + database = aws_redshiftserverless_namespace.test.db_name + sql = "CREATE DATASHARE tfacctest;" +} +`, rName), + // Split this resource into a string literal so the terraform `format` function + // interpolates properly. + // + // Grant statement must be run before the data share will be returned from the + // DescribeDataShares API. + ` +resource "aws_redshiftdata_statement" "test_grant_usage" { + depends_on = [aws_redshiftdata_statement.test_create] + workgroup_name = aws_redshiftserverless_workgroup.test.workgroup_name + database = aws_redshiftserverless_namespace.test.db_name + sql = format("GRANT USAGE ON DATASHARE tfacctest TO ACCOUNT '%s';", data.aws_caller_identity.current.account_id) +} + +data "aws_redshift_data_shares" "test" { + depends_on = [aws_redshiftdata_statement.test_grant_usage] +} +`) +} diff --git a/internal/service/redshift/service_package_gen.go b/internal/service/redshift/service_package_gen.go index a1665a5c1332..154d5a1e6c64 100644 --- a/internal/service/redshift/service_package_gen.go +++ b/internal/service/redshift/service_package_gen.go @@ -18,7 +18,12 @@ import ( type servicePackage struct{} func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.ServicePackageFrameworkDataSource { - return []*types.ServicePackageFrameworkDataSource{} + return []*types.ServicePackageFrameworkDataSource{ + { + Factory: newDataSourceDataShares, + Name: "Data Shares", + }, + } } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { diff --git a/website/docs/d/redshift_data_shares.html.markdown b/website/docs/d/redshift_data_shares.html.markdown new file mode 100644 index 000000000000..00635a4041e8 --- /dev/null +++ b/website/docs/d/redshift_data_shares.html.markdown @@ -0,0 +1,36 @@ +--- +subcategory: "Redshift" +layout: "aws" +page_title: "AWS: aws_redshift_data_shares" +description: |- + Terraform data source for managing AWS Redshift Data Shares. +--- + +# Data Source: aws_redshift_data_shares + +Terraform data source for managing AWS Redshift Data Shares. + +## Example Usage + +### Basic Usage + +```terraform +data "aws_redshift_data_shares" "example" {} +``` + +## Argument Reference + +There are no arguments available for this data source. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `id` - AWS region. +* `data_shares` - An array of all data shares in the current region. See [`data_shares`](#datashares-attribute-reference) below. + +### `data_shares` Attribute Reference + +* `data_share_arn` - ARN (Amazon Resource Name) of the data share. +* `managed_by` - Identifier of a datashare to show its managing entity. +* `producer_arn` - ARN (Amazon Resource Name) of the producer.