diff --git a/.changelog/39389.txt b/.changelog/39389.txt new file mode 100644 index 000000000000..146e9896869d --- /dev/null +++ b/.changelog/39389.txt @@ -0,0 +1,3 @@ +```release-note:bug +data-source/aws_region: Fix lookups for the `ap-southeast-5` Region +``` diff --git a/internal/service/meta/arn_data_source.go b/internal/service/meta/arn_data_source.go index c3a320f69b1b..0851905c6c19 100644 --- a/internal/service/meta/arn_data_source.go +++ b/internal/service/meta/arn_data_source.go @@ -1,8 +1,6 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -// Code generated by tools/tfsdk2fw/main.go. Manual editing is required. - package meta import ( @@ -12,30 +10,28 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "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 -func newDataSourceARN(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceARN{} +// @FrameworkDataSource(name="ARN") +func newARNDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := &arnDataSource{} return d, nil } -type dataSourceARN struct { +type arnDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceARN) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*arnDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_arn" } -// Schema returns the schema for this data source. -func (d *dataSourceARN) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *arnDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "account": schema.StringAttribute{ Computed: true, @@ -64,30 +60,26 @@ func (d *dataSourceARN) Schema(ctx context.Context, req datasource.SchemaRequest } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceARN) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceARNData - +func (d *arnDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data arnDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } arn := data.ARN.ValueARN() - data.Account = types.StringValue(arn.AccountID) - data.ID = types.StringValue(arn.String()) - data.Partition = types.StringValue(arn.Partition) - data.Region = types.StringValue(arn.Region) - data.Resource = types.StringValue(arn.Resource) - data.Service = types.StringValue(arn.Service) + data.Account = fwflex.StringValueToFrameworkLegacy(ctx, arn.AccountID) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, arn.String()) + data.Partition = fwflex.StringValueToFrameworkLegacy(ctx, arn.Partition) + data.Region = fwflex.StringValueToFrameworkLegacy(ctx, arn.Region) + data.Resource = fwflex.StringValueToFrameworkLegacy(ctx, arn.Resource) + data.Service = fwflex.StringValueToFrameworkLegacy(ctx, arn.Service) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourceARNData struct { +type arnDataSourceModel struct { Account types.String `tfsdk:"account"` ARN fwtypes.ARN `tfsdk:"arn"` ID types.String `tfsdk:"id"` diff --git a/internal/service/meta/billing_service_account_data_source.go b/internal/service/meta/billing_service_account_data_source.go index f3ebd8f8acca..bd98e3c37d7f 100644 --- a/internal/service/meta/billing_service_account_data_source.go +++ b/internal/service/meta/billing_service_account_data_source.go @@ -11,29 +11,27 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource -func newDataSourceBillingServiceAccount(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceBillingServiceAccount{} +// @FrameworkDataSource(name="Billing Service Account") +func newBillingServiceAccountDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := &billingServiceAccountDataSource{} return d, nil } -type dataSourceBillingServiceAccount struct { +type billingServiceAccountDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceBillingServiceAccount) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*billingServiceAccountDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_billing_service_account" } -// Schema returns the schema for this data source. -func (d *dataSourceBillingServiceAccount) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *billingServiceAccountDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ names.AttrARN: schema.StringAttribute{ Computed: true, @@ -46,13 +44,9 @@ func (d *dataSourceBillingServiceAccount) Schema(ctx context.Context, req dataso } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceBillingServiceAccount) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceBillingServiceAccountData - +func (d *billingServiceAccountDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data billingServiceAccountDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } @@ -66,14 +60,13 @@ func (d *dataSourceBillingServiceAccount) Read(ctx context.Context, request data AccountID: billingAccountID, Resource: "root", } - - data.ARN = types.StringValue(arn.String()) - data.ID = types.StringValue(billingAccountID) + data.ARN = fwflex.StringValueToFrameworkLegacy(ctx, arn.String()) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, billingAccountID) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourceBillingServiceAccountData struct { +type billingServiceAccountDataSourceModel struct { ARN types.String `tfsdk:"arn"` ID types.String `tfsdk:"id"` } diff --git a/internal/service/meta/default_tags_data_source.go b/internal/service/meta/default_tags_data_source.go index 84d91b5a37c5..a4742e26a56d 100644 --- a/internal/service/meta/default_tags_data_source.go +++ b/internal/service/meta/default_tags_data_source.go @@ -1,8 +1,6 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -// Code generated by tools/tfsdk2fw/main.go. Manual editing is required. - package meta import ( @@ -12,30 +10,28 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "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 -func newDataSourceDefaultTags(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceDefaultTags{} +// @FrameworkDataSource(name="Default Tags") +func newDefaultTagsDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := &defaultTagsDataSource{} return d, nil } -type dataSourceDefaultTags struct { +type defaultTagsDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceDefaultTags) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*defaultTagsDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_default_tags" } -// Schema returns the schema for this data source. -func (d *dataSourceDefaultTags) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *defaultTagsDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ names.AttrID: schema.StringAttribute{ Optional: true, @@ -46,13 +42,9 @@ func (d *dataSourceDefaultTags) Schema(ctx context.Context, req datasource.Schem } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceDefaultTags) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceDefaultTagsData - +func (d *defaultTagsDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data defaultTagsDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } @@ -61,13 +53,13 @@ func (d *dataSourceDefaultTags) Read(ctx context.Context, request datasource.Rea ignoreTagsConfig := d.Meta().IgnoreTagsConfig tags := defaultTagsConfig.GetTags() - data.ID = types.StringValue(d.Meta().Partition) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, d.Meta().Partition) data.Tags = tftags.FlattenStringValueMap(ctx, tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourceDefaultTagsData struct { +type defaultTagsDataSourceModel struct { ID types.String `tfsdk:"id"` Tags tftags.Map `tfsdk:"tags"` } diff --git a/internal/service/meta/exports_test.go b/internal/service/meta/exports_test.go new file mode 100644 index 000000000000..f5b16159cfb6 --- /dev/null +++ b/internal/service/meta/exports_test.go @@ -0,0 +1,10 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package meta + +// Exports for use in tests only. +var ( + FindRegionByEC2Endpoint = findRegionByEC2Endpoint + FindRegionByName = findRegionByName +) diff --git a/internal/service/meta/ip_ranges_data_source.go b/internal/service/meta/ip_ranges_data_source.go index 9213f0cc0cb9..94d9456a775b 100644 --- a/internal/service/meta/ip_ranges_data_source.go +++ b/internal/service/meta/ip_ranges_data_source.go @@ -19,31 +19,28 @@ import ( "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" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource -func newDataSourceIPRanges(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceIPRanges{} +// @FrameworkDataSource(name="IP Ranges") +func newIPRangesDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := &ipRangesDataSource{} return d, nil } -type dataSourceIPRanges struct { +type ipRangesDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceIPRanges) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*ipRangesDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_ip_ranges" } -// Schema returns the schema for this data source. -func (d *dataSourceIPRanges) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *ipRangesDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "cidr_blocks": schema.ListAttribute{ ElementType: types.StringType, @@ -78,19 +75,14 @@ func (d *dataSourceIPRanges) Schema(ctx context.Context, req datasource.SchemaRe } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceIPRanges) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceIPRangesData - +func (d *ipRangesDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data ipRangesDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } var url string - if data.URL.IsNull() { // Data sources make no use of AttributePlanModifiers to set default values. url = "https://ip-ranges.amazonaws.com/ip-ranges.json" @@ -99,7 +91,6 @@ func (d *dataSourceIPRanges) Read(ctx context.Context, request datasource.ReadRe } bytes, err := readAll(ctx, url) - if err != nil { response.Diagnostics.AddError("downloading IP ranges", err.Error()) @@ -107,7 +98,6 @@ func (d *dataSourceIPRanges) Read(ctx context.Context, request datasource.ReadRe } ipRanges := new(ipRanges) - if err := json.Unmarshal(bytes, ipRanges); err != nil { response.Diagnostics.AddError("parsing JSON", err.Error()) @@ -115,15 +105,14 @@ func (d *dataSourceIPRanges) Read(ctx context.Context, request datasource.ReadRe } syncToken, err := strconv.Atoi(ipRanges.SyncToken) - if err != nil { response.Diagnostics.AddError("parsing SyncToken", err.Error()) return } - regions := tfslices.ApplyToAll(flex.ExpandFrameworkStringValueSet(ctx, data.Regions), strings.ToLower) - services := tfslices.ApplyToAll(flex.ExpandFrameworkStringValueSet(ctx, data.Services), strings.ToLower) + regions := tfslices.ApplyToAll(fwflex.ExpandFrameworkStringValueSet(ctx, data.Regions), strings.ToLower) + services := tfslices.ApplyToAll(fwflex.ExpandFrameworkStringValueSet(ctx, data.Services), strings.ToLower) matchFilter := func(region, service string) bool { matchRegion := len(regions) == 0 || slices.Contains(regions, strings.ToLower(region)) matchService := slices.Contains(services, strings.ToLower(service)) @@ -132,36 +121,32 @@ func (d *dataSourceIPRanges) Read(ctx context.Context, request datasource.ReadRe } var ipv4Prefixes []string - for _, v := range ipRanges.IPv4Prefixes { if matchFilter(v.Region, v.Service) { ipv4Prefixes = append(ipv4Prefixes, v.Prefix) } } - sort.Strings(ipv4Prefixes) var ipv6Prefixes []string - for _, v := range ipRanges.IPv6Prefixes { if matchFilter(v.Region, v.Service) { ipv6Prefixes = append(ipv6Prefixes, v.Prefix) } } - sort.Strings(ipv6Prefixes) - data.CreateDate = types.StringValue(ipRanges.CreateDate) - data.ID = types.StringValue(ipRanges.SyncToken) - data.IPv4CIDRBlocks = flex.FlattenFrameworkStringValueListLegacy(ctx, ipv4Prefixes) - data.IPv6CIDRBlocks = flex.FlattenFrameworkStringValueListLegacy(ctx, ipv6Prefixes) + data.CreateDate = fwflex.StringValueToFrameworkLegacy(ctx, ipRanges.CreateDate) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, ipRanges.SyncToken) + data.IPv4CIDRBlocks = fwflex.FlattenFrameworkStringValueListLegacy(ctx, ipv4Prefixes) + data.IPv6CIDRBlocks = fwflex.FlattenFrameworkStringValueListLegacy(ctx, ipv6Prefixes) data.SyncToken = types.Int64Value(int64(syncToken)) - data.URL = types.StringValue(url) + data.URL = fwflex.StringValueToFrameworkLegacy(ctx, url) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourceIPRangesData struct { +type ipRangesDataSourceModel struct { CreateDate types.String `tfsdk:"create_date"` ID types.String `tfsdk:"id"` IPv4CIDRBlocks types.List `tfsdk:"cidr_blocks"` @@ -174,21 +159,17 @@ type dataSourceIPRangesData struct { func readAll(ctx context.Context, url string) ([]byte, error) { request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { return nil, err } response, err := cleanhttp.DefaultClient().Do(request) - if err != nil { return nil, fmt.Errorf("HTTP GET (%s): %w", url, err) } - defer response.Body.Close() bytes, err := io.ReadAll(response.Body) - if err != nil { return nil, fmt.Errorf("reading response body (%s): %w", url, err) } diff --git a/internal/service/meta/partition_data_source.go b/internal/service/meta/partition_data_source.go index 1efb18a2481f..26684a300a29 100644 --- a/internal/service/meta/partition_data_source.go +++ b/internal/service/meta/partition_data_source.go @@ -10,29 +10,27 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource -func newDataSourcePartition(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourcePartition{} +// @FrameworkDataSource(name="Partition") +func newPartitionDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := &partitionDataSource{} return d, nil } -type dataSourcePartition struct { +type partitionDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourcePartition) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*partitionDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_partition" } -// Schema returns the schema for this data source. -func (d *dataSourcePartition) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *partitionDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "dns_suffix": schema.StringAttribute{ Computed: true, @@ -51,26 +49,22 @@ func (d *dataSourcePartition) Schema(ctx context.Context, req datasource.SchemaR } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourcePartition) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourcePartitionData - +func (d *partitionDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data partitionDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } - data.DNSSuffix = types.StringValue(d.Meta().DNSSuffix(ctx)) - data.ID = types.StringValue(d.Meta().Partition) - data.Partition = types.StringValue(d.Meta().Partition) - data.ReverseDNSPrefix = types.StringValue(d.Meta().ReverseDNSPrefix(ctx)) + data.DNSSuffix = fwflex.StringValueToFrameworkLegacy(ctx, d.Meta().DNSSuffix(ctx)) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, d.Meta().Partition) + data.Partition = fwflex.StringValueToFrameworkLegacy(ctx, d.Meta().Partition) + data.ReverseDNSPrefix = fwflex.StringValueToFrameworkLegacy(ctx, d.Meta().ReverseDNSPrefix(ctx)) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourcePartitionData struct { +type partitionDataSourceModel struct { DNSSuffix types.String `tfsdk:"dns_suffix"` ID types.String `tfsdk:"id"` Partition types.String `tfsdk:"partition"` diff --git a/internal/service/meta/region_data_source.go b/internal/service/meta/region_data_source.go index c97f4005c800..8c37e882fcaf 100644 --- a/internal/service/meta/region_data_source.go +++ b/internal/service/meta/region_data_source.go @@ -6,36 +6,37 @@ package meta import ( "context" "fmt" - "strings" + "net/url" - "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/hashicorp/aws-sdk-go-base/v2/endpoints" "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-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource -func newDataSourceRegion(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceRegion{} +// @FrameworkDataSource(name="Region") +func newRegionDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := ®ionDataSource{} return d, nil } -type dataSourceRegion struct { +type regionDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceRegion) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*regionDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_region" } -// Schema returns the schema for this data source. -func (d *dataSourceRegion) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *regionDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ names.AttrDescription: schema.StringAttribute{ Computed: true, @@ -56,13 +57,9 @@ func (d *dataSourceRegion) Schema(ctx context.Context, req datasource.SchemaRequ } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceRegion) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceRegionData - +func (d *regionDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data regionDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } @@ -70,10 +67,11 @@ func (d *dataSourceRegion) Read(ctx context.Context, request datasource.ReadRequ var region *endpoints.Region if !data.Endpoint.IsNull() { - matchingRegion, err := FindRegionByEndpoint(data.Endpoint.ValueString()) + endpoint := data.Endpoint.ValueString() + matchingRegion, err := findRegionByEC2Endpoint(ctx, endpoint) if err != nil { - response.Diagnostics.AddError("finding Region by endpoint", err.Error()) + response.Diagnostics.AddError(fmt.Sprintf("finding Region by endpoint (%s)", endpoint), err.Error()) return } @@ -82,10 +80,11 @@ func (d *dataSourceRegion) Read(ctx context.Context, request datasource.ReadRequ } if !data.Name.IsNull() { - matchingRegion, err := FindRegionByName(data.Name.ValueString()) + name := data.Name.ValueString() + matchingRegion, err := findRegionByName(ctx, name) if err != nil { - response.Diagnostics.AddError("finding Region by name", err.Error()) + response.Diagnostics.AddError(fmt.Sprintf("finding Region by name (%s)", name), err.Error()) return } @@ -99,12 +98,13 @@ func (d *dataSourceRegion) Read(ctx context.Context, request datasource.ReadRequ region = matchingRegion } - // Default to provider current region if no other filters matched + // Default to provider current Region if no other filters matched. if region == nil { - matchingRegion, err := FindRegionByName(d.Meta().Region) + name := d.Meta().Region + matchingRegion, err := findRegionByName(ctx, name) if err != nil { - response.Diagnostics.AddError("finding Region by name", err.Error()) + response.Diagnostics.AddError(fmt.Sprintf("finding Region by name (%s)", name), err.Error()) return } @@ -112,7 +112,7 @@ func (d *dataSourceRegion) Read(ctx context.Context, request datasource.ReadRequ region = matchingRegion } - regionEndpointEC2, err := region.ResolveEndpoint(names.EC2) + regionEndpointEC2, err := ec2Endpoint(ctx, region) if err != nil { response.Diagnostics.AddError("resolving EC2 endpoint", err.Error()) @@ -120,40 +120,40 @@ func (d *dataSourceRegion) Read(ctx context.Context, request datasource.ReadRequ return } - data.Description = types.StringValue(region.Description()) - data.Endpoint = types.StringValue(strings.TrimPrefix(regionEndpointEC2.URL, "https://")) - data.ID = types.StringValue(region.ID()) - data.Name = types.StringValue(region.ID()) + data.Description = fwflex.StringValueToFrameworkLegacy(ctx, region.Description()) + data.Endpoint = fwflex.StringValueToFrameworkLegacy(ctx, regionEndpointEC2.Host) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, region.ID()) + data.Name = fwflex.StringValueToFrameworkLegacy(ctx, region.ID()) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourceRegionData struct { +type regionDataSourceModel struct { Description types.String `tfsdk:"description"` Endpoint types.String `tfsdk:"endpoint"` ID types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` } -func FindRegionByEndpoint(endpoint string) (*endpoints.Region, error) { +func findRegionByEC2Endpoint(ctx context.Context, endpoint string) (*endpoints.Region, error) { for _, partition := range endpoints.DefaultPartitions() { for _, region := range partition.Regions() { - regionEndpointEC2, err := region.ResolveEndpoint(names.EC2) + regionEndpointEC2, err := ec2Endpoint(ctx, ®ion) if err != nil { return nil, err } - if strings.TrimPrefix(regionEndpointEC2.URL, "https://") == endpoint { + if regionEndpointEC2.Host == endpoint { return ®ion, nil } } } - return nil, fmt.Errorf("region not found for endpoint %q", endpoint) + return nil, &retry.NotFoundError{} } -func FindRegionByName(name string) (*endpoints.Region, error) { +func findRegionByName(_ context.Context, name string) (*endpoints.Region, error) { for _, partition := range endpoints.DefaultPartitions() { for _, region := range partition.Regions() { if region.ID() == name { @@ -162,5 +162,16 @@ func FindRegionByName(name string) (*endpoints.Region, error) { } } - return nil, fmt.Errorf("region not found for name %q", name) + return nil, &retry.NotFoundError{} +} + +func ec2Endpoint(ctx context.Context, region *endpoints.Region) (*url.URL, error) { + endpoint, err := ec2.NewDefaultEndpointResolverV2().ResolveEndpoint(ctx, ec2.EndpointParameters{ + Region: aws.String(region.ID()), + }) + if err != nil { + return nil, err + } + + return &endpoint.URI, nil } diff --git a/internal/service/meta/region_data_source_test.go b/internal/service/meta/region_data_source_test.go index 376ffc913299..37b5fe8072cc 100644 --- a/internal/service/meta/region_data_source_test.go +++ b/internal/service/meta/region_data_source_test.go @@ -17,6 +17,7 @@ import ( func TestFindRegionByEC2Endpoint(t *testing.T) { t.Parallel() + ctx := acctest.Context(t) var testCases = []struct { Value string ErrCount int @@ -40,7 +41,7 @@ func TestFindRegionByEC2Endpoint(t *testing.T) { } for _, tc := range testCases { - _, err := tfmeta.FindRegionByEndpoint(tc.Value) + _, err := tfmeta.FindRegionByEC2Endpoint(ctx, tc.Value) if tc.ErrCount == 0 && err != nil { t.Fatalf("expected %q not to trigger an error, received: %s", tc.Value, err) } @@ -53,6 +54,7 @@ func TestFindRegionByEC2Endpoint(t *testing.T) { func TestFindRegionByName(t *testing.T) { t.Parallel() + ctx := acctest.Context(t) var testCases = []struct { Value string ErrCount int @@ -69,10 +71,14 @@ func TestFindRegionByName(t *testing.T) { Value: "us-east-1", // lintignore:AWSAT003 ErrCount: 0, }, + { + Value: "ap-southeast-5", // lintignore:AWSAT003 + ErrCount: 0, + }, } for _, tc := range testCases { - _, err := tfmeta.FindRegionByName(tc.Value) + _, err := tfmeta.FindRegionByName(ctx, tc.Value) if tc.ErrCount == 0 && err != nil { t.Fatalf("expected %q not to trigger an error, received: %s", tc.Value, err) } diff --git a/internal/service/meta/regions_data_source.go b/internal/service/meta/regions_data_source.go index b415b1c8c558..ed167c0efca7 100644 --- a/internal/service/meta/regions_data_source.go +++ b/internal/service/meta/regions_data_source.go @@ -8,35 +8,34 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ec2" + awstypes "github.com/aws/aws-sdk-go-v2/service/ec2/types" "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" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource(name=Regions) -func newDataSourceRegions(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceRegions{} +// @FrameworkDataSource(name="Regions") +func newRegionsDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := ®ionsDataSource{} return d, nil } -type dataSourceRegions struct { +type regionsDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceRegions) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*regionsDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_regions" } -// Schema returns the schema for this data source. -func (d *dataSourceRegions) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *regionsDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "all_regions": schema.BoolAttribute{ Optional: true, @@ -56,13 +55,9 @@ func (d *dataSourceRegions) Schema(ctx context.Context, req datasource.SchemaReq } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceRegions) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceRegionsData - +func (d *regionsDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data regionsDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } @@ -70,7 +65,7 @@ func (d *dataSourceRegions) Read(ctx context.Context, request datasource.ReadReq conn := d.Meta().EC2Client(ctx) input := &ec2.DescribeRegionsInput{ - AllRegions: flex.BoolFromFramework(ctx, data.AllRegions), + AllRegions: fwflex.BoolFromFramework(ctx, data.AllRegions), Filters: tfec2.NewCustomFilterListFramework(ctx, data.Filters), } @@ -82,18 +77,16 @@ func (d *dataSourceRegions) Read(ctx context.Context, request datasource.ReadReq return } - var names []string - for _, v := range output.Regions { - names = append(names, aws.ToString(v.RegionName)) - } - - data.ID = types.StringValue(d.Meta().Partition) - data.Names = flex.FlattenFrameworkStringValueSetLegacy(ctx, names) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, d.Meta().Partition) + names := tfslices.ApplyToAll(output.Regions, func(v awstypes.Region) string { + return aws.ToString(v.RegionName) + }) + data.Names = fwflex.FlattenFrameworkStringValueSetLegacy(ctx, names) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourceRegionsData struct { +type regionsDataSourceModel struct { AllRegions types.Bool `tfsdk:"all_regions"` Filters types.Set `tfsdk:"filter"` ID types.String `tfsdk:"id"` diff --git a/internal/service/meta/service_data_source.go b/internal/service/meta/service_data_source.go index c1582c415f60..8822a2eef30d 100644 --- a/internal/service/meta/service_data_source.go +++ b/internal/service/meta/service_data_source.go @@ -13,30 +13,28 @@ import ( "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/slices" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource -func newDataSourceService(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceService{} +// @FrameworkDataSource(name="Service") +func newServiceDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := &serviceDataSource{} return d, nil } -type dataSourceService struct { +type serviceDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceService) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name +func (*serviceDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name response.TypeName = "aws_service" } -// Schema returns the schema for this data source. -func (d *dataSourceService) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *serviceDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ names.AttrDNSName: schema.StringAttribute{ Optional: true, @@ -72,13 +70,9 @@ func (d *dataSourceService) Schema(ctx context.Context, req datasource.SchemaReq } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceService) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceServiceData - +func (d *serviceDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data serviceDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } @@ -94,14 +88,14 @@ func (d *dataSourceService) Read(ctx context.Context, request datasource.ReadReq return } - data.Region = types.StringValue(serviceParts[n-2]) - data.ReverseDNSPrefix = types.StringValue(strings.Join(serviceParts[0:n-2], ".")) - data.ServiceID = types.StringValue(serviceParts[n-1]) + data.Region = fwflex.StringValueToFrameworkLegacy(ctx, serviceParts[n-2]) + data.ReverseDNSPrefix = fwflex.StringValueToFrameworkLegacy(ctx, strings.Join(serviceParts[0:n-2], ".")) + data.ServiceID = fwflex.StringValueToFrameworkLegacy(ctx, serviceParts[n-1]) } if !data.DNSName.IsNull() { v := data.DNSName.ValueString() - serviceParts := slices.Reverse(strings.Split(v, ".")) + serviceParts := tfslices.Reverse(strings.Split(v, ".")) n := len(serviceParts) if n < 4 { @@ -110,13 +104,13 @@ func (d *dataSourceService) Read(ctx context.Context, request datasource.ReadReq return } - data.Region = types.StringValue(serviceParts[n-2]) - data.ReverseDNSPrefix = types.StringValue(strings.Join(serviceParts[0:n-2], ".")) - data.ServiceID = types.StringValue(serviceParts[n-1]) + data.Region = fwflex.StringValueToFrameworkLegacy(ctx, serviceParts[n-2]) + data.ReverseDNSPrefix = fwflex.StringValueToFrameworkLegacy(ctx, strings.Join(serviceParts[0:n-2], ".")) + data.ServiceID = fwflex.StringValueToFrameworkLegacy(ctx, serviceParts[n-1]) } if data.Region.IsNull() { - data.Region = types.StringValue(d.Meta().Region) + data.Region = fwflex.StringValueToFrameworkLegacy(ctx, d.Meta().Region) } if data.ServiceID.IsNull() { @@ -127,16 +121,16 @@ func (d *dataSourceService) Read(ctx context.Context, request datasource.ReadReq if data.ReverseDNSPrefix.IsNull() { dnsParts := strings.Split(d.Meta().DNSSuffix(ctx), ".") - data.ReverseDNSPrefix = types.StringValue(strings.Join(slices.Reverse(dnsParts), ".")) + data.ReverseDNSPrefix = fwflex.StringValueToFrameworkLegacy(ctx, strings.Join(tfslices.Reverse(dnsParts), ".")) } reverseDNSName := fmt.Sprintf("%s.%s.%s", data.ReverseDNSPrefix.ValueString(), data.Region.ValueString(), data.ServiceID.ValueString()) - data.ReverseDNSName = types.StringValue(reverseDNSName) - data.DNSName = types.StringValue(strings.ToLower(strings.Join(slices.Reverse(strings.Split(reverseDNSName, ".")), "."))) + data.ReverseDNSName = fwflex.StringValueToFrameworkLegacy(ctx, reverseDNSName) + data.DNSName = fwflex.StringValueToFrameworkLegacy(ctx, strings.ToLower(strings.Join(tfslices.Reverse(strings.Split(reverseDNSName, ".")), "."))) data.Supported = types.BoolValue(true) if partition, ok := endpoints.PartitionForRegion(endpoints.DefaultPartitions(), data.Region.ValueString()); ok { - data.Partition = types.StringValue(partition.ID()) + data.Partition = fwflex.StringValueToFrameworkLegacy(ctx, partition.ID()) if _, ok := partition.Services()[data.ServiceID.ValueString()]; !ok { data.Supported = types.BoolValue(false) @@ -145,12 +139,12 @@ func (d *dataSourceService) Read(ctx context.Context, request datasource.ReadReq data.Partition = types.StringNull() } - data.ID = types.StringValue(reverseDNSName) + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, reverseDNSName) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -type dataSourceServiceData struct { +type serviceDataSourceModel struct { DNSName types.String `tfsdk:"dns_name"` ID types.String `tfsdk:"id"` Partition types.String `tfsdk:"partition"` diff --git a/internal/service/meta/service_data_source_test.go b/internal/service/meta/service_data_source_test.go index 0c5443e5a038..6541f7181009 100644 --- a/internal/service/meta/service_data_source_test.go +++ b/internal/service/meta/service_data_source_test.go @@ -13,9 +13,10 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func TestAccMetaService_basic(t *testing.T) { +func TestAccMetaServiceDataSource_basic(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service.test" + serviceID := "ec2" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, @@ -23,14 +24,14 @@ func TestAccMetaService_basic(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccServiceDataSourceConfig_basic(), + Config: testAccServiceDataSourceConfig_serviceID(serviceID), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dataSourceName, names.AttrDNSName, fmt.Sprintf("%s.%s.%s", names.EC2, acctest.Region(), "amazonaws.com")), + resource.TestCheckResourceAttr(dataSourceName, names.AttrDNSName, fmt.Sprintf("%s.%s.%s", serviceID, acctest.Region(), "amazonaws.com")), resource.TestCheckResourceAttr(dataSourceName, "partition", acctest.Partition()), resource.TestCheckResourceAttr(dataSourceName, "reverse_dns_prefix", "com.amazonaws"), resource.TestCheckResourceAttr(dataSourceName, names.AttrRegion, acctest.Region()), - resource.TestCheckResourceAttr(dataSourceName, "reverse_dns_name", fmt.Sprintf("%s.%s.%s", "com.amazonaws", acctest.Region(), names.EC2)), - resource.TestCheckResourceAttr(dataSourceName, "service_id", names.EC2), + resource.TestCheckResourceAttr(dataSourceName, "reverse_dns_name", fmt.Sprintf("%s.%s.%s", "com.amazonaws", acctest.Region(), serviceID)), + resource.TestCheckResourceAttr(dataSourceName, "service_id", serviceID), resource.TestCheckResourceAttr(dataSourceName, "supported", acctest.CtTrue), ), }, @@ -38,7 +39,58 @@ func TestAccMetaService_basic(t *testing.T) { }) } -func TestAccMetaService_byReverseDNSName(t *testing.T) { +func TestAccMetaServiceDataSource_irregularServiceID(t *testing.T) { + ctx := acctest.Context(t) + dataSourceName := "data.aws_service.test" + serviceID := "resource-explorer-2" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, tfmeta.PseudoServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccServiceDataSourceConfig_serviceID(serviceID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, names.AttrDNSName, fmt.Sprintf("%s.%s.%s", serviceID, acctest.Region(), "amazonaws.com")), + resource.TestCheckResourceAttr(dataSourceName, "partition", acctest.Partition()), + resource.TestCheckResourceAttr(dataSourceName, "reverse_dns_prefix", "com.amazonaws"), + resource.TestCheckResourceAttr(dataSourceName, names.AttrRegion, acctest.Region()), + resource.TestCheckResourceAttr(dataSourceName, "reverse_dns_name", fmt.Sprintf("%s.%s.%s", "com.amazonaws", acctest.Region(), serviceID)), + resource.TestCheckResourceAttr(dataSourceName, "service_id", serviceID), + resource.TestCheckResourceAttr(dataSourceName, "supported", acctest.CtTrue), + ), + }, + }, + }) +} +func TestAccMetaServiceDataSource_irregularServiceIDUnsupported(t *testing.T) { + ctx := acctest.Context(t) + dataSourceName := "data.aws_service.test" + serviceID := "resourceexplorer2" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, tfmeta.PseudoServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccServiceDataSourceConfig_serviceID(serviceID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, names.AttrDNSName, fmt.Sprintf("%s.%s.%s", serviceID, acctest.Region(), "amazonaws.com")), + resource.TestCheckResourceAttr(dataSourceName, "partition", acctest.Partition()), + resource.TestCheckResourceAttr(dataSourceName, "reverse_dns_prefix", "com.amazonaws"), + resource.TestCheckResourceAttr(dataSourceName, names.AttrRegion, acctest.Region()), + resource.TestCheckResourceAttr(dataSourceName, "reverse_dns_name", fmt.Sprintf("%s.%s.%s", "com.amazonaws", acctest.Region(), serviceID)), + resource.TestCheckResourceAttr(dataSourceName, "service_id", serviceID), + resource.TestCheckResourceAttr(dataSourceName, "supported", acctest.CtFalse), + ), + }, + }, + }) +} + +func TestAccMetaServiceDataSource_byReverseDNSName(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service.test" @@ -61,7 +113,7 @@ func TestAccMetaService_byReverseDNSName(t *testing.T) { }) } -func TestAccMetaService_byDNSName(t *testing.T) { +func TestAccMetaServiceDataSource_byDNSName(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service.test" @@ -84,7 +136,7 @@ func TestAccMetaService_byDNSName(t *testing.T) { }) } -func TestAccMetaService_byParts(t *testing.T) { +func TestAccMetaServiceDataSource_byParts(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service.test" @@ -105,7 +157,7 @@ func TestAccMetaService_byParts(t *testing.T) { }) } -func TestAccMetaService_unsupported(t *testing.T) { +func TestAccMetaServiceDataSource_unsupported(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service.test" @@ -130,12 +182,12 @@ func TestAccMetaService_unsupported(t *testing.T) { }) } -func testAccServiceDataSourceConfig_basic() string { +func testAccServiceDataSourceConfig_serviceID(id string) string { return fmt.Sprintf(` data "aws_service" "test" { service_id = %[1]q } -`, names.EC2) +`, id) } func testAccServiceDataSourceConfig_byReverseDNSName() string { diff --git a/internal/service/meta/service_package_gen.go b/internal/service/meta/service_package_gen.go index 60399ce195f3..ab0666720bc0 100644 --- a/internal/service/meta/service_package_gen.go +++ b/internal/service/meta/service_package_gen.go @@ -14,32 +14,40 @@ type servicePackage struct{} func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.ServicePackageFrameworkDataSource { return []*types.ServicePackageFrameworkDataSource{ { - Factory: newDataSourceARN, + Factory: newARNDataSource, + Name: "ARN", }, { - Factory: newDataSourceBillingServiceAccount, + Factory: newBillingServiceAccountDataSource, + Name: "Billing Service Account", }, { - Factory: newDataSourceDefaultTags, + Factory: newDefaultTagsDataSource, + Name: "Default Tags", }, { - Factory: newDataSourceIPRanges, + Factory: newIPRangesDataSource, + Name: "IP Ranges", }, { - Factory: newDataSourcePartition, + Factory: newPartitionDataSource, + Name: "Partition", }, { - Factory: newDataSourceRegion, + Factory: newRegionDataSource, + Name: "Region", }, { - Factory: newDataSourceRegions, + Factory: newRegionsDataSource, Name: "Regions", }, { - Factory: newDataSourceService, + Factory: newServiceDataSource, + Name: "Service", }, { Factory: newServicePrincipalDataSource, + Name: "Service Principal", }, } } diff --git a/internal/service/meta/service_principal_data_source.go b/internal/service/meta/service_principal_data_source.go index 69405791f8e4..79e372e4cbb8 100644 --- a/internal/service/meta/service_principal_data_source.go +++ b/internal/service/meta/service_principal_data_source.go @@ -5,16 +5,18 @@ package meta import ( "context" + "fmt" - "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/aws-sdk-go-base/v2/endpoints" "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" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource +// @FrameworkDataSource(name="Service Principal") func newServicePrincipalDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { d := &servicePrincipalDataSource{} @@ -63,10 +65,11 @@ func (d *servicePrincipalDataSource) Read(ctx context.Context, request datasourc // find the region given by the user if !data.Region.IsNull() { - matchingRegion, err := FindRegionByName(data.Region.ValueString()) + name := data.Region.ValueString() + matchingRegion, err := findRegionByName(ctx, name) if err != nil { - response.Diagnostics.AddError("finding Region by name", err.Error()) + response.Diagnostics.AddError(fmt.Sprintf("finding Region by name (%s)", name), err.Error()) return } @@ -74,12 +77,13 @@ func (d *servicePrincipalDataSource) Read(ctx context.Context, request datasourc region = matchingRegion } - // Default to provider current region if no other filters matched + // Default to provider current Region if no other filters matched. if region == nil { - matchingRegion, err := FindRegionByName(d.Meta().Region) + name := d.Meta().Region + matchingRegion, err := findRegionByName(ctx, name) if err != nil { - response.Diagnostics.AddError("finding Region using the provider", err.Error()) + response.Diagnostics.AddError(fmt.Sprintf("finding Region by name (%s)", name), err.Error()) return } @@ -95,12 +99,13 @@ func (d *servicePrincipalDataSource) Read(ctx context.Context, request datasourc serviceName = data.ServiceName.ValueString() } - SourceServicePrincipal := names.ServicePrincipalNameForPartition(serviceName, partition) + sourceServicePrincipal := names.ServicePrincipalNameForPartition(serviceName, partition) + + data.ID = fwflex.StringValueToFrameworkLegacy(ctx, serviceName+"."+region.ID()+"."+sourceServicePrincipal) + data.Name = fwflex.StringValueToFrameworkLegacy(ctx, serviceName+"."+sourceServicePrincipal) + data.Suffix = fwflex.StringValueToFrameworkLegacy(ctx, sourceServicePrincipal) + data.Region = fwflex.StringValueToFrameworkLegacy(ctx, region.ID()) - data.ID = types.StringValue(serviceName + "." + region.ID() + "." + SourceServicePrincipal) - data.Name = types.StringValue(serviceName + "." + SourceServicePrincipal) - data.Suffix = types.StringValue(SourceServicePrincipal) - data.Region = types.StringValue(region.ID()) response.Diagnostics.Append(response.State.Set(ctx, &data)...) } diff --git a/internal/service/meta/service_principal_data_source_test.go b/internal/service/meta/service_principal_data_source_test.go index b8431f54845c..ecba46ed4f02 100644 --- a/internal/service/meta/service_principal_data_source_test.go +++ b/internal/service/meta/service_principal_data_source_test.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func TestAccMetaServicePrincipal_basic(t *testing.T) { +func TestAccMetaServicePrincipalDataSource_basic(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service_principal.test" @@ -24,7 +24,7 @@ func TestAccMetaServicePrincipal_basic(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccSPNDataSourceConfig_basic, + Config: testAccServicePrincipalDataSourceConfig_basic, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, names.AttrID, "s3."+acctest.Region()+".amazonaws.com"), resource.TestCheckResourceAttr(dataSourceName, names.AttrName, "s3.amazonaws.com"), @@ -37,7 +37,7 @@ func TestAccMetaServicePrincipal_basic(t *testing.T) { }) } -func TestAccMetaServicePrincipal_MissingService(t *testing.T) { +func TestAccMetaServicePrincipalDataSource_MissingService(t *testing.T) { ctx := acctest.Context(t) resource.ParallelTest(t, resource.TestCase{ @@ -46,14 +46,14 @@ func TestAccMetaServicePrincipal_MissingService(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccSPNDataSourceConfig_empty, + Config: testAccServicePrincipalDataSourceConfig_empty, ExpectError: regexache.MustCompile(`The argument "service_name" is required, but no definition was found.`), }, }, }) } -func TestAccMetaServicePrincipal_ByRegion(t *testing.T) { +func TestAccMetaServicePrincipalDataSource_ByRegion(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service_principal.test" @@ -68,7 +68,7 @@ func TestAccMetaServicePrincipal_ByRegion(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccSPNDataSourceConfig_withRegion("s3", region), + Config: testAccServicePrincipalDataSourceConfig_withRegion("s3", region), Check: resource.ComposeTestCheckFunc( //lintignore:AWSR001 resource.TestCheckResourceAttr(dataSourceName, names.AttrID, fmt.Sprintf("s3.%s.amazonaws.com", region)), @@ -83,7 +83,7 @@ func TestAccMetaServicePrincipal_ByRegion(t *testing.T) { } } -func TestAccMetaServicePrincipal_UniqueForServiceInRegion(t *testing.T) { +func TestAccMetaServicePrincipalDataSource_UniqueForServiceInRegion(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_service_principal.test" @@ -140,7 +140,7 @@ func TestAccMetaServicePrincipal_UniqueForServiceInRegion(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccSPNDataSourceConfig_withRegion(testCase.Service, testCase.Region), + Config: testAccServicePrincipalDataSourceConfig_withRegion(testCase.Service, testCase.Region), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, names.AttrID, testCase.ID), resource.TestCheckResourceAttr(dataSourceName, names.AttrName, testCase.SPN), @@ -154,16 +154,17 @@ func TestAccMetaServicePrincipal_UniqueForServiceInRegion(t *testing.T) { } } -const testAccSPNDataSourceConfig_empty = ` +const testAccServicePrincipalDataSourceConfig_empty = ` data "aws_service_principal" "test" {} ` -const testAccSPNDataSourceConfig_basic = ` + +const testAccServicePrincipalDataSourceConfig_basic = ` data "aws_service_principal" "test" { service_name = "s3" } ` -func testAccSPNDataSourceConfig_withRegion(service string, region string) string { +func testAccServicePrincipalDataSourceConfig_withRegion(service string, region string) string { return fmt.Sprintf(` data "aws_service_principal" "test" { region = %[1]q