diff --git a/.changelog/44085.txt b/.changelog/44085.txt new file mode 100644 index 000000000000..06fd1f2acf19 --- /dev/null +++ b/.changelog/44085.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +aws_account_account +``` \ No newline at end of file diff --git a/internal/service/account/account_data_source.go b/internal/service/account/account_data_source.go new file mode 100644 index 000000000000..e724bbb8cb1b --- /dev/null +++ b/internal/service/account/account_data_source.go @@ -0,0 +1,96 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package account + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/account" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "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/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + "github.com/hashicorp/terraform-provider-aws/internal/smerr" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkDataSource("aws_account_account", name="Account") +func newAccountDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { // nosemgrep:ci.account-in-func-name + return &dataSourceAccount{}, nil +} + +type dataSourceAccount struct { + framework.DataSourceWithModel[dataSourceAccountModel] +} + +func (d *dataSourceAccount) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "account_created_date": schema.StringAttribute{ + CustomType: timetypes.RFC3339Type{}, + Computed: true, + }, + names.AttrAccountID: schema.StringAttribute{ + Computed: true, + Optional: true, + }, + "account_name": schema.StringAttribute{ + Computed: true, + }, + }, + } +} + +func (d *dataSourceAccount) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().AccountClient(ctx) + + // TIP: -- 2. Fetch the config + var data dataSourceAccountModel + smerr.EnrichAppend(ctx, &resp.Diagnostics, req.Config.Get(ctx, &data)) + if resp.Diagnostics.HasError() { + return + } + + out, err := findAccountInformation(ctx, conn, data.AccountID.ValueString()) + if err != nil { + smerr.AddError(ctx, &resp.Diagnostics, err, smerr.ID) + return + } + + smerr.EnrichAppend(ctx, &resp.Diagnostics, flex.Flatten(ctx, out, &data, flex.WithFieldNamePrefix("Account")), smerr.ID) + if resp.Diagnostics.HasError() { + return + } + + smerr.EnrichAppend(ctx, &resp.Diagnostics, resp.State.Set(ctx, &data), smerr.ID) +} + +type dataSourceAccountModel struct { + AccountCreatedDate timetypes.RFC3339 `tfsdk:"account_created_date"` + AccountID types.String `tfsdk:"account_id"` + AccountName types.String `tfsdk:"account_name"` +} + +func findAccountInformation(ctx context.Context, conn *account.Client, accountID string) (*account.GetAccountInformationOutput, error) { // nosemgrep:ci.account-in-func-name + input := account.GetAccountInformationInput{} + if accountID != "" { + input.AccountId = aws.String(accountID) + } + + output, err := conn.GetAccountInformation(ctx, &input) + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} diff --git a/internal/service/account/account_data_source_test.go b/internal/service/account/account_data_source_test.go new file mode 100644 index 000000000000..7c60e566597e --- /dev/null +++ b/internal/service/account/account_data_source_test.go @@ -0,0 +1,79 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package account_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func testAccAccountDataSource_basic(t *testing.T) { // nosemgrep:ci.account-in-func-name + ctx := acctest.Context(t) + dataSourceName := "data.aws_account_account.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.AccountServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccAccountDataSourceConfig_basic(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, names.AttrAccountID), + resource.TestCheckResourceAttrSet(dataSourceName, "account_name"), + resource.TestCheckResourceAttrSet(dataSourceName, "account_created_date"), + ), + }, + }, + }) +} + +func testAccAccountDataSource_accountID(t *testing.T) { // nosemgrep:ci.account-in-func-name + ctx := acctest.Context(t) + dataSourceName := "data.aws_account_account.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckAlternateAccount(t) + acctest.PreCheckOrganizationManagementAccount(ctx, t) + acctest.PreCheckOrganizationsEnabledServicePrincipal(ctx, t, "account.amazonaws.com") + }, + ErrorCheck: acctest.ErrorCheck(t, names.AccountServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5FactoriesAlternate(ctx, t), + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccAccountDataSourceConfig_organization(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, names.AttrAccountID), + resource.TestCheckResourceAttrSet(dataSourceName, "account_name"), + resource.TestCheckResourceAttrSet(dataSourceName, "account_created_date"), + ), + }, + }, + }) +} + +func testAccAccountDataSourceConfig_basic() string { // nosemgrep:ci.account-in-func-name + return ` +data "aws_account_account" "test" {} +` +} + +func testAccAccountDataSourceConfig_organization() string { // nosemgrep:ci.account-in-func-name + return acctest.ConfigCompose(acctest.ConfigAlternateAccountProvider(), ` +data "aws_caller_identity" "test" { + provider = "awsalternate" +} + +data "aws_account_account" "test" { + account_id = data.aws_caller_identity.test.account_id +} +`) +} diff --git a/internal/service/account/account_test.go b/internal/service/account/account_test.go index dfd976db9bd5..9ce43d4d6832 100644 --- a/internal/service/account/account_test.go +++ b/internal/service/account/account_test.go @@ -13,6 +13,10 @@ func TestAccAccount_serial(t *testing.T) { t.Parallel() testCases := map[string]map[string]func(t *testing.T){ + "Account": { + "dataSourceBasic": testAccAccountDataSource_basic, + "dataSourceAccountID": testAccAccountDataSource_accountID, + }, "AlternateContact": { acctest.CtBasic: testAccAlternateContact_basic, acctest.CtDisappears: testAccAlternateContact_disappears, diff --git a/internal/service/account/service_package_gen.go b/internal/service/account/service_package_gen.go index e2b4451fd74f..86ad6ac855fd 100644 --- a/internal/service/account/service_package_gen.go +++ b/internal/service/account/service_package_gen.go @@ -20,6 +20,12 @@ type servicePackage struct{} func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*inttypes.ServicePackageFrameworkDataSource { return []*inttypes.ServicePackageFrameworkDataSource{ + { + Factory: newAccountDataSource, + TypeName: "aws_account_account", + Name: "Account", + Region: unique.Make(inttypes.ResourceRegionDisabled()), + }, { Factory: newPrimaryContactDataSource, TypeName: "aws_account_primary_contact", diff --git a/website/docs/d/account_account.html.markdown b/website/docs/d/account_account.html.markdown new file mode 100644 index 000000000000..201332a2a3b0 --- /dev/null +++ b/website/docs/d/account_account.html.markdown @@ -0,0 +1,41 @@ +--- +subcategory: "Account Management" +layout: "aws" +page_title: "AWS: aws_account_account" +description: |- + Provides details about an AWS Account. +--- + +# Data Source: aws_account_account + +Provides the account information about an AWS Account. + +## Example Usage + +### Basic Usage + +```terraform +data "aws_account_account" "example" { +} +``` + +### Organization Management Account Usage + +```terraform +data "aws_account_account" "example" { + account_id = "123456789000" +} +``` + +## Argument Reference + +The following arguments are optional: + +* `account_id` - (Optional) The ID of the target account when managing member accounts. The caller must be an identity in the organization's management account or a delegated administrator account. It will return current user's account by default if omitted. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `account_name` - The name of the account. +* `account_created_date` - The date and time the account was created.