diff --git a/.changelog/41669.txt b/.changelog/41669.txt new file mode 100644 index 000000000000..af32ceaafe72 --- /dev/null +++ b/.changelog/41669.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +aws_rds_global_cluster +``` diff --git a/internal/service/rds/global_cluster_data_source.go b/internal/service/rds/global_cluster_data_source.go new file mode 100644 index 000000000000..0ff3c50a12fe --- /dev/null +++ b/internal/service/rds/global_cluster_data_source.go @@ -0,0 +1,134 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package rds + +import ( + "context" + "strings" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @SDKDataSource("aws_rds_global_cluster", name="Global Cluster") +func DataSourceGlobalCluster() *schema.Resource { + return &schema.Resource{ + ReadWithoutTimeout: dataSourceGlobalClusterRead, + + Schema: map[string]*schema.Schema{ + names.AttrARN: { + Type: schema.TypeString, + Computed: true, + }, + names.AttrDatabaseName: { + Type: schema.TypeString, + Computed: true, + }, + names.AttrDeletionProtection: { + Type: schema.TypeBool, + Computed: true, + }, + names.AttrEndpoint: { + Type: schema.TypeString, + Computed: true, + }, + names.AttrEngine: { + Type: schema.TypeString, + Computed: true, + }, + "engine_lifecycle_support": { + Type: schema.TypeString, + Computed: true, + }, + names.AttrEngineVersion: { + Type: schema.TypeString, + Computed: true, + }, + "engine_version_actual": { + Type: schema.TypeString, + Computed: true, + }, + "global_cluster_identifier": { + Type: schema.TypeString, + Required: true, + }, + "global_cluster_members": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "db_cluster_arn": { + Type: schema.TypeString, + Computed: true, + }, + "is_writer": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + "global_cluster_resource_id": { + Type: schema.TypeString, + Computed: true, + }, + names.AttrStorageEncrypted: { + Type: schema.TypeBool, + Computed: true, + }, + names.AttrTags: tftags.TagsSchemaComputed(), + }, + } +} + +func dataSourceGlobalClusterRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).RDSClient(ctx) + + globalClusterID := d.Get("global_cluster_identifier").(string) + globalCluster, err := findGlobalClusterByID(ctx, conn, globalClusterID) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading RDS Global Cluster (%s): %s", globalClusterID, err) + } + + d.SetId(aws.ToString(globalCluster.GlobalClusterIdentifier)) + d.Set(names.AttrARN, globalCluster.GlobalClusterArn) + d.Set(names.AttrDatabaseName, globalCluster.DatabaseName) + d.Set(names.AttrDeletionProtection, globalCluster.DeletionProtection) + d.Set(names.AttrEndpoint, globalCluster.Endpoint) + d.Set(names.AttrEngine, globalCluster.Engine) + d.Set("engine_lifecycle_support", globalCluster.EngineLifecycleSupport) + d.Set("global_cluster_identifier", globalCluster.GlobalClusterIdentifier) + if err := d.Set("global_cluster_members", flattenGlobalClusterMembers(globalCluster.GlobalClusterMembers)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting global_cluster_members: %s", err) + } + d.Set("global_cluster_resource_id", globalCluster.GlobalClusterResourceId) + d.Set(names.AttrStorageEncrypted, globalCluster.StorageEncrypted) + + oldEngineVersion, newEngineVersion := d.Get(names.AttrEngineVersion).(string), aws.ToString(globalCluster.EngineVersion) + + // For example a configured engine_version of "5.6.10a" and a returned engine_version of "5.6.global_10a". + if oldParts, newParts := strings.Split(oldEngineVersion, "."), strings.Split(newEngineVersion, "."); len(oldParts) == 3 && + len(newParts) == 3 && + oldParts[0] == newParts[0] && + oldParts[1] == newParts[1] && + strings.HasSuffix(newParts[2], oldParts[2]) { + d.Set(names.AttrEngineVersion, oldEngineVersion) + d.Set("engine_version_actual", newEngineVersion) + } else { + d.Set(names.AttrEngineVersion, newEngineVersion) + d.Set("engine_version_actual", newEngineVersion) + } + + // Use the same approach as the resource for setting tags + setTagsOut(ctx, globalCluster.TagList) + + return diags +} diff --git a/internal/service/rds/global_cluster_data_source_test.go b/internal/service/rds/global_cluster_data_source_test.go new file mode 100644 index 000000000000..355adfa5c066 --- /dev/null +++ b/internal/service/rds/global_cluster_data_source_test.go @@ -0,0 +1,101 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package rds_test + +import ( + "fmt" + "testing" + + 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 TestAccRDSGlobalClusterDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + dataSourceName := "data.aws_rds_global_cluster.test" + resourceName := "aws_rds_global_cluster.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckGlobalCluster(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.RDSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccGlobalClusterDataSourceConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrARN, resourceName, names.AttrARN), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrDatabaseName, resourceName, names.AttrDatabaseName), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrDeletionProtection, resourceName, names.AttrDeletionProtection), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrEndpoint, resourceName, names.AttrEndpoint), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrEngine, resourceName, names.AttrEngine), + resource.TestCheckResourceAttrPair(dataSourceName, "engine_lifecycle_support", resourceName, "engine_lifecycle_support"), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrEngineVersion, resourceName, names.AttrEngineVersion), + resource.TestCheckResourceAttrPair(dataSourceName, "engine_version_actual", resourceName, "engine_version_actual"), + resource.TestCheckResourceAttrPair(dataSourceName, "global_cluster_identifier", resourceName, "global_cluster_identifier"), + resource.TestCheckResourceAttrPair(dataSourceName, "global_cluster_members.#", resourceName, "global_cluster_members.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "global_cluster_resource_id", resourceName, "global_cluster_resource_id"), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrStorageEncrypted, resourceName, names.AttrStorageEncrypted), + ), + }, + }, + }) +} + +func TestAccRDSGlobalClusterDataSource_withTags(t *testing.T) { + ctx := acctest.Context(t) + dataSourceName := "data.aws_rds_global_cluster.test" + resourceName := "aws_rds_global_cluster.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckGlobalCluster(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.RDSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccGlobalClusterDataSourceConfig_tags(rName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrARN, resourceName, names.AttrARN), + resource.TestCheckResourceAttrPair(dataSourceName, "global_cluster_identifier", resourceName, "global_cluster_identifier"), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrTags, resourceName, names.AttrTags), + ), + }, + }, + }) +} + +func testAccGlobalClusterDataSourceConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_rds_global_cluster" "test" { + global_cluster_identifier = %[1]q + engine = "aurora-postgresql" +} + +data "aws_rds_global_cluster" "test" { + global_cluster_identifier = aws_rds_global_cluster.test.global_cluster_identifier +} +`, rName) +} + +func testAccGlobalClusterDataSourceConfig_tags(rName string) string { + return fmt.Sprintf(` +resource "aws_rds_global_cluster" "test" { + global_cluster_identifier = %[1]q + engine = "aurora-postgresql" + + tags = { + Name = %[1]q + Key1 = "Value1" + Key2 = "Value2" + } +} + +data "aws_rds_global_cluster" "test" { + global_cluster_identifier = aws_rds_global_cluster.test.global_cluster_identifier +} +`, rName) +} diff --git a/internal/service/rds/service_package_gen.go b/internal/service/rds/service_package_gen.go index 0bf99ed206db..d9c91b7e35c7 100644 --- a/internal/service/rds/service_package_gen.go +++ b/internal/service/rds/service_package_gen.go @@ -129,6 +129,11 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac TypeName: "aws_rds_engine_version", Name: "Engine Version", }, + { + Factory: DataSourceGlobalCluster, + TypeName: "aws_rds_global_cluster", + Name: "Global Cluster", + }, { Factory: dataSourceOrderableInstance, TypeName: "aws_rds_orderable_db_instance", diff --git a/website/docs/d/rds_global_cluster.html.markdown b/website/docs/d/rds_global_cluster.html.markdown new file mode 100644 index 000000000000..c5ce7c8a2082 --- /dev/null +++ b/website/docs/d/rds_global_cluster.html.markdown @@ -0,0 +1,50 @@ +--- +subcategory: "RDS (Relational Database)" +layout: "aws" +page_title: "AWS: aws_rds_global_cluster" +description: |- + Terraform data source for retrieving information about an AWS RDS Global Cluster. +--- + +# Data Source: aws_rds_global_cluster + +Terraform data source for retrieving information about an AWS RDS Global Cluster. + +## Example Usage + +```terraform +data "aws_rds_global_cluster" "example" { + global_cluster_identifier = "example-global-cluster" +} +``` + +## Argument Reference + +The following arguments are required: + +* `global_cluster_identifier` - (Required) Identifier of the RDS Global Cluster. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `arn` - ARN of the RDS Global Cluster. +* `database_name` - Name of the database. +* `deletion_protection` - Whether the Global Cluster has deletion protection enabled. +* `endpoint` - Writer endpoint for the RDS Global Cluster. +* `engine` - Database engine used by the Global Cluster (e.g., `aurora`, `aurora-mysql`, `aurora-postgresql`). +* `engine_lifecycle_support` - Lifecycle support state for the cluster's engine. +* `engine_version` - Engine version of the Aurora global database. +* `engine_version_actual` - Full engine version information, containing version number and additional details. +* `global_cluster_members` - Set of global cluster members (RDS Clusters) that are part of this global cluster. Detailed below. +* `global_cluster_resource_id` - Immutable identifier assigned by AWS for the global cluster. +* `id` - Identifier of the RDS Global Cluster. +* `storage_encrypted` - Whether the Global Cluster is encrypted. +* `tags` - Map of tags assigned to the Global Cluster. + +### global_cluster_members + +The `global_cluster_members` attribute has these exported attributes: + +* `db_cluster_arn` - ARN of the RDS Cluster. +* `is_writer` - Whether the RDS Cluster is the primary/writer cluster.