diff --git a/.changelog/38057.txt b/.changelog/38057.txt new file mode 100644 index 00000000000..78d69677fd4 --- /dev/null +++ b/.changelog/38057.txt @@ -0,0 +1,3 @@ +```release-note:bug +provider: Now falls back to non-FIPS endpoint if `use_fips_endpoint` is set and no FIPS endpoint is available +``` diff --git a/docs/add-a-new-service.md b/docs/add-a-new-service.md index a45f3d56aa3..c91ba78e5f2 100644 --- a/docs/add-a-new-service.md +++ b/docs/add-a-new-service.md @@ -93,14 +93,22 @@ If an AWS service must be created in a non-standard way, for example, the servic func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*costoptimizationhub.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return costoptimizationhub.NewFromConfig(cfg, func(o *costoptimizationhub.Options) { - if endpoint := config["endpoint"].(string); endpoint != "" { - o.BaseEndpoint = aws.String(endpoint) - } else if config["partition"].(string) == names.StandardPartitionID { - // Cost Optimization Hub endpoint is available only in us-east-1 Region. - o.Region = names.USEast1RegionID - } - }), nil + return costoptimizationhub.NewFromConfig(cfg, + costoptimizationhub.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *costoptimizationhub.Options) { + if config["partition"].(string) == names.StandardPartitionID { + // Cost Optimization Hub endpoint is available only in us-east-1 Region. + if cfg.Region != names.USEast1RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USEast1RegionID, + }) + o.Region = names.USEast1RegionID + } + } + }, + ), nil } ``` @@ -121,11 +129,27 @@ If an AWS service must be created in a non-standard way, for example, the servic // NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. func (p *servicePackage) NewConn(ctx context.Context) (*globalaccelerator_sdkv1.GlobalAccelerator, error) { sess := p.config["session"].(*session_sdkv1.Session) - config := &aws_sdkv1.Config{Endpoint: aws_sdkv1.String(p.config["endpoint"].(string))} + + cfg := aws.Config{} + + if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + cfg.Endpoint = aws.String(endpoint) + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) + } // Force "global" services to correct Regions. - if p.config["partition"].(string) == endpoints_sdkv1.AwsPartitionID { - config.Region = aws_sdkv1.String(endpoints_sdkv1.UsWest2RegionID) + if config["partition"].(string) == endpoints.AwsPartitionID { + if aws.StringValue(cfg.Region) != endpoints.UsWest2RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": aws.StringValue(cfg.Region), + "override_region": endpoints.UsWest2RegionID, + }) + cfg.Region = aws.String(endpoints.UsWest2RegionID) + } } return globalaccelerator_sdkv1.New(sess.Copy(config)), nil diff --git a/docs/retries-and-waiters.md b/docs/retries-and-waiters.md index ad2e6451ca5..37d9bdb8203 100644 --- a/docs/retries-and-waiters.md +++ b/docs/retries-and-waiters.md @@ -85,16 +85,20 @@ When custom service client configurations are applied, these will be defined in func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*s3_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return s3_sdkv2.NewFromConfig(cfg, func(o *s3_sdkv2.Options) { - // ..other configuration.. - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws_sdkv2.RetryerV2), retry_sdkv2.IsErrorRetryableFunc(func(err error) aws_sdkv2.Ternary { - if tfawserr_sdkv2.ErrMessageContains(err, errCodeOperationAborted, "A conflicting conditional operation is currently in progress against this resource. Please try again.") { - return aws_sdkv2.TrueTernary - } - return aws_sdkv2.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return s3_sdkv2.NewFromConfig(cfg, + s3.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *s3_sdkv2.Options) { + // ..other configuration.. + + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws_sdkv2.RetryerV2), retry_sdkv2.IsErrorRetryableFunc(func(err error) aws_sdkv2.Ternary { + if tfawserr_sdkv2.ErrMessageContains(err, errCodeOperationAborted, "A conflicting conditional operation is currently in progress against this resource. Please try again.") { + return aws_sdkv2.TrueTernary + } + return aws_sdkv2.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } ``` diff --git a/internal/generate/serviceendpointtests/file.gtpl b/internal/generate/serviceendpointtests/file.gtpl index 90138808b3a..ac57f2580a9 100644 --- a/internal/generate/serviceendpointtests/file.gtpl +++ b/internal/generate/serviceendpointtests/file.gtpl @@ -10,9 +10,8 @@ import ( {{- end }} "fmt" "maps" - {{- if and (ne .GoV1Package "") (eq .GoV2Package "") }} + "net" "net/url" - {{- end }} "os" "path/filepath" "strings" @@ -133,7 +132,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -474,7 +473,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -517,7 +516,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S {{ end -}} } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { {{- if ne .GoV2Package "" }} r := {{ .GoV2Package }}_sdkv2.NewDefaultEndpointResolverV2() @@ -525,14 +524,14 @@ func defaultEndpoint(region string) string { Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil {{ else }} r := endpoints.DefaultResolver() @@ -543,7 +542,7 @@ func defaultEndpoint(region string) string { {{- end -}} ) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -552,11 +551,11 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil {{ end -}} } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { {{- if ne .GoV2Package "" }} r := {{ .GoV2Package }}_sdkv2.NewDefaultEndpointResolverV2() @@ -565,14 +564,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil {{ else }} r := endpoints.DefaultResolver() @@ -581,7 +580,7 @@ func defaultFIPSEndpoint(region string) string { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -590,7 +589,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil {{ end -}} } @@ -716,16 +715,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { - return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + + return caseExpectations{ + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/generate/servicepackage/endpoint_resolver.go.gtpl b/internal/generate/servicepackage/endpoint_resolver.go.gtpl new file mode 100644 index 00000000000..bdc4c6e3294 --- /dev/null +++ b/internal/generate/servicepackage/endpoint_resolver.go.gtpl @@ -0,0 +1,156 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package {{ .ProviderPackage }} + +import ( + "context" + "fmt" + "net" +{{ if .ClientSDKV1 -}} + "net/url" +{{ end }} + +{{- if .ClientSDKV1 }} + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" +{{- end }} +{{- if .ClientSDKV2 }} + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + {{ .GoV2Package }}_sdkv2 "github.com/aws/aws-sdk-go-v2/service/{{ .GoV2Package }}" + smithyendpoints "github.com/aws/smithy-go/endpoints" +{{- end }} + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +{{ if .ClientSDKV1 }} +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} +{{ end }} + +{{ if .ClientSDKV2 }} +var _ {{ .GoV2Package }}_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver {{ .GoV2Package }}_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: {{ .GoV2Package }}_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params {{ .GoV2Package }}_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up {{ .GoV2Package }} endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*{{ .GoV2Package }}_sdkv2.Options) { + return func(o *{{ .GoV2Package }}_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} +{{ end }} diff --git a/internal/generate/servicepackage/file.tmpl b/internal/generate/servicepackage/file.gtpl similarity index 79% rename from internal/generate/servicepackage/file.tmpl rename to internal/generate/servicepackage/file.gtpl index b23304204a8..403cf19244b 100644 --- a/internal/generate/servicepackage/file.tmpl +++ b/internal/generate/servicepackage/file.gtpl @@ -1,24 +1,21 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package {{ .ProviderPackage }} import ( "context" -{{if not .SkipClientGenerate }} - {{- if eq .SDKVersion "1" "1,2" }} +{{ if .GenerateClient }} + {{- if .ClientSDKV1 }} aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" {{ .GoV1Package }}_sdkv1 "github.com/aws/aws-sdk-go/service/{{ .GoV1Package }}" + "github.com/hashicorp/terraform-plugin-log/tflog" {{- end }} - {{- if eq .SDKVersion "2" "1,2" }} + {{- if .ClientSDKV2 }} aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" {{ .GoV2Package }}_sdkv2 "github.com/aws/aws-sdk-go-v2/service/{{ .GoV2Package }}" {{- end }} - {{- if .SDKVersion }} - "github.com/hashicorp/terraform-plugin-log/tflog" - {{- end }} {{- end }} "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" @@ -131,8 +128,8 @@ func (p *servicePackage) ServicePackageName() string { {{- end }} } -{{- if not .SkipClientGenerate }} - {{if eq .SDKVersion "1" "1,2" }} +{{- if .GenerateClient }} + {{ if .ClientSDKV1 }} // NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*{{ .GoV1Package }}_sdkv1.{{ .GoV1ClientTypeName }}, error) { sess := config[names.AttrSession].(*session_sdkv1.Session) @@ -144,35 +141,23 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*{ "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return {{ .GoV1Package }}_sdkv1.New(sess.Copy(&cfg)), nil } {{- end }} - {{if eq .SDKVersion "2" "1,2" }} + {{ if .ClientSDKV2 }} // NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*{{ .GoV2Package }}_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return {{ .GoV2Package }}_sdkv2.NewFromConfig(cfg, func(o *{{ .GoV2Package }}_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if (o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled) { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return {{ .GoV2Package }}_sdkv2.NewFromConfig(cfg, + {{ .GoV2Package }}_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } {{- end }} {{- end }} diff --git a/internal/generate/servicepackage/main.go b/internal/generate/servicepackage/main.go index 869c497dc7e..ac628cf3d67 100644 --- a/internal/generate/servicepackage/main.go +++ b/internal/generate/servicepackage/main.go @@ -26,7 +26,8 @@ import ( func main() { const ( - filename = `service_package_gen.go` + filename = `service_package_gen.go` + endpointResolverFilenamne = `service_endpoint_resolver_gen.go` ) g := common.NewGenerator() @@ -66,8 +67,10 @@ func main() { } s := ServiceDatum{ - SkipClientGenerate: l.SkipClientGenerate(), + GenerateClient: !l.SkipClientGenerate(), + ClientSDKV1: l.ClientSDKV1(), GoV1Package: l.GoV1Package(), + ClientSDKV2: l.ClientSDKV2(), GoV2Package: l.GoV2Package(), ProviderPackage: p, ProviderNameUpper: l.ProviderNameUpper(), @@ -77,7 +80,6 @@ func main() { SDKResources: v.sdkResources, } - s.SDKVersion = l.SDKVersion() if l.ClientSDKV1() { s.GoV1ClientTypeName = l.GoV1ClientTypeName() } @@ -99,6 +101,20 @@ func main() { g.Fatalf("generating file (%s): %s", filename, err) } + if p != "meta" { + g.Infof("Generating internal/service/%s/%s", servicePackage, endpointResolverFilenamne) + + d = g.NewGoFileDestination(endpointResolverFilenamne) + + if err := d.WriteTemplate("endpointresolver", endpointResolverTmpl, s); err != nil { + g.Fatalf("error generating %s endpoint resolver: %s", p, err) + } + + if err := d.Write(); err != nil { + g.Fatalf("generating file (%s): %s", endpointResolverFilenamne, err) + } + } + break } } @@ -112,10 +128,11 @@ type ResourceDatum struct { } type ServiceDatum struct { - SkipClientGenerate bool - SDKVersion string // AWS SDK for Go version ("1", "2" or "1,2") + GenerateClient bool + ClientSDKV1 bool GoV1Package string // AWS SDK for Go v1 package name GoV1ClientTypeName string // AWS SDK for Go v1 client type name + ClientSDKV2 bool GoV2Package string // AWS SDK for Go v2 package name ProviderPackage string ProviderNameUpper string @@ -125,9 +142,12 @@ type ServiceDatum struct { SDKResources map[string]ResourceDatum } -//go:embed file.tmpl +//go:embed file.gtpl var tmpl string +//go:embed endpoint_resolver.go.gtpl +var endpointResolverTmpl string + // Annotation processing. var ( annotation = regexache.MustCompile(`^//\s*@([0-9A-Za-z]+)(\(([^)]*)\))?\s*$`) diff --git a/internal/service/accessanalyzer/service_endpoint_resolver_gen.go b/internal/service/accessanalyzer/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e79f9750e15 --- /dev/null +++ b/internal/service/accessanalyzer/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package accessanalyzer + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + accessanalyzer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/accessanalyzer" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ accessanalyzer_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver accessanalyzer_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: accessanalyzer_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params accessanalyzer_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*accessanalyzer_sdkv2.Options) { + return func(o *accessanalyzer_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/accessanalyzer/service_endpoints_gen_test.go b/internal/service/accessanalyzer/service_endpoints_gen_test.go index 25b71095dc1..8a28013d643 100644 --- a/internal/service/accessanalyzer/service_endpoints_gen_test.go +++ b/internal/service/accessanalyzer/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := accessanalyzer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), accessanalyzer_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := accessanalyzer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), accessanalyzer_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/accessanalyzer/service_package_gen.go b/internal/service/accessanalyzer/service_package_gen.go index c3b7c09378c..15dbaba5022 100644 --- a/internal/service/accessanalyzer/service_package_gen.go +++ b/internal/service/accessanalyzer/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package accessanalyzer @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" accessanalyzer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/accessanalyzer" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -52,19 +51,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*accessanalyzer_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return accessanalyzer_sdkv2.NewFromConfig(cfg, func(o *accessanalyzer_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return accessanalyzer_sdkv2.NewFromConfig(cfg, + accessanalyzer_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/account/service_endpoint_resolver_gen.go b/internal/service/account/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..72cf9078368 --- /dev/null +++ b/internal/service/account/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package account + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + account_sdkv2 "github.com/aws/aws-sdk-go-v2/service/account" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ account_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver account_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: account_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params account_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up account endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*account_sdkv2.Options) { + return func(o *account_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/account/service_endpoints_gen_test.go b/internal/service/account/service_endpoints_gen_test.go index 538f2f1adde..ff2d5701f60 100644 --- a/internal/service/account/service_endpoints_gen_test.go +++ b/internal/service/account/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := account_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), account_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := account_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), account_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/account/service_package_gen.go b/internal/service/account/service_package_gen.go index 9281a81c75f..56a0e7b1589 100644 --- a/internal/service/account/service_package_gen.go +++ b/internal/service/account/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package account @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" account_sdkv2 "github.com/aws/aws-sdk-go-v2/service/account" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -53,19 +52,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*account_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return account_sdkv2.NewFromConfig(cfg, func(o *account_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return account_sdkv2.NewFromConfig(cfg, + account_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/acm/service_endpoint_resolver_gen.go b/internal/service/acm/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7480d799fe9 --- /dev/null +++ b/internal/service/acm/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package acm + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + acm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/acm" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ acm_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver acm_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: acm_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params acm_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up acm endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*acm_sdkv2.Options) { + return func(o *acm_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/acm/service_endpoints_gen_test.go b/internal/service/acm/service_endpoints_gen_test.go index 5e15d53a283..ec8b64d6107 100644 --- a/internal/service/acm/service_endpoints_gen_test.go +++ b/internal/service/acm/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := acm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), acm_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := acm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), acm_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/acm/service_package_gen.go b/internal/service/acm/service_package_gen.go index cd3c01f9c99..d76d5533294 100644 --- a/internal/service/acm/service_package_gen.go +++ b/internal/service/acm/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package acm @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" acm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/acm" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -61,19 +60,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*acm_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return acm_sdkv2.NewFromConfig(cfg, func(o *acm_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return acm_sdkv2.NewFromConfig(cfg, + acm_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/acmpca/service_endpoint_resolver_gen.go b/internal/service/acmpca/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..4b66c791a76 --- /dev/null +++ b/internal/service/acmpca/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package acmpca + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + acmpca_sdkv2 "github.com/aws/aws-sdk-go-v2/service/acmpca" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ acmpca_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver acmpca_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: acmpca_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params acmpca_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up acmpca endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*acmpca_sdkv2.Options) { + return func(o *acmpca_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/acmpca/service_endpoints_gen_test.go b/internal/service/acmpca/service_endpoints_gen_test.go index 0b342af1776..e544ebd74eb 100644 --- a/internal/service/acmpca/service_endpoints_gen_test.go +++ b/internal/service/acmpca/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := acmpca_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), acmpca_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := acmpca_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), acmpca_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/acmpca/service_package_gen.go b/internal/service/acmpca/service_package_gen.go index c9d94f134f9..0673ef94f28 100644 --- a/internal/service/acmpca/service_package_gen.go +++ b/internal/service/acmpca/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package acmpca @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" acmpca_sdkv2 "github.com/aws/aws-sdk-go-v2/service/acmpca" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -82,19 +81,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*acmpca_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return acmpca_sdkv2.NewFromConfig(cfg, func(o *acmpca_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return acmpca_sdkv2.NewFromConfig(cfg, + acmpca_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/amp/service_endpoint_resolver_gen.go b/internal/service/amp/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6f695368d70 --- /dev/null +++ b/internal/service/amp/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package amp + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + amp_sdkv2 "github.com/aws/aws-sdk-go-v2/service/amp" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ amp_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver amp_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: amp_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params amp_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up amp endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*amp_sdkv2.Options) { + return func(o *amp_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/amp/service_endpoints_gen_test.go b/internal/service/amp/service_endpoints_gen_test.go index abc1eec3005..0301d8d856c 100644 --- a/internal/service/amp/service_endpoints_gen_test.go +++ b/internal/service/amp/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -93,7 +95,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -333,7 +335,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -354,24 +356,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := amp_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), amp_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := amp_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), amp_sdkv2.EndpointParameters{ @@ -379,14 +381,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -478,16 +480,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/amp/service_package_gen.go b/internal/service/amp/service_package_gen.go index 6d39c2a9ec4..ee3a5812e4e 100644 --- a/internal/service/amp/service_package_gen.go +++ b/internal/service/amp/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package amp @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" amp_sdkv2 "github.com/aws/aws-sdk-go-v2/service/amp" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -78,19 +77,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*amp_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return amp_sdkv2.NewFromConfig(cfg, func(o *amp_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return amp_sdkv2.NewFromConfig(cfg, + amp_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/amplify/service_endpoint_resolver_gen.go b/internal/service/amplify/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e9240af9bec --- /dev/null +++ b/internal/service/amplify/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package amplify + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + amplify_sdkv2 "github.com/aws/aws-sdk-go-v2/service/amplify" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ amplify_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver amplify_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: amplify_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params amplify_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up amplify endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*amplify_sdkv2.Options) { + return func(o *amplify_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/amplify/service_endpoints_gen_test.go b/internal/service/amplify/service_endpoints_gen_test.go index e8987a44bd5..2ca6f8c9f15 100644 --- a/internal/service/amplify/service_endpoints_gen_test.go +++ b/internal/service/amplify/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := amplify_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), amplify_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := amplify_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), amplify_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/amplify/service_package_gen.go b/internal/service/amplify/service_package_gen.go index ba0930a242b..8031aa179ce 100644 --- a/internal/service/amplify/service_package_gen.go +++ b/internal/service/amplify/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package amplify @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" amplify_sdkv2 "github.com/aws/aws-sdk-go-v2/service/amplify" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -71,19 +70,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*amplify_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return amplify_sdkv2.NewFromConfig(cfg, func(o *amplify_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return amplify_sdkv2.NewFromConfig(cfg, + amplify_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/apigateway/service_endpoint_resolver_gen.go b/internal/service/apigateway/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ef2fdd642c0 --- /dev/null +++ b/internal/service/apigateway/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package apigateway + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + apigateway_sdkv2 "github.com/aws/aws-sdk-go-v2/service/apigateway" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ apigateway_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver apigateway_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: apigateway_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params apigateway_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up apigateway endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*apigateway_sdkv2.Options) { + return func(o *apigateway_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/apigateway/service_endpoints_gen_test.go b/internal/service/apigateway/service_endpoints_gen_test.go index 9d22208db68..b0dcb43c2ad 100644 --- a/internal/service/apigateway/service_endpoints_gen_test.go +++ b/internal/service/apigateway/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := apigateway_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), apigateway_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := apigateway_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), apigateway_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/apigateway/service_package.go b/internal/service/apigateway/service_package.go index a48bb411c7c..cbc956a44bb 100644 --- a/internal/service/apigateway/service_package.go +++ b/internal/service/apigateway/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/apigateway" "github.com/aws/aws-sdk-go-v2/service/apigateway/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,27 +19,19 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*apigateway.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return apigateway.NewFromConfig(cfg, func(o *apigateway.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - // Many operations can return an error such as: - // ConflictException: Unable to complete operation due to concurrent modification. Please try again later. - // Handle them all globally for the service client. - if errs.IsAErrorMessageContains[*types.ConflictException](err, "try again later") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return apigateway.NewFromConfig(cfg, + apigateway.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *apigateway.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + // Many operations can return an error such as: + // ConflictException: Unable to complete operation due to concurrent modification. Please try again later. + // Handle them all globally for the service client. + if errs.IsAErrorMessageContains[*types.ConflictException](err, "try again later") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/apigateway/service_package_gen.go b/internal/service/apigateway/service_package_gen.go index ee26dadb07e..0c9dbd98479 100644 --- a/internal/service/apigateway/service_package_gen.go +++ b/internal/service/apigateway/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package apigateway diff --git a/internal/service/apigatewayv2/service_endpoint_resolver_gen.go b/internal/service/apigatewayv2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..17adefe840e --- /dev/null +++ b/internal/service/apigatewayv2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package apigatewayv2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + apigatewayv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ apigatewayv2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver apigatewayv2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: apigatewayv2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params apigatewayv2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up apigatewayv2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*apigatewayv2_sdkv2.Options) { + return func(o *apigatewayv2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/apigatewayv2/service_endpoints_gen_test.go b/internal/service/apigatewayv2/service_endpoints_gen_test.go index 92564f0fc33..1b29d667399 100644 --- a/internal/service/apigatewayv2/service_endpoints_gen_test.go +++ b/internal/service/apigatewayv2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := apigatewayv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), apigatewayv2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := apigatewayv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), apigatewayv2_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/apigatewayv2/service_package.go b/internal/service/apigatewayv2/service_package.go index 47d0582b72c..2eeade0b917 100644 --- a/internal/service/apigatewayv2/service_package.go +++ b/internal/service/apigatewayv2/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" awstypes "github.com/aws/aws-sdk-go-v2/service/apigatewayv2/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*apigatewayv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return apigatewayv2.NewFromConfig(cfg, func(o *apigatewayv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*awstypes.ConflictException](err, "try again later") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return apigatewayv2.NewFromConfig(cfg, + apigatewayv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *apigatewayv2.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*awstypes.ConflictException](err, "try again later") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/apigatewayv2/service_package_gen.go b/internal/service/apigatewayv2/service_package_gen.go index 72d2363996a..53b3048bbf2 100644 --- a/internal/service/apigatewayv2/service_package_gen.go +++ b/internal/service/apigatewayv2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package apigatewayv2 diff --git a/internal/service/appautoscaling/service_endpoint_resolver_gen.go b/internal/service/appautoscaling/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2cf14a255e7 --- /dev/null +++ b/internal/service/appautoscaling/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appautoscaling + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + applicationautoscaling_sdkv2 "github.com/aws/aws-sdk-go-v2/service/applicationautoscaling" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ applicationautoscaling_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver applicationautoscaling_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: applicationautoscaling_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params applicationautoscaling_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up applicationautoscaling endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*applicationautoscaling_sdkv2.Options) { + return func(o *applicationautoscaling_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/appautoscaling/service_endpoints_gen_test.go b/internal/service/appautoscaling/service_endpoints_gen_test.go index 2f142fbba0a..989b8233bb1 100644 --- a/internal/service/appautoscaling/service_endpoints_gen_test.go +++ b/internal/service/appautoscaling/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -92,7 +94,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -275,7 +277,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -296,24 +298,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := applicationautoscaling_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), applicationautoscaling_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := applicationautoscaling_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), applicationautoscaling_sdkv2.EndpointParameters{ @@ -321,14 +323,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -411,16 +413,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appautoscaling/service_package_gen.go b/internal/service/appautoscaling/service_package_gen.go index 47ce740919d..ff76ed4fb5c 100644 --- a/internal/service/appautoscaling/service_package_gen.go +++ b/internal/service/appautoscaling/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appautoscaling @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" applicationautoscaling_sdkv2 "github.com/aws/aws-sdk-go-v2/service/applicationautoscaling" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -57,19 +56,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*applicationautoscaling_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return applicationautoscaling_sdkv2.NewFromConfig(cfg, func(o *applicationautoscaling_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return applicationautoscaling_sdkv2.NewFromConfig(cfg, + applicationautoscaling_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/appconfig/service_endpoint_resolver_gen.go b/internal/service/appconfig/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b4d977b4c89 --- /dev/null +++ b/internal/service/appconfig/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appconfig + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + appconfig_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appconfig" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ appconfig_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver appconfig_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: appconfig_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params appconfig_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up appconfig endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*appconfig_sdkv2.Options) { + return func(o *appconfig_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/appconfig/service_endpoints_gen_test.go b/internal/service/appconfig/service_endpoints_gen_test.go index 92b91c136e5..b0b61c36938 100644 --- a/internal/service/appconfig/service_endpoints_gen_test.go +++ b/internal/service/appconfig/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := appconfig_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appconfig_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := appconfig_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appconfig_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appconfig/service_package_gen.go b/internal/service/appconfig/service_package_gen.go index 2a17bf9bdec..eb833c78857 100644 --- a/internal/service/appconfig/service_package_gen.go +++ b/internal/service/appconfig/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appconfig @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" appconfig_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appconfig" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -123,19 +122,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*appconfig_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return appconfig_sdkv2.NewFromConfig(cfg, func(o *appconfig_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return appconfig_sdkv2.NewFromConfig(cfg, + appconfig_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/appfabric/service_endpoint_resolver_gen.go b/internal/service/appfabric/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..9fd29f6066c --- /dev/null +++ b/internal/service/appfabric/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appfabric + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + appfabric_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appfabric" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ appfabric_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver appfabric_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: appfabric_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params appfabric_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up appfabric endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*appfabric_sdkv2.Options) { + return func(o *appfabric_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/appfabric/service_endpoints_gen_test.go b/internal/service/appfabric/service_endpoints_gen_test.go index dd9bd9f6a23..e58b3ca4fd2 100644 --- a/internal/service/appfabric/service_endpoints_gen_test.go +++ b/internal/service/appfabric/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := appfabric_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appfabric_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := appfabric_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appfabric_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appfabric/service_package_gen.go b/internal/service/appfabric/service_package_gen.go index ea20d1b5068..d83176c47f4 100644 --- a/internal/service/appfabric/service_package_gen.go +++ b/internal/service/appfabric/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appfabric @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" appfabric_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appfabric" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -54,19 +53,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*appfabric_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return appfabric_sdkv2.NewFromConfig(cfg, func(o *appfabric_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return appfabric_sdkv2.NewFromConfig(cfg, + appfabric_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/appflow/service_endpoint_resolver_gen.go b/internal/service/appflow/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ba1bddce5c4 --- /dev/null +++ b/internal/service/appflow/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appflow + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + appflow_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appflow" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ appflow_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver appflow_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: appflow_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params appflow_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up appflow endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*appflow_sdkv2.Options) { + return func(o *appflow_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/appflow/service_endpoints_gen_test.go b/internal/service/appflow/service_endpoints_gen_test.go index 2d833986dc1..66f3767e7c3 100644 --- a/internal/service/appflow/service_endpoints_gen_test.go +++ b/internal/service/appflow/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := appflow_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appflow_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := appflow_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appflow_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appflow/service_package_gen.go b/internal/service/appflow/service_package_gen.go index 17b8069b2de..d14b92a0eae 100644 --- a/internal/service/appflow/service_package_gen.go +++ b/internal/service/appflow/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appflow @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" appflow_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appflow" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -53,19 +52,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*appflow_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return appflow_sdkv2.NewFromConfig(cfg, func(o *appflow_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return appflow_sdkv2.NewFromConfig(cfg, + appflow_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/appintegrations/service_endpoint_resolver_gen.go b/internal/service/appintegrations/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a0418374c30 --- /dev/null +++ b/internal/service/appintegrations/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appintegrations + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + appintegrations_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appintegrations" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ appintegrations_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver appintegrations_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: appintegrations_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params appintegrations_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up appintegrations endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*appintegrations_sdkv2.Options) { + return func(o *appintegrations_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/appintegrations/service_endpoints_gen_test.go b/internal/service/appintegrations/service_endpoints_gen_test.go index fd9f02dfbab..8d773dd904c 100644 --- a/internal/service/appintegrations/service_endpoints_gen_test.go +++ b/internal/service/appintegrations/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := appintegrations_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appintegrations_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := appintegrations_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appintegrations_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appintegrations/service_package_gen.go b/internal/service/appintegrations/service_package_gen.go index ed8c219fabd..4755db0ac21 100644 --- a/internal/service/appintegrations/service_package_gen.go +++ b/internal/service/appintegrations/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appintegrations @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" appintegrations_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appintegrations" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -63,19 +62,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*appintegrations_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return appintegrations_sdkv2.NewFromConfig(cfg, func(o *appintegrations_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return appintegrations_sdkv2.NewFromConfig(cfg, + appintegrations_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/applicationinsights/service_endpoint_resolver_gen.go b/internal/service/applicationinsights/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..9d2d60447ae --- /dev/null +++ b/internal/service/applicationinsights/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package applicationinsights + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + applicationinsights_sdkv2 "github.com/aws/aws-sdk-go-v2/service/applicationinsights" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ applicationinsights_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver applicationinsights_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: applicationinsights_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params applicationinsights_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up applicationinsights endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*applicationinsights_sdkv2.Options) { + return func(o *applicationinsights_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/applicationinsights/service_endpoints_gen_test.go b/internal/service/applicationinsights/service_endpoints_gen_test.go index a071dba649c..87f7c34ab14 100644 --- a/internal/service/applicationinsights/service_endpoints_gen_test.go +++ b/internal/service/applicationinsights/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := applicationinsights_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), applicationinsights_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := applicationinsights_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), applicationinsights_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/applicationinsights/service_package_gen.go b/internal/service/applicationinsights/service_package_gen.go index 8934cfdc0d0..e6692a10ee4 100644 --- a/internal/service/applicationinsights/service_package_gen.go +++ b/internal/service/applicationinsights/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package applicationinsights @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" applicationinsights_sdkv2 "github.com/aws/aws-sdk-go-v2/service/applicationinsights" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*applicationinsights_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return applicationinsights_sdkv2.NewFromConfig(cfg, func(o *applicationinsights_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return applicationinsights_sdkv2.NewFromConfig(cfg, + applicationinsights_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/applicationsignals/service_endpoint_resolver_gen.go b/internal/service/applicationsignals/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1cce75da679 --- /dev/null +++ b/internal/service/applicationsignals/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package applicationsignals + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + applicationsignals_sdkv2 "github.com/aws/aws-sdk-go-v2/service/applicationsignals" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ applicationsignals_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver applicationsignals_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: applicationsignals_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params applicationsignals_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up applicationsignals endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*applicationsignals_sdkv2.Options) { + return func(o *applicationsignals_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/applicationsignals/service_endpoints_gen_test.go b/internal/service/applicationsignals/service_endpoints_gen_test.go index e1aaa7e1c0a..2b41cb46dbc 100644 --- a/internal/service/applicationsignals/service_endpoints_gen_test.go +++ b/internal/service/applicationsignals/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := applicationsignals_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), applicationsignals_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := applicationsignals_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), applicationsignals_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/applicationsignals/service_package_gen.go b/internal/service/applicationsignals/service_package_gen.go index d218b5781c0..de55458f7c8 100644 --- a/internal/service/applicationsignals/service_package_gen.go +++ b/internal/service/applicationsignals/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package applicationsignals @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" applicationsignals_sdkv2 "github.com/aws/aws-sdk-go-v2/service/applicationsignals" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*applicationsignals_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return applicationsignals_sdkv2.NewFromConfig(cfg, func(o *applicationsignals_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return applicationsignals_sdkv2.NewFromConfig(cfg, + applicationsignals_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/appmesh/service_endpoint_resolver_gen.go b/internal/service/appmesh/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..973c251fc8c --- /dev/null +++ b/internal/service/appmesh/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appmesh + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/appmesh/service_endpoints_gen_test.go b/internal/service/appmesh/service_endpoints_gen_test.go index 55fa1ac31aa..4057e3aca52 100644 --- a/internal/service/appmesh/service_endpoints_gen_test.go +++ b/internal/service/appmesh/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(appmesh_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(appmesh_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appmesh/service_package_gen.go b/internal/service/appmesh/service_package_gen.go index 390eaf80254..37c06727ff6 100644 --- a/internal/service/appmesh/service_package_gen.go +++ b/internal/service/appmesh/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appmesh @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" appmesh_sdkv1 "github.com/aws/aws-sdk-go/service/appmesh" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -148,11 +147,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*a "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return appmesh_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/apprunner/service_endpoint_resolver_gen.go b/internal/service/apprunner/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..af87f59ac6a --- /dev/null +++ b/internal/service/apprunner/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package apprunner + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + apprunner_sdkv2 "github.com/aws/aws-sdk-go-v2/service/apprunner" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ apprunner_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver apprunner_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: apprunner_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params apprunner_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up apprunner endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*apprunner_sdkv2.Options) { + return func(o *apprunner_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/apprunner/service_endpoints_gen_test.go b/internal/service/apprunner/service_endpoints_gen_test.go index a65c93e42e0..28192b44c00 100644 --- a/internal/service/apprunner/service_endpoints_gen_test.go +++ b/internal/service/apprunner/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := apprunner_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), apprunner_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := apprunner_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), apprunner_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/apprunner/service_package_gen.go b/internal/service/apprunner/service_package_gen.go index 36370fec44f..2a5092ed121 100644 --- a/internal/service/apprunner/service_package_gen.go +++ b/internal/service/apprunner/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package apprunner @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" apprunner_sdkv2 "github.com/aws/aws-sdk-go-v2/service/apprunner" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -107,19 +106,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*apprunner_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return apprunner_sdkv2.NewFromConfig(cfg, func(o *apprunner_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return apprunner_sdkv2.NewFromConfig(cfg, + apprunner_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/appstream/service_endpoint_resolver_gen.go b/internal/service/appstream/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3514cc65271 --- /dev/null +++ b/internal/service/appstream/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appstream + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + appstream_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appstream" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ appstream_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver appstream_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: appstream_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params appstream_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up appstream endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*appstream_sdkv2.Options) { + return func(o *appstream_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/appstream/service_endpoints_gen_test.go b/internal/service/appstream/service_endpoints_gen_test.go index 82235597b5e..2d22f4739af 100644 --- a/internal/service/appstream/service_endpoints_gen_test.go +++ b/internal/service/appstream/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := appstream_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appstream_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := appstream_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appstream_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appstream/service_package_gen.go b/internal/service/appstream/service_package_gen.go index 00740848b9f..1be9ebb69ef 100644 --- a/internal/service/appstream/service_package_gen.go +++ b/internal/service/appstream/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appstream @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" appstream_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appstream" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -80,19 +79,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*appstream_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return appstream_sdkv2.NewFromConfig(cfg, func(o *appstream_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return appstream_sdkv2.NewFromConfig(cfg, + appstream_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/appsync/service_endpoint_resolver_gen.go b/internal/service/appsync/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b05d35ea7d2 --- /dev/null +++ b/internal/service/appsync/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package appsync + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + appsync_sdkv2 "github.com/aws/aws-sdk-go-v2/service/appsync" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ appsync_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver appsync_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: appsync_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params appsync_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up appsync endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*appsync_sdkv2.Options) { + return func(o *appsync_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/appsync/service_endpoints_gen_test.go b/internal/service/appsync/service_endpoints_gen_test.go index 8e45a42f223..8924b03c34a 100644 --- a/internal/service/appsync/service_endpoints_gen_test.go +++ b/internal/service/appsync/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := appsync_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appsync_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := appsync_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), appsync_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/appsync/service_package.go b/internal/service/appsync/service_package.go index b64f2619042..2242dc1175b 100644 --- a/internal/service/appsync/service_package.go +++ b/internal/service/appsync/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/appsync" awstypes "github.com/aws/aws-sdk-go-v2/service/appsync/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,15 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*appsync.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return appsync.NewFromConfig(cfg, func(o *appsync.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*awstypes.ConcurrentModificationException](err, "a GraphQL API creation is already in progress") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return appsync.NewFromConfig(cfg, + appsync.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *appsync.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*awstypes.ConcurrentModificationException](err, "a GraphQL API creation is already in progress") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }), nil } diff --git a/internal/service/appsync/service_package_gen.go b/internal/service/appsync/service_package_gen.go index 1fd057df4bc..3f2fef90ca8 100644 --- a/internal/service/appsync/service_package_gen.go +++ b/internal/service/appsync/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package appsync diff --git a/internal/service/athena/service_endpoint_resolver_gen.go b/internal/service/athena/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6bb495fdaae --- /dev/null +++ b/internal/service/athena/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package athena + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + athena_sdkv2 "github.com/aws/aws-sdk-go-v2/service/athena" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ athena_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver athena_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: athena_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params athena_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up athena endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*athena_sdkv2.Options) { + return func(o *athena_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/athena/service_endpoints_gen_test.go b/internal/service/athena/service_endpoints_gen_test.go index 620d6674300..7777c256879 100644 --- a/internal/service/athena/service_endpoints_gen_test.go +++ b/internal/service/athena/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := athena_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), athena_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := athena_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), athena_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/athena/service_package_gen.go b/internal/service/athena/service_package_gen.go index 34edfc2f4ae..c35211a04fa 100644 --- a/internal/service/athena/service_package_gen.go +++ b/internal/service/athena/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package athena @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" athena_sdkv2 "github.com/aws/aws-sdk-go-v2/service/athena" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -74,19 +73,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*athena_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return athena_sdkv2.NewFromConfig(cfg, func(o *athena_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return athena_sdkv2.NewFromConfig(cfg, + athena_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/auditmanager/service_endpoint_resolver_gen.go b/internal/service/auditmanager/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5694d8436b9 --- /dev/null +++ b/internal/service/auditmanager/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package auditmanager + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + auditmanager_sdkv2 "github.com/aws/aws-sdk-go-v2/service/auditmanager" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ auditmanager_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver auditmanager_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: auditmanager_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params auditmanager_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up auditmanager endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*auditmanager_sdkv2.Options) { + return func(o *auditmanager_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/auditmanager/service_endpoints_gen_test.go b/internal/service/auditmanager/service_endpoints_gen_test.go index 6d2d605dd65..18afec6a538 100644 --- a/internal/service/auditmanager/service_endpoints_gen_test.go +++ b/internal/service/auditmanager/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := auditmanager_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), auditmanager_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := auditmanager_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), auditmanager_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/auditmanager/service_package_gen.go b/internal/service/auditmanager/service_package_gen.go index 3e80724c8fb..99ead68abd5 100644 --- a/internal/service/auditmanager/service_package_gen.go +++ b/internal/service/auditmanager/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package auditmanager @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" auditmanager_sdkv2 "github.com/aws/aws-sdk-go-v2/service/auditmanager" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -83,19 +82,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*auditmanager_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return auditmanager_sdkv2.NewFromConfig(cfg, func(o *auditmanager_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return auditmanager_sdkv2.NewFromConfig(cfg, + auditmanager_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/autoscaling/service_endpoint_resolver_gen.go b/internal/service/autoscaling/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7957c8ce8dd --- /dev/null +++ b/internal/service/autoscaling/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package autoscaling + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + autoscaling_sdkv2 "github.com/aws/aws-sdk-go-v2/service/autoscaling" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ autoscaling_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver autoscaling_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: autoscaling_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params autoscaling_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up autoscaling endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*autoscaling_sdkv2.Options) { + return func(o *autoscaling_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/autoscaling/service_endpoints_gen_test.go b/internal/service/autoscaling/service_endpoints_gen_test.go index c6ebc02ddd1..790a7bc829b 100644 --- a/internal/service/autoscaling/service_endpoints_gen_test.go +++ b/internal/service/autoscaling/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := autoscaling_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), autoscaling_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := autoscaling_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), autoscaling_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/autoscaling/service_package_gen.go b/internal/service/autoscaling/service_package_gen.go index 86dc639da63..3eca5059adb 100644 --- a/internal/service/autoscaling/service_package_gen.go +++ b/internal/service/autoscaling/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package autoscaling @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" autoscaling_sdkv2 "github.com/aws/aws-sdk-go-v2/service/autoscaling" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -101,19 +100,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*autoscaling_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return autoscaling_sdkv2.NewFromConfig(cfg, func(o *autoscaling_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return autoscaling_sdkv2.NewFromConfig(cfg, + autoscaling_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/autoscalingplans/service_endpoint_resolver_gen.go b/internal/service/autoscalingplans/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..8c35b996615 --- /dev/null +++ b/internal/service/autoscalingplans/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package autoscalingplans + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + autoscalingplans_sdkv2 "github.com/aws/aws-sdk-go-v2/service/autoscalingplans" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ autoscalingplans_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver autoscalingplans_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: autoscalingplans_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params autoscalingplans_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up autoscalingplans endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*autoscalingplans_sdkv2.Options) { + return func(o *autoscalingplans_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/autoscalingplans/service_endpoints_gen_test.go b/internal/service/autoscalingplans/service_endpoints_gen_test.go index 136e923b352..31e88ea87c1 100644 --- a/internal/service/autoscalingplans/service_endpoints_gen_test.go +++ b/internal/service/autoscalingplans/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := autoscalingplans_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), autoscalingplans_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := autoscalingplans_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), autoscalingplans_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/autoscalingplans/service_package_gen.go b/internal/service/autoscalingplans/service_package_gen.go index aa09439d7c0..f7153419f7c 100644 --- a/internal/service/autoscalingplans/service_package_gen.go +++ b/internal/service/autoscalingplans/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package autoscalingplans @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" autoscalingplans_sdkv2 "github.com/aws/aws-sdk-go-v2/service/autoscalingplans" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -44,19 +43,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*autoscalingplans_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return autoscalingplans_sdkv2.NewFromConfig(cfg, func(o *autoscalingplans_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return autoscalingplans_sdkv2.NewFromConfig(cfg, + autoscalingplans_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/backup/service_endpoint_resolver_gen.go b/internal/service/backup/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f858b73d3da --- /dev/null +++ b/internal/service/backup/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package backup + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + backup_sdkv2 "github.com/aws/aws-sdk-go-v2/service/backup" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ backup_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver backup_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: backup_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params backup_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up backup endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*backup_sdkv2.Options) { + return func(o *backup_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/backup/service_endpoints_gen_test.go b/internal/service/backup/service_endpoints_gen_test.go index ff5f1e42104..28c210b2512 100644 --- a/internal/service/backup/service_endpoints_gen_test.go +++ b/internal/service/backup/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := backup_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), backup_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := backup_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), backup_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/backup/service_package_gen.go b/internal/service/backup/service_package_gen.go index a89ab28ca6f..4cdedfc56f4 100644 --- a/internal/service/backup/service_package_gen.go +++ b/internal/service/backup/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package backup @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" backup_sdkv2 "github.com/aws/aws-sdk-go-v2/service/backup" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -117,19 +116,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*backup_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return backup_sdkv2.NewFromConfig(cfg, func(o *backup_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return backup_sdkv2.NewFromConfig(cfg, + backup_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/batch/service_endpoint_resolver_gen.go b/internal/service/batch/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..86b3db123bd --- /dev/null +++ b/internal/service/batch/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package batch + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + batch_sdkv2 "github.com/aws/aws-sdk-go-v2/service/batch" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ batch_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver batch_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: batch_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params batch_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up batch endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*batch_sdkv2.Options) { + return func(o *batch_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/batch/service_endpoints_gen_test.go b/internal/service/batch/service_endpoints_gen_test.go index cea6fe288c9..fb4d05255e8 100644 --- a/internal/service/batch/service_endpoints_gen_test.go +++ b/internal/service/batch/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := batch_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), batch_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := batch_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), batch_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/batch/service_package_gen.go b/internal/service/batch/service_package_gen.go index 2a317f3a7e9..438ef0d5a39 100644 --- a/internal/service/batch/service_package_gen.go +++ b/internal/service/batch/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package batch @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" batch_sdkv2 "github.com/aws/aws-sdk-go-v2/service/batch" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" batch_sdkv1 "github.com/aws/aws-sdk-go/service/batch" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -107,11 +106,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*b "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return batch_sdkv1.New(sess.Copy(&cfg)), nil @@ -121,19 +117,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*b func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*batch_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return batch_sdkv2.NewFromConfig(cfg, func(o *batch_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return batch_sdkv2.NewFromConfig(cfg, + batch_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/bcmdataexports/service_endpoint_resolver_gen.go b/internal/service/bcmdataexports/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f50188abbe5 --- /dev/null +++ b/internal/service/bcmdataexports/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package bcmdataexports + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + bcmdataexports_sdkv2 "github.com/aws/aws-sdk-go-v2/service/bcmdataexports" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ bcmdataexports_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver bcmdataexports_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: bcmdataexports_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params bcmdataexports_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up bcmdataexports endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*bcmdataexports_sdkv2.Options) { + return func(o *bcmdataexports_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/bcmdataexports/service_endpoints_gen_test.go b/internal/service/bcmdataexports/service_endpoints_gen_test.go index c461a4ae456..261364a9a92 100644 --- a/internal/service/bcmdataexports/service_endpoints_gen_test.go +++ b/internal/service/bcmdataexports/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := bcmdataexports_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), bcmdataexports_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := bcmdataexports_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), bcmdataexports_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/bcmdataexports/service_package_gen.go b/internal/service/bcmdataexports/service_package_gen.go index fabdc192f60..8d4ce2ea1e1 100644 --- a/internal/service/bcmdataexports/service_package_gen.go +++ b/internal/service/bcmdataexports/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package bcmdataexports @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" bcmdataexports_sdkv2 "github.com/aws/aws-sdk-go-v2/service/bcmdataexports" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -47,19 +46,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*bcmdataexports_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return bcmdataexports_sdkv2.NewFromConfig(cfg, func(o *bcmdataexports_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return bcmdataexports_sdkv2.NewFromConfig(cfg, + bcmdataexports_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/bedrock/service_endpoint_resolver_gen.go b/internal/service/bedrock/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..d6fea1353f1 --- /dev/null +++ b/internal/service/bedrock/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package bedrock + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + bedrock_sdkv2 "github.com/aws/aws-sdk-go-v2/service/bedrock" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ bedrock_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver bedrock_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: bedrock_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params bedrock_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up bedrock endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*bedrock_sdkv2.Options) { + return func(o *bedrock_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/bedrock/service_endpoints_gen_test.go b/internal/service/bedrock/service_endpoints_gen_test.go index f6f2d64678b..a41897029ca 100644 --- a/internal/service/bedrock/service_endpoints_gen_test.go +++ b/internal/service/bedrock/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := bedrock_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), bedrock_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := bedrock_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), bedrock_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/bedrock/service_package_gen.go b/internal/service/bedrock/service_package_gen.go index 3a1e99db950..1ee0b19ee2b 100644 --- a/internal/service/bedrock/service_package_gen.go +++ b/internal/service/bedrock/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package bedrock @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" bedrock_sdkv2 "github.com/aws/aws-sdk-go-v2/service/bedrock" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -75,19 +74,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*bedrock_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return bedrock_sdkv2.NewFromConfig(cfg, func(o *bedrock_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return bedrock_sdkv2.NewFromConfig(cfg, + bedrock_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/bedrockagent/service_endpoint_resolver_gen.go b/internal/service/bedrockagent/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..60e5a6f7fc2 --- /dev/null +++ b/internal/service/bedrockagent/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package bedrockagent + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + bedrockagent_sdkv2 "github.com/aws/aws-sdk-go-v2/service/bedrockagent" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ bedrockagent_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver bedrockagent_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: bedrockagent_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params bedrockagent_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up bedrockagent endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*bedrockagent_sdkv2.Options) { + return func(o *bedrockagent_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/bedrockagent/service_endpoints_gen_test.go b/internal/service/bedrockagent/service_endpoints_gen_test.go index f2b48359c61..32305838fc3 100644 --- a/internal/service/bedrockagent/service_endpoints_gen_test.go +++ b/internal/service/bedrockagent/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := bedrockagent_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), bedrockagent_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := bedrockagent_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), bedrockagent_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/bedrockagent/service_package_gen.go b/internal/service/bedrockagent/service_package_gen.go index f0695149bb7..cdbd786dd01 100644 --- a/internal/service/bedrockagent/service_package_gen.go +++ b/internal/service/bedrockagent/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package bedrockagent @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" bedrockagent_sdkv2 "github.com/aws/aws-sdk-go-v2/service/bedrockagent" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -73,19 +72,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*bedrockagent_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return bedrockagent_sdkv2.NewFromConfig(cfg, func(o *bedrockagent_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return bedrockagent_sdkv2.NewFromConfig(cfg, + bedrockagent_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/budgets/service_endpoint_resolver_gen.go b/internal/service/budgets/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..57ad8f67282 --- /dev/null +++ b/internal/service/budgets/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package budgets + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + budgets_sdkv2 "github.com/aws/aws-sdk-go-v2/service/budgets" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ budgets_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver budgets_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: budgets_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params budgets_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up budgets endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*budgets_sdkv2.Options) { + return func(o *budgets_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/budgets/service_endpoints_gen_test.go b/internal/service/budgets/service_endpoints_gen_test.go index a3d094ead3b..14463e7cfbf 100644 --- a/internal/service/budgets/service_endpoints_gen_test.go +++ b/internal/service/budgets/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := budgets_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), budgets_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := budgets_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), budgets_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/budgets/service_package_gen.go b/internal/service/budgets/service_package_gen.go index 3fdcd2a1c87..dcc002de27d 100644 --- a/internal/service/budgets/service_package_gen.go +++ b/internal/service/budgets/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package budgets @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" budgets_sdkv2 "github.com/aws/aws-sdk-go-v2/service/budgets" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -59,19 +58,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*budgets_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return budgets_sdkv2.NewFromConfig(cfg, func(o *budgets_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return budgets_sdkv2.NewFromConfig(cfg, + budgets_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ce/service_endpoint_resolver_gen.go b/internal/service/ce/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ec2655a1f54 --- /dev/null +++ b/internal/service/ce/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ce + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + costexplorer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/costexplorer" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ costexplorer_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver costexplorer_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: costexplorer_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params costexplorer_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up costexplorer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*costexplorer_sdkv2.Options) { + return func(o *costexplorer_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ce/service_endpoints_gen_test.go b/internal/service/ce/service_endpoints_gen_test.go index de259309c25..d9d1460d882 100644 --- a/internal/service/ce/service_endpoints_gen_test.go +++ b/internal/service/ce/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := costexplorer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), costexplorer_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := costexplorer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), costexplorer_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ce/service_package_gen.go b/internal/service/ce/service_package_gen.go index 3992dbafee5..482009bfad6 100644 --- a/internal/service/ce/service_package_gen.go +++ b/internal/service/ce/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ce @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" costexplorer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/costexplorer" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -80,19 +79,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*costexplorer_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return costexplorer_sdkv2.NewFromConfig(cfg, func(o *costexplorer_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return costexplorer_sdkv2.NewFromConfig(cfg, + costexplorer_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/chatbot/service_endpoint_resolver_gen.go b/internal/service/chatbot/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..97545a9c42f --- /dev/null +++ b/internal/service/chatbot/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package chatbot + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + chatbot_sdkv2 "github.com/aws/aws-sdk-go-v2/service/chatbot" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ chatbot_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver chatbot_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: chatbot_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params chatbot_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up chatbot endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*chatbot_sdkv2.Options) { + return func(o *chatbot_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/chatbot/service_endpoints_gen_test.go b/internal/service/chatbot/service_endpoints_gen_test.go index 6afc31fe91e..e022c7a0539 100644 --- a/internal/service/chatbot/service_endpoints_gen_test.go +++ b/internal/service/chatbot/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -243,24 +245,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := chatbot_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), chatbot_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := chatbot_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), chatbot_sdkv2.EndpointParameters{ @@ -268,14 +270,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/chatbot/service_package.go b/internal/service/chatbot/service_package.go index fbe7a9e657f..f7f994d91bd 100644 --- a/internal/service/chatbot/service_package.go +++ b/internal/service/chatbot/service_package.go @@ -17,27 +17,23 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*chatbot.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return chatbot.NewFromConfig(cfg, func(o *chatbot.Options) { - if config["partition"].(string) == names.StandardPartitionID { - // Chatbot endpoint is available only in the 4 regions us-east-2, us-west-2, eu-west-1, and ap-southeast-1. - // If the region from the context is one of those four, then use that region. If not default to us-west-2 - if slices.Contains([]string{names.USEast2RegionID, names.USWest2RegionID, names.EUWest1RegionID, names.APSoutheast1RegionID}, cfg.Region) { - o.Region = cfg.Region - } else { - o.Region = names.USWest2RegionID + return chatbot.NewFromConfig(cfg, + chatbot.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *chatbot.Options) { + if config["partition"].(string) == names.StandardPartitionID { + // Chatbot endpoint is available only in the 4 regions us-east-2, us-west-2, eu-west-1, and ap-southeast-1. + // If the region from the context is one of those four, then use that region. If not default to us-west-2 + if slices.Contains([]string{names.USEast2RegionID, names.USWest2RegionID, names.EUWest1RegionID, names.APSoutheast1RegionID}, cfg.Region) { + o.Region = cfg.Region + } else { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USWest2RegionID, + }) + o.Region = names.USWest2RegionID + } } - } - - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - }), nil + }, + ), nil } diff --git a/internal/service/chatbot/service_package_gen.go b/internal/service/chatbot/service_package_gen.go index bfed1d17e95..e720db628d8 100644 --- a/internal/service/chatbot/service_package_gen.go +++ b/internal/service/chatbot/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package chatbot diff --git a/internal/service/chime/service_endpoint_resolver_gen.go b/internal/service/chime/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b143693a7b4 --- /dev/null +++ b/internal/service/chime/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package chime + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/chime/service_endpoints_gen_test.go b/internal/service/chime/service_endpoints_gen_test.go index bf9f932eca4..9609fc1178f 100644 --- a/internal/service/chime/service_endpoints_gen_test.go +++ b/internal/service/chime/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(chime_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(chime_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/chime/service_package_gen.go b/internal/service/chime/service_package_gen.go index 42058367e2b..23f3610851b 100644 --- a/internal/service/chime/service_package_gen.go +++ b/internal/service/chime/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package chime @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" chime_sdkv1 "github.com/aws/aws-sdk-go/service/chime" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -81,11 +80,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*c "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return chime_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/chimesdkmediapipelines/service_endpoint_resolver_gen.go b/internal/service/chimesdkmediapipelines/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f41b43341cc --- /dev/null +++ b/internal/service/chimesdkmediapipelines/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package chimesdkmediapipelines + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + chimesdkmediapipelines_sdkv2 "github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ chimesdkmediapipelines_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver chimesdkmediapipelines_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: chimesdkmediapipelines_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params chimesdkmediapipelines_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up chimesdkmediapipelines endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*chimesdkmediapipelines_sdkv2.Options) { + return func(o *chimesdkmediapipelines_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/chimesdkmediapipelines/service_endpoints_gen_test.go b/internal/service/chimesdkmediapipelines/service_endpoints_gen_test.go index 3a8886f8581..88707528d6d 100644 --- a/internal/service/chimesdkmediapipelines/service_endpoints_gen_test.go +++ b/internal/service/chimesdkmediapipelines/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := chimesdkmediapipelines_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), chimesdkmediapipelines_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := chimesdkmediapipelines_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), chimesdkmediapipelines_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/chimesdkmediapipelines/service_package_gen.go b/internal/service/chimesdkmediapipelines/service_package_gen.go index 8f78a51d33a..9ce8ac0b2d5 100644 --- a/internal/service/chimesdkmediapipelines/service_package_gen.go +++ b/internal/service/chimesdkmediapipelines/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package chimesdkmediapipelines @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" chimesdkmediapipelines_sdkv2 "github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*chimesdkmediapipelines_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return chimesdkmediapipelines_sdkv2.NewFromConfig(cfg, func(o *chimesdkmediapipelines_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return chimesdkmediapipelines_sdkv2.NewFromConfig(cfg, + chimesdkmediapipelines_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/chimesdkvoice/service_endpoint_resolver_gen.go b/internal/service/chimesdkvoice/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f05b10fd2bb --- /dev/null +++ b/internal/service/chimesdkvoice/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package chimesdkvoice + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + chimesdkvoice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/chimesdkvoice" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ chimesdkvoice_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver chimesdkvoice_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: chimesdkvoice_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params chimesdkvoice_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up chimesdkvoice endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*chimesdkvoice_sdkv2.Options) { + return func(o *chimesdkvoice_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/chimesdkvoice/service_endpoints_gen_test.go b/internal/service/chimesdkvoice/service_endpoints_gen_test.go index 220802de047..1238fde0ae1 100644 --- a/internal/service/chimesdkvoice/service_endpoints_gen_test.go +++ b/internal/service/chimesdkvoice/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := chimesdkvoice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), chimesdkvoice_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := chimesdkvoice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), chimesdkvoice_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/chimesdkvoice/service_package_gen.go b/internal/service/chimesdkvoice/service_package_gen.go index 8f0c383857d..40ba76b8aae 100644 --- a/internal/service/chimesdkvoice/service_package_gen.go +++ b/internal/service/chimesdkvoice/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package chimesdkvoice @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" chimesdkvoice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/chimesdkvoice" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -65,19 +64,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*chimesdkvoice_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return chimesdkvoice_sdkv2.NewFromConfig(cfg, func(o *chimesdkvoice_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return chimesdkvoice_sdkv2.NewFromConfig(cfg, + chimesdkvoice_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cleanrooms/service_endpoint_resolver_gen.go b/internal/service/cleanrooms/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..85d8ecfde4b --- /dev/null +++ b/internal/service/cleanrooms/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cleanrooms + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cleanrooms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cleanrooms" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cleanrooms_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cleanrooms_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cleanrooms_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cleanrooms_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cleanrooms endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cleanrooms_sdkv2.Options) { + return func(o *cleanrooms_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cleanrooms/service_endpoints_gen_test.go b/internal/service/cleanrooms/service_endpoints_gen_test.go index 029f60a7aca..d199fa3ea51 100644 --- a/internal/service/cleanrooms/service_endpoints_gen_test.go +++ b/internal/service/cleanrooms/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cleanrooms_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cleanrooms_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cleanrooms_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cleanrooms_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cleanrooms/service_package_gen.go b/internal/service/cleanrooms/service_package_gen.go index 410cdd30211..2e32cee494b 100644 --- a/internal/service/cleanrooms/service_package_gen.go +++ b/internal/service/cleanrooms/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cleanrooms @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cleanrooms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cleanrooms" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -54,19 +53,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cleanrooms_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cleanrooms_sdkv2.NewFromConfig(cfg, func(o *cleanrooms_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cleanrooms_sdkv2.NewFromConfig(cfg, + cleanrooms_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cloud9/service_endpoint_resolver_gen.go b/internal/service/cloud9/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..c84a54f62bf --- /dev/null +++ b/internal/service/cloud9/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloud9 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloud9_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloud9" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloud9_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloud9_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloud9_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloud9_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloud9 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloud9_sdkv2.Options) { + return func(o *cloud9_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloud9/service_endpoints_gen_test.go b/internal/service/cloud9/service_endpoints_gen_test.go index 4eaac93e86b..915a7877f15 100644 --- a/internal/service/cloud9/service_endpoints_gen_test.go +++ b/internal/service/cloud9/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloud9_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloud9_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloud9_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloud9_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloud9/service_package_gen.go b/internal/service/cloud9/service_package_gen.go index e6c936c20ec..a0f0c583f6f 100644 --- a/internal/service/cloud9/service_package_gen.go +++ b/internal/service/cloud9/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloud9 @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloud9_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloud9" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -53,19 +52,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloud9_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloud9_sdkv2.NewFromConfig(cfg, func(o *cloud9_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloud9_sdkv2.NewFromConfig(cfg, + cloud9_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cloudcontrol/service_endpoint_resolver_gen.go b/internal/service/cloudcontrol/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..320a69e3193 --- /dev/null +++ b/internal/service/cloudcontrol/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudcontrol + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudcontrol_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudcontrol" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudcontrol_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudcontrol_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudcontrol_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudcontrol_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudcontrol endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudcontrol_sdkv2.Options) { + return func(o *cloudcontrol_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudcontrol/service_endpoints_gen_test.go b/internal/service/cloudcontrol/service_endpoints_gen_test.go index f9532d3f352..da0057352b9 100644 --- a/internal/service/cloudcontrol/service_endpoints_gen_test.go +++ b/internal/service/cloudcontrol/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudcontrol_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudcontrol_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudcontrol_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudcontrol_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloudcontrol/service_package_gen.go b/internal/service/cloudcontrol/service_package_gen.go index 50cf1249b46..f6ec831ebf0 100644 --- a/internal/service/cloudcontrol/service_package_gen.go +++ b/internal/service/cloudcontrol/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudcontrol @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloudcontrol_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudcontrol" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -51,19 +50,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudcontrol_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloudcontrol_sdkv2.NewFromConfig(cfg, func(o *cloudcontrol_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloudcontrol_sdkv2.NewFromConfig(cfg, + cloudcontrol_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cloudformation/service_endpoint_resolver_gen.go b/internal/service/cloudformation/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..441c8f8b889 --- /dev/null +++ b/internal/service/cloudformation/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudformation + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudformation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudformation" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudformation_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudformation_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudformation_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudformation_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudformation endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudformation_sdkv2.Options) { + return func(o *cloudformation_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudformation/service_endpoints_gen_test.go b/internal/service/cloudformation/service_endpoints_gen_test.go index bb5fab7aaa6..20198e3936f 100644 --- a/internal/service/cloudformation/service_endpoints_gen_test.go +++ b/internal/service/cloudformation/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudformation_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudformation_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudformation_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudformation_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloudformation/service_package.go b/internal/service/cloudformation/service_package.go index dd34c8c8d90..08663bb7d2a 100644 --- a/internal/service/cloudformation/service_package.go +++ b/internal/service/cloudformation/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/cloudformation" "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudformation.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return cloudformation.NewFromConfig(cfg, func(o *cloudformation.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*types.OperationInProgressException](err, "Another Operation on StackSet") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return cloudformation.NewFromConfig(cfg, + cloudformation.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *cloudformation.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*types.OperationInProgressException](err, "Another Operation on StackSet") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/cloudformation/service_package_gen.go b/internal/service/cloudformation/service_package_gen.go index 48646010ba1..d47138c21fb 100644 --- a/internal/service/cloudformation/service_package_gen.go +++ b/internal/service/cloudformation/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudformation diff --git a/internal/service/cloudfront/service_endpoint_resolver_gen.go b/internal/service/cloudfront/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ecb4e95c031 --- /dev/null +++ b/internal/service/cloudfront/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudfront + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudfront_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudfront" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudfront_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudfront_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudfront_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudfront_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudfront endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudfront_sdkv2.Options) { + return func(o *cloudfront_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudfront/service_endpoints_gen_test.go b/internal/service/cloudfront/service_endpoints_gen_test.go index 15e0d92aa1b..3f001e4e08a 100644 --- a/internal/service/cloudfront/service_endpoints_gen_test.go +++ b/internal/service/cloudfront/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudfront_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudfront_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudfront_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudfront_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloudfront/service_package_gen.go b/internal/service/cloudfront/service_package_gen.go index 52bdf96d2b1..796e503c460 100644 --- a/internal/service/cloudfront/service_package_gen.go +++ b/internal/service/cloudfront/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudfront @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloudfront_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudfront" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -166,19 +165,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudfront_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloudfront_sdkv2.NewFromConfig(cfg, func(o *cloudfront_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloudfront_sdkv2.NewFromConfig(cfg, + cloudfront_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cloudfrontkeyvaluestore/service_endpoint_resolver_gen.go b/internal/service/cloudfrontkeyvaluestore/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..620ffba3694 --- /dev/null +++ b/internal/service/cloudfrontkeyvaluestore/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudfrontkeyvaluestore + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudfrontkeyvaluestore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudfrontkeyvaluestore_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudfrontkeyvaluestore_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudfrontkeyvaluestore_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudfrontkeyvaluestore_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudfrontkeyvaluestore endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudfrontkeyvaluestore_sdkv2.Options) { + return func(o *cloudfrontkeyvaluestore_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudfrontkeyvaluestore/service_package_gen.go b/internal/service/cloudfrontkeyvaluestore/service_package_gen.go index 7c236d77a24..3411f7c1329 100644 --- a/internal/service/cloudfrontkeyvaluestore/service_package_gen.go +++ b/internal/service/cloudfrontkeyvaluestore/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudfrontkeyvaluestore @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloudfrontkeyvaluestore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -44,19 +43,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudfrontkeyvaluestore_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloudfrontkeyvaluestore_sdkv2.NewFromConfig(cfg, func(o *cloudfrontkeyvaluestore_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloudfrontkeyvaluestore_sdkv2.NewFromConfig(cfg, + cloudfrontkeyvaluestore_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cloudhsmv2/service_endpoint_resolver_gen.go b/internal/service/cloudhsmv2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..da2305dd18d --- /dev/null +++ b/internal/service/cloudhsmv2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudhsmv2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudhsmv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudhsmv2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudhsmv2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudhsmv2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudhsmv2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudhsmv2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudhsmv2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudhsmv2_sdkv2.Options) { + return func(o *cloudhsmv2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudhsmv2/service_endpoints_gen_test.go b/internal/service/cloudhsmv2/service_endpoints_gen_test.go index c7868f9e1cd..46b19669c04 100644 --- a/internal/service/cloudhsmv2/service_endpoints_gen_test.go +++ b/internal/service/cloudhsmv2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudhsmv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudhsmv2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudhsmv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudhsmv2_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloudhsmv2/service_package.go b/internal/service/cloudhsmv2/service_package.go index c34eaf6a67a..674210e94d2 100644 --- a/internal/service/cloudhsmv2/service_package.go +++ b/internal/service/cloudhsmv2/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/cloudhsmv2" "github.com/aws/aws-sdk-go-v2/service/cloudhsmv2/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudhsmv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return cloudhsmv2.NewFromConfig(cfg, func(o *cloudhsmv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*types.CloudHsmInternalFailureException](err, "request was rejected because of an AWS CloudHSM internal failure") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return cloudhsmv2.NewFromConfig(cfg, + cloudhsmv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *cloudhsmv2.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*types.CloudHsmInternalFailureException](err, "request was rejected because of an AWS CloudHSM internal failure") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/cloudhsmv2/service_package_gen.go b/internal/service/cloudhsmv2/service_package_gen.go index d3d61647406..44de4fe0621 100644 --- a/internal/service/cloudhsmv2/service_package_gen.go +++ b/internal/service/cloudhsmv2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudhsmv2 diff --git a/internal/service/cloudsearch/service_endpoint_resolver_gen.go b/internal/service/cloudsearch/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..8231ab82f37 --- /dev/null +++ b/internal/service/cloudsearch/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudsearch + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudsearch_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudsearch" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudsearch_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudsearch_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudsearch_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudsearch_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudsearch endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudsearch_sdkv2.Options) { + return func(o *cloudsearch_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudsearch/service_endpoints_gen_test.go b/internal/service/cloudsearch/service_endpoints_gen_test.go index 28a814f5ab5..0ca66dc3b20 100644 --- a/internal/service/cloudsearch/service_endpoints_gen_test.go +++ b/internal/service/cloudsearch/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudsearch_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudsearch_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudsearch_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudsearch_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloudsearch/service_package_gen.go b/internal/service/cloudsearch/service_package_gen.go index e712b71f007..4a2aba2be6e 100644 --- a/internal/service/cloudsearch/service_package_gen.go +++ b/internal/service/cloudsearch/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudsearch @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloudsearch_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudsearch" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -50,19 +49,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudsearch_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloudsearch_sdkv2.NewFromConfig(cfg, func(o *cloudsearch_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloudsearch_sdkv2.NewFromConfig(cfg, + cloudsearch_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cloudtrail/service_endpoint_resolver_gen.go b/internal/service/cloudtrail/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..4def6ac6f8d --- /dev/null +++ b/internal/service/cloudtrail/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudtrail + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudtrail_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudtrail" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudtrail_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudtrail_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudtrail_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudtrail_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudtrail endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudtrail_sdkv2.Options) { + return func(o *cloudtrail_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudtrail/service_endpoints_gen_test.go b/internal/service/cloudtrail/service_endpoints_gen_test.go index aaacfc1abf5..a6c8e24747c 100644 --- a/internal/service/cloudtrail/service_endpoints_gen_test.go +++ b/internal/service/cloudtrail/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudtrail_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudtrail_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudtrail_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudtrail_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloudtrail/service_package_gen.go b/internal/service/cloudtrail/service_package_gen.go index f2fc05bb468..9d995bb1aed 100644 --- a/internal/service/cloudtrail/service_package_gen.go +++ b/internal/service/cloudtrail/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudtrail @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloudtrail_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudtrail" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -62,19 +61,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudtrail_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloudtrail_sdkv2.NewFromConfig(cfg, func(o *cloudtrail_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloudtrail_sdkv2.NewFromConfig(cfg, + cloudtrail_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cloudwatch/service_endpoint_resolver_gen.go b/internal/service/cloudwatch/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ef81ebe7107 --- /dev/null +++ b/internal/service/cloudwatch/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cloudwatch + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudwatch_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudwatch" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudwatch_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudwatch_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudwatch_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudwatch_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudwatch endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudwatch_sdkv2.Options) { + return func(o *cloudwatch_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cloudwatch/service_endpoints_gen_test.go b/internal/service/cloudwatch/service_endpoints_gen_test.go index f487b873387..4a83208444d 100644 --- a/internal/service/cloudwatch/service_endpoints_gen_test.go +++ b/internal/service/cloudwatch/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudwatch_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudwatch_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudwatch_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudwatch_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cloudwatch/service_package_gen.go b/internal/service/cloudwatch/service_package_gen.go index ff843efc388..9a13c354e3d 100644 --- a/internal/service/cloudwatch/service_package_gen.go +++ b/internal/service/cloudwatch/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cloudwatch @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloudwatch_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudwatch" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -69,19 +68,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudwatch_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloudwatch_sdkv2.NewFromConfig(cfg, func(o *cloudwatch_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloudwatch_sdkv2.NewFromConfig(cfg, + cloudwatch_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codeartifact/service_endpoint_resolver_gen.go b/internal/service/codeartifact/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f6d18561c7e --- /dev/null +++ b/internal/service/codeartifact/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codeartifact + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codeartifact_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codeartifact" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codeartifact_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codeartifact_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codeartifact_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codeartifact_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codeartifact endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codeartifact_sdkv2.Options) { + return func(o *codeartifact_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codeartifact/service_endpoints_gen_test.go b/internal/service/codeartifact/service_endpoints_gen_test.go index 35469c2629e..52f947f8927 100644 --- a/internal/service/codeartifact/service_endpoints_gen_test.go +++ b/internal/service/codeartifact/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codeartifact_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codeartifact_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codeartifact_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codeartifact_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codeartifact/service_package_gen.go b/internal/service/codeartifact/service_package_gen.go index 0cd5c87dada..168cacaca52 100644 --- a/internal/service/codeartifact/service_package_gen.go +++ b/internal/service/codeartifact/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codeartifact @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codeartifact_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codeartifact" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -77,19 +76,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codeartifact_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codeartifact_sdkv2.NewFromConfig(cfg, func(o *codeartifact_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codeartifact_sdkv2.NewFromConfig(cfg, + codeartifact_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codebuild/service_endpoint_resolver_gen.go b/internal/service/codebuild/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3e7182c0523 --- /dev/null +++ b/internal/service/codebuild/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codebuild + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codebuild_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codebuild" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codebuild_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codebuild_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codebuild_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codebuild_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codebuild endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codebuild_sdkv2.Options) { + return func(o *codebuild_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codebuild/service_endpoints_gen_test.go b/internal/service/codebuild/service_endpoints_gen_test.go index 2dbd2ac7a4e..c11ccb1dd83 100644 --- a/internal/service/codebuild/service_endpoints_gen_test.go +++ b/internal/service/codebuild/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codebuild_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codebuild_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codebuild_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codebuild_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codebuild/service_package_gen.go b/internal/service/codebuild/service_package_gen.go index 3336ede1efe..dfce895ba83 100644 --- a/internal/service/codebuild/service_package_gen.go +++ b/internal/service/codebuild/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codebuild @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codebuild_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codebuild" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -67,19 +66,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codebuild_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codebuild_sdkv2.NewFromConfig(cfg, func(o *codebuild_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codebuild_sdkv2.NewFromConfig(cfg, + codebuild_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codecatalyst/service_endpoint_resolver_gen.go b/internal/service/codecatalyst/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..43b6ef1eae4 --- /dev/null +++ b/internal/service/codecatalyst/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codecatalyst + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codecatalyst_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codecatalyst" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codecatalyst_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codecatalyst_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codecatalyst_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codecatalyst_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codecatalyst endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codecatalyst_sdkv2.Options) { + return func(o *codecatalyst_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codecatalyst/service_package_gen.go b/internal/service/codecatalyst/service_package_gen.go index a3aa2ef23e7..255fb7a8bc2 100644 --- a/internal/service/codecatalyst/service_package_gen.go +++ b/internal/service/codecatalyst/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codecatalyst @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codecatalyst_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codecatalyst" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -61,19 +60,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codecatalyst_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codecatalyst_sdkv2.NewFromConfig(cfg, func(o *codecatalyst_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codecatalyst_sdkv2.NewFromConfig(cfg, + codecatalyst_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codecommit/service_endpoint_resolver_gen.go b/internal/service/codecommit/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..afb73a1e822 --- /dev/null +++ b/internal/service/codecommit/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codecommit + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codecommit_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codecommit" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codecommit_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codecommit_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codecommit_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codecommit_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codecommit endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codecommit_sdkv2.Options) { + return func(o *codecommit_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codecommit/service_endpoints_gen_test.go b/internal/service/codecommit/service_endpoints_gen_test.go index a3eedd261a4..6acd86e6198 100644 --- a/internal/service/codecommit/service_endpoints_gen_test.go +++ b/internal/service/codecommit/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codecommit_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codecommit_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codecommit_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codecommit_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codecommit/service_package_gen.go b/internal/service/codecommit/service_package_gen.go index ae362c48704..9a6c2d5f8de 100644 --- a/internal/service/codecommit/service_package_gen.go +++ b/internal/service/codecommit/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codecommit @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codecommit_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codecommit" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -74,19 +73,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codecommit_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codecommit_sdkv2.NewFromConfig(cfg, func(o *codecommit_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codecommit_sdkv2.NewFromConfig(cfg, + codecommit_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codeguruprofiler/service_endpoint_resolver_gen.go b/internal/service/codeguruprofiler/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5de7eba5e10 --- /dev/null +++ b/internal/service/codeguruprofiler/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codeguruprofiler + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codeguruprofiler_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codeguruprofiler_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codeguruprofiler_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codeguruprofiler_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codeguruprofiler_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codeguruprofiler endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codeguruprofiler_sdkv2.Options) { + return func(o *codeguruprofiler_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codeguruprofiler/service_endpoints_gen_test.go b/internal/service/codeguruprofiler/service_endpoints_gen_test.go index 724f8442dc5..8426219547f 100644 --- a/internal/service/codeguruprofiler/service_endpoints_gen_test.go +++ b/internal/service/codeguruprofiler/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codeguruprofiler_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codeguruprofiler_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codeguruprofiler_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codeguruprofiler_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codeguruprofiler/service_package_gen.go b/internal/service/codeguruprofiler/service_package_gen.go index 219c629715e..636daad2c35 100644 --- a/internal/service/codeguruprofiler/service_package_gen.go +++ b/internal/service/codeguruprofiler/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codeguruprofiler @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codeguruprofiler_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -52,19 +51,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codeguruprofiler_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codeguruprofiler_sdkv2.NewFromConfig(cfg, func(o *codeguruprofiler_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codeguruprofiler_sdkv2.NewFromConfig(cfg, + codeguruprofiler_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codegurureviewer/service_endpoint_resolver_gen.go b/internal/service/codegurureviewer/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6ca17a9a960 --- /dev/null +++ b/internal/service/codegurureviewer/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codegurureviewer + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codegurureviewer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codegurureviewer" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codegurureviewer_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codegurureviewer_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codegurureviewer_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codegurureviewer_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codegurureviewer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codegurureviewer_sdkv2.Options) { + return func(o *codegurureviewer_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codegurureviewer/service_endpoints_gen_test.go b/internal/service/codegurureviewer/service_endpoints_gen_test.go index 1c84c0b7a72..1f573bf3d54 100644 --- a/internal/service/codegurureviewer/service_endpoints_gen_test.go +++ b/internal/service/codegurureviewer/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -87,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -221,7 +223,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -242,24 +244,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codegurureviewer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codegurureviewer_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codegurureviewer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codegurureviewer_sdkv2.EndpointParameters{ @@ -267,14 +269,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -338,16 +340,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codegurureviewer/service_package_gen.go b/internal/service/codegurureviewer/service_package_gen.go index b69d2ab50fb..711ad2f4cfc 100644 --- a/internal/service/codegurureviewer/service_package_gen.go +++ b/internal/service/codegurureviewer/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codegurureviewer @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codegurureviewer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codegurureviewer" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codegurureviewer_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codegurureviewer_sdkv2.NewFromConfig(cfg, func(o *codegurureviewer_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codegurureviewer_sdkv2.NewFromConfig(cfg, + codegurureviewer_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codepipeline/service_endpoint_resolver_gen.go b/internal/service/codepipeline/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b1ee40353db --- /dev/null +++ b/internal/service/codepipeline/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codepipeline + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codepipeline_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codepipeline" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codepipeline_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codepipeline_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codepipeline_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codepipeline_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codepipeline endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codepipeline_sdkv2.Options) { + return func(o *codepipeline_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codepipeline/service_endpoints_gen_test.go b/internal/service/codepipeline/service_endpoints_gen_test.go index bd392b47c37..ac6e0bfbbff 100644 --- a/internal/service/codepipeline/service_endpoints_gen_test.go +++ b/internal/service/codepipeline/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codepipeline_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codepipeline_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codepipeline_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codepipeline_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codepipeline/service_package_gen.go b/internal/service/codepipeline/service_package_gen.go index b0cd23a26df..6689d01acf1 100644 --- a/internal/service/codepipeline/service_package_gen.go +++ b/internal/service/codepipeline/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codepipeline @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codepipeline_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codepipeline" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -64,19 +63,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codepipeline_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codepipeline_sdkv2.NewFromConfig(cfg, func(o *codepipeline_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codepipeline_sdkv2.NewFromConfig(cfg, + codepipeline_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codestarconnections/service_endpoint_resolver_gen.go b/internal/service/codestarconnections/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ca67d0e38c4 --- /dev/null +++ b/internal/service/codestarconnections/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codestarconnections + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codestarconnections_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codestarconnections" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codestarconnections_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codestarconnections_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codestarconnections_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codestarconnections_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codestarconnections endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codestarconnections_sdkv2.Options) { + return func(o *codestarconnections_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codestarconnections/service_endpoints_gen_test.go b/internal/service/codestarconnections/service_endpoints_gen_test.go index fc2109ec1ab..7e984327f26 100644 --- a/internal/service/codestarconnections/service_endpoints_gen_test.go +++ b/internal/service/codestarconnections/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codestarconnections_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codestarconnections_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codestarconnections_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codestarconnections_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codestarconnections/service_package_gen.go b/internal/service/codestarconnections/service_package_gen.go index 5ccf55d1d4c..d61c0f7a43a 100644 --- a/internal/service/codestarconnections/service_package_gen.go +++ b/internal/service/codestarconnections/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codestarconnections @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codestarconnections_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codestarconnections" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -58,19 +57,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codestarconnections_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codestarconnections_sdkv2.NewFromConfig(cfg, func(o *codestarconnections_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codestarconnections_sdkv2.NewFromConfig(cfg, + codestarconnections_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/codestarnotifications/service_endpoint_resolver_gen.go b/internal/service/codestarnotifications/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..c9c8379b45f --- /dev/null +++ b/internal/service/codestarnotifications/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package codestarnotifications + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codestarnotifications_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codestarnotifications" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codestarnotifications_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codestarnotifications_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codestarnotifications_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codestarnotifications_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codestarnotifications endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codestarnotifications_sdkv2.Options) { + return func(o *codestarnotifications_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/codestarnotifications/service_endpoints_gen_test.go b/internal/service/codestarnotifications/service_endpoints_gen_test.go index 47c99b6146f..4116ac5670b 100644 --- a/internal/service/codestarnotifications/service_endpoints_gen_test.go +++ b/internal/service/codestarnotifications/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codestarnotifications_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codestarnotifications_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codestarnotifications_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codestarnotifications_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/codestarnotifications/service_package_gen.go b/internal/service/codestarnotifications/service_package_gen.go index 9183a2840a2..a63e77cce9a 100644 --- a/internal/service/codestarnotifications/service_package_gen.go +++ b/internal/service/codestarnotifications/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package codestarnotifications @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codestarnotifications_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codestarnotifications" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codestarnotifications_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codestarnotifications_sdkv2.NewFromConfig(cfg, func(o *codestarnotifications_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codestarnotifications_sdkv2.NewFromConfig(cfg, + codestarnotifications_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cognitoidentity/service_endpoint_resolver_gen.go b/internal/service/cognitoidentity/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6b24b637ac8 --- /dev/null +++ b/internal/service/cognitoidentity/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cognitoidentity + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cognitoidentity_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cognitoidentity" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cognitoidentity_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cognitoidentity_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cognitoidentity_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cognitoidentity_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cognitoidentity endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cognitoidentity_sdkv2.Options) { + return func(o *cognitoidentity_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cognitoidentity/service_endpoints_gen_test.go b/internal/service/cognitoidentity/service_endpoints_gen_test.go index 516d1a8316b..3134656aec0 100644 --- a/internal/service/cognitoidentity/service_endpoints_gen_test.go +++ b/internal/service/cognitoidentity/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cognitoidentity_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cognitoidentity_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cognitoidentity_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cognitoidentity_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cognitoidentity/service_package_gen.go b/internal/service/cognitoidentity/service_package_gen.go index 67aa7c6b8bf..75fe8908a20 100644 --- a/internal/service/cognitoidentity/service_package_gen.go +++ b/internal/service/cognitoidentity/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cognitoidentity @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cognitoidentity_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cognitoidentity" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -67,19 +66,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cognitoidentity_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cognitoidentity_sdkv2.NewFromConfig(cfg, func(o *cognitoidentity_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cognitoidentity_sdkv2.NewFromConfig(cfg, + cognitoidentity_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/cognitoidp/service_endpoint_resolver_gen.go b/internal/service/cognitoidp/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..595de9ea205 --- /dev/null +++ b/internal/service/cognitoidp/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cognitoidp + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/cognitoidp/service_endpoints_gen_test.go b/internal/service/cognitoidp/service_endpoints_gen_test.go index a48fe5cbe9c..6ee2c40bcdf 100644 --- a/internal/service/cognitoidp/service_endpoints_gen_test.go +++ b/internal/service/cognitoidp/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -88,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -271,7 +272,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -292,12 +293,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(cognitoidentityprovider_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -306,17 +307,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(cognitoidentityprovider_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -325,7 +326,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -396,16 +397,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cognitoidp/service_package_gen.go b/internal/service/cognitoidp/service_package_gen.go index 527b597144c..d253e4a7afa 100644 --- a/internal/service/cognitoidp/service_package_gen.go +++ b/internal/service/cognitoidp/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cognitoidp @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" cognitoidentityprovider_sdkv1 "github.com/aws/aws-sdk-go/service/cognitoidentityprovider" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -134,11 +133,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*c "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return cognitoidentityprovider_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/comprehend/service_endpoint_resolver_gen.go b/internal/service/comprehend/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1d65e617e95 --- /dev/null +++ b/internal/service/comprehend/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package comprehend + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + comprehend_sdkv2 "github.com/aws/aws-sdk-go-v2/service/comprehend" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ comprehend_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver comprehend_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: comprehend_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params comprehend_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up comprehend endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*comprehend_sdkv2.Options) { + return func(o *comprehend_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/comprehend/service_endpoints_gen_test.go b/internal/service/comprehend/service_endpoints_gen_test.go index fd36f64bbb8..3bf5c4e3415 100644 --- a/internal/service/comprehend/service_endpoints_gen_test.go +++ b/internal/service/comprehend/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := comprehend_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), comprehend_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := comprehend_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), comprehend_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/comprehend/service_package_gen.go b/internal/service/comprehend/service_package_gen.go index f9d5943fbe5..d2d1a692b49 100644 --- a/internal/service/comprehend/service_package_gen.go +++ b/internal/service/comprehend/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package comprehend @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" comprehend_sdkv2 "github.com/aws/aws-sdk-go-v2/service/comprehend" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*comprehend_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return comprehend_sdkv2.NewFromConfig(cfg, func(o *comprehend_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return comprehend_sdkv2.NewFromConfig(cfg, + comprehend_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/computeoptimizer/service_endpoint_resolver_gen.go b/internal/service/computeoptimizer/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ae76d51e24d --- /dev/null +++ b/internal/service/computeoptimizer/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package computeoptimizer + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + computeoptimizer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/computeoptimizer" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ computeoptimizer_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver computeoptimizer_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: computeoptimizer_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params computeoptimizer_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up computeoptimizer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*computeoptimizer_sdkv2.Options) { + return func(o *computeoptimizer_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/computeoptimizer/service_endpoints_gen_test.go b/internal/service/computeoptimizer/service_endpoints_gen_test.go index 47ef905d6f1..8d1ae0a4fbf 100644 --- a/internal/service/computeoptimizer/service_endpoints_gen_test.go +++ b/internal/service/computeoptimizer/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := computeoptimizer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), computeoptimizer_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := computeoptimizer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), computeoptimizer_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/computeoptimizer/service_package_gen.go b/internal/service/computeoptimizer/service_package_gen.go index 5a2862cf7dc..1fc4ab60df6 100644 --- a/internal/service/computeoptimizer/service_package_gen.go +++ b/internal/service/computeoptimizer/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package computeoptimizer @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" computeoptimizer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/computeoptimizer" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*computeoptimizer_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return computeoptimizer_sdkv2.NewFromConfig(cfg, func(o *computeoptimizer_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return computeoptimizer_sdkv2.NewFromConfig(cfg, + computeoptimizer_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/configservice/service_endpoint_resolver_gen.go b/internal/service/configservice/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b4c40a3b13c --- /dev/null +++ b/internal/service/configservice/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package configservice + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + configservice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/configservice" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ configservice_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver configservice_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: configservice_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params configservice_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up configservice endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*configservice_sdkv2.Options) { + return func(o *configservice_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/configservice/service_endpoints_gen_test.go b/internal/service/configservice/service_endpoints_gen_test.go index 04e52863855..d778d581ca8 100644 --- a/internal/service/configservice/service_endpoints_gen_test.go +++ b/internal/service/configservice/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := configservice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), configservice_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := configservice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), configservice_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/configservice/service_package_gen.go b/internal/service/configservice/service_package_gen.go index 861d8e46343..fab6d043788 100644 --- a/internal/service/configservice/service_package_gen.go +++ b/internal/service/configservice/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package configservice @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" configservice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/configservice" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -114,19 +113,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*configservice_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return configservice_sdkv2.NewFromConfig(cfg, func(o *configservice_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return configservice_sdkv2.NewFromConfig(cfg, + configservice_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/connect/service_endpoint_resolver_gen.go b/internal/service/connect/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a01203a7218 --- /dev/null +++ b/internal/service/connect/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package connect + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/connect/service_endpoints_gen_test.go b/internal/service/connect/service_endpoints_gen_test.go index 88dfef7f6f5..5d45b023d71 100644 --- a/internal/service/connect/service_endpoints_gen_test.go +++ b/internal/service/connect/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(connect_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(connect_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/connect/service_package_gen.go b/internal/service/connect/service_package_gen.go index 5b42ea5edd4..ca76a90687b 100644 --- a/internal/service/connect/service_package_gen.go +++ b/internal/service/connect/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package connect @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" connect_sdkv1 "github.com/aws/aws-sdk-go/service/connect" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -222,11 +221,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*c "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return connect_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/connectcases/service_endpoint_resolver_gen.go b/internal/service/connectcases/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ecbe3728fc0 --- /dev/null +++ b/internal/service/connectcases/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package connectcases + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + connectcases_sdkv2 "github.com/aws/aws-sdk-go-v2/service/connectcases" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ connectcases_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver connectcases_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: connectcases_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params connectcases_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up connectcases endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*connectcases_sdkv2.Options) { + return func(o *connectcases_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/connectcases/service_endpoints_gen_test.go b/internal/service/connectcases/service_endpoints_gen_test.go index b8c4b716412..7828b34b8f7 100644 --- a/internal/service/connectcases/service_endpoints_gen_test.go +++ b/internal/service/connectcases/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := connectcases_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), connectcases_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := connectcases_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), connectcases_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/connectcases/service_package_gen.go b/internal/service/connectcases/service_package_gen.go index b1b1b2433fc..71e95edfac4 100644 --- a/internal/service/connectcases/service_package_gen.go +++ b/internal/service/connectcases/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package connectcases @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" connectcases_sdkv2 "github.com/aws/aws-sdk-go-v2/service/connectcases" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*connectcases_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return connectcases_sdkv2.NewFromConfig(cfg, func(o *connectcases_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return connectcases_sdkv2.NewFromConfig(cfg, + connectcases_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/controltower/service_endpoint_resolver_gen.go b/internal/service/controltower/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..845783a2ef3 --- /dev/null +++ b/internal/service/controltower/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package controltower + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + controltower_sdkv2 "github.com/aws/aws-sdk-go-v2/service/controltower" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ controltower_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver controltower_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: controltower_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params controltower_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up controltower endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*controltower_sdkv2.Options) { + return func(o *controltower_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/controltower/service_endpoints_gen_test.go b/internal/service/controltower/service_endpoints_gen_test.go index ade0d064297..4177f22267e 100644 --- a/internal/service/controltower/service_endpoints_gen_test.go +++ b/internal/service/controltower/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := controltower_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), controltower_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := controltower_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), controltower_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/controltower/service_package_gen.go b/internal/service/controltower/service_package_gen.go index 25b7f44a602..f28e6f5de8c 100644 --- a/internal/service/controltower/service_package_gen.go +++ b/internal/service/controltower/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package controltower @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" controltower_sdkv2 "github.com/aws/aws-sdk-go-v2/service/controltower" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -59,19 +58,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*controltower_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return controltower_sdkv2.NewFromConfig(cfg, func(o *controltower_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return controltower_sdkv2.NewFromConfig(cfg, + controltower_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/costoptimizationhub/service_endpoint_resolver_gen.go b/internal/service/costoptimizationhub/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..4b9d334a683 --- /dev/null +++ b/internal/service/costoptimizationhub/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package costoptimizationhub + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + costoptimizationhub_sdkv2 "github.com/aws/aws-sdk-go-v2/service/costoptimizationhub" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ costoptimizationhub_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver costoptimizationhub_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: costoptimizationhub_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params costoptimizationhub_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up costoptimizationhub endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*costoptimizationhub_sdkv2.Options) { + return func(o *costoptimizationhub_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/costoptimizationhub/service_endpoints_gen_test.go b/internal/service/costoptimizationhub/service_endpoints_gen_test.go index f0dadbbb35e..9a5e89bf8ed 100644 --- a/internal/service/costoptimizationhub/service_endpoints_gen_test.go +++ b/internal/service/costoptimizationhub/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -243,24 +245,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := costoptimizationhub_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), costoptimizationhub_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := costoptimizationhub_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), costoptimizationhub_sdkv2.EndpointParameters{ @@ -268,14 +270,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/costoptimizationhub/service_package.go b/internal/service/costoptimizationhub/service_package.go index db43c01421e..54a63e556f6 100644 --- a/internal/service/costoptimizationhub/service_package.go +++ b/internal/service/costoptimizationhub/service_package.go @@ -16,22 +16,20 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*costoptimizationhub.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return costoptimizationhub.NewFromConfig(cfg, func(o *costoptimizationhub.Options) { - if config["partition"].(string) == names.StandardPartitionID { - // Cost Optimization Hub endpoint is available only in us-east-1 Region. - o.Region = names.USEast1RegionID - } - - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled + return costoptimizationhub.NewFromConfig(cfg, + costoptimizationhub.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *costoptimizationhub.Options) { + if config["partition"].(string) == names.StandardPartitionID { + // Cost Optimization Hub endpoint is available only in us-east-1 Region. + if cfg.Region != names.USEast1RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USEast1RegionID, + }) + o.Region = names.USEast1RegionID + } } - } - }), nil + }, + ), nil } diff --git a/internal/service/costoptimizationhub/service_package_gen.go b/internal/service/costoptimizationhub/service_package_gen.go index 50f15a9e930..e67ee41129b 100644 --- a/internal/service/costoptimizationhub/service_package_gen.go +++ b/internal/service/costoptimizationhub/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package costoptimizationhub diff --git a/internal/service/cur/service_endpoint_resolver_gen.go b/internal/service/cur/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..25fbdce7659 --- /dev/null +++ b/internal/service/cur/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package cur + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + costandusagereportservice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/costandusagereportservice" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ costandusagereportservice_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver costandusagereportservice_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: costandusagereportservice_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params costandusagereportservice_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up costandusagereportservice endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*costandusagereportservice_sdkv2.Options) { + return func(o *costandusagereportservice_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/cur/service_endpoints_gen_test.go b/internal/service/cur/service_endpoints_gen_test.go index fbce07ffabb..9a06ce0c82e 100644 --- a/internal/service/cur/service_endpoints_gen_test.go +++ b/internal/service/cur/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -93,7 +95,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -276,7 +278,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -297,24 +299,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := costandusagereportservice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), costandusagereportservice_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := costandusagereportservice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), costandusagereportservice_sdkv2.EndpointParameters{ @@ -322,14 +324,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -410,16 +412,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/cur/service_package.go b/internal/service/cur/service_package.go index 95d5d45ae6f..8ad3ede742d 100644 --- a/internal/service/cur/service_package.go +++ b/internal/service/cur/service_package.go @@ -1,4 +1,5 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 package cur @@ -15,23 +16,21 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*costandusagereportservice.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return costandusagereportservice.NewFromConfig(cfg, func(o *costandusagereportservice.Options) { - if config["partition"].(string) == names.StandardPartitionID { - // AWS Cost and Usage Reports is only available in AWS Commercial us-east-1 Region. - // https://docs.aws.amazon.com/general/latest/gr/billing.html. - o.Region = names.USEast1RegionID - } - - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled + return costandusagereportservice.NewFromConfig(cfg, + costandusagereportservice.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *costandusagereportservice.Options) { + if config["partition"].(string) == names.StandardPartitionID { + // AWS Cost and Usage Reports is only available in AWS Commercial us-east-1 Region. + // https://docs.aws.amazon.com/general/latest/gr/billing.html. + if cfg.Region != names.USEast1RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USEast1RegionID, + }) + o.Region = names.USEast1RegionID + } } - } - }), nil + }, + ), nil } diff --git a/internal/service/cur/service_package_gen.go b/internal/service/cur/service_package_gen.go index 94b052a58d7..7f131def9b2 100644 --- a/internal/service/cur/service_package_gen.go +++ b/internal/service/cur/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package cur diff --git a/internal/service/customerprofiles/service_endpoint_resolver_gen.go b/internal/service/customerprofiles/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..fede695c66d --- /dev/null +++ b/internal/service/customerprofiles/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package customerprofiles + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + customerprofiles_sdkv2 "github.com/aws/aws-sdk-go-v2/service/customerprofiles" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ customerprofiles_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver customerprofiles_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: customerprofiles_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params customerprofiles_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up customerprofiles endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*customerprofiles_sdkv2.Options) { + return func(o *customerprofiles_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/customerprofiles/service_endpoints_gen_test.go b/internal/service/customerprofiles/service_endpoints_gen_test.go index 3a22a4566a8..8f2441f6063 100644 --- a/internal/service/customerprofiles/service_endpoints_gen_test.go +++ b/internal/service/customerprofiles/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := customerprofiles_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), customerprofiles_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := customerprofiles_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), customerprofiles_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/customerprofiles/service_package_gen.go b/internal/service/customerprofiles/service_package_gen.go index f018f3595ee..13a4c11bdac 100644 --- a/internal/service/customerprofiles/service_package_gen.go +++ b/internal/service/customerprofiles/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package customerprofiles @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" customerprofiles_sdkv2 "github.com/aws/aws-sdk-go-v2/service/customerprofiles" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -51,19 +50,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*customerprofiles_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return customerprofiles_sdkv2.NewFromConfig(cfg, func(o *customerprofiles_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return customerprofiles_sdkv2.NewFromConfig(cfg, + customerprofiles_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/dataexchange/service_endpoint_resolver_gen.go b/internal/service/dataexchange/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..bceab315cb0 --- /dev/null +++ b/internal/service/dataexchange/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package dataexchange + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/dataexchange/service_endpoints_gen_test.go b/internal/service/dataexchange/service_endpoints_gen_test.go index aceaa5b70f0..fa48e547771 100644 --- a/internal/service/dataexchange/service_endpoints_gen_test.go +++ b/internal/service/dataexchange/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(dataexchange_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(dataexchange_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/dataexchange/service_package_gen.go b/internal/service/dataexchange/service_package_gen.go index 8ffacc16ec0..f274c4ae3be 100644 --- a/internal/service/dataexchange/service_package_gen.go +++ b/internal/service/dataexchange/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package dataexchange @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" dataexchange_sdkv1 "github.com/aws/aws-sdk-go/service/dataexchange" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -65,11 +64,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*d "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return dataexchange_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/datapipeline/service_endpoint_resolver_gen.go b/internal/service/datapipeline/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2fd2f228d8a --- /dev/null +++ b/internal/service/datapipeline/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package datapipeline + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/datapipeline/service_endpoints_gen_test.go b/internal/service/datapipeline/service_endpoints_gen_test.go index f0237581313..2107b43966d 100644 --- a/internal/service/datapipeline/service_endpoints_gen_test.go +++ b/internal/service/datapipeline/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(datapipeline_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(datapipeline_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/datapipeline/service_package_gen.go b/internal/service/datapipeline/service_package_gen.go index c94266e423d..b14207a407c 100644 --- a/internal/service/datapipeline/service_package_gen.go +++ b/internal/service/datapipeline/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package datapipeline @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" datapipeline_sdkv1 "github.com/aws/aws-sdk-go/service/datapipeline" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -70,11 +69,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*d "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return datapipeline_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/datasync/service_endpoint_resolver_gen.go b/internal/service/datasync/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b2f112f16df --- /dev/null +++ b/internal/service/datasync/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package datasync + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + datasync_sdkv2 "github.com/aws/aws-sdk-go-v2/service/datasync" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ datasync_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver datasync_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: datasync_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params datasync_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up datasync endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*datasync_sdkv2.Options) { + return func(o *datasync_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/datasync/service_endpoints_gen_test.go b/internal/service/datasync/service_endpoints_gen_test.go index 945dfff355f..2c33885b57c 100644 --- a/internal/service/datasync/service_endpoints_gen_test.go +++ b/internal/service/datasync/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := datasync_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), datasync_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := datasync_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), datasync_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/datasync/service_package_gen.go b/internal/service/datasync/service_package_gen.go index 58608bf491d..52a0f8e077f 100644 --- a/internal/service/datasync/service_package_gen.go +++ b/internal/service/datasync/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package datasync @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" datasync_sdkv2 "github.com/aws/aws-sdk-go-v2/service/datasync" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -144,19 +143,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*datasync_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return datasync_sdkv2.NewFromConfig(cfg, func(o *datasync_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return datasync_sdkv2.NewFromConfig(cfg, + datasync_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/datazone/service_endpoint_resolver_gen.go b/internal/service/datazone/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..189bcbd6331 --- /dev/null +++ b/internal/service/datazone/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package datazone + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + datazone_sdkv2 "github.com/aws/aws-sdk-go-v2/service/datazone" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ datazone_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver datazone_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: datazone_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params datazone_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up datazone endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*datazone_sdkv2.Options) { + return func(o *datazone_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/datazone/service_endpoints_gen_test.go b/internal/service/datazone/service_endpoints_gen_test.go index e794e776047..d9757cb8085 100644 --- a/internal/service/datazone/service_endpoints_gen_test.go +++ b/internal/service/datazone/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := datazone_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), datazone_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := datazone_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), datazone_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/datazone/service_package_gen.go b/internal/service/datazone/service_package_gen.go index b5861812072..7f0e80c975a 100644 --- a/internal/service/datazone/service_package_gen.go +++ b/internal/service/datazone/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package datazone @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" datazone_sdkv2 "github.com/aws/aws-sdk-go-v2/service/datazone" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*datazone_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return datazone_sdkv2.NewFromConfig(cfg, func(o *datazone_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return datazone_sdkv2.NewFromConfig(cfg, + datazone_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/dax/service_endpoint_resolver_gen.go b/internal/service/dax/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..669b613d31d --- /dev/null +++ b/internal/service/dax/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package dax + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + dax_sdkv2 "github.com/aws/aws-sdk-go-v2/service/dax" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ dax_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver dax_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: dax_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params dax_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up dax endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*dax_sdkv2.Options) { + return func(o *dax_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/dax/service_endpoints_gen_test.go b/internal/service/dax/service_endpoints_gen_test.go index 2d117dcd24f..69508d5850a 100644 --- a/internal/service/dax/service_endpoints_gen_test.go +++ b/internal/service/dax/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := dax_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), dax_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := dax_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), dax_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/dax/service_package_gen.go b/internal/service/dax/service_package_gen.go index d6b86d61205..e944d854b4a 100644 --- a/internal/service/dax/service_package_gen.go +++ b/internal/service/dax/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package dax @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" dax_sdkv2 "github.com/aws/aws-sdk-go-v2/service/dax" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*dax_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return dax_sdkv2.NewFromConfig(cfg, func(o *dax_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return dax_sdkv2.NewFromConfig(cfg, + dax_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/deploy/service_endpoint_resolver_gen.go b/internal/service/deploy/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..adff12f265a --- /dev/null +++ b/internal/service/deploy/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package deploy + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + codedeploy_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codedeploy" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ codedeploy_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver codedeploy_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: codedeploy_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params codedeploy_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up codedeploy endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*codedeploy_sdkv2.Options) { + return func(o *codedeploy_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/deploy/service_endpoints_gen_test.go b/internal/service/deploy/service_endpoints_gen_test.go index a8957a49874..8484f47323b 100644 --- a/internal/service/deploy/service_endpoints_gen_test.go +++ b/internal/service/deploy/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := codedeploy_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codedeploy_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := codedeploy_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), codedeploy_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/deploy/service_package_gen.go b/internal/service/deploy/service_package_gen.go index dc50224c8b7..bee170a538f 100644 --- a/internal/service/deploy/service_package_gen.go +++ b/internal/service/deploy/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package deploy @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" codedeploy_sdkv2 "github.com/aws/aws-sdk-go-v2/service/codedeploy" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -61,19 +60,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*codedeploy_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return codedeploy_sdkv2.NewFromConfig(cfg, func(o *codedeploy_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return codedeploy_sdkv2.NewFromConfig(cfg, + codedeploy_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/detective/service_endpoint_resolver_gen.go b/internal/service/detective/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f7e2881d3b5 --- /dev/null +++ b/internal/service/detective/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package detective + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/detective/service_endpoints_gen_test.go b/internal/service/detective/service_endpoints_gen_test.go index 9461bf9fdf9..4ab21896f68 100644 --- a/internal/service/detective/service_endpoints_gen_test.go +++ b/internal/service/detective/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(detective_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(detective_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/detective/service_package_gen.go b/internal/service/detective/service_package_gen.go index f7f45de9f88..d4566e0926f 100644 --- a/internal/service/detective/service_package_gen.go +++ b/internal/service/detective/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package detective @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" detective_sdkv1 "github.com/aws/aws-sdk-go/service/detective" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -73,11 +72,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*d "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return detective_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/devicefarm/service_endpoint_resolver_gen.go b/internal/service/devicefarm/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..8407250ab33 --- /dev/null +++ b/internal/service/devicefarm/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package devicefarm + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + devicefarm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/devicefarm" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ devicefarm_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver devicefarm_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: devicefarm_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params devicefarm_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up devicefarm endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*devicefarm_sdkv2.Options) { + return func(o *devicefarm_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/devicefarm/service_endpoints_gen_test.go b/internal/service/devicefarm/service_endpoints_gen_test.go index 99b15da2f63..b7e18d3b75f 100644 --- a/internal/service/devicefarm/service_endpoints_gen_test.go +++ b/internal/service/devicefarm/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := devicefarm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), devicefarm_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := devicefarm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), devicefarm_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/devicefarm/service_package_gen.go b/internal/service/devicefarm/service_package_gen.go index 31316f5da53..c0aacd111c4 100644 --- a/internal/service/devicefarm/service_package_gen.go +++ b/internal/service/devicefarm/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package devicefarm @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" devicefarm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/devicefarm" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -85,19 +84,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*devicefarm_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return devicefarm_sdkv2.NewFromConfig(cfg, func(o *devicefarm_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return devicefarm_sdkv2.NewFromConfig(cfg, + devicefarm_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/devopsguru/service_endpoint_resolver_gen.go b/internal/service/devopsguru/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7d75a9544c1 --- /dev/null +++ b/internal/service/devopsguru/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package devopsguru + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + devopsguru_sdkv2 "github.com/aws/aws-sdk-go-v2/service/devopsguru" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ devopsguru_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver devopsguru_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: devopsguru_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params devopsguru_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up devopsguru endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*devopsguru_sdkv2.Options) { + return func(o *devopsguru_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/devopsguru/service_endpoints_gen_test.go b/internal/service/devopsguru/service_endpoints_gen_test.go index d1d0eaeb12c..c954744b265 100644 --- a/internal/service/devopsguru/service_endpoints_gen_test.go +++ b/internal/service/devopsguru/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := devopsguru_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), devopsguru_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := devopsguru_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), devopsguru_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/devopsguru/service_package_gen.go b/internal/service/devopsguru/service_package_gen.go index a1ea8470104..013da856af1 100644 --- a/internal/service/devopsguru/service_package_gen.go +++ b/internal/service/devopsguru/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package devopsguru @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" devopsguru_sdkv2 "github.com/aws/aws-sdk-go-v2/service/devopsguru" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -65,19 +64,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*devopsguru_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return devopsguru_sdkv2.NewFromConfig(cfg, func(o *devopsguru_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return devopsguru_sdkv2.NewFromConfig(cfg, + devopsguru_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/directconnect/service_endpoint_resolver_gen.go b/internal/service/directconnect/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..8445f971931 --- /dev/null +++ b/internal/service/directconnect/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package directconnect + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/directconnect/service_endpoints_gen_test.go b/internal/service/directconnect/service_endpoints_gen_test.go index 054e9411b83..910a8e7822f 100644 --- a/internal/service/directconnect/service_endpoints_gen_test.go +++ b/internal/service/directconnect/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(directconnect_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(directconnect_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/directconnect/service_package_gen.go b/internal/service/directconnect/service_package_gen.go index a65a5a64097..aa7c0014dfc 100644 --- a/internal/service/directconnect/service_package_gen.go +++ b/internal/service/directconnect/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package directconnect @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" directconnect_sdkv1 "github.com/aws/aws-sdk-go/service/directconnect" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -178,11 +177,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*d "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return directconnect_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/dlm/service_endpoint_resolver_gen.go b/internal/service/dlm/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..d2ecec96a2c --- /dev/null +++ b/internal/service/dlm/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package dlm + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + dlm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/dlm" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ dlm_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver dlm_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: dlm_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params dlm_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up dlm endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*dlm_sdkv2.Options) { + return func(o *dlm_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/dlm/service_endpoints_gen_test.go b/internal/service/dlm/service_endpoints_gen_test.go index ebd47c83bda..63e66178022 100644 --- a/internal/service/dlm/service_endpoints_gen_test.go +++ b/internal/service/dlm/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := dlm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), dlm_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := dlm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), dlm_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/dlm/service_package_gen.go b/internal/service/dlm/service_package_gen.go index 5101affdd72..6552b7c43d1 100644 --- a/internal/service/dlm/service_package_gen.go +++ b/internal/service/dlm/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package dlm @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" dlm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/dlm" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*dlm_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return dlm_sdkv2.NewFromConfig(cfg, func(o *dlm_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return dlm_sdkv2.NewFromConfig(cfg, + dlm_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/dms/service_endpoint_resolver_gen.go b/internal/service/dms/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..0dd3f0e70a2 --- /dev/null +++ b/internal/service/dms/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package dms + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/dms/service_endpoints_gen_test.go b/internal/service/dms/service_endpoints_gen_test.go index 04bedfc4c45..de0605363bb 100644 --- a/internal/service/dms/service_endpoints_gen_test.go +++ b/internal/service/dms/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -90,7 +91,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -330,7 +331,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -351,12 +352,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(databasemigrationservice_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -365,17 +366,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(databasemigrationservice_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -384,7 +385,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -466,16 +467,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/dms/service_package_gen.go b/internal/service/dms/service_package_gen.go index 8f670d8a92a..ea9ef5d38a4 100644 --- a/internal/service/dms/service_package_gen.go +++ b/internal/service/dms/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package dms @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" databasemigrationservice_sdkv1 "github.com/aws/aws-sdk-go/service/databasemigrationservice" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -134,11 +133,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*d "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return databasemigrationservice_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/docdb/service_endpoint_resolver_gen.go b/internal/service/docdb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..8d551cfd7b9 --- /dev/null +++ b/internal/service/docdb/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package docdb + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + docdb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/docdb" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ docdb_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver docdb_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: docdb_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params docdb_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up docdb endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*docdb_sdkv2.Options) { + return func(o *docdb_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/docdb/service_endpoints_gen_test.go b/internal/service/docdb/service_endpoints_gen_test.go index 5c1b1b68949..75c8751a3de 100644 --- a/internal/service/docdb/service_endpoints_gen_test.go +++ b/internal/service/docdb/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := docdb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), docdb_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := docdb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), docdb_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/docdb/service_package_gen.go b/internal/service/docdb/service_package_gen.go index d06fe85387c..a6154e666ba 100644 --- a/internal/service/docdb/service_package_gen.go +++ b/internal/service/docdb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package docdb @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" docdb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/docdb" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -97,19 +96,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*docdb_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return docdb_sdkv2.NewFromConfig(cfg, func(o *docdb_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return docdb_sdkv2.NewFromConfig(cfg, + docdb_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/docdbelastic/service_endpoint_resolver_gen.go b/internal/service/docdbelastic/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2f0ca4f25f2 --- /dev/null +++ b/internal/service/docdbelastic/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package docdbelastic + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + docdbelastic_sdkv2 "github.com/aws/aws-sdk-go-v2/service/docdbelastic" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ docdbelastic_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver docdbelastic_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: docdbelastic_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params docdbelastic_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up docdbelastic endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*docdbelastic_sdkv2.Options) { + return func(o *docdbelastic_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/docdbelastic/service_endpoints_gen_test.go b/internal/service/docdbelastic/service_endpoints_gen_test.go index a9ac7cf6b26..874c229c4e0 100644 --- a/internal/service/docdbelastic/service_endpoints_gen_test.go +++ b/internal/service/docdbelastic/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := docdbelastic_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), docdbelastic_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := docdbelastic_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), docdbelastic_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/docdbelastic/service_package_gen.go b/internal/service/docdbelastic/service_package_gen.go index 6a18acda69e..4a9d0907313 100644 --- a/internal/service/docdbelastic/service_package_gen.go +++ b/internal/service/docdbelastic/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package docdbelastic @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" docdbelastic_sdkv2 "github.com/aws/aws-sdk-go-v2/service/docdbelastic" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -47,19 +46,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*docdbelastic_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return docdbelastic_sdkv2.NewFromConfig(cfg, func(o *docdbelastic_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return docdbelastic_sdkv2.NewFromConfig(cfg, + docdbelastic_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/drs/service_endpoint_resolver_gen.go b/internal/service/drs/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..660ba2ba0d7 --- /dev/null +++ b/internal/service/drs/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package drs + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + drs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/drs" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ drs_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver drs_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: drs_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params drs_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up drs endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*drs_sdkv2.Options) { + return func(o *drs_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/drs/service_endpoints_gen_test.go b/internal/service/drs/service_endpoints_gen_test.go index 4ee4b72c3f2..0b1051365de 100644 --- a/internal/service/drs/service_endpoints_gen_test.go +++ b/internal/service/drs/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := drs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), drs_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := drs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), drs_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/drs/service_package_gen.go b/internal/service/drs/service_package_gen.go index 60cf41df056..bef76c21f67 100644 --- a/internal/service/drs/service_package_gen.go +++ b/internal/service/drs/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package drs @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" drs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/drs" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -47,19 +46,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*drs_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return drs_sdkv2.NewFromConfig(cfg, func(o *drs_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return drs_sdkv2.NewFromConfig(cfg, + drs_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ds/service_endpoint_resolver_gen.go b/internal/service/ds/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..c8b9f898652 --- /dev/null +++ b/internal/service/ds/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ds + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + directoryservice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/directoryservice" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ directoryservice_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver directoryservice_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: directoryservice_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params directoryservice_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up directoryservice endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*directoryservice_sdkv2.Options) { + return func(o *directoryservice_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ds/service_endpoints_gen_test.go b/internal/service/ds/service_endpoints_gen_test.go index 38ab27caa91..2fb79fd4596 100644 --- a/internal/service/ds/service_endpoints_gen_test.go +++ b/internal/service/ds/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -93,7 +95,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -276,7 +278,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -309,24 +311,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := directoryservice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), directoryservice_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := directoryservice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), directoryservice_sdkv2.EndpointParameters{ @@ -334,14 +336,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -437,16 +439,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ds/service_package_gen.go b/internal/service/ds/service_package_gen.go index f491b2f9ab1..b30c67d2857 100644 --- a/internal/service/ds/service_package_gen.go +++ b/internal/service/ds/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ds @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" directoryservice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/directoryservice" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" directoryservice_sdkv1 "github.com/aws/aws-sdk-go/service/directoryservice" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -94,11 +93,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*d "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return directoryservice_sdkv1.New(sess.Copy(&cfg)), nil @@ -108,19 +104,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*d func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*directoryservice_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return directoryservice_sdkv2.NewFromConfig(cfg, func(o *directoryservice_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return directoryservice_sdkv2.NewFromConfig(cfg, + directoryservice_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/dynamodb/service_endpoint_resolver_gen.go b/internal/service/dynamodb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..49fe698597c --- /dev/null +++ b/internal/service/dynamodb/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package dynamodb + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + dynamodb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/dynamodb" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ dynamodb_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver dynamodb_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: dynamodb_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params dynamodb_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up dynamodb endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*dynamodb_sdkv2.Options) { + return func(o *dynamodb_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/dynamodb/service_endpoints_gen_test.go b/internal/service/dynamodb/service_endpoints_gen_test.go index 00ed085b88b..62835b5ca52 100644 --- a/internal/service/dynamodb/service_endpoints_gen_test.go +++ b/internal/service/dynamodb/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -90,7 +92,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -330,7 +332,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -351,24 +353,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := dynamodb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), dynamodb_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := dynamodb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), dynamodb_sdkv2.EndpointParameters{ @@ -376,14 +378,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -453,16 +455,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/dynamodb/service_package.go b/internal/service/dynamodb/service_package.go index 8ac0ae0fcfc..f9589244928 100644 --- a/internal/service/dynamodb/service_package.go +++ b/internal/service/dynamodb/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/dynamodb" awstypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*dynamodb.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return dynamodb.NewFromConfig(cfg, func(o *dynamodb.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*awstypes.LimitExceededException](err, "Subscriber limit exceeded:") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return dynamodb.NewFromConfig(cfg, + dynamodb.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *dynamodb.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*awstypes.LimitExceededException](err, "Subscriber limit exceeded:") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/dynamodb/service_package_gen.go b/internal/service/dynamodb/service_package_gen.go index e8054560af4..68ba88bcbb3 100644 --- a/internal/service/dynamodb/service_package_gen.go +++ b/internal/service/dynamodb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package dynamodb diff --git a/internal/service/ec2/service_endpoint_resolver_gen.go b/internal/service/ec2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..0b1b24d201c --- /dev/null +++ b/internal/service/ec2/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ec2 + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ec2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ec2" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ ec2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ec2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ec2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ec2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ec2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ec2_sdkv2.Options) { + return func(o *ec2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ec2/service_endpoints_gen_test.go b/internal/service/ec2/service_endpoints_gen_test.go index b68337d9be6..6eab3c485f4 100644 --- a/internal/service/ec2/service_endpoints_gen_test.go +++ b/internal/service/ec2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ec2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ec2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ec2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ec2_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ec2/service_package.go b/internal/service/ec2/service_package.go index 4dc23ca9249..268d87e43d6 100644 --- a/internal/service/ec2/service_package.go +++ b/internal/service/ec2/service_package.go @@ -10,7 +10,6 @@ import ( retry_sdkv2 "github.com/aws/aws-sdk-go-v2/aws/retry" ec2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ec2" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" request_sdkv1 "github.com/aws/aws-sdk-go/aws/request" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" ec2_sdkv1 "github.com/aws/aws-sdk-go/service/ec2" @@ -32,11 +31,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return ec2_sdkv1.New(sess.Copy(&cfg)), nil @@ -61,41 +57,33 @@ func (p *servicePackage) CustomizeConn(ctx context.Context, conn *ec2_sdkv1.EC2) func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ec2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ec2_sdkv2.NewFromConfig(cfg, func(o *ec2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws_sdkv2.RetryerV2), retry_sdkv2.IsErrorRetryableFunc(func(err error) aws_sdkv2.Ternary { - if tfawserr_sdkv2.ErrMessageContains(err, errCodeInvalidParameterValue, "This call cannot be completed because there are pending VPNs or Virtual Interfaces") { // AttachVpnGateway, DetachVpnGateway - return aws_sdkv2.TrueTernary - } - - if tfawserr_sdkv2.ErrMessageContains(err, errCodeOperationNotPermitted, "Endpoint cannot be created while another endpoint is being created") { // CreateClientVpnEndpoint - return aws_sdkv2.TrueTernary - } - - if tfawserr_sdkv2.ErrMessageContains(err, errCodeConcurrentMutationLimitExceeded, "Cannot initiate another change for this endpoint at this time") { // CreateClientVpnRoute, DeleteClientVpnRoute - return aws_sdkv2.TrueTernary - } - - if tfawserr_sdkv2.ErrMessageContains(err, errCodeVPNConnectionLimitExceeded, "maximum number of mutating objects has been reached") { // CreateVpnConnection - return aws_sdkv2.TrueTernary - } - - if tfawserr_sdkv2.ErrMessageContains(err, errCodeVPNGatewayLimitExceeded, "maximum number of mutating objects has been reached") { // CreateVpnGateway - return aws_sdkv2.TrueTernary - } - - return aws_sdkv2.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return ec2_sdkv2.NewFromConfig(cfg, + ec2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *ec2_sdkv2.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws_sdkv2.RetryerV2), retry_sdkv2.IsErrorRetryableFunc(func(err error) aws_sdkv2.Ternary { + if tfawserr_sdkv2.ErrMessageContains(err, errCodeInvalidParameterValue, "This call cannot be completed because there are pending VPNs or Virtual Interfaces") { // AttachVpnGateway, DetachVpnGateway + return aws_sdkv2.TrueTernary + } + + if tfawserr_sdkv2.ErrMessageContains(err, errCodeOperationNotPermitted, "Endpoint cannot be created while another endpoint is being created") { // CreateClientVpnEndpoint + return aws_sdkv2.TrueTernary + } + + if tfawserr_sdkv2.ErrMessageContains(err, errCodeConcurrentMutationLimitExceeded, "Cannot initiate another change for this endpoint at this time") { // CreateClientVpnRoute, DeleteClientVpnRoute + return aws_sdkv2.TrueTernary + } + + if tfawserr_sdkv2.ErrMessageContains(err, errCodeVPNConnectionLimitExceeded, "maximum number of mutating objects has been reached") { // CreateVpnConnection + return aws_sdkv2.TrueTernary + } + + if tfawserr_sdkv2.ErrMessageContains(err, errCodeVPNGatewayLimitExceeded, "maximum number of mutating objects has been reached") { // CreateVpnGateway + return aws_sdkv2.TrueTernary + } + + return aws_sdkv2.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/ec2/service_package_gen.go b/internal/service/ec2/service_package_gen.go index 9c3ef9b110a..42565197ff7 100644 --- a/internal/service/ec2/service_package_gen.go +++ b/internal/service/ec2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ec2 diff --git a/internal/service/ecr/service_endpoint_resolver_gen.go b/internal/service/ecr/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..550251f394c --- /dev/null +++ b/internal/service/ecr/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ecr + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ecr_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ecr" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ecr_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ecr_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ecr_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ecr_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ecr endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ecr_sdkv2.Options) { + return func(o *ecr_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ecr/service_endpoints_gen_test.go b/internal/service/ecr/service_endpoints_gen_test.go index a733dcbf304..ebb1c083a2a 100644 --- a/internal/service/ecr/service_endpoints_gen_test.go +++ b/internal/service/ecr/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ecr_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ecr_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ecr_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ecr_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ecr/service_package_gen.go b/internal/service/ecr/service_package_gen.go index 3cdc67b28e1..d04ab8e2aa7 100644 --- a/internal/service/ecr/service_package_gen.go +++ b/internal/service/ecr/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ecr @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ecr_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ecr" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -108,19 +107,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ecr_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ecr_sdkv2.NewFromConfig(cfg, func(o *ecr_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ecr_sdkv2.NewFromConfig(cfg, + ecr_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ecrpublic/service_endpoint_resolver_gen.go b/internal/service/ecrpublic/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e87de1cf693 --- /dev/null +++ b/internal/service/ecrpublic/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ecrpublic + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ecrpublic_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ecrpublic" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ecrpublic_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ecrpublic_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ecrpublic_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ecrpublic_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ecrpublic endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ecrpublic_sdkv2.Options) { + return func(o *ecrpublic_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ecrpublic/service_endpoints_gen_test.go b/internal/service/ecrpublic/service_endpoints_gen_test.go index 8517b3685ea..eebd960a6ba 100644 --- a/internal/service/ecrpublic/service_endpoints_gen_test.go +++ b/internal/service/ecrpublic/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ecrpublic_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ecrpublic_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ecrpublic_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ecrpublic_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ecrpublic/service_package_gen.go b/internal/service/ecrpublic/service_package_gen.go index c3c39fc450e..6f3b96d38ff 100644 --- a/internal/service/ecrpublic/service_package_gen.go +++ b/internal/service/ecrpublic/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ecrpublic @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ecrpublic_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ecrpublic" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -57,19 +56,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ecrpublic_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ecrpublic_sdkv2.NewFromConfig(cfg, func(o *ecrpublic_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ecrpublic_sdkv2.NewFromConfig(cfg, + ecrpublic_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ecs/service_endpoint_resolver_gen.go b/internal/service/ecs/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..74753d5032d --- /dev/null +++ b/internal/service/ecs/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ecs + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ecs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ecs" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ ecs_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ecs_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ecs_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ecs_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ecs endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ecs_sdkv2.Options) { + return func(o *ecs_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ecs/service_endpoints_gen_test.go b/internal/service/ecs/service_endpoints_gen_test.go index 2e7e6ba0262..25f36a84d2e 100644 --- a/internal/service/ecs/service_endpoints_gen_test.go +++ b/internal/service/ecs/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ecs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ecs_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ecs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ecs_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ecs/service_package_gen.go b/internal/service/ecs/service_package_gen.go index 1166a226303..fc2a0ca65b1 100644 --- a/internal/service/ecs/service_package_gen.go +++ b/internal/service/ecs/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ecs @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ecs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ecs" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" ecs_sdkv1 "github.com/aws/aws-sdk-go/service/ecs" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -126,11 +125,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return ecs_sdkv1.New(sess.Copy(&cfg)), nil @@ -140,19 +136,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ecs_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ecs_sdkv2.NewFromConfig(cfg, func(o *ecs_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ecs_sdkv2.NewFromConfig(cfg, + ecs_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/efs/service_endpoint_resolver_gen.go b/internal/service/efs/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..fc579f2e353 --- /dev/null +++ b/internal/service/efs/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package efs + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/efs/service_endpoints_gen_test.go b/internal/service/efs/service_endpoints_gen_test.go index d8ce6e2c590..66b02389937 100644 --- a/internal/service/efs/service_endpoints_gen_test.go +++ b/internal/service/efs/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(efs_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(efs_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/efs/service_package_gen.go b/internal/service/efs/service_package_gen.go index 98d34b8546d..f438cf30bc9 100644 --- a/internal/service/efs/service_package_gen.go +++ b/internal/service/efs/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package efs @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" efs_sdkv1 "github.com/aws/aws-sdk-go/service/efs" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -100,11 +99,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return efs_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/eks/service_endpoint_resolver_gen.go b/internal/service/eks/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ac68cc8cc13 --- /dev/null +++ b/internal/service/eks/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package eks + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + eks_sdkv2 "github.com/aws/aws-sdk-go-v2/service/eks" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ eks_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver eks_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: eks_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params eks_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up eks endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*eks_sdkv2.Options) { + return func(o *eks_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/eks/service_endpoints_gen_test.go b/internal/service/eks/service_endpoints_gen_test.go index 7df8770dbae..df336e50006 100644 --- a/internal/service/eks/service_endpoints_gen_test.go +++ b/internal/service/eks/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := eks_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), eks_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := eks_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), eks_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/eks/service_package_gen.go b/internal/service/eks/service_package_gen.go index afe30d44ab2..bfb87d2f2bf 100644 --- a/internal/service/eks/service_package_gen.go +++ b/internal/service/eks/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package eks @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" eks_sdkv2 "github.com/aws/aws-sdk-go-v2/service/eks" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -135,19 +134,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*eks_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return eks_sdkv2.NewFromConfig(cfg, func(o *eks_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return eks_sdkv2.NewFromConfig(cfg, + eks_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/elasticache/service_endpoint_resolver_gen.go b/internal/service/elasticache/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b815da2c226 --- /dev/null +++ b/internal/service/elasticache/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package elasticache + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + elasticache_sdkv2 "github.com/aws/aws-sdk-go-v2/service/elasticache" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ elasticache_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver elasticache_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: elasticache_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params elasticache_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up elasticache endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*elasticache_sdkv2.Options) { + return func(o *elasticache_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/elasticache/service_endpoints_gen_test.go b/internal/service/elasticache/service_endpoints_gen_test.go index 7577ac6846b..1559e3f8ff1 100644 --- a/internal/service/elasticache/service_endpoints_gen_test.go +++ b/internal/service/elasticache/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := elasticache_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), elasticache_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := elasticache_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), elasticache_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/elasticache/service_package_gen.go b/internal/service/elasticache/service_package_gen.go index 40f7853654e..211383c06b8 100644 --- a/internal/service/elasticache/service_package_gen.go +++ b/internal/service/elasticache/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package elasticache @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" elasticache_sdkv2 "github.com/aws/aws-sdk-go-v2/service/elasticache" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" elasticache_sdkv1 "github.com/aws/aws-sdk-go/service/elasticache" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -138,11 +137,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return elasticache_sdkv1.New(sess.Copy(&cfg)), nil @@ -152,19 +148,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*elasticache_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return elasticache_sdkv2.NewFromConfig(cfg, func(o *elasticache_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return elasticache_sdkv2.NewFromConfig(cfg, + elasticache_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/elasticbeanstalk/service_endpoint_resolver_gen.go b/internal/service/elasticbeanstalk/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..c80d6aa11e4 --- /dev/null +++ b/internal/service/elasticbeanstalk/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package elasticbeanstalk + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + elasticbeanstalk_sdkv2 "github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ elasticbeanstalk_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver elasticbeanstalk_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: elasticbeanstalk_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params elasticbeanstalk_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up elasticbeanstalk endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*elasticbeanstalk_sdkv2.Options) { + return func(o *elasticbeanstalk_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/elasticbeanstalk/service_endpoints_gen_test.go b/internal/service/elasticbeanstalk/service_endpoints_gen_test.go index 88ee3a2a32b..8aa8305fd23 100644 --- a/internal/service/elasticbeanstalk/service_endpoints_gen_test.go +++ b/internal/service/elasticbeanstalk/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := elasticbeanstalk_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), elasticbeanstalk_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := elasticbeanstalk_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), elasticbeanstalk_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/elasticbeanstalk/service_package_gen.go b/internal/service/elasticbeanstalk/service_package_gen.go index 8158108bc3f..e93665734f8 100644 --- a/internal/service/elasticbeanstalk/service_package_gen.go +++ b/internal/service/elasticbeanstalk/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package elasticbeanstalk @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" elasticbeanstalk_sdkv2 "github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -81,19 +80,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*elasticbeanstalk_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return elasticbeanstalk_sdkv2.NewFromConfig(cfg, func(o *elasticbeanstalk_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return elasticbeanstalk_sdkv2.NewFromConfig(cfg, + elasticbeanstalk_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/elasticsearch/service_endpoint_resolver_gen.go b/internal/service/elasticsearch/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3fdf3d9fd22 --- /dev/null +++ b/internal/service/elasticsearch/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package elasticsearch + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/elasticsearch/service_endpoints_gen_test.go b/internal/service/elasticsearch/service_endpoints_gen_test.go index a732ab343f3..296c5c1bd56 100644 --- a/internal/service/elasticsearch/service_endpoints_gen_test.go +++ b/internal/service/elasticsearch/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -90,7 +91,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -330,7 +331,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -351,12 +352,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(elasticsearchservice_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -365,17 +366,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(elasticsearchservice_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -384,7 +385,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -466,16 +467,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/elasticsearch/service_package_gen.go b/internal/service/elasticsearch/service_package_gen.go index 1e483ca6d66..40fad5395cb 100644 --- a/internal/service/elasticsearch/service_package_gen.go +++ b/internal/service/elasticsearch/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package elasticsearch @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" elasticsearchservice_sdkv1 "github.com/aws/aws-sdk-go/service/elasticsearchservice" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -74,11 +73,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return elasticsearchservice_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/elastictranscoder/service_endpoint_resolver_gen.go b/internal/service/elastictranscoder/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..4832e51953b --- /dev/null +++ b/internal/service/elastictranscoder/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package elastictranscoder + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/elastictranscoder/service_endpoints_gen_test.go b/internal/service/elastictranscoder/service_endpoints_gen_test.go index 6ad3a92103e..66486d69bb1 100644 --- a/internal/service/elastictranscoder/service_endpoints_gen_test.go +++ b/internal/service/elastictranscoder/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(elastictranscoder_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(elastictranscoder_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/elastictranscoder/service_package_gen.go b/internal/service/elastictranscoder/service_package_gen.go index 632576761a2..74c5789f3f6 100644 --- a/internal/service/elastictranscoder/service_package_gen.go +++ b/internal/service/elastictranscoder/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package elastictranscoder @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" elastictranscoder_sdkv1 "github.com/aws/aws-sdk-go/service/elastictranscoder" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -57,11 +56,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return elastictranscoder_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/elb/service_endpoint_resolver_gen.go b/internal/service/elb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..43ac900d381 --- /dev/null +++ b/internal/service/elb/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package elb + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/elb/service_endpoints_gen_test.go b/internal/service/elb/service_endpoints_gen_test.go index 39f797de522..20485ecf20a 100644 --- a/internal/service/elb/service_endpoints_gen_test.go +++ b/internal/service/elb/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -88,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -271,7 +272,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -292,12 +293,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(elb_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -306,17 +307,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(elb_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -325,7 +326,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -396,16 +397,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/elb/service_package_gen.go b/internal/service/elb/service_package_gen.go index 00111dd9313..0979859a4db 100644 --- a/internal/service/elb/service_package_gen.go +++ b/internal/service/elb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package elb @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" elb_sdkv1 "github.com/aws/aws-sdk-go/service/elb" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -102,11 +101,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return elb_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/elbv2/service_endpoint_resolver_gen.go b/internal/service/elbv2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..882ddb2aa4f --- /dev/null +++ b/internal/service/elbv2/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package elbv2 + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + elasticloadbalancingv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ elasticloadbalancingv2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver elasticloadbalancingv2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: elasticloadbalancingv2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params elasticloadbalancingv2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up elasticloadbalancingv2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*elasticloadbalancingv2_sdkv2.Options) { + return func(o *elasticloadbalancingv2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/elbv2/service_endpoints_gen_test.go b/internal/service/elbv2/service_endpoints_gen_test.go index c51b45db7ce..1cc34f7765d 100644 --- a/internal/service/elbv2/service_endpoints_gen_test.go +++ b/internal/service/elbv2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -93,7 +95,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -276,7 +278,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -309,24 +311,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := elasticloadbalancingv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), elasticloadbalancingv2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := elasticloadbalancingv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), elasticloadbalancingv2_sdkv2.EndpointParameters{ @@ -334,14 +336,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -437,16 +439,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/elbv2/service_package_gen.go b/internal/service/elbv2/service_package_gen.go index 087bcb97606..28851503a1a 100644 --- a/internal/service/elbv2/service_package_gen.go +++ b/internal/service/elbv2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package elbv2 @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" elasticloadbalancingv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" elbv2_sdkv1 "github.com/aws/aws-sdk-go/service/elbv2" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -182,11 +181,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return elbv2_sdkv1.New(sess.Copy(&cfg)), nil @@ -196,19 +192,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*elasticloadbalancingv2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return elasticloadbalancingv2_sdkv2.NewFromConfig(cfg, func(o *elasticloadbalancingv2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return elasticloadbalancingv2_sdkv2.NewFromConfig(cfg, + elasticloadbalancingv2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/emr/service_endpoint_resolver_gen.go b/internal/service/emr/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2ab4e13c2d8 --- /dev/null +++ b/internal/service/emr/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package emr + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + emr_sdkv2 "github.com/aws/aws-sdk-go-v2/service/emr" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ emr_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver emr_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: emr_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params emr_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up emr endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*emr_sdkv2.Options) { + return func(o *emr_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/emr/service_endpoints_gen_test.go b/internal/service/emr/service_endpoints_gen_test.go index a0f3a025c5b..db0da56e3d8 100644 --- a/internal/service/emr/service_endpoints_gen_test.go +++ b/internal/service/emr/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := emr_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), emr_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := emr_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), emr_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/emr/service_package_gen.go b/internal/service/emr/service_package_gen.go index db86d6e7074..43ac84ff7ac 100644 --- a/internal/service/emr/service_package_gen.go +++ b/internal/service/emr/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package emr @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" emr_sdkv2 "github.com/aws/aws-sdk-go-v2/service/emr" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" emr_sdkv1 "github.com/aws/aws-sdk-go/service/emr" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -108,11 +107,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return emr_sdkv1.New(sess.Copy(&cfg)), nil @@ -122,19 +118,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*emr_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return emr_sdkv2.NewFromConfig(cfg, func(o *emr_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return emr_sdkv2.NewFromConfig(cfg, + emr_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/emrcontainers/service_endpoint_resolver_gen.go b/internal/service/emrcontainers/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..9f03022d390 --- /dev/null +++ b/internal/service/emrcontainers/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package emrcontainers + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/emrcontainers/service_endpoints_gen_test.go b/internal/service/emrcontainers/service_endpoints_gen_test.go index 4360c641ce0..5acb2473bcd 100644 --- a/internal/service/emrcontainers/service_endpoints_gen_test.go +++ b/internal/service/emrcontainers/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(emrcontainers_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(emrcontainers_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/emrcontainers/service_package_gen.go b/internal/service/emrcontainers/service_package_gen.go index 1a4f65b054d..f247f7faa4f 100644 --- a/internal/service/emrcontainers/service_package_gen.go +++ b/internal/service/emrcontainers/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package emrcontainers @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" emrcontainers_sdkv1 "github.com/aws/aws-sdk-go/service/emrcontainers" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -70,11 +69,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*e "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return emrcontainers_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/emrserverless/service_endpoint_resolver_gen.go b/internal/service/emrserverless/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1e5a0a357fc --- /dev/null +++ b/internal/service/emrserverless/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package emrserverless + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + emrserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/emrserverless" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ emrserverless_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver emrserverless_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: emrserverless_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params emrserverless_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up emrserverless endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*emrserverless_sdkv2.Options) { + return func(o *emrserverless_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/emrserverless/service_endpoints_gen_test.go b/internal/service/emrserverless/service_endpoints_gen_test.go index 3248697ff8c..a86c2c6c35b 100644 --- a/internal/service/emrserverless/service_endpoints_gen_test.go +++ b/internal/service/emrserverless/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := emrserverless_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), emrserverless_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := emrserverless_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), emrserverless_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/emrserverless/service_package_gen.go b/internal/service/emrserverless/service_package_gen.go index ba546201fb0..92fdfd78ebd 100644 --- a/internal/service/emrserverless/service_package_gen.go +++ b/internal/service/emrserverless/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package emrserverless @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" emrserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/emrserverless" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*emrserverless_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return emrserverless_sdkv2.NewFromConfig(cfg, func(o *emrserverless_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return emrserverless_sdkv2.NewFromConfig(cfg, + emrserverless_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/events/service_endpoint_resolver_gen.go b/internal/service/events/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3506ec51991 --- /dev/null +++ b/internal/service/events/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package events + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + eventbridge_sdkv2 "github.com/aws/aws-sdk-go-v2/service/eventbridge" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ eventbridge_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver eventbridge_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: eventbridge_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params eventbridge_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up eventbridge endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*eventbridge_sdkv2.Options) { + return func(o *eventbridge_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/events/service_endpoints_gen_test.go b/internal/service/events/service_endpoints_gen_test.go index 938cab7f209..de3aa35c867 100644 --- a/internal/service/events/service_endpoints_gen_test.go +++ b/internal/service/events/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -93,7 +95,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -333,7 +335,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -354,24 +356,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := eventbridge_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), eventbridge_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := eventbridge_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), eventbridge_sdkv2.EndpointParameters{ @@ -379,14 +381,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -478,16 +480,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/events/service_package_gen.go b/internal/service/events/service_package_gen.go index 044088c642a..e0cca987a99 100644 --- a/internal/service/events/service_package_gen.go +++ b/internal/service/events/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package events @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" eventbridge_sdkv2 "github.com/aws/aws-sdk-go-v2/service/eventbridge" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -107,19 +106,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*eventbridge_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return eventbridge_sdkv2.NewFromConfig(cfg, func(o *eventbridge_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return eventbridge_sdkv2.NewFromConfig(cfg, + eventbridge_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/evidently/service_endpoint_resolver_gen.go b/internal/service/evidently/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ef4156707ad --- /dev/null +++ b/internal/service/evidently/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package evidently + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + evidently_sdkv2 "github.com/aws/aws-sdk-go-v2/service/evidently" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ evidently_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver evidently_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: evidently_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params evidently_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up evidently endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*evidently_sdkv2.Options) { + return func(o *evidently_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/evidently/service_endpoints_gen_test.go b/internal/service/evidently/service_endpoints_gen_test.go index f198cf0cf70..6d6e4e5f1c5 100644 --- a/internal/service/evidently/service_endpoints_gen_test.go +++ b/internal/service/evidently/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := evidently_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), evidently_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := evidently_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), evidently_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/evidently/service_package_gen.go b/internal/service/evidently/service_package_gen.go index 8b7b79cd644..df2ecbd1b68 100644 --- a/internal/service/evidently/service_package_gen.go +++ b/internal/service/evidently/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package evidently @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" evidently_sdkv2 "github.com/aws/aws-sdk-go-v2/service/evidently" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -72,19 +71,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*evidently_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return evidently_sdkv2.NewFromConfig(cfg, func(o *evidently_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return evidently_sdkv2.NewFromConfig(cfg, + evidently_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/finspace/service_endpoint_resolver_gen.go b/internal/service/finspace/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ee6aad2fed0 --- /dev/null +++ b/internal/service/finspace/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package finspace + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + finspace_sdkv2 "github.com/aws/aws-sdk-go-v2/service/finspace" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ finspace_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver finspace_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: finspace_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params finspace_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up finspace endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*finspace_sdkv2.Options) { + return func(o *finspace_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/finspace/service_endpoints_gen_test.go b/internal/service/finspace/service_endpoints_gen_test.go index 1483c5ecfc0..600018888c8 100644 --- a/internal/service/finspace/service_endpoints_gen_test.go +++ b/internal/service/finspace/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := finspace_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), finspace_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := finspace_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), finspace_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/finspace/service_package_gen.go b/internal/service/finspace/service_package_gen.go index b54cbb18723..a08f0926312 100644 --- a/internal/service/finspace/service_package_gen.go +++ b/internal/service/finspace/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package finspace @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" finspace_sdkv2 "github.com/aws/aws-sdk-go-v2/service/finspace" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -96,19 +95,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*finspace_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return finspace_sdkv2.NewFromConfig(cfg, func(o *finspace_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return finspace_sdkv2.NewFromConfig(cfg, + finspace_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/firehose/service_endpoint_resolver_gen.go b/internal/service/firehose/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..35ce6c8e9cf --- /dev/null +++ b/internal/service/firehose/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package firehose + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + firehose_sdkv2 "github.com/aws/aws-sdk-go-v2/service/firehose" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ firehose_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver firehose_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: firehose_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params firehose_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up firehose endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*firehose_sdkv2.Options) { + return func(o *firehose_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/firehose/service_endpoints_gen_test.go b/internal/service/firehose/service_endpoints_gen_test.go index ac99e42e4f4..43e377a9cb0 100644 --- a/internal/service/firehose/service_endpoints_gen_test.go +++ b/internal/service/firehose/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := firehose_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), firehose_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := firehose_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), firehose_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/firehose/service_package_gen.go b/internal/service/firehose/service_package_gen.go index ea996fe2382..b1de02419a0 100644 --- a/internal/service/firehose/service_package_gen.go +++ b/internal/service/firehose/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package firehose @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" firehose_sdkv2 "github.com/aws/aws-sdk-go-v2/service/firehose" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -53,19 +52,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*firehose_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return firehose_sdkv2.NewFromConfig(cfg, func(o *firehose_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return firehose_sdkv2.NewFromConfig(cfg, + firehose_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/fis/service_endpoint_resolver_gen.go b/internal/service/fis/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7d0816e8673 --- /dev/null +++ b/internal/service/fis/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package fis + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + fis_sdkv2 "github.com/aws/aws-sdk-go-v2/service/fis" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ fis_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver fis_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: fis_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params fis_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up fis endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*fis_sdkv2.Options) { + return func(o *fis_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/fis/service_endpoints_gen_test.go b/internal/service/fis/service_endpoints_gen_test.go index 26f93a45af9..42d82b4d95a 100644 --- a/internal/service/fis/service_endpoints_gen_test.go +++ b/internal/service/fis/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := fis_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), fis_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := fis_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), fis_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/fis/service_package_gen.go b/internal/service/fis/service_package_gen.go index adb7375351e..20600afce85 100644 --- a/internal/service/fis/service_package_gen.go +++ b/internal/service/fis/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package fis @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" fis_sdkv2 "github.com/aws/aws-sdk-go-v2/service/fis" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -46,19 +45,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*fis_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return fis_sdkv2.NewFromConfig(cfg, func(o *fis_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return fis_sdkv2.NewFromConfig(cfg, + fis_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/fms/service_endpoint_resolver_gen.go b/internal/service/fms/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..cdfe197026f --- /dev/null +++ b/internal/service/fms/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package fms + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + fms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/fms" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ fms_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver fms_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: fms_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params fms_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up fms endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*fms_sdkv2.Options) { + return func(o *fms_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/fms/service_endpoints_gen_test.go b/internal/service/fms/service_endpoints_gen_test.go index 50c2ba3233f..66ed0ae4db0 100644 --- a/internal/service/fms/service_endpoints_gen_test.go +++ b/internal/service/fms/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := fms_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), fms_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := fms_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), fms_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/fms/service_package.go b/internal/service/fms/service_package.go index 566bb11b215..c14bacb15eb 100644 --- a/internal/service/fms/service_package.go +++ b/internal/service/fms/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/fms" awstypes "github.com/aws/aws-sdk-go-v2/service/fms/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,29 +19,21 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*fms.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return fms.NewFromConfig(cfg, func(o *fms.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - // Acceptance testing creates and deletes resources in quick succession. - // The FMS onboarding process into Organizations is opaque to consumers. - // Since we cannot reasonably check this status before receiving the error, - // set the operation as retryable. - if errs.IsAErrorMessageContains[*awstypes.InvalidOperationException](err, "Your AWS Organization is currently onboarding with AWS Firewall Manager and cannot be offboarded") || - errs.IsAErrorMessageContains[*awstypes.InvalidOperationException](err, "Your AWS Organization is currently offboarding with AWS Firewall Manager. Please submit onboard request after offboarded") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return fms.NewFromConfig(cfg, + fms.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *fms.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + // Acceptance testing creates and deletes resources in quick succession. + // The FMS onboarding process into Organizations is opaque to consumers. + // Since we cannot reasonably check this status before receiving the error, + // set the operation as retryable. + if errs.IsAErrorMessageContains[*awstypes.InvalidOperationException](err, "Your AWS Organization is currently onboarding with AWS Firewall Manager and cannot be offboarded") || + errs.IsAErrorMessageContains[*awstypes.InvalidOperationException](err, "Your AWS Organization is currently offboarding with AWS Firewall Manager. Please submit onboard request after offboarded") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/fms/service_package_gen.go b/internal/service/fms/service_package_gen.go index 83fbd11608e..d63cf2f91a1 100644 --- a/internal/service/fms/service_package_gen.go +++ b/internal/service/fms/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package fms diff --git a/internal/service/fsx/service_endpoint_resolver_gen.go b/internal/service/fsx/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5b3ebdb7ac2 --- /dev/null +++ b/internal/service/fsx/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package fsx + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/fsx/service_endpoints_gen_test.go b/internal/service/fsx/service_endpoints_gen_test.go index 57de05fcec1..6ca13f8d7b9 100644 --- a/internal/service/fsx/service_endpoints_gen_test.go +++ b/internal/service/fsx/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(fsx_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(fsx_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/fsx/service_package_gen.go b/internal/service/fsx/service_package_gen.go index c26a77334f7..4b4ad114d64 100644 --- a/internal/service/fsx/service_package_gen.go +++ b/internal/service/fsx/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package fsx @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" fsx_sdkv1 "github.com/aws/aws-sdk-go/service/fsx" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -166,11 +165,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*f "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return fsx_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/gamelift/service_endpoint_resolver_gen.go b/internal/service/gamelift/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..74ac7d7ccab --- /dev/null +++ b/internal/service/gamelift/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package gamelift + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/gamelift/service_endpoints_gen_test.go b/internal/service/gamelift/service_endpoints_gen_test.go index 983de29fec6..beba1fc465e 100644 --- a/internal/service/gamelift/service_endpoints_gen_test.go +++ b/internal/service/gamelift/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(gamelift_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(gamelift_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/gamelift/service_package_gen.go b/internal/service/gamelift/service_package_gen.go index 150d7ffe265..92641c9fcbb 100644 --- a/internal/service/gamelift/service_package_gen.go +++ b/internal/service/gamelift/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package gamelift @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" gamelift_sdkv1 "github.com/aws/aws-sdk-go/service/gamelift" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -97,11 +96,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*g "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return gamelift_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/glacier/service_endpoint_resolver_gen.go b/internal/service/glacier/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..231b2af334a --- /dev/null +++ b/internal/service/glacier/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package glacier + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + glacier_sdkv2 "github.com/aws/aws-sdk-go-v2/service/glacier" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ glacier_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver glacier_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: glacier_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params glacier_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up glacier endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*glacier_sdkv2.Options) { + return func(o *glacier_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/glacier/service_endpoints_gen_test.go b/internal/service/glacier/service_endpoints_gen_test.go index b4d2fe7b024..1f3c37d8129 100644 --- a/internal/service/glacier/service_endpoints_gen_test.go +++ b/internal/service/glacier/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := glacier_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), glacier_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := glacier_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), glacier_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/glacier/service_package_gen.go b/internal/service/glacier/service_package_gen.go index 781609fddc9..a9c4186d699 100644 --- a/internal/service/glacier/service_package_gen.go +++ b/internal/service/glacier/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package glacier @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" glacier_sdkv2 "github.com/aws/aws-sdk-go-v2/service/glacier" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -52,19 +51,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*glacier_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return glacier_sdkv2.NewFromConfig(cfg, func(o *glacier_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return glacier_sdkv2.NewFromConfig(cfg, + glacier_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/globalaccelerator/service_endpoint_resolver_gen.go b/internal/service/globalaccelerator/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f278b6c4634 --- /dev/null +++ b/internal/service/globalaccelerator/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package globalaccelerator + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + globalaccelerator_sdkv2 "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ globalaccelerator_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver globalaccelerator_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: globalaccelerator_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params globalaccelerator_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up globalaccelerator endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*globalaccelerator_sdkv2.Options) { + return func(o *globalaccelerator_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/globalaccelerator/service_endpoints_gen_test.go b/internal/service/globalaccelerator/service_endpoints_gen_test.go index 3d082d2d207..0f3672ed127 100644 --- a/internal/service/globalaccelerator/service_endpoints_gen_test.go +++ b/internal/service/globalaccelerator/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -243,24 +245,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := globalaccelerator_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), globalaccelerator_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := globalaccelerator_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), globalaccelerator_sdkv2.EndpointParameters{ @@ -268,14 +270,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/globalaccelerator/service_package.go b/internal/service/globalaccelerator/service_package.go index 2f4a49d2f38..6627b43d968 100644 --- a/internal/service/globalaccelerator/service_package.go +++ b/internal/service/globalaccelerator/service_package.go @@ -16,22 +16,20 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*globalaccelerator.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return globalaccelerator.NewFromConfig(cfg, func(o *globalaccelerator.Options) { - if config["partition"].(string) == names.StandardPartitionID { - // Global Accelerator endpoint is only available in AWS Commercial us-west-2 Region. - o.Region = names.USWest2RegionID - } - - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled + return globalaccelerator.NewFromConfig(cfg, + globalaccelerator.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *globalaccelerator.Options) { + if config["partition"].(string) == names.StandardPartitionID { + // Global Accelerator endpoint is only available in AWS Commercial us-west-2 Region. + if cfg.Region != names.USWest2RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USWest2RegionID, + }) + o.Region = names.USWest2RegionID + } } - } - }), nil + }, + ), nil } diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index c6b631d8166..2818d999b3d 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package globalaccelerator diff --git a/internal/service/glue/service_endpoint_resolver_gen.go b/internal/service/glue/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2842a690a24 --- /dev/null +++ b/internal/service/glue/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package glue + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/glue/service_endpoints_gen_test.go b/internal/service/glue/service_endpoints_gen_test.go index af9a2c56ba1..ce4b40e444b 100644 --- a/internal/service/glue/service_endpoints_gen_test.go +++ b/internal/service/glue/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(glue_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(glue_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/glue/service_package_gen.go b/internal/service/glue/service_package_gen.go index 06d04b14b01..111dd5b979a 100644 --- a/internal/service/glue/service_package_gen.go +++ b/internal/service/glue/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package glue @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" glue_sdkv1 "github.com/aws/aws-sdk-go/service/glue" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -186,11 +185,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*g "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return glue_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/grafana/service_endpoint_resolver_gen.go b/internal/service/grafana/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2a0ee666576 --- /dev/null +++ b/internal/service/grafana/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package grafana + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/grafana/service_endpoints_gen_test.go b/internal/service/grafana/service_endpoints_gen_test.go index 1a0b1b8a698..5412815afe9 100644 --- a/internal/service/grafana/service_endpoints_gen_test.go +++ b/internal/service/grafana/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -90,7 +91,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -330,7 +331,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -351,12 +352,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(managedgrafana_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -365,17 +366,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(managedgrafana_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -384,7 +385,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -466,16 +467,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/grafana/service_package_gen.go b/internal/service/grafana/service_package_gen.go index ecdf48b4634..4df97d2ff10 100644 --- a/internal/service/grafana/service_package_gen.go +++ b/internal/service/grafana/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package grafana @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" managedgrafana_sdkv1 "github.com/aws/aws-sdk-go/service/managedgrafana" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -78,11 +77,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*m "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return managedgrafana_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/greengrass/service_endpoint_resolver_gen.go b/internal/service/greengrass/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..39bb3bc7003 --- /dev/null +++ b/internal/service/greengrass/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package greengrass + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/greengrass/service_endpoints_gen_test.go b/internal/service/greengrass/service_endpoints_gen_test.go index bca8626fb03..bf752d93c7d 100644 --- a/internal/service/greengrass/service_endpoints_gen_test.go +++ b/internal/service/greengrass/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(greengrass_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(greengrass_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/greengrass/service_package_gen.go b/internal/service/greengrass/service_package_gen.go index 8347378ae0f..9ae480b6113 100644 --- a/internal/service/greengrass/service_package_gen.go +++ b/internal/service/greengrass/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package greengrass @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" greengrass_sdkv1 "github.com/aws/aws-sdk-go/service/greengrass" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -48,11 +47,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*g "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return greengrass_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/groundstation/service_endpoint_resolver_gen.go b/internal/service/groundstation/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e449cafde9f --- /dev/null +++ b/internal/service/groundstation/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package groundstation + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + groundstation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/groundstation" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ groundstation_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver groundstation_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: groundstation_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params groundstation_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up groundstation endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*groundstation_sdkv2.Options) { + return func(o *groundstation_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/groundstation/service_endpoints_gen_test.go b/internal/service/groundstation/service_endpoints_gen_test.go index f78516cf4a0..07bff147631 100644 --- a/internal/service/groundstation/service_endpoints_gen_test.go +++ b/internal/service/groundstation/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := groundstation_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), groundstation_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := groundstation_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), groundstation_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/groundstation/service_package_gen.go b/internal/service/groundstation/service_package_gen.go index 4ce181199a4..8f6b5a5ea31 100644 --- a/internal/service/groundstation/service_package_gen.go +++ b/internal/service/groundstation/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package groundstation @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" groundstation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/groundstation" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*groundstation_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return groundstation_sdkv2.NewFromConfig(cfg, func(o *groundstation_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return groundstation_sdkv2.NewFromConfig(cfg, + groundstation_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/guardduty/service_endpoint_resolver_gen.go b/internal/service/guardduty/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..450e4f42eb5 --- /dev/null +++ b/internal/service/guardduty/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package guardduty + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + guardduty_sdkv2 "github.com/aws/aws-sdk-go-v2/service/guardduty" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ guardduty_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver guardduty_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: guardduty_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params guardduty_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up guardduty endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*guardduty_sdkv2.Options) { + return func(o *guardduty_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/guardduty/service_endpoints_gen_test.go b/internal/service/guardduty/service_endpoints_gen_test.go index 7c50f087414..5e96c6bccd7 100644 --- a/internal/service/guardduty/service_endpoints_gen_test.go +++ b/internal/service/guardduty/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := guardduty_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), guardduty_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := guardduty_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), guardduty_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/guardduty/service_package_gen.go b/internal/service/guardduty/service_package_gen.go index c8f12f08eb1..ebdc4535ff1 100644 --- a/internal/service/guardduty/service_package_gen.go +++ b/internal/service/guardduty/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package guardduty @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" guardduty_sdkv2 "github.com/aws/aws-sdk-go-v2/service/guardduty" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" guardduty_sdkv1 "github.com/aws/aws-sdk-go/service/guardduty" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -132,11 +131,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*g "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return guardduty_sdkv1.New(sess.Copy(&cfg)), nil @@ -146,19 +142,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*g func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*guardduty_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return guardduty_sdkv2.NewFromConfig(cfg, func(o *guardduty_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return guardduty_sdkv2.NewFromConfig(cfg, + guardduty_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/healthlake/service_endpoint_resolver_gen.go b/internal/service/healthlake/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..d106de30043 --- /dev/null +++ b/internal/service/healthlake/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package healthlake + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + healthlake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/healthlake" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ healthlake_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver healthlake_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: healthlake_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params healthlake_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up healthlake endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*healthlake_sdkv2.Options) { + return func(o *healthlake_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/healthlake/service_endpoints_gen_test.go b/internal/service/healthlake/service_endpoints_gen_test.go index 4042125d703..1379fbffcc0 100644 --- a/internal/service/healthlake/service_endpoints_gen_test.go +++ b/internal/service/healthlake/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := healthlake_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), healthlake_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := healthlake_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), healthlake_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/healthlake/service_package_gen.go b/internal/service/healthlake/service_package_gen.go index c9da7b7221b..46da7a8c1a7 100644 --- a/internal/service/healthlake/service_package_gen.go +++ b/internal/service/healthlake/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package healthlake @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" healthlake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/healthlake" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*healthlake_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return healthlake_sdkv2.NewFromConfig(cfg, func(o *healthlake_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return healthlake_sdkv2.NewFromConfig(cfg, + healthlake_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/iam/service_endpoint_resolver_gen.go b/internal/service/iam/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..288dd84b150 --- /dev/null +++ b/internal/service/iam/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package iam + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + iam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/iam" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ iam_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver iam_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: iam_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params iam_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up iam endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*iam_sdkv2.Options) { + return func(o *iam_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/iam/service_endpoints_gen_test.go b/internal/service/iam/service_endpoints_gen_test.go index 92581c8d922..9ce89ce14f8 100644 --- a/internal/service/iam/service_endpoints_gen_test.go +++ b/internal/service/iam/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -90,7 +92,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -330,7 +332,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -351,24 +353,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := iam_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), iam_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := iam_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), iam_sdkv2.EndpointParameters{ @@ -376,14 +378,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -453,16 +455,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/iam/service_package_gen.go b/internal/service/iam/service_package_gen.go index 38903cbb814..f199832ce96 100644 --- a/internal/service/iam/service_package_gen.go +++ b/internal/service/iam/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package iam @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" iam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/iam" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -301,19 +300,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*iam_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return iam_sdkv2.NewFromConfig(cfg, func(o *iam_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return iam_sdkv2.NewFromConfig(cfg, + iam_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/identitystore/service_endpoint_resolver_gen.go b/internal/service/identitystore/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f0ecaf695ce --- /dev/null +++ b/internal/service/identitystore/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package identitystore + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + identitystore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/identitystore" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ identitystore_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver identitystore_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: identitystore_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params identitystore_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up identitystore endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*identitystore_sdkv2.Options) { + return func(o *identitystore_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/identitystore/service_endpoints_gen_test.go b/internal/service/identitystore/service_endpoints_gen_test.go index dba9961ba82..5c4cb36e617 100644 --- a/internal/service/identitystore/service_endpoints_gen_test.go +++ b/internal/service/identitystore/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := identitystore_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), identitystore_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := identitystore_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), identitystore_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/identitystore/service_package_gen.go b/internal/service/identitystore/service_package_gen.go index d11401004bf..885caf6f0f8 100644 --- a/internal/service/identitystore/service_package_gen.go +++ b/internal/service/identitystore/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package identitystore @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" identitystore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/identitystore" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -66,19 +65,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*identitystore_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return identitystore_sdkv2.NewFromConfig(cfg, func(o *identitystore_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return identitystore_sdkv2.NewFromConfig(cfg, + identitystore_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/imagebuilder/service_endpoint_resolver_gen.go b/internal/service/imagebuilder/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..993463ab654 --- /dev/null +++ b/internal/service/imagebuilder/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package imagebuilder + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/imagebuilder/service_endpoints_gen_test.go b/internal/service/imagebuilder/service_endpoints_gen_test.go index 703d471eeb7..92339031efa 100644 --- a/internal/service/imagebuilder/service_endpoints_gen_test.go +++ b/internal/service/imagebuilder/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,14 +239,14 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(imagebuilder_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.ResolveUnknownService = true }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -254,10 +255,10 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(imagebuilder_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { @@ -265,7 +266,7 @@ func defaultFIPSEndpoint(region string) string { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -274,7 +275,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -326,16 +327,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/imagebuilder/service_package_gen.go b/internal/service/imagebuilder/service_package_gen.go index 3802c9e9348..fde42af5d3c 100644 --- a/internal/service/imagebuilder/service_package_gen.go +++ b/internal/service/imagebuilder/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package imagebuilder @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" imagebuilder_sdkv1 "github.com/aws/aws-sdk-go/service/imagebuilder" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -169,11 +168,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*i "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return imagebuilder_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/inspector/service_endpoint_resolver_gen.go b/internal/service/inspector/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ec8bc211f5b --- /dev/null +++ b/internal/service/inspector/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package inspector + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/inspector/service_endpoints_gen_test.go b/internal/service/inspector/service_endpoints_gen_test.go index ed15776d1ac..4c24b3db9a6 100644 --- a/internal/service/inspector/service_endpoints_gen_test.go +++ b/internal/service/inspector/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(inspector_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(inspector_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/inspector/service_package_gen.go b/internal/service/inspector/service_package_gen.go index 59c6d61a624..060b15894db 100644 --- a/internal/service/inspector/service_package_gen.go +++ b/internal/service/inspector/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package inspector @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" inspector_sdkv1 "github.com/aws/aws-sdk-go/service/inspector" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -70,11 +69,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*i "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return inspector_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/inspector2/service_endpoint_resolver_gen.go b/internal/service/inspector2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f01799d5882 --- /dev/null +++ b/internal/service/inspector2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package inspector2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + inspector2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/inspector2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ inspector2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver inspector2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: inspector2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params inspector2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up inspector2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*inspector2_sdkv2.Options) { + return func(o *inspector2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/inspector2/service_endpoints_gen_test.go b/internal/service/inspector2/service_endpoints_gen_test.go index 6cc4911c2ed..69c9102c477 100644 --- a/internal/service/inspector2/service_endpoints_gen_test.go +++ b/internal/service/inspector2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := inspector2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), inspector2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := inspector2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), inspector2_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/inspector2/service_package_gen.go b/internal/service/inspector2/service_package_gen.go index f2a7d4ce7ac..70f40d55f18 100644 --- a/internal/service/inspector2/service_package_gen.go +++ b/internal/service/inspector2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package inspector2 @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" inspector2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/inspector2" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*inspector2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return inspector2_sdkv2.NewFromConfig(cfg, func(o *inspector2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return inspector2_sdkv2.NewFromConfig(cfg, + inspector2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/internetmonitor/service_endpoint_resolver_gen.go b/internal/service/internetmonitor/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2585620b6e9 --- /dev/null +++ b/internal/service/internetmonitor/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package internetmonitor + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + internetmonitor_sdkv2 "github.com/aws/aws-sdk-go-v2/service/internetmonitor" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ internetmonitor_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver internetmonitor_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: internetmonitor_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params internetmonitor_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up internetmonitor endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*internetmonitor_sdkv2.Options) { + return func(o *internetmonitor_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/internetmonitor/service_endpoints_gen_test.go b/internal/service/internetmonitor/service_endpoints_gen_test.go index bccb4c3a2c7..136c0a13823 100644 --- a/internal/service/internetmonitor/service_endpoints_gen_test.go +++ b/internal/service/internetmonitor/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := internetmonitor_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), internetmonitor_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := internetmonitor_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), internetmonitor_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/internetmonitor/service_package_gen.go b/internal/service/internetmonitor/service_package_gen.go index 26967a5fd53..28fe340ad32 100644 --- a/internal/service/internetmonitor/service_package_gen.go +++ b/internal/service/internetmonitor/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package internetmonitor @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" internetmonitor_sdkv2 "github.com/aws/aws-sdk-go-v2/service/internetmonitor" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*internetmonitor_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return internetmonitor_sdkv2.NewFromConfig(cfg, func(o *internetmonitor_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return internetmonitor_sdkv2.NewFromConfig(cfg, + internetmonitor_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/iot/service_endpoint_resolver_gen.go b/internal/service/iot/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1c58dedd2e2 --- /dev/null +++ b/internal/service/iot/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package iot + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/iot/service_endpoints_gen_test.go b/internal/service/iot/service_endpoints_gen_test.go index 295d520f32c..0877228e5f6 100644 --- a/internal/service/iot/service_endpoints_gen_test.go +++ b/internal/service/iot/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(iot_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(iot_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/iot/service_package_gen.go b/internal/service/iot/service_package_gen.go index c46e92fe61c..1b2c040fee8 100644 --- a/internal/service/iot/service_package_gen.go +++ b/internal/service/iot/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package iot @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" iot_sdkv1 "github.com/aws/aws-sdk-go/service/iot" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -171,11 +170,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*i "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return iot_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/iotanalytics/service_endpoint_resolver_gen.go b/internal/service/iotanalytics/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..feff5a3440d --- /dev/null +++ b/internal/service/iotanalytics/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package iotanalytics + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/iotanalytics/service_endpoints_gen_test.go b/internal/service/iotanalytics/service_endpoints_gen_test.go index 23a2618e356..43266b58965 100644 --- a/internal/service/iotanalytics/service_endpoints_gen_test.go +++ b/internal/service/iotanalytics/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(iotanalytics_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(iotanalytics_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/iotanalytics/service_package_gen.go b/internal/service/iotanalytics/service_package_gen.go index 2c067beb601..0bf9e8a5e0f 100644 --- a/internal/service/iotanalytics/service_package_gen.go +++ b/internal/service/iotanalytics/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package iotanalytics @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" iotanalytics_sdkv1 "github.com/aws/aws-sdk-go/service/iotanalytics" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -48,11 +47,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*i "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return iotanalytics_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/iotevents/service_endpoint_resolver_gen.go b/internal/service/iotevents/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..8848888c5d6 --- /dev/null +++ b/internal/service/iotevents/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package iotevents + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/iotevents/service_endpoints_gen_test.go b/internal/service/iotevents/service_endpoints_gen_test.go index ab177d881a6..deb66f9606d 100644 --- a/internal/service/iotevents/service_endpoints_gen_test.go +++ b/internal/service/iotevents/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(iotevents_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(iotevents_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/iotevents/service_package_gen.go b/internal/service/iotevents/service_package_gen.go index 903ee5c35e7..bd734ea2837 100644 --- a/internal/service/iotevents/service_package_gen.go +++ b/internal/service/iotevents/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package iotevents @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" iotevents_sdkv1 "github.com/aws/aws-sdk-go/service/iotevents" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -48,11 +47,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*i "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return iotevents_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/ivs/service_endpoint_resolver_gen.go b/internal/service/ivs/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3c733fde680 --- /dev/null +++ b/internal/service/ivs/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ivs + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/ivs/service_endpoints_gen_test.go b/internal/service/ivs/service_endpoints_gen_test.go index 6c3a50cb6e5..780ee904757 100644 --- a/internal/service/ivs/service_endpoints_gen_test.go +++ b/internal/service/ivs/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(ivs_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(ivs_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ivs/service_package_gen.go b/internal/service/ivs/service_package_gen.go index cb60aae4161..04946040bcd 100644 --- a/internal/service/ivs/service_package_gen.go +++ b/internal/service/ivs/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ivs @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" ivs_sdkv1 "github.com/aws/aws-sdk-go/service/ivs" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -78,11 +77,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*i "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return ivs_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/ivschat/service_endpoint_resolver_gen.go b/internal/service/ivschat/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..846167405ce --- /dev/null +++ b/internal/service/ivschat/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ivschat + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ivschat_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ivschat" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ivschat_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ivschat_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ivschat_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ivschat_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ivschat endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ivschat_sdkv2.Options) { + return func(o *ivschat_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ivschat/service_endpoints_gen_test.go b/internal/service/ivschat/service_endpoints_gen_test.go index f194bc35a51..ce933e468d5 100644 --- a/internal/service/ivschat/service_endpoints_gen_test.go +++ b/internal/service/ivschat/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ivschat_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ivschat_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ivschat_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ivschat_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ivschat/service_package_gen.go b/internal/service/ivschat/service_package_gen.go index e56bc6927ce..e5309be335e 100644 --- a/internal/service/ivschat/service_package_gen.go +++ b/internal/service/ivschat/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ivschat @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ivschat_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ivschat" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ivschat_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ivschat_sdkv2.NewFromConfig(cfg, func(o *ivschat_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ivschat_sdkv2.NewFromConfig(cfg, + ivschat_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/kafka/service_endpoint_resolver_gen.go b/internal/service/kafka/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..8b1b945be3f --- /dev/null +++ b/internal/service/kafka/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kafka + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + kafka_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kafka" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ kafka_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver kafka_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: kafka_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params kafka_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up kafka endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*kafka_sdkv2.Options) { + return func(o *kafka_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/kafka/service_endpoints_gen_test.go b/internal/service/kafka/service_endpoints_gen_test.go index f975264656d..1d7e1653858 100644 --- a/internal/service/kafka/service_endpoints_gen_test.go +++ b/internal/service/kafka/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := kafka_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kafka_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := kafka_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kafka_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kafka/service_package.go b/internal/service/kafka/service_package.go index 0f4215efd87..7fb8e126004 100644 --- a/internal/service/kafka/service_package.go +++ b/internal/service/kafka/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/kafka" "github.com/aws/aws-sdk-go-v2/service/kafka/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*kafka.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return kafka.NewFromConfig(cfg, func(o *kafka.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*types.TooManyRequestsException](err, "Too Many Requests") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return kafka.NewFromConfig(cfg, + kafka.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *kafka.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*types.TooManyRequestsException](err, "Too Many Requests") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/kafka/service_package_gen.go b/internal/service/kafka/service_package_gen.go index 4b03e87d8f1..f4d8944fa3d 100644 --- a/internal/service/kafka/service_package_gen.go +++ b/internal/service/kafka/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kafka diff --git a/internal/service/kafkaconnect/service_endpoint_resolver_gen.go b/internal/service/kafkaconnect/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..07d2eb7068a --- /dev/null +++ b/internal/service/kafkaconnect/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kafkaconnect + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/kafkaconnect/service_endpoints_gen_test.go b/internal/service/kafkaconnect/service_endpoints_gen_test.go index 724ce8ef02b..fccafb6be6a 100644 --- a/internal/service/kafkaconnect/service_endpoints_gen_test.go +++ b/internal/service/kafkaconnect/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kafkaconnect_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kafkaconnect_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kafkaconnect/service_package_gen.go b/internal/service/kafkaconnect/service_package_gen.go index cec5bb0353f..034abdf10f6 100644 --- a/internal/service/kafkaconnect/service_package_gen.go +++ b/internal/service/kafkaconnect/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kafkaconnect @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" kafkaconnect_sdkv1 "github.com/aws/aws-sdk-go/service/kafkaconnect" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -74,11 +73,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*k "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return kafkaconnect_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/kendra/service_endpoint_resolver_gen.go b/internal/service/kendra/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ebaa1cc8ade --- /dev/null +++ b/internal/service/kendra/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kendra + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + kendra_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kendra" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ kendra_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver kendra_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: kendra_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params kendra_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up kendra endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*kendra_sdkv2.Options) { + return func(o *kendra_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/kendra/service_endpoints_gen_test.go b/internal/service/kendra/service_endpoints_gen_test.go index b0215e83ee9..ad68216be65 100644 --- a/internal/service/kendra/service_endpoints_gen_test.go +++ b/internal/service/kendra/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := kendra_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kendra_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := kendra_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kendra_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kendra/service_package_gen.go b/internal/service/kendra/service_package_gen.go index eac1dec1b5b..9020eca3fb0 100644 --- a/internal/service/kendra/service_package_gen.go +++ b/internal/service/kendra/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kendra @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" kendra_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kendra" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -105,19 +104,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*kendra_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return kendra_sdkv2.NewFromConfig(cfg, func(o *kendra_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return kendra_sdkv2.NewFromConfig(cfg, + kendra_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/keyspaces/service_endpoint_resolver_gen.go b/internal/service/keyspaces/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..d0ffb20e630 --- /dev/null +++ b/internal/service/keyspaces/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package keyspaces + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + keyspaces_sdkv2 "github.com/aws/aws-sdk-go-v2/service/keyspaces" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ keyspaces_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver keyspaces_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: keyspaces_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params keyspaces_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up keyspaces endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*keyspaces_sdkv2.Options) { + return func(o *keyspaces_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/keyspaces/service_endpoints_gen_test.go b/internal/service/keyspaces/service_endpoints_gen_test.go index 042ef58b3b7..a06e2d15149 100644 --- a/internal/service/keyspaces/service_endpoints_gen_test.go +++ b/internal/service/keyspaces/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := keyspaces_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), keyspaces_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := keyspaces_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), keyspaces_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/keyspaces/service_package_gen.go b/internal/service/keyspaces/service_package_gen.go index ff026cfdf27..552afe84e43 100644 --- a/internal/service/keyspaces/service_package_gen.go +++ b/internal/service/keyspaces/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package keyspaces @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" keyspaces_sdkv2 "github.com/aws/aws-sdk-go-v2/service/keyspaces" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*keyspaces_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return keyspaces_sdkv2.NewFromConfig(cfg, func(o *keyspaces_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return keyspaces_sdkv2.NewFromConfig(cfg, + keyspaces_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/kinesis/service_endpoint_resolver_gen.go b/internal/service/kinesis/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..155859018d3 --- /dev/null +++ b/internal/service/kinesis/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kinesis + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + kinesis_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kinesis" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ kinesis_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver kinesis_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: kinesis_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params kinesis_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up kinesis endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*kinesis_sdkv2.Options) { + return func(o *kinesis_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/kinesis/service_endpoints_gen_test.go b/internal/service/kinesis/service_endpoints_gen_test.go index 7ece10b9de7..1bea3dd2a85 100644 --- a/internal/service/kinesis/service_endpoints_gen_test.go +++ b/internal/service/kinesis/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := kinesis_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kinesis_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := kinesis_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kinesis_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kinesis/service_package.go b/internal/service/kinesis/service_package.go index 2b37994c6ae..b5998e7c503 100644 --- a/internal/service/kinesis/service_package.go +++ b/internal/service/kinesis/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/kinesis" "github.com/aws/aws-sdk-go-v2/service/kinesis/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,25 +19,17 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*kinesis.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return kinesis.NewFromConfig(cfg, func(o *kinesis.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*types.LimitExceededException](err, "simultaneously be in CREATING or DELETING") || - errs.IsAErrorMessageContains[*types.LimitExceededException](err, "Rate exceeded for stream") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return kinesis.NewFromConfig(cfg, + kinesis.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *kinesis.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*types.LimitExceededException](err, "simultaneously be in CREATING or DELETING") || + errs.IsAErrorMessageContains[*types.LimitExceededException](err, "Rate exceeded for stream") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/kinesis/service_package_gen.go b/internal/service/kinesis/service_package_gen.go index 197c86439d7..f5630118e42 100644 --- a/internal/service/kinesis/service_package_gen.go +++ b/internal/service/kinesis/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kinesis diff --git a/internal/service/kinesisanalytics/service_endpoint_resolver_gen.go b/internal/service/kinesisanalytics/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7de61f347e2 --- /dev/null +++ b/internal/service/kinesisanalytics/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kinesisanalytics + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/kinesisanalytics/service_endpoints_gen_test.go b/internal/service/kinesisanalytics/service_endpoints_gen_test.go index 86db9141a85..4bb1de4390d 100644 --- a/internal/service/kinesisanalytics/service_endpoints_gen_test.go +++ b/internal/service/kinesisanalytics/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kinesisanalytics_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kinesisanalytics_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kinesisanalytics/service_package_gen.go b/internal/service/kinesisanalytics/service_package_gen.go index 16adb1a7b29..836090a3138 100644 --- a/internal/service/kinesisanalytics/service_package_gen.go +++ b/internal/service/kinesisanalytics/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kinesisanalytics @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" kinesisanalytics_sdkv1 "github.com/aws/aws-sdk-go/service/kinesisanalytics" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -57,11 +56,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*k "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return kinesisanalytics_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/kinesisanalyticsv2/service_endpoint_resolver_gen.go b/internal/service/kinesisanalyticsv2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..574bb9239ad --- /dev/null +++ b/internal/service/kinesisanalyticsv2/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kinesisanalyticsv2 + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/kinesisanalyticsv2/service_endpoints_gen_test.go b/internal/service/kinesisanalyticsv2/service_endpoints_gen_test.go index c4f950700b0..c91cc9c7cd4 100644 --- a/internal/service/kinesisanalyticsv2/service_endpoints_gen_test.go +++ b/internal/service/kinesisanalyticsv2/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kinesisanalyticsv2_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kinesisanalyticsv2_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kinesisanalyticsv2/service_package_gen.go b/internal/service/kinesisanalyticsv2/service_package_gen.go index c1ea138868c..596d26624ea 100644 --- a/internal/service/kinesisanalyticsv2/service_package_gen.go +++ b/internal/service/kinesisanalyticsv2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kinesisanalyticsv2 @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" kinesisanalyticsv2_sdkv1 "github.com/aws/aws-sdk-go/service/kinesisanalyticsv2" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -61,11 +60,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*k "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return kinesisanalyticsv2_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/kinesisvideo/service_endpoint_resolver_gen.go b/internal/service/kinesisvideo/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ae5852d4d0f --- /dev/null +++ b/internal/service/kinesisvideo/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kinesisvideo + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/kinesisvideo/service_endpoints_gen_test.go b/internal/service/kinesisvideo/service_endpoints_gen_test.go index ad3f34d0152..a2e86632759 100644 --- a/internal/service/kinesisvideo/service_endpoints_gen_test.go +++ b/internal/service/kinesisvideo/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kinesisvideo_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(kinesisvideo_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kinesisvideo/service_package_gen.go b/internal/service/kinesisvideo/service_package_gen.go index cb330cdcca5..d5d795bf37e 100644 --- a/internal/service/kinesisvideo/service_package_gen.go +++ b/internal/service/kinesisvideo/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kinesisvideo @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" kinesisvideo_sdkv1 "github.com/aws/aws-sdk-go/service/kinesisvideo" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -57,11 +56,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*k "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return kinesisvideo_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/kms/service_endpoint_resolver_gen.go b/internal/service/kms/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3d191ecadc8 --- /dev/null +++ b/internal/service/kms/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package kms + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + kms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kms" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ kms_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver kms_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: kms_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params kms_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up kms endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*kms_sdkv2.Options) { + return func(o *kms_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/kms/service_endpoints_gen_test.go b/internal/service/kms/service_endpoints_gen_test.go index eec0c8504f5..f9af45871de 100644 --- a/internal/service/kms/service_endpoints_gen_test.go +++ b/internal/service/kms/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := kms_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kms_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := kms_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), kms_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/kms/service_package_gen.go b/internal/service/kms/service_package_gen.go index ce0288cfe09..012e16b31ba 100644 --- a/internal/service/kms/service_package_gen.go +++ b/internal/service/kms/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package kms @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" kms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kms" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -133,19 +132,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*kms_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return kms_sdkv2.NewFromConfig(cfg, func(o *kms_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return kms_sdkv2.NewFromConfig(cfg, + kms_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/lakeformation/service_endpoint_resolver_gen.go b/internal/service/lakeformation/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..9da1ed421d4 --- /dev/null +++ b/internal/service/lakeformation/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package lakeformation + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + lakeformation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lakeformation" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ lakeformation_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver lakeformation_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: lakeformation_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params lakeformation_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up lakeformation endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*lakeformation_sdkv2.Options) { + return func(o *lakeformation_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/lakeformation/service_endpoints_gen_test.go b/internal/service/lakeformation/service_endpoints_gen_test.go index 824ef9ca1e5..5eaebb3a8b2 100644 --- a/internal/service/lakeformation/service_endpoints_gen_test.go +++ b/internal/service/lakeformation/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := lakeformation_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lakeformation_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := lakeformation_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lakeformation_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/lakeformation/service_package_gen.go b/internal/service/lakeformation/service_package_gen.go index 7faed1d4374..b979bbfdeff 100644 --- a/internal/service/lakeformation/service_package_gen.go +++ b/internal/service/lakeformation/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package lakeformation @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" lakeformation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lakeformation" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -83,19 +82,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*lakeformation_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return lakeformation_sdkv2.NewFromConfig(cfg, func(o *lakeformation_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return lakeformation_sdkv2.NewFromConfig(cfg, + lakeformation_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/lambda/service_endpoint_resolver_gen.go b/internal/service/lambda/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..eddf02e25ce --- /dev/null +++ b/internal/service/lambda/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package lambda + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + lambda_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lambda" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ lambda_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver lambda_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: lambda_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params lambda_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up lambda endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*lambda_sdkv2.Options) { + return func(o *lambda_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/lambda/service_endpoints_gen_test.go b/internal/service/lambda/service_endpoints_gen_test.go index 390b3dc2a6e..e215a4b7cd5 100644 --- a/internal/service/lambda/service_endpoints_gen_test.go +++ b/internal/service/lambda/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := lambda_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lambda_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := lambda_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lambda_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/lambda/service_package_gen.go b/internal/service/lambda/service_package_gen.go index 6b8ecf2c57f..95c6c04302f 100644 --- a/internal/service/lambda/service_package_gen.go +++ b/internal/service/lambda/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package lambda @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" lambda_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lambda" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -139,19 +138,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*lambda_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return lambda_sdkv2.NewFromConfig(cfg, func(o *lambda_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return lambda_sdkv2.NewFromConfig(cfg, + lambda_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/launchwizard/service_endpoint_resolver_gen.go b/internal/service/launchwizard/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..05074f34636 --- /dev/null +++ b/internal/service/launchwizard/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package launchwizard + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + launchwizard_sdkv2 "github.com/aws/aws-sdk-go-v2/service/launchwizard" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ launchwizard_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver launchwizard_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: launchwizard_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params launchwizard_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up launchwizard endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*launchwizard_sdkv2.Options) { + return func(o *launchwizard_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/launchwizard/service_endpoints_gen_test.go b/internal/service/launchwizard/service_endpoints_gen_test.go index 2cd8acf5877..9cd14d75958 100644 --- a/internal/service/launchwizard/service_endpoints_gen_test.go +++ b/internal/service/launchwizard/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := launchwizard_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), launchwizard_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := launchwizard_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), launchwizard_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/launchwizard/service_package_gen.go b/internal/service/launchwizard/service_package_gen.go index e6297e0e65e..7686a7cb4f2 100644 --- a/internal/service/launchwizard/service_package_gen.go +++ b/internal/service/launchwizard/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package launchwizard @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" launchwizard_sdkv2 "github.com/aws/aws-sdk-go-v2/service/launchwizard" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*launchwizard_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return launchwizard_sdkv2.NewFromConfig(cfg, func(o *launchwizard_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return launchwizard_sdkv2.NewFromConfig(cfg, + launchwizard_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/lexmodels/service_endpoint_resolver_gen.go b/internal/service/lexmodels/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..19a0b4e67d6 --- /dev/null +++ b/internal/service/lexmodels/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package lexmodels + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/lexmodels/service_endpoints_gen_test.go b/internal/service/lexmodels/service_endpoints_gen_test.go index d97c9aa1d2d..d448db96621 100644 --- a/internal/service/lexmodels/service_endpoints_gen_test.go +++ b/internal/service/lexmodels/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -92,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -397,7 +398,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -418,12 +419,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(lexmodelbuildingservice_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -432,17 +433,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(lexmodelbuildingservice_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -451,7 +452,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -544,16 +545,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/lexmodels/service_package_gen.go b/internal/service/lexmodels/service_package_gen.go index b2f22abb466..24a05ab7c65 100644 --- a/internal/service/lexmodels/service_package_gen.go +++ b/internal/service/lexmodels/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package lexmodels @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" lexmodelbuildingservice_sdkv1 "github.com/aws/aws-sdk-go/service/lexmodelbuildingservice" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -82,11 +81,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*l "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return lexmodelbuildingservice_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/lexv2models/service_endpoint_resolver_gen.go b/internal/service/lexv2models/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..58668959901 --- /dev/null +++ b/internal/service/lexv2models/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package lexv2models + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + lexmodelsv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lexmodelsv2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ lexmodelsv2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver lexmodelsv2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: lexmodelsv2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params lexmodelsv2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up lexmodelsv2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*lexmodelsv2_sdkv2.Options) { + return func(o *lexmodelsv2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/lexv2models/service_endpoints_gen_test.go b/internal/service/lexv2models/service_endpoints_gen_test.go index 9ca31a16198..f707e8ab3f0 100644 --- a/internal/service/lexv2models/service_endpoints_gen_test.go +++ b/internal/service/lexv2models/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := lexmodelsv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lexmodelsv2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := lexmodelsv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lexmodelsv2_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/lexv2models/service_package_gen.go b/internal/service/lexv2models/service_package_gen.go index 23dc130aff5..5e59cad211b 100644 --- a/internal/service/lexv2models/service_package_gen.go +++ b/internal/service/lexv2models/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package lexv2models @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" lexmodelsv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lexmodelsv2" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -67,19 +66,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*lexmodelsv2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return lexmodelsv2_sdkv2.NewFromConfig(cfg, func(o *lexmodelsv2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return lexmodelsv2_sdkv2.NewFromConfig(cfg, + lexmodelsv2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/licensemanager/service_endpoint_resolver_gen.go b/internal/service/licensemanager/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3a5ae337f3e --- /dev/null +++ b/internal/service/licensemanager/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package licensemanager + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/licensemanager/service_endpoints_gen_test.go b/internal/service/licensemanager/service_endpoints_gen_test.go index 4d4805ea78c..922adbb20a2 100644 --- a/internal/service/licensemanager/service_endpoints_gen_test.go +++ b/internal/service/licensemanager/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(licensemanager_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(licensemanager_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/licensemanager/service_package_gen.go b/internal/service/licensemanager/service_package_gen.go index 7b7774e5563..0aaf7b0a0df 100644 --- a/internal/service/licensemanager/service_package_gen.go +++ b/internal/service/licensemanager/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package licensemanager @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" licensemanager_sdkv1 "github.com/aws/aws-sdk-go/service/licensemanager" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -82,11 +81,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*l "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return licensemanager_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/lightsail/service_endpoint_resolver_gen.go b/internal/service/lightsail/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b8945a34e37 --- /dev/null +++ b/internal/service/lightsail/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package lightsail + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + lightsail_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lightsail" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ lightsail_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver lightsail_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: lightsail_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params lightsail_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up lightsail endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*lightsail_sdkv2.Options) { + return func(o *lightsail_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/lightsail/service_endpoints_gen_test.go b/internal/service/lightsail/service_endpoints_gen_test.go index b40e5c127f9..e0935d7b360 100644 --- a/internal/service/lightsail/service_endpoints_gen_test.go +++ b/internal/service/lightsail/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := lightsail_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lightsail_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := lightsail_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lightsail_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/lightsail/service_package.go b/internal/service/lightsail/service_package.go index 30a7f5e51c7..9741b0aba11 100644 --- a/internal/service/lightsail/service_package.go +++ b/internal/service/lightsail/service_package.go @@ -8,38 +8,29 @@ import ( "strings" "github.com/aws/aws-sdk-go-v2/aws" - retry_sdkv2 "github.com/aws/aws-sdk-go-v2/aws/retry" - lightsail_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lightsail" + "github.com/aws/aws-sdk-go-v2/aws/retry" + "github.com/aws/aws-sdk-go-v2/service/lightsail" "github.com/aws/aws-sdk-go-v2/service/lightsail/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" ) // NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. -func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*lightsail_sdkv2.Client, error) { +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*lightsail.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return lightsail_sdkv2.NewFromConfig(cfg, func(o *lightsail_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry_sdkv2.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*types.InvalidInputException](err, "Please try again in a few minutes") || - strings.Contains(err.Error(), "Please wait for it to complete before trying again") { - return aws.TrueTernary - } - return aws.UnknownTernary - })) - }), nil + return lightsail.NewFromConfig(cfg, + lightsail.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *lightsail.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*types.InvalidInputException](err, "Please try again in a few minutes") || + strings.Contains(err.Error(), "Please wait for it to complete before trying again") { + return aws.TrueTernary + } + return aws.UnknownTernary + })) + }, + ), nil } diff --git a/internal/service/lightsail/service_package_gen.go b/internal/service/lightsail/service_package_gen.go index fbf365a40bb..e72ecd67fb6 100644 --- a/internal/service/lightsail/service_package_gen.go +++ b/internal/service/lightsail/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package lightsail diff --git a/internal/service/location/service_endpoint_resolver_gen.go b/internal/service/location/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7c02b5ed93d --- /dev/null +++ b/internal/service/location/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package location + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/location/service_endpoints_gen_test.go b/internal/service/location/service_endpoints_gen_test.go index 8c28d7cd1fc..abf128b75d8 100644 --- a/internal/service/location/service_endpoints_gen_test.go +++ b/internal/service/location/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -88,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -271,7 +272,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -292,12 +293,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(locationservice_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -306,17 +307,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(locationservice_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -325,7 +326,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -396,16 +397,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/location/service_package_gen.go b/internal/service/location/service_package_gen.go index 15286e23f3c..0d9cfacbfd2 100644 --- a/internal/service/location/service_package_gen.go +++ b/internal/service/location/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package location @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" locationservice_sdkv1 "github.com/aws/aws-sdk-go/service/locationservice" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -122,11 +121,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*l "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return locationservice_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/logs/service_endpoint_resolver_gen.go b/internal/service/logs/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ad3874557d0 --- /dev/null +++ b/internal/service/logs/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package logs + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + cloudwatchlogs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ cloudwatchlogs_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver cloudwatchlogs_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: cloudwatchlogs_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params cloudwatchlogs_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up cloudwatchlogs endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*cloudwatchlogs_sdkv2.Options) { + return func(o *cloudwatchlogs_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/logs/service_endpoints_gen_test.go b/internal/service/logs/service_endpoints_gen_test.go index a8e19038888..3e9d2e98aef 100644 --- a/internal/service/logs/service_endpoints_gen_test.go +++ b/internal/service/logs/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -93,7 +95,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -333,7 +335,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -354,24 +356,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := cloudwatchlogs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudwatchlogs_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := cloudwatchlogs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), cloudwatchlogs_sdkv2.EndpointParameters{ @@ -379,14 +381,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -478,16 +480,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/logs/service_package_gen.go b/internal/service/logs/service_package_gen.go index d5bae8ead4d..acd6ed1884f 100644 --- a/internal/service/logs/service_package_gen.go +++ b/internal/service/logs/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package logs @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" cloudwatchlogs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -101,19 +100,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*cloudwatchlogs_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return cloudwatchlogs_sdkv2.NewFromConfig(cfg, func(o *cloudwatchlogs_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return cloudwatchlogs_sdkv2.NewFromConfig(cfg, + cloudwatchlogs_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/lookoutmetrics/service_endpoint_resolver_gen.go b/internal/service/lookoutmetrics/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..4bba23d3d1d --- /dev/null +++ b/internal/service/lookoutmetrics/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package lookoutmetrics + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + lookoutmetrics_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lookoutmetrics" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ lookoutmetrics_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver lookoutmetrics_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: lookoutmetrics_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params lookoutmetrics_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up lookoutmetrics endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*lookoutmetrics_sdkv2.Options) { + return func(o *lookoutmetrics_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/lookoutmetrics/service_endpoints_gen_test.go b/internal/service/lookoutmetrics/service_endpoints_gen_test.go index c954b142066..668ef9f66d8 100644 --- a/internal/service/lookoutmetrics/service_endpoints_gen_test.go +++ b/internal/service/lookoutmetrics/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := lookoutmetrics_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lookoutmetrics_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := lookoutmetrics_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), lookoutmetrics_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/lookoutmetrics/service_package_gen.go b/internal/service/lookoutmetrics/service_package_gen.go index 6dd911d0b22..589afbfc397 100644 --- a/internal/service/lookoutmetrics/service_package_gen.go +++ b/internal/service/lookoutmetrics/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package lookoutmetrics @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" lookoutmetrics_sdkv2 "github.com/aws/aws-sdk-go-v2/service/lookoutmetrics" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*lookoutmetrics_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return lookoutmetrics_sdkv2.NewFromConfig(cfg, func(o *lookoutmetrics_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return lookoutmetrics_sdkv2.NewFromConfig(cfg, + lookoutmetrics_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/m2/service_endpoint_resolver_gen.go b/internal/service/m2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b02504b1580 --- /dev/null +++ b/internal/service/m2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package m2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + m2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/m2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ m2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver m2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: m2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params m2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up m2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*m2_sdkv2.Options) { + return func(o *m2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/m2/service_endpoints_gen_test.go b/internal/service/m2/service_endpoints_gen_test.go index fc2224ae028..3fe928c2ec9 100644 --- a/internal/service/m2/service_endpoints_gen_test.go +++ b/internal/service/m2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := m2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), m2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := m2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), m2_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/m2/service_package_gen.go b/internal/service/m2/service_package_gen.go index d69b95704e2..5d730add214 100644 --- a/internal/service/m2/service_package_gen.go +++ b/internal/service/m2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package m2 @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" m2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/m2" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -58,19 +57,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*m2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return m2_sdkv2.NewFromConfig(cfg, func(o *m2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return m2_sdkv2.NewFromConfig(cfg, + m2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/macie2/service_endpoint_resolver_gen.go b/internal/service/macie2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..951f8e931d2 --- /dev/null +++ b/internal/service/macie2/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package macie2 + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/macie2/service_endpoints_gen_test.go b/internal/service/macie2/service_endpoints_gen_test.go index 044f0d68313..f2ad02f5d18 100644 --- a/internal/service/macie2/service_endpoints_gen_test.go +++ b/internal/service/macie2/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(macie2_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(macie2_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/macie2/service_package_gen.go b/internal/service/macie2/service_package_gen.go index c59dc5236ff..eae4bd32aee 100644 --- a/internal/service/macie2/service_package_gen.go +++ b/internal/service/macie2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package macie2 @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" macie2_sdkv1 "github.com/aws/aws-sdk-go/service/macie2" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -89,11 +88,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*m "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return macie2_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/mediaconnect/service_endpoint_resolver_gen.go b/internal/service/mediaconnect/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..edce80ae4b4 --- /dev/null +++ b/internal/service/mediaconnect/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package mediaconnect + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mediaconnect_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediaconnect" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ mediaconnect_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver mediaconnect_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: mediaconnect_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params mediaconnect_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up mediaconnect endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*mediaconnect_sdkv2.Options) { + return func(o *mediaconnect_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/mediaconnect/service_endpoints_gen_test.go b/internal/service/mediaconnect/service_endpoints_gen_test.go index a1818cb2713..f78b29f92bf 100644 --- a/internal/service/mediaconnect/service_endpoints_gen_test.go +++ b/internal/service/mediaconnect/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := mediaconnect_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediaconnect_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := mediaconnect_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediaconnect_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/mediaconnect/service_package_gen.go b/internal/service/mediaconnect/service_package_gen.go index d7ff980f452..20f3febc209 100644 --- a/internal/service/mediaconnect/service_package_gen.go +++ b/internal/service/mediaconnect/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package mediaconnect @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" mediaconnect_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediaconnect" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mediaconnect_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mediaconnect_sdkv2.NewFromConfig(cfg, func(o *mediaconnect_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return mediaconnect_sdkv2.NewFromConfig(cfg, + mediaconnect_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/mediaconvert/service_endpoint_resolver_gen.go b/internal/service/mediaconvert/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f18489f36d9 --- /dev/null +++ b/internal/service/mediaconvert/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package mediaconvert + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mediaconvert_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediaconvert" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ mediaconvert_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver mediaconvert_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: mediaconvert_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params mediaconvert_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up mediaconvert endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*mediaconvert_sdkv2.Options) { + return func(o *mediaconvert_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/mediaconvert/service_endpoints_gen_test.go b/internal/service/mediaconvert/service_endpoints_gen_test.go index 09f742a21f4..ea5b7f7e00c 100644 --- a/internal/service/mediaconvert/service_endpoints_gen_test.go +++ b/internal/service/mediaconvert/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := mediaconvert_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediaconvert_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := mediaconvert_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediaconvert_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/mediaconvert/service_package_gen.go b/internal/service/mediaconvert/service_package_gen.go index 47233f70ce1..dbd9672aef7 100644 --- a/internal/service/mediaconvert/service_package_gen.go +++ b/internal/service/mediaconvert/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package mediaconvert @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" mediaconvert_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediaconvert" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -57,19 +56,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mediaconvert_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mediaconvert_sdkv2.NewFromConfig(cfg, func(o *mediaconvert_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return mediaconvert_sdkv2.NewFromConfig(cfg, + mediaconvert_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/medialive/service_endpoint_resolver_gen.go b/internal/service/medialive/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..fbaf32ec2b4 --- /dev/null +++ b/internal/service/medialive/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package medialive + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + medialive_sdkv2 "github.com/aws/aws-sdk-go-v2/service/medialive" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ medialive_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver medialive_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: medialive_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params medialive_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up medialive endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*medialive_sdkv2.Options) { + return func(o *medialive_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/medialive/service_endpoints_gen_test.go b/internal/service/medialive/service_endpoints_gen_test.go index b39c210c172..b90ee39c6cd 100644 --- a/internal/service/medialive/service_endpoints_gen_test.go +++ b/internal/service/medialive/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := medialive_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), medialive_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := medialive_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), medialive_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/medialive/service_package_gen.go b/internal/service/medialive/service_package_gen.go index 477c0926706..5fdc269e9a5 100644 --- a/internal/service/medialive/service_package_gen.go +++ b/internal/service/medialive/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package medialive @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" medialive_sdkv2 "github.com/aws/aws-sdk-go-v2/service/medialive" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -81,19 +80,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*medialive_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return medialive_sdkv2.NewFromConfig(cfg, func(o *medialive_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return medialive_sdkv2.NewFromConfig(cfg, + medialive_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/mediapackage/service_endpoint_resolver_gen.go b/internal/service/mediapackage/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..10e45dc9536 --- /dev/null +++ b/internal/service/mediapackage/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package mediapackage + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mediapackage_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediapackage" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ mediapackage_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver mediapackage_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: mediapackage_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params mediapackage_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up mediapackage endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*mediapackage_sdkv2.Options) { + return func(o *mediapackage_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/mediapackage/service_endpoints_gen_test.go b/internal/service/mediapackage/service_endpoints_gen_test.go index 36055f4e405..e0034ff4753 100644 --- a/internal/service/mediapackage/service_endpoints_gen_test.go +++ b/internal/service/mediapackage/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := mediapackage_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediapackage_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := mediapackage_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediapackage_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/mediapackage/service_package_gen.go b/internal/service/mediapackage/service_package_gen.go index 2fe02aba5d6..2ad78fcf337 100644 --- a/internal/service/mediapackage/service_package_gen.go +++ b/internal/service/mediapackage/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package mediapackage @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" mediapackage_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediapackage" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mediapackage_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mediapackage_sdkv2.NewFromConfig(cfg, func(o *mediapackage_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return mediapackage_sdkv2.NewFromConfig(cfg, + mediapackage_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/mediapackagev2/service_endpoint_resolver_gen.go b/internal/service/mediapackagev2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1173787d817 --- /dev/null +++ b/internal/service/mediapackagev2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package mediapackagev2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mediapackagev2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediapackagev2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ mediapackagev2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver mediapackagev2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: mediapackagev2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params mediapackagev2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up mediapackagev2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*mediapackagev2_sdkv2.Options) { + return func(o *mediapackagev2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/mediapackagev2/service_endpoints_gen_test.go b/internal/service/mediapackagev2/service_endpoints_gen_test.go index f8290ca9eb0..04e98251e10 100644 --- a/internal/service/mediapackagev2/service_endpoints_gen_test.go +++ b/internal/service/mediapackagev2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := mediapackagev2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediapackagev2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := mediapackagev2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediapackagev2_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/mediapackagev2/service_package_gen.go b/internal/service/mediapackagev2/service_package_gen.go index c280eb568bc..1a5bf9e1f7a 100644 --- a/internal/service/mediapackagev2/service_package_gen.go +++ b/internal/service/mediapackagev2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package mediapackagev2 @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" mediapackagev2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediapackagev2" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mediapackagev2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mediapackagev2_sdkv2.NewFromConfig(cfg, func(o *mediapackagev2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return mediapackagev2_sdkv2.NewFromConfig(cfg, + mediapackagev2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/mediastore/service_endpoint_resolver_gen.go b/internal/service/mediastore/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a3f770246ac --- /dev/null +++ b/internal/service/mediastore/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package mediastore + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mediastore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediastore" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ mediastore_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver mediastore_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: mediastore_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params mediastore_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up mediastore endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*mediastore_sdkv2.Options) { + return func(o *mediastore_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/mediastore/service_endpoints_gen_test.go b/internal/service/mediastore/service_endpoints_gen_test.go index 3d78e79d276..a967b6552f8 100644 --- a/internal/service/mediastore/service_endpoints_gen_test.go +++ b/internal/service/mediastore/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := mediastore_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediastore_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := mediastore_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mediastore_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/mediastore/service_package_gen.go b/internal/service/mediastore/service_package_gen.go index b011ea718d5..8b0c82c7788 100644 --- a/internal/service/mediastore/service_package_gen.go +++ b/internal/service/mediastore/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package mediastore @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" mediastore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediastore" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -52,19 +51,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mediastore_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mediastore_sdkv2.NewFromConfig(cfg, func(o *mediastore_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return mediastore_sdkv2.NewFromConfig(cfg, + mediastore_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/memorydb/service_endpoint_resolver_gen.go b/internal/service/memorydb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..185906c0b20 --- /dev/null +++ b/internal/service/memorydb/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package memorydb + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/memorydb/service_endpoints_gen_test.go b/internal/service/memorydb/service_endpoints_gen_test.go index 0f1ebc09422..1e19c62146f 100644 --- a/internal/service/memorydb/service_endpoints_gen_test.go +++ b/internal/service/memorydb/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(memorydb_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(memorydb_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/memorydb/service_package_gen.go b/internal/service/memorydb/service_package_gen.go index b6ef402c04f..9b026311bb6 100644 --- a/internal/service/memorydb/service_package_gen.go +++ b/internal/service/memorydb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package memorydb @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" memorydb_sdkv1 "github.com/aws/aws-sdk-go/service/memorydb" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -122,11 +121,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*m "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return memorydb_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/meta/service_package_gen.go b/internal/service/meta/service_package_gen.go index 8ae99fcad16..2abe76c7625 100644 --- a/internal/service/meta/service_package_gen.go +++ b/internal/service/meta/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package meta diff --git a/internal/service/mq/service_endpoint_resolver_gen.go b/internal/service/mq/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b34425906f7 --- /dev/null +++ b/internal/service/mq/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package mq + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mq_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mq" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ mq_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver mq_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: mq_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params mq_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up mq endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*mq_sdkv2.Options) { + return func(o *mq_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/mq/service_endpoints_gen_test.go b/internal/service/mq/service_endpoints_gen_test.go index 641786b65cd..4321844e88e 100644 --- a/internal/service/mq/service_endpoints_gen_test.go +++ b/internal/service/mq/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := mq_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mq_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := mq_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), mq_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/mq/service_package_gen.go b/internal/service/mq/service_package_gen.go index d3338933cb3..e2f4dafde65 100644 --- a/internal/service/mq/service_package_gen.go +++ b/internal/service/mq/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package mq @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" mq_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mq" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -72,19 +71,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mq_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mq_sdkv2.NewFromConfig(cfg, func(o *mq_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return mq_sdkv2.NewFromConfig(cfg, + mq_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/mwaa/service_endpoint_resolver_gen.go b/internal/service/mwaa/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f2d52704cc6 --- /dev/null +++ b/internal/service/mwaa/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package mwaa + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mwaa_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mwaa" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ mwaa_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver mwaa_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: mwaa_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params mwaa_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up mwaa endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*mwaa_sdkv2.Options) { + return func(o *mwaa_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/mwaa/service_package_gen.go b/internal/service/mwaa/service_package_gen.go index 557a1052ce3..544c283240a 100644 --- a/internal/service/mwaa/service_package_gen.go +++ b/internal/service/mwaa/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package mwaa @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" mwaa_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mwaa" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mwaa_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mwaa_sdkv2.NewFromConfig(cfg, func(o *mwaa_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return mwaa_sdkv2.NewFromConfig(cfg, + mwaa_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/neptune/service_endpoint_resolver_gen.go b/internal/service/neptune/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e6396b11bad --- /dev/null +++ b/internal/service/neptune/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package neptune + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/neptune/service_endpoints_gen_test.go b/internal/service/neptune/service_endpoints_gen_test.go index 23149d67360..34f31264714 100644 --- a/internal/service/neptune/service_endpoints_gen_test.go +++ b/internal/service/neptune/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(neptune_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(neptune_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/neptune/service_package_gen.go b/internal/service/neptune/service_package_gen.go index ae90ff3983e..fdcf2b44ea5 100644 --- a/internal/service/neptune/service_package_gen.go +++ b/internal/service/neptune/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package neptune @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" neptune_sdkv1 "github.com/aws/aws-sdk-go/service/neptune" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -122,11 +121,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*n "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return neptune_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/neptunegraph/service_endpoint_resolver_gen.go b/internal/service/neptunegraph/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..20805e472f0 --- /dev/null +++ b/internal/service/neptunegraph/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package neptunegraph + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + neptunegraph_sdkv2 "github.com/aws/aws-sdk-go-v2/service/neptunegraph" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ neptunegraph_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver neptunegraph_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: neptunegraph_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params neptunegraph_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up neptunegraph endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*neptunegraph_sdkv2.Options) { + return func(o *neptunegraph_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/neptunegraph/service_package_gen.go b/internal/service/neptunegraph/service_package_gen.go index bd5fe2c6b90..699cca71095 100644 --- a/internal/service/neptunegraph/service_package_gen.go +++ b/internal/service/neptunegraph/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package neptunegraph @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" neptunegraph_sdkv2 "github.com/aws/aws-sdk-go-v2/service/neptunegraph" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*neptunegraph_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return neptunegraph_sdkv2.NewFromConfig(cfg, func(o *neptunegraph_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return neptunegraph_sdkv2.NewFromConfig(cfg, + neptunegraph_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/networkfirewall/service_endpoint_resolver_gen.go b/internal/service/networkfirewall/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6452c703481 --- /dev/null +++ b/internal/service/networkfirewall/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package networkfirewall + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/networkfirewall/service_endpoints_gen_test.go b/internal/service/networkfirewall/service_endpoints_gen_test.go index f61943cd786..e5c6621ae25 100644 --- a/internal/service/networkfirewall/service_endpoints_gen_test.go +++ b/internal/service/networkfirewall/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(networkfirewall_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(networkfirewall_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 97879c0a68e..bb6c8e6331f 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package networkfirewall @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" networkfirewall_sdkv1 "github.com/aws/aws-sdk-go/service/networkfirewall" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -94,11 +93,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*n "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return networkfirewall_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/networkmanager/service_endpoint_resolver_gen.go b/internal/service/networkmanager/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..85d9eaab057 --- /dev/null +++ b/internal/service/networkmanager/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package networkmanager + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/networkmanager/service_endpoints_gen_test.go b/internal/service/networkmanager/service_endpoints_gen_test.go index f309aa0f608..22e63eca7d6 100644 --- a/internal/service/networkmanager/service_endpoints_gen_test.go +++ b/internal/service/networkmanager/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(networkmanager_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(networkmanager_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/networkmanager/service_package_gen.go b/internal/service/networkmanager/service_package_gen.go index 503cb4d0005..660c9593902 100644 --- a/internal/service/networkmanager/service_package_gen.go +++ b/internal/service/networkmanager/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package networkmanager @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" networkmanager_sdkv1 "github.com/aws/aws-sdk-go/service/networkmanager" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -214,11 +213,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*n "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return networkmanager_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/oam/service_endpoint_resolver_gen.go b/internal/service/oam/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..06de202246c --- /dev/null +++ b/internal/service/oam/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package oam + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + oam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/oam" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ oam_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver oam_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: oam_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params oam_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up oam endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*oam_sdkv2.Options) { + return func(o *oam_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/oam/service_endpoints_gen_test.go b/internal/service/oam/service_endpoints_gen_test.go index c34ed793937..8761c852c4f 100644 --- a/internal/service/oam/service_endpoints_gen_test.go +++ b/internal/service/oam/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := oam_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), oam_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := oam_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), oam_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/oam/service_package_gen.go b/internal/service/oam/service_package_gen.go index f6a5e91ab4c..2778bea7d35 100644 --- a/internal/service/oam/service_package_gen.go +++ b/internal/service/oam/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package oam @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" oam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/oam" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -77,19 +76,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*oam_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return oam_sdkv2.NewFromConfig(cfg, func(o *oam_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return oam_sdkv2.NewFromConfig(cfg, + oam_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/opensearch/service_endpoint_resolver_gen.go b/internal/service/opensearch/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3e4e71bc0d9 --- /dev/null +++ b/internal/service/opensearch/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package opensearch + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/opensearch/service_endpoints_gen_test.go b/internal/service/opensearch/service_endpoints_gen_test.go index 1df5c4b1f01..af5f1d5543b 100644 --- a/internal/service/opensearch/service_endpoints_gen_test.go +++ b/internal/service/opensearch/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -88,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -271,7 +272,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -292,12 +293,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(opensearchservice_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -306,17 +307,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(opensearchservice_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -325,7 +326,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -396,16 +397,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/opensearch/service_package_gen.go b/internal/service/opensearch/service_package_gen.go index 4dd8ae4b597..b4b1a8103d4 100644 --- a/internal/service/opensearch/service_package_gen.go +++ b/internal/service/opensearch/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package opensearch @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" opensearchservice_sdkv1 "github.com/aws/aws-sdk-go/service/opensearchservice" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -90,11 +89,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*o "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return opensearchservice_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/opensearchserverless/service_endpoint_resolver_gen.go b/internal/service/opensearchserverless/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5d8f1b501c6 --- /dev/null +++ b/internal/service/opensearchserverless/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package opensearchserverless + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + opensearchserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/opensearchserverless" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ opensearchserverless_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver opensearchserverless_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: opensearchserverless_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params opensearchserverless_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up opensearchserverless endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*opensearchserverless_sdkv2.Options) { + return func(o *opensearchserverless_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/opensearchserverless/service_endpoints_gen_test.go b/internal/service/opensearchserverless/service_endpoints_gen_test.go index 23e72508d77..9ebb72f97b5 100644 --- a/internal/service/opensearchserverless/service_endpoints_gen_test.go +++ b/internal/service/opensearchserverless/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := opensearchserverless_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), opensearchserverless_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := opensearchserverless_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), opensearchserverless_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/opensearchserverless/service_package_gen.go b/internal/service/opensearchserverless/service_package_gen.go index 8857ae29747..d90ff9867a4 100644 --- a/internal/service/opensearchserverless/service_package_gen.go +++ b/internal/service/opensearchserverless/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package opensearchserverless @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" opensearchserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/opensearchserverless" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -89,19 +88,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*opensearchserverless_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return opensearchserverless_sdkv2.NewFromConfig(cfg, func(o *opensearchserverless_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return opensearchserverless_sdkv2.NewFromConfig(cfg, + opensearchserverless_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/opsworks/service_endpoint_resolver_gen.go b/internal/service/opsworks/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6f09d847eec --- /dev/null +++ b/internal/service/opsworks/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package opsworks + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/opsworks/service_endpoints_gen_test.go b/internal/service/opsworks/service_endpoints_gen_test.go index 1eed4760957..09f8ed6291a 100644 --- a/internal/service/opsworks/service_endpoints_gen_test.go +++ b/internal/service/opsworks/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(opsworks_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(opsworks_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/opsworks/service_package_gen.go b/internal/service/opsworks/service_package_gen.go index 17196336b0e..e218ee36fc1 100644 --- a/internal/service/opsworks/service_package_gen.go +++ b/internal/service/opsworks/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package opsworks @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" opsworks_sdkv1 "github.com/aws/aws-sdk-go/service/opsworks" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -163,11 +162,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*o "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return opsworks_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/organizations/service_endpoint_resolver_gen.go b/internal/service/organizations/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6d88c9fd916 --- /dev/null +++ b/internal/service/organizations/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package organizations + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + organizations_sdkv2 "github.com/aws/aws-sdk-go-v2/service/organizations" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ organizations_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver organizations_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: organizations_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params organizations_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up organizations endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*organizations_sdkv2.Options) { + return func(o *organizations_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/organizations/service_endpoints_gen_test.go b/internal/service/organizations/service_endpoints_gen_test.go index f35ae8f69a1..3941633f604 100644 --- a/internal/service/organizations/service_endpoints_gen_test.go +++ b/internal/service/organizations/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := organizations_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), organizations_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := organizations_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), organizations_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/organizations/service_package.go b/internal/service/organizations/service_package.go index b6a95ab8a27..62b07ffb4dc 100644 --- a/internal/service/organizations/service_package.go +++ b/internal/service/organizations/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/organizations" awstypes "github.com/aws/aws-sdk-go-v2/service/organizations/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*organizations.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return organizations.NewFromConfig(cfg, func(o *organizations.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*awstypes.ConcurrentModificationException](err, "Try again later") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return organizations.NewFromConfig(cfg, + organizations.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *organizations.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*awstypes.ConcurrentModificationException](err, "Try again later") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/organizations/service_package_gen.go b/internal/service/organizations/service_package_gen.go index 01c8fccdb9a..5aba3d9eedf 100644 --- a/internal/service/organizations/service_package_gen.go +++ b/internal/service/organizations/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package organizations diff --git a/internal/service/osis/service_endpoint_resolver_gen.go b/internal/service/osis/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5f57e01330e --- /dev/null +++ b/internal/service/osis/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package osis + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + osis_sdkv2 "github.com/aws/aws-sdk-go-v2/service/osis" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ osis_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver osis_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: osis_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params osis_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up osis endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*osis_sdkv2.Options) { + return func(o *osis_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/osis/service_endpoints_gen_test.go b/internal/service/osis/service_endpoints_gen_test.go index 548247185db..940518484c6 100644 --- a/internal/service/osis/service_endpoints_gen_test.go +++ b/internal/service/osis/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := osis_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), osis_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := osis_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), osis_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/osis/service_package_gen.go b/internal/service/osis/service_package_gen.go index 7b183a2c152..c290f3ba01a 100644 --- a/internal/service/osis/service_package_gen.go +++ b/internal/service/osis/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package osis @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" osis_sdkv2 "github.com/aws/aws-sdk-go-v2/service/osis" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -47,19 +46,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*osis_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return osis_sdkv2.NewFromConfig(cfg, func(o *osis_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return osis_sdkv2.NewFromConfig(cfg, + osis_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/outposts/service_endpoint_resolver_gen.go b/internal/service/outposts/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e2e9cbe7d39 --- /dev/null +++ b/internal/service/outposts/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package outposts + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/outposts/service_endpoints_gen_test.go b/internal/service/outposts/service_endpoints_gen_test.go index a5675a6f43a..4da82a857ff 100644 --- a/internal/service/outposts/service_endpoints_gen_test.go +++ b/internal/service/outposts/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(outposts_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(outposts_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/outposts/service_package_gen.go b/internal/service/outposts/service_package_gen.go index 43230cdddb3..41b43754f56 100644 --- a/internal/service/outposts/service_package_gen.go +++ b/internal/service/outposts/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package outposts @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" outposts_sdkv1 "github.com/aws/aws-sdk-go/service/outposts" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -81,11 +80,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*o "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return outposts_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/paymentcryptography/service_endpoint_resolver_gen.go b/internal/service/paymentcryptography/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..fc57ac8a514 --- /dev/null +++ b/internal/service/paymentcryptography/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package paymentcryptography + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + paymentcryptography_sdkv2 "github.com/aws/aws-sdk-go-v2/service/paymentcryptography" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ paymentcryptography_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver paymentcryptography_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: paymentcryptography_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params paymentcryptography_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up paymentcryptography endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*paymentcryptography_sdkv2.Options) { + return func(o *paymentcryptography_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/paymentcryptography/service_package_gen.go b/internal/service/paymentcryptography/service_package_gen.go index 12aaf10726d..ef747eda518 100644 --- a/internal/service/paymentcryptography/service_package_gen.go +++ b/internal/service/paymentcryptography/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package paymentcryptography @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" paymentcryptography_sdkv2 "github.com/aws/aws-sdk-go-v2/service/paymentcryptography" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -51,19 +50,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*paymentcryptography_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return paymentcryptography_sdkv2.NewFromConfig(cfg, func(o *paymentcryptography_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return paymentcryptography_sdkv2.NewFromConfig(cfg, + paymentcryptography_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/pcaconnectorad/service_endpoint_resolver_gen.go b/internal/service/pcaconnectorad/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..dc488d05723 --- /dev/null +++ b/internal/service/pcaconnectorad/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package pcaconnectorad + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + pcaconnectorad_sdkv2 "github.com/aws/aws-sdk-go-v2/service/pcaconnectorad" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ pcaconnectorad_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver pcaconnectorad_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: pcaconnectorad_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params pcaconnectorad_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up pcaconnectorad endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*pcaconnectorad_sdkv2.Options) { + return func(o *pcaconnectorad_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/pcaconnectorad/service_endpoints_gen_test.go b/internal/service/pcaconnectorad/service_endpoints_gen_test.go index b767a7e618d..fd53a886ea9 100644 --- a/internal/service/pcaconnectorad/service_endpoints_gen_test.go +++ b/internal/service/pcaconnectorad/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := pcaconnectorad_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), pcaconnectorad_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := pcaconnectorad_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), pcaconnectorad_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/pcaconnectorad/service_package_gen.go b/internal/service/pcaconnectorad/service_package_gen.go index 8b9d067a6b8..2723b987d99 100644 --- a/internal/service/pcaconnectorad/service_package_gen.go +++ b/internal/service/pcaconnectorad/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package pcaconnectorad @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" pcaconnectorad_sdkv2 "github.com/aws/aws-sdk-go-v2/service/pcaconnectorad" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*pcaconnectorad_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return pcaconnectorad_sdkv2.NewFromConfig(cfg, func(o *pcaconnectorad_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return pcaconnectorad_sdkv2.NewFromConfig(cfg, + pcaconnectorad_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/pinpoint/service_endpoint_resolver_gen.go b/internal/service/pinpoint/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..59d160d67cb --- /dev/null +++ b/internal/service/pinpoint/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package pinpoint + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/pinpoint/service_endpoints_gen_test.go b/internal/service/pinpoint/service_endpoints_gen_test.go index d777caf603f..5bf7bed558c 100644 --- a/internal/service/pinpoint/service_endpoints_gen_test.go +++ b/internal/service/pinpoint/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(pinpoint_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(pinpoint_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/pinpoint/service_package_gen.go b/internal/service/pinpoint/service_package_gen.go index 7d2b3d4b77f..08d563cff4a 100644 --- a/internal/service/pinpoint/service_package_gen.go +++ b/internal/service/pinpoint/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package pinpoint @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" pinpoint_sdkv1 "github.com/aws/aws-sdk-go/service/pinpoint" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -97,11 +96,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*p "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return pinpoint_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/pipes/service_endpoint_resolver_gen.go b/internal/service/pipes/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..81c0d5f49b1 --- /dev/null +++ b/internal/service/pipes/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package pipes + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + pipes_sdkv2 "github.com/aws/aws-sdk-go-v2/service/pipes" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ pipes_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver pipes_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: pipes_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params pipes_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up pipes endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*pipes_sdkv2.Options) { + return func(o *pipes_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/pipes/service_endpoints_gen_test.go b/internal/service/pipes/service_endpoints_gen_test.go index d8d4b91752f..6996fb58bee 100644 --- a/internal/service/pipes/service_endpoints_gen_test.go +++ b/internal/service/pipes/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := pipes_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), pipes_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := pipes_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), pipes_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/pipes/service_package_gen.go b/internal/service/pipes/service_package_gen.go index f071123258e..c268b1f80d5 100644 --- a/internal/service/pipes/service_package_gen.go +++ b/internal/service/pipes/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package pipes @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" pipes_sdkv2 "github.com/aws/aws-sdk-go-v2/service/pipes" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*pipes_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return pipes_sdkv2.NewFromConfig(cfg, func(o *pipes_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return pipes_sdkv2.NewFromConfig(cfg, + pipes_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/polly/service_endpoint_resolver_gen.go b/internal/service/polly/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..cd3672f6520 --- /dev/null +++ b/internal/service/polly/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package polly + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + polly_sdkv2 "github.com/aws/aws-sdk-go-v2/service/polly" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ polly_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver polly_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: polly_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params polly_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up polly endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*polly_sdkv2.Options) { + return func(o *polly_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/polly/service_endpoints_gen_test.go b/internal/service/polly/service_endpoints_gen_test.go index 366f5bb424e..1b12cee4ca5 100644 --- a/internal/service/polly/service_endpoints_gen_test.go +++ b/internal/service/polly/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := polly_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), polly_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := polly_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), polly_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/polly/service_package_gen.go b/internal/service/polly/service_package_gen.go index 019d6190e78..e3fa6f7dd0c 100644 --- a/internal/service/polly/service_package_gen.go +++ b/internal/service/polly/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package polly @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" polly_sdkv2 "github.com/aws/aws-sdk-go-v2/service/polly" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -44,19 +43,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*polly_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return polly_sdkv2.NewFromConfig(cfg, func(o *polly_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return polly_sdkv2.NewFromConfig(cfg, + polly_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/pricing/service_endpoint_resolver_gen.go b/internal/service/pricing/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..15b32059979 --- /dev/null +++ b/internal/service/pricing/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package pricing + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + pricing_sdkv2 "github.com/aws/aws-sdk-go-v2/service/pricing" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ pricing_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver pricing_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: pricing_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params pricing_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up pricing endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*pricing_sdkv2.Options) { + return func(o *pricing_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/pricing/service_endpoints_gen_test.go b/internal/service/pricing/service_endpoints_gen_test.go index 24b6be6fb89..00c87d52019 100644 --- a/internal/service/pricing/service_endpoints_gen_test.go +++ b/internal/service/pricing/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := pricing_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), pricing_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := pricing_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), pricing_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/pricing/service_package_gen.go b/internal/service/pricing/service_package_gen.go index 62d1e64ba29..2fed2364644 100644 --- a/internal/service/pricing/service_package_gen.go +++ b/internal/service/pricing/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package pricing @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" pricing_sdkv2 "github.com/aws/aws-sdk-go-v2/service/pricing" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -44,19 +43,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*pricing_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return pricing_sdkv2.NewFromConfig(cfg, func(o *pricing_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return pricing_sdkv2.NewFromConfig(cfg, + pricing_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/qbusiness/service_endpoint_resolver_gen.go b/internal/service/qbusiness/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1d24494ea9a --- /dev/null +++ b/internal/service/qbusiness/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package qbusiness + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + qbusiness_sdkv2 "github.com/aws/aws-sdk-go-v2/service/qbusiness" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ qbusiness_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver qbusiness_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: qbusiness_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params qbusiness_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up qbusiness endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*qbusiness_sdkv2.Options) { + return func(o *qbusiness_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/qbusiness/service_endpoints_gen_test.go b/internal/service/qbusiness/service_endpoints_gen_test.go index e7d0fb408e7..dd995ba0375 100644 --- a/internal/service/qbusiness/service_endpoints_gen_test.go +++ b/internal/service/qbusiness/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := qbusiness_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), qbusiness_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := qbusiness_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), qbusiness_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/qbusiness/service_package_gen.go b/internal/service/qbusiness/service_package_gen.go index 60138df50c3..b02a4b2b74e 100644 --- a/internal/service/qbusiness/service_package_gen.go +++ b/internal/service/qbusiness/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package qbusiness @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" qbusiness_sdkv2 "github.com/aws/aws-sdk-go-v2/service/qbusiness" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*qbusiness_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return qbusiness_sdkv2.NewFromConfig(cfg, func(o *qbusiness_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return qbusiness_sdkv2.NewFromConfig(cfg, + qbusiness_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/qldb/service_endpoint_resolver_gen.go b/internal/service/qldb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1db7b08627a --- /dev/null +++ b/internal/service/qldb/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package qldb + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + qldb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/qldb" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ qldb_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver qldb_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: qldb_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params qldb_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up qldb endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*qldb_sdkv2.Options) { + return func(o *qldb_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/qldb/service_endpoints_gen_test.go b/internal/service/qldb/service_endpoints_gen_test.go index 563115948c2..c3ed46c410c 100644 --- a/internal/service/qldb/service_endpoints_gen_test.go +++ b/internal/service/qldb/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := qldb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), qldb_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := qldb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), qldb_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/qldb/service_package_gen.go b/internal/service/qldb/service_package_gen.go index 4dc5155ea09..2af8b39f05e 100644 --- a/internal/service/qldb/service_package_gen.go +++ b/internal/service/qldb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package qldb @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" qldb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/qldb" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -61,19 +60,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*qldb_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return qldb_sdkv2.NewFromConfig(cfg, func(o *qldb_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return qldb_sdkv2.NewFromConfig(cfg, + qldb_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/quicksight/service_endpoint_resolver_gen.go b/internal/service/quicksight/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..aa39a967cdd --- /dev/null +++ b/internal/service/quicksight/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package quicksight + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/quicksight/service_endpoints_gen_test.go b/internal/service/quicksight/service_endpoints_gen_test.go index 3f1e3a462ca..c0468f9f4be 100644 --- a/internal/service/quicksight/service_endpoints_gen_test.go +++ b/internal/service/quicksight/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(quicksight_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(quicksight_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -325,16 +326,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/quicksight/service_package_gen.go b/internal/service/quicksight/service_package_gen.go index c4823c3a621..923d0e41fa6 100644 --- a/internal/service/quicksight/service_package_gen.go +++ b/internal/service/quicksight/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package quicksight @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" quicksight_sdkv1 "github.com/aws/aws-sdk-go/service/quicksight" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -181,11 +180,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*q "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return quicksight_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/ram/service_endpoint_resolver_gen.go b/internal/service/ram/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..850db742de4 --- /dev/null +++ b/internal/service/ram/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ram + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ram_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ram" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ram_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ram_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ram_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ram_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ram endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ram_sdkv2.Options) { + return func(o *ram_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ram/service_endpoints_gen_test.go b/internal/service/ram/service_endpoints_gen_test.go index c18e23add22..562edb8339c 100644 --- a/internal/service/ram/service_endpoints_gen_test.go +++ b/internal/service/ram/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ram_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ram_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ram_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ram_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ram/service_package_gen.go b/internal/service/ram/service_package_gen.go index 6f0bf06dd97..dc830590c4c 100644 --- a/internal/service/ram/service_package_gen.go +++ b/internal/service/ram/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ram @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ram_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ram" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -75,19 +74,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ram_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ram_sdkv2.NewFromConfig(cfg, func(o *ram_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ram_sdkv2.NewFromConfig(cfg, + ram_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/rbin/service_endpoint_resolver_gen.go b/internal/service/rbin/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..c2030262e0e --- /dev/null +++ b/internal/service/rbin/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package rbin + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + rbin_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rbin" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ rbin_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver rbin_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: rbin_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params rbin_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up rbin endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*rbin_sdkv2.Options) { + return func(o *rbin_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/rbin/service_endpoints_gen_test.go b/internal/service/rbin/service_endpoints_gen_test.go index 28c5ca0b63d..c8dcffc3425 100644 --- a/internal/service/rbin/service_endpoints_gen_test.go +++ b/internal/service/rbin/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -92,7 +94,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -275,7 +277,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -296,24 +298,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := rbin_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rbin_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := rbin_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rbin_sdkv2.EndpointParameters{ @@ -321,14 +323,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -411,16 +413,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/rbin/service_package_gen.go b/internal/service/rbin/service_package_gen.go index 7b80b7e1a00..063072945e6 100644 --- a/internal/service/rbin/service_package_gen.go +++ b/internal/service/rbin/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package rbin @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" rbin_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rbin" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*rbin_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return rbin_sdkv2.NewFromConfig(cfg, func(o *rbin_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return rbin_sdkv2.NewFromConfig(cfg, + rbin_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/rds/service_endpoint_resolver_gen.go b/internal/service/rds/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..423d25fb15b --- /dev/null +++ b/internal/service/rds/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package rds + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + rds_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rds" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ rds_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver rds_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: rds_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params rds_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up rds endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*rds_sdkv2.Options) { + return func(o *rds_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/rds/service_endpoints_gen_test.go b/internal/service/rds/service_endpoints_gen_test.go index 7c1d9d5facf..3c640b715c8 100644 --- a/internal/service/rds/service_endpoints_gen_test.go +++ b/internal/service/rds/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := rds_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rds_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := rds_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rds_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/rds/service_package_gen.go b/internal/service/rds/service_package_gen.go index ba69fdb4711..1a77cb04838 100644 --- a/internal/service/rds/service_package_gen.go +++ b/internal/service/rds/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package rds @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" rds_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rds" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" rds_sdkv1 "github.com/aws/aws-sdk-go/service/rds" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -278,11 +277,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*r "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return rds_sdkv1.New(sess.Copy(&cfg)), nil @@ -292,19 +288,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*r func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*rds_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return rds_sdkv2.NewFromConfig(cfg, func(o *rds_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return rds_sdkv2.NewFromConfig(cfg, + rds_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/redshift/service_endpoint_resolver_gen.go b/internal/service/redshift/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..236035e47c2 --- /dev/null +++ b/internal/service/redshift/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package redshift + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + redshift_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshift" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ redshift_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver redshift_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: redshift_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params redshift_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up redshift endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*redshift_sdkv2.Options) { + return func(o *redshift_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/redshift/service_endpoints_gen_test.go b/internal/service/redshift/service_endpoints_gen_test.go index f7b82e45642..850d8658850 100644 --- a/internal/service/redshift/service_endpoints_gen_test.go +++ b/internal/service/redshift/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := redshift_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), redshift_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := redshift_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), redshift_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/redshift/service_package_gen.go b/internal/service/redshift/service_package_gen.go index 279b7e5fd6b..0363c278822 100644 --- a/internal/service/redshift/service_package_gen.go +++ b/internal/service/redshift/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package redshift @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" redshift_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshift" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" redshift_sdkv1 "github.com/aws/aws-sdk-go/service/redshift" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -225,11 +224,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*r "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return redshift_sdkv1.New(sess.Copy(&cfg)), nil @@ -239,19 +235,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*r func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*redshift_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return redshift_sdkv2.NewFromConfig(cfg, func(o *redshift_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return redshift_sdkv2.NewFromConfig(cfg, + redshift_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/redshiftdata/service_endpoint_resolver_gen.go b/internal/service/redshiftdata/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1dcefd43622 --- /dev/null +++ b/internal/service/redshiftdata/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package redshiftdata + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + redshiftdata_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshiftdata" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ redshiftdata_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver redshiftdata_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: redshiftdata_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params redshiftdata_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up redshiftdata endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*redshiftdata_sdkv2.Options) { + return func(o *redshiftdata_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/redshiftdata/service_endpoints_gen_test.go b/internal/service/redshiftdata/service_endpoints_gen_test.go index e015f374ca0..c0ee43c23b4 100644 --- a/internal/service/redshiftdata/service_endpoints_gen_test.go +++ b/internal/service/redshiftdata/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := redshiftdata_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), redshiftdata_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := redshiftdata_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), redshiftdata_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -410,16 +412,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/redshiftdata/service_package_gen.go b/internal/service/redshiftdata/service_package_gen.go index ccd809ec732..21d6ae2a271 100644 --- a/internal/service/redshiftdata/service_package_gen.go +++ b/internal/service/redshiftdata/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package redshiftdata @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" redshiftdata_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshiftdata" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -44,19 +43,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*redshiftdata_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return redshiftdata_sdkv2.NewFromConfig(cfg, func(o *redshiftdata_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return redshiftdata_sdkv2.NewFromConfig(cfg, + redshiftdata_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/redshiftserverless/service_endpoint_resolver_gen.go b/internal/service/redshiftserverless/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a9f40a001da --- /dev/null +++ b/internal/service/redshiftserverless/service_endpoint_resolver_gen.go @@ -0,0 +1,146 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package redshiftserverless + +import ( + "context" + "fmt" + "net" + "net/url" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + redshiftserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} + +var _ redshiftserverless_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver redshiftserverless_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: redshiftserverless_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params redshiftserverless_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up redshiftserverless endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*redshiftserverless_sdkv2.Options) { + return func(o *redshiftserverless_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/redshiftserverless/service_endpoints_gen_test.go b/internal/service/redshiftserverless/service_endpoints_gen_test.go index 0f0671ff261..fc4ca9899a7 100644 --- a/internal/service/redshiftserverless/service_endpoints_gen_test.go +++ b/internal/service/redshiftserverless/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -255,24 +257,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }) } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := redshiftserverless_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), redshiftserverless_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := redshiftserverless_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), redshiftserverless_sdkv2.EndpointParameters{ @@ -280,14 +282,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -364,16 +366,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/redshiftserverless/service_package_gen.go b/internal/service/redshiftserverless/service_package_gen.go index 1caabc829a4..6cc96608022 100644 --- a/internal/service/redshiftserverless/service_package_gen.go +++ b/internal/service/redshiftserverless/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package redshiftserverless @@ -8,7 +8,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" redshiftserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" redshiftserverless_sdkv1 "github.com/aws/aws-sdk-go/service/redshiftserverless" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -108,11 +107,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*r "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return redshiftserverless_sdkv1.New(sess.Copy(&cfg)), nil @@ -122,19 +118,10 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*r func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*redshiftserverless_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return redshiftserverless_sdkv2.NewFromConfig(cfg, func(o *redshiftserverless_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return redshiftserverless_sdkv2.NewFromConfig(cfg, + redshiftserverless_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/rekognition/service_endpoint_resolver_gen.go b/internal/service/rekognition/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5a8fe0a7ff1 --- /dev/null +++ b/internal/service/rekognition/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package rekognition + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + rekognition_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rekognition" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ rekognition_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver rekognition_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: rekognition_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params rekognition_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up rekognition endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*rekognition_sdkv2.Options) { + return func(o *rekognition_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/rekognition/service_endpoints_gen_test.go b/internal/service/rekognition/service_endpoints_gen_test.go index d4f0c9c1abb..22fde1ae7a8 100644 --- a/internal/service/rekognition/service_endpoints_gen_test.go +++ b/internal/service/rekognition/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := rekognition_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rekognition_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := rekognition_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rekognition_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/rekognition/service_package_gen.go b/internal/service/rekognition/service_package_gen.go index dc32dc866c4..eac0885db13 100644 --- a/internal/service/rekognition/service_package_gen.go +++ b/internal/service/rekognition/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package rekognition @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" rekognition_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rekognition" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -51,19 +50,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*rekognition_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return rekognition_sdkv2.NewFromConfig(cfg, func(o *rekognition_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return rekognition_sdkv2.NewFromConfig(cfg, + rekognition_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/resourceexplorer2/service_endpoint_resolver_gen.go b/internal/service/resourceexplorer2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f1bfe5122bf --- /dev/null +++ b/internal/service/resourceexplorer2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package resourceexplorer2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + resourceexplorer2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/resourceexplorer2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ resourceexplorer2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver resourceexplorer2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: resourceexplorer2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params resourceexplorer2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up resourceexplorer2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*resourceexplorer2_sdkv2.Options) { + return func(o *resourceexplorer2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/resourceexplorer2/service_endpoints_gen_test.go b/internal/service/resourceexplorer2/service_endpoints_gen_test.go index a8a62f8c937..12047d59f13 100644 --- a/internal/service/resourceexplorer2/service_endpoints_gen_test.go +++ b/internal/service/resourceexplorer2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := resourceexplorer2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), resourceexplorer2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := resourceexplorer2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), resourceexplorer2_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/resourceexplorer2/service_package_gen.go b/internal/service/resourceexplorer2/service_package_gen.go index e37931dde0f..841b5454dab 100644 --- a/internal/service/resourceexplorer2/service_package_gen.go +++ b/internal/service/resourceexplorer2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package resourceexplorer2 @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" resourceexplorer2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/resourceexplorer2" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -59,19 +58,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*resourceexplorer2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return resourceexplorer2_sdkv2.NewFromConfig(cfg, func(o *resourceexplorer2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return resourceexplorer2_sdkv2.NewFromConfig(cfg, + resourceexplorer2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/resourcegroups/service_endpoint_resolver_gen.go b/internal/service/resourcegroups/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5153c50eca9 --- /dev/null +++ b/internal/service/resourcegroups/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package resourcegroups + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + resourcegroups_sdkv2 "github.com/aws/aws-sdk-go-v2/service/resourcegroups" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ resourcegroups_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver resourcegroups_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: resourcegroups_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params resourcegroups_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up resourcegroups endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*resourcegroups_sdkv2.Options) { + return func(o *resourcegroups_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/resourcegroups/service_endpoints_gen_test.go b/internal/service/resourcegroups/service_endpoints_gen_test.go index 506daa7fbf1..c7511e0323f 100644 --- a/internal/service/resourcegroups/service_endpoints_gen_test.go +++ b/internal/service/resourcegroups/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := resourcegroups_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), resourcegroups_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := resourcegroups_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), resourcegroups_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/resourcegroups/service_package_gen.go b/internal/service/resourcegroups/service_package_gen.go index cfabb5d5ffd..e678b38a0ff 100644 --- a/internal/service/resourcegroups/service_package_gen.go +++ b/internal/service/resourcegroups/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package resourcegroups @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" resourcegroups_sdkv2 "github.com/aws/aws-sdk-go-v2/service/resourcegroups" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -53,19 +52,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*resourcegroups_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return resourcegroups_sdkv2.NewFromConfig(cfg, func(o *resourcegroups_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return resourcegroups_sdkv2.NewFromConfig(cfg, + resourcegroups_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/resourcegroupstaggingapi/service_endpoint_resolver_gen.go b/internal/service/resourcegroupstaggingapi/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..470727433f2 --- /dev/null +++ b/internal/service/resourcegroupstaggingapi/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package resourcegroupstaggingapi + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + resourcegroupstaggingapi_sdkv2 "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ resourcegroupstaggingapi_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver resourcegroupstaggingapi_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: resourcegroupstaggingapi_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params resourcegroupstaggingapi_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up resourcegroupstaggingapi endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*resourcegroupstaggingapi_sdkv2.Options) { + return func(o *resourcegroupstaggingapi_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/resourcegroupstaggingapi/service_endpoints_gen_test.go b/internal/service/resourcegroupstaggingapi/service_endpoints_gen_test.go index 3c4003c92e9..3fd6010e792 100644 --- a/internal/service/resourcegroupstaggingapi/service_endpoints_gen_test.go +++ b/internal/service/resourcegroupstaggingapi/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := resourcegroupstaggingapi_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), resourcegroupstaggingapi_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := resourcegroupstaggingapi_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), resourcegroupstaggingapi_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/resourcegroupstaggingapi/service_package_gen.go b/internal/service/resourcegroupstaggingapi/service_package_gen.go index 404ef92684b..32348897fe6 100644 --- a/internal/service/resourcegroupstaggingapi/service_package_gen.go +++ b/internal/service/resourcegroupstaggingapi/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package resourcegroupstaggingapi @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" resourcegroupstaggingapi_sdkv2 "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -44,19 +43,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*resourcegroupstaggingapi_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return resourcegroupstaggingapi_sdkv2.NewFromConfig(cfg, func(o *resourcegroupstaggingapi_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return resourcegroupstaggingapi_sdkv2.NewFromConfig(cfg, + resourcegroupstaggingapi_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/rolesanywhere/service_endpoint_resolver_gen.go b/internal/service/rolesanywhere/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..5d03433d57c --- /dev/null +++ b/internal/service/rolesanywhere/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package rolesanywhere + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + rolesanywhere_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rolesanywhere" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ rolesanywhere_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver rolesanywhere_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: rolesanywhere_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params rolesanywhere_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up rolesanywhere endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*rolesanywhere_sdkv2.Options) { + return func(o *rolesanywhere_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/rolesanywhere/service_endpoints_gen_test.go b/internal/service/rolesanywhere/service_endpoints_gen_test.go index 65e9b3dd526..e8b6e4292de 100644 --- a/internal/service/rolesanywhere/service_endpoints_gen_test.go +++ b/internal/service/rolesanywhere/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := rolesanywhere_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rolesanywhere_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := rolesanywhere_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rolesanywhere_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/rolesanywhere/service_package_gen.go b/internal/service/rolesanywhere/service_package_gen.go index c5c97bb205a..6ed74afb30d 100644 --- a/internal/service/rolesanywhere/service_package_gen.go +++ b/internal/service/rolesanywhere/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package rolesanywhere @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" rolesanywhere_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rolesanywhere" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*rolesanywhere_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return rolesanywhere_sdkv2.NewFromConfig(cfg, func(o *rolesanywhere_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return rolesanywhere_sdkv2.NewFromConfig(cfg, + rolesanywhere_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/route53/service_endpoint_resolver_gen.go b/internal/service/route53/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..db1d4a68e6c --- /dev/null +++ b/internal/service/route53/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package route53 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + route53_sdkv2 "github.com/aws/aws-sdk-go-v2/service/route53" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ route53_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver route53_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: route53_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params route53_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up route53 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*route53_sdkv2.Options) { + return func(o *route53_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/route53/service_endpoints_gen_test.go b/internal/service/route53/service_endpoints_gen_test.go index ac39336221c..5676b3df7f2 100644 --- a/internal/service/route53/service_endpoints_gen_test.go +++ b/internal/service/route53/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := route53_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), route53_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := route53_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), route53_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/route53/service_package.go b/internal/service/route53/service_package.go index ab76a4d82c1..cb1a94c876f 100644 --- a/internal/service/route53/service_package.go +++ b/internal/service/route53/service_package.go @@ -16,33 +16,37 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*route53.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return route53.NewFromConfig(cfg, func(o *route53.Options) { - // Always override the service region - switch config["partition"].(string) { - case names.StandardPartitionID: - // https://docs.aws.amazon.com/general/latest/gr/r53.html Setting default to us-east-1. - o.Region = names.USEast1RegionID - case names.ChinaPartitionID: - // The AWS Go SDK is missing endpoint information for Route 53 in the AWS China partition. - // This can likely be removed in the future. - if aws.ToString(o.BaseEndpoint) == "" { - o.BaseEndpoint = aws.String("https://api.route53.cn") + return route53.NewFromConfig(cfg, + route53.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *route53.Options) { + // Always override the service region + switch config["partition"].(string) { + case names.StandardPartitionID: + // https://docs.aws.amazon.com/general/latest/gr/r53.html Setting default to us-east-1. + if cfg.Region != names.USEast1RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USEast1RegionID, + }) + } + o.Region = names.USEast1RegionID + case names.ChinaPartitionID: + // The AWS Go SDK is missing endpoint information for Route 53 in the AWS China partition. + // This can likely be removed in the future. + if aws.ToString(o.BaseEndpoint) == "" { + o.BaseEndpoint = aws.String("https://api.route53.cn") + } + o.Region = names.CNNorthwest1RegionID + case names.USGovCloudPartitionID: + if cfg.Region != names.USGovWest1RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USGovWest1RegionID, + }) + } + o.Region = names.USGovWest1RegionID } - o.Region = names.CNNorthwest1RegionID - case names.USGovCloudPartitionID: - o.Region = names.USGovWest1RegionID - } - - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - }), nil + }, + ), nil } diff --git a/internal/service/route53/service_package_gen.go b/internal/service/route53/service_package_gen.go index 89baf108686..505e473c857 100644 --- a/internal/service/route53/service_package_gen.go +++ b/internal/service/route53/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package route53 diff --git a/internal/service/route53domains/service_endpoint_resolver_gen.go b/internal/service/route53domains/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7ef9fe3f5af --- /dev/null +++ b/internal/service/route53domains/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package route53domains + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + route53domains_sdkv2 "github.com/aws/aws-sdk-go-v2/service/route53domains" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ route53domains_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver route53domains_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: route53domains_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params route53domains_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up route53domains endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*route53domains_sdkv2.Options) { + return func(o *route53domains_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/route53domains/service_endpoints_gen_test.go b/internal/service/route53domains/service_endpoints_gen_test.go index a74f70ad80a..e19416d84c5 100644 --- a/internal/service/route53domains/service_endpoints_gen_test.go +++ b/internal/service/route53domains/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -88,7 +90,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -222,7 +224,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -243,24 +245,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := route53domains_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), route53domains_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := route53domains_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), route53domains_sdkv2.EndpointParameters{ @@ -268,14 +270,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/route53domains/service_package.go b/internal/service/route53domains/service_package.go index 3a072ade9a0..864905dd906 100644 --- a/internal/service/route53domains/service_package.go +++ b/internal/service/route53domains/service_package.go @@ -16,22 +16,20 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*route53domains.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return route53domains.NewFromConfig(cfg, func(o *route53domains.Options) { - if config["partition"].(string) == names.StandardPartitionID { - // Route 53 Domains is only available in AWS Commercial us-east-1 Region. - o.Region = names.USEast1RegionID - } - - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled + return route53domains.NewFromConfig(cfg, + route53domains.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *route53domains.Options) { + if config["partition"].(string) == names.StandardPartitionID { + // Route 53 Domains is only available in AWS Commercial us-east-1 Region. + if cfg.Region != names.USEast1RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USEast1RegionID, + }) + } + o.Region = names.USEast1RegionID } - } - }), nil + }, + ), nil } diff --git a/internal/service/route53domains/service_package_gen.go b/internal/service/route53domains/service_package_gen.go index af62cd4e913..46cefd6eb86 100644 --- a/internal/service/route53domains/service_package_gen.go +++ b/internal/service/route53domains/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package route53domains diff --git a/internal/service/route53profiles/service_endpoint_resolver_gen.go b/internal/service/route53profiles/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..d15c75fb9dc --- /dev/null +++ b/internal/service/route53profiles/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package route53profiles + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + route53profiles_sdkv2 "github.com/aws/aws-sdk-go-v2/service/route53profiles" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ route53profiles_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver route53profiles_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: route53profiles_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params route53profiles_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up route53profiles endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*route53profiles_sdkv2.Options) { + return func(o *route53profiles_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/route53profiles/service_package_gen.go b/internal/service/route53profiles/service_package_gen.go index 1bfbbc08855..c7187e55b73 100644 --- a/internal/service/route53profiles/service_package_gen.go +++ b/internal/service/route53profiles/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package route53profiles @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" route53profiles_sdkv2 "github.com/aws/aws-sdk-go-v2/service/route53profiles" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*route53profiles_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return route53profiles_sdkv2.NewFromConfig(cfg, func(o *route53profiles_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return route53profiles_sdkv2.NewFromConfig(cfg, + route53profiles_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/route53recoverycontrolconfig/service_endpoint_resolver_gen.go b/internal/service/route53recoverycontrolconfig/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a217e0f1660 --- /dev/null +++ b/internal/service/route53recoverycontrolconfig/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package route53recoverycontrolconfig + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/route53recoverycontrolconfig/service_endpoints_gen_test.go b/internal/service/route53recoverycontrolconfig/service_endpoints_gen_test.go index d913d7d0e64..3ebc393f0df 100644 --- a/internal/service/route53recoverycontrolconfig/service_endpoints_gen_test.go +++ b/internal/service/route53recoverycontrolconfig/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(route53recoverycontrolconfig_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(route53recoverycontrolconfig_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/route53recoverycontrolconfig/service_package.go b/internal/service/route53recoverycontrolconfig/service_package.go index ac38fc859e7..40b80654f04 100644 --- a/internal/service/route53recoverycontrolconfig/service_package.go +++ b/internal/service/route53recoverycontrolconfig/service_package.go @@ -6,36 +6,39 @@ package route53recoverycontrolconfig import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - route53recoverycontrolconfig_sdkv1 "github.com/aws/aws-sdk-go/service/route53recoverycontrolconfig" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/route53recoverycontrolconfig" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/names" ) // NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*route53recoverycontrolconfig_sdkv1.Route53RecoveryControlConfig, error) { - sess := config[names.AttrSession].(*session_sdkv1.Session) +func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*route53recoverycontrolconfig.Route53RecoveryControlConfig, error) { + sess := config[names.AttrSession].(*session.Session) - cfg := aws_sdkv1.Config{} + cfg := aws.Config{} if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { tflog.Debug(ctx, "setting endpoint", map[string]any{ "tf_aws.endpoint": endpoint, }) - cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + cfg.Endpoint = aws.String(endpoint) + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } // Force "global" services to correct Regions. - if config["partition"].(string) == endpoints_sdkv1.AwsPartitionID { - cfg.Region = aws_sdkv1.String(endpoints_sdkv1.UsWest2RegionID) + if config["partition"].(string) == endpoints.AwsPartitionID { + if aws.StringValue(cfg.Region) != endpoints.UsWest2RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": aws.StringValue(cfg.Region), + "override_region": endpoints.UsWest2RegionID, + }) + cfg.Region = aws.String(endpoints.UsWest2RegionID) + } } - return route53recoverycontrolconfig_sdkv1.New(sess.Copy(&cfg)), nil + return route53recoverycontrolconfig.New(sess.Copy(&cfg)), nil } diff --git a/internal/service/route53recoverycontrolconfig/service_package_gen.go b/internal/service/route53recoverycontrolconfig/service_package_gen.go index 5aeb51c243a..3fd3a00e12f 100644 --- a/internal/service/route53recoverycontrolconfig/service_package_gen.go +++ b/internal/service/route53recoverycontrolconfig/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package route53recoverycontrolconfig diff --git a/internal/service/route53recoveryreadiness/service_endpoint_resolver_gen.go b/internal/service/route53recoveryreadiness/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..6b345c4cc55 --- /dev/null +++ b/internal/service/route53recoveryreadiness/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package route53recoveryreadiness + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/route53recoveryreadiness/service_endpoints_gen_test.go b/internal/service/route53recoveryreadiness/service_endpoints_gen_test.go index 863b25c3276..293bc01bbeb 100644 --- a/internal/service/route53recoveryreadiness/service_endpoints_gen_test.go +++ b/internal/service/route53recoveryreadiness/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,14 +239,14 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(route53recoveryreadiness_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.ResolveUnknownService = true }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -254,10 +255,10 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(route53recoveryreadiness_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { @@ -265,7 +266,7 @@ func defaultFIPSEndpoint(region string) string { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -274,7 +275,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -326,16 +327,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/route53recoveryreadiness/service_package.go b/internal/service/route53recoveryreadiness/service_package.go index ef5216de999..bdf39e4607c 100644 --- a/internal/service/route53recoveryreadiness/service_package.go +++ b/internal/service/route53recoveryreadiness/service_package.go @@ -6,36 +6,39 @@ package route53recoveryreadiness import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - route53recoveryreadiness_sdkv1 "github.com/aws/aws-sdk-go/service/route53recoveryreadiness" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/route53recoveryreadiness" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/names" ) // NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*route53recoveryreadiness_sdkv1.Route53RecoveryReadiness, error) { - sess := config[names.AttrSession].(*session_sdkv1.Session) +func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*route53recoveryreadiness.Route53RecoveryReadiness, error) { + sess := config[names.AttrSession].(*session.Session) - cfg := aws_sdkv1.Config{} + cfg := aws.Config{} if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { tflog.Debug(ctx, "setting endpoint", map[string]any{ "tf_aws.endpoint": endpoint, }) - cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + cfg.Endpoint = aws.String(endpoint) + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } // Force "global" services to correct Regions. - if config["partition"].(string) == endpoints_sdkv1.AwsPartitionID { - cfg.Region = aws_sdkv1.String(endpoints_sdkv1.UsWest2RegionID) + if config["partition"].(string) == endpoints.AwsPartitionID { + if aws.StringValue(cfg.Region) != endpoints.UsWest2RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": aws.StringValue(cfg.Region), + "override_region": endpoints.UsWest2RegionID, + }) + cfg.Region = aws.String(endpoints.UsWest2RegionID) + } } - return route53recoveryreadiness_sdkv1.New(sess.Copy(&cfg)), nil + return route53recoveryreadiness.New(sess.Copy(&cfg)), nil } diff --git a/internal/service/route53recoveryreadiness/service_package_gen.go b/internal/service/route53recoveryreadiness/service_package_gen.go index b4c1981689c..f8beee79246 100644 --- a/internal/service/route53recoveryreadiness/service_package_gen.go +++ b/internal/service/route53recoveryreadiness/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package route53recoveryreadiness diff --git a/internal/service/route53resolver/service_endpoint_resolver_gen.go b/internal/service/route53resolver/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..c6ac13e09fe --- /dev/null +++ b/internal/service/route53resolver/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package route53resolver + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/route53resolver/service_endpoints_gen_test.go b/internal/service/route53resolver/service_endpoints_gen_test.go index d774666c5d6..2f319bf1548 100644 --- a/internal/service/route53resolver/service_endpoints_gen_test.go +++ b/internal/service/route53resolver/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(route53resolver_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(route53resolver_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/route53resolver/service_package_gen.go b/internal/service/route53resolver/service_package_gen.go index d0c0fd7db3c..358ef8563a1 100644 --- a/internal/service/route53resolver/service_package_gen.go +++ b/internal/service/route53resolver/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package route53resolver @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" route53resolver_sdkv1 "github.com/aws/aws-sdk-go/service/route53resolver" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -158,11 +157,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*r "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return route53resolver_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/rum/service_endpoint_resolver_gen.go b/internal/service/rum/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1c954121cf4 --- /dev/null +++ b/internal/service/rum/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package rum + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + rum_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rum" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ rum_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver rum_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: rum_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params rum_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up rum endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*rum_sdkv2.Options) { + return func(o *rum_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/rum/service_endpoints_gen_test.go b/internal/service/rum/service_endpoints_gen_test.go index bc01c610bff..30590c71de8 100644 --- a/internal/service/rum/service_endpoints_gen_test.go +++ b/internal/service/rum/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := rum_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rum_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := rum_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), rum_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/rum/service_package_gen.go b/internal/service/rum/service_package_gen.go index 27ae33426ae..45c6405a230 100644 --- a/internal/service/rum/service_package_gen.go +++ b/internal/service/rum/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package rum @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" rum_sdkv2 "github.com/aws/aws-sdk-go-v2/service/rum" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -53,19 +52,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*rum_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return rum_sdkv2.NewFromConfig(cfg, func(o *rum_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return rum_sdkv2.NewFromConfig(cfg, + rum_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/s3/service_endpoint_resolver_gen.go b/internal/service/s3/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..85140be3a69 --- /dev/null +++ b/internal/service/s3/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package s3 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + s3_sdkv2 "github.com/aws/aws-sdk-go-v2/service/s3" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ s3_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver s3_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: s3_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params s3_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up s3 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*s3_sdkv2.Options) { + return func(o *s3_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/s3/service_endpoints_gen_test.go b/internal/service/s3/service_endpoints_gen_test.go index b4deec6125a..f86ff5a6435 100644 --- a/internal/service/s3/service_endpoints_gen_test.go +++ b/internal/service/s3/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -93,7 +95,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -398,7 +400,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -419,24 +421,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := s3_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), s3_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := s3_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), s3_sdkv2.EndpointParameters{ @@ -444,14 +446,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -540,16 +542,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/s3/service_package.go b/internal/service/s3/service_package.go index b6a546256b7..0c9b6d78f72 100644 --- a/internal/service/s3/service_package.go +++ b/internal/service/s3/service_package.go @@ -19,29 +19,27 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*s3.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return s3.NewFromConfig(cfg, func(o *s3.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled + return s3.NewFromConfig(cfg, + s3.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *s3.Options) { + if o.Region == names.USEast1RegionID && config["s3_us_east_1_regional_endpoint"].(string) != "regional" { + // Maintain the AWS SDK for Go v1 default of using the global endpoint in us-east-1. + // See https://github.com/hashicorp/terraform-provider-aws/issues/33028. + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.GlobalRegionID, + }) + o.Region = names.GlobalRegionID } - } else if o.Region == names.USEast1RegionID && config["s3_us_east_1_regional_endpoint"].(string) != "regional" { - // Maintain the AWS SDK for Go v1 default of using the global endpoint in us-east-1. - // See https://github.com/hashicorp/terraform-provider-aws/issues/33028. - o.Region = names.GlobalRegionID - } - o.UsePathStyle = config["s3_use_path_style"].(bool) + o.UsePathStyle = config["s3_use_path_style"].(bool) - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if tfawserr.ErrMessageContains(err, errCodeOperationAborted, "A conflicting conditional operation is currently in progress against this resource. Please try again.") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if tfawserr.ErrMessageContains(err, errCodeOperationAborted, "A conflicting conditional operation is currently in progress against this resource. Please try again.") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/s3/service_package_gen.go b/internal/service/s3/service_package_gen.go index 4a8a6584983..ce97c095153 100644 --- a/internal/service/s3/service_package_gen.go +++ b/internal/service/s3/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package s3 diff --git a/internal/service/s3control/service_endpoint_resolver_gen.go b/internal/service/s3control/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2446353f251 --- /dev/null +++ b/internal/service/s3control/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package s3control + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + s3control_sdkv2 "github.com/aws/aws-sdk-go-v2/service/s3control" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ s3control_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver s3control_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: s3control_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params s3control_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up s3control endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*s3control_sdkv2.Options) { + return func(o *s3control_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/s3control/service_package_gen.go b/internal/service/s3control/service_package_gen.go index 54976b944a0..f0eb92a7942 100644 --- a/internal/service/s3control/service_package_gen.go +++ b/internal/service/s3control/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package s3control @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" s3control_sdkv2 "github.com/aws/aws-sdk-go-v2/service/s3control" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -119,19 +118,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*s3control_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return s3control_sdkv2.NewFromConfig(cfg, func(o *s3control_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return s3control_sdkv2.NewFromConfig(cfg, + s3control_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/s3outposts/service_endpoint_resolver_gen.go b/internal/service/s3outposts/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a000d80130b --- /dev/null +++ b/internal/service/s3outposts/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package s3outposts + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/s3outposts/service_endpoints_gen_test.go b/internal/service/s3outposts/service_endpoints_gen_test.go index ae3e984c6da..081d3144981 100644 --- a/internal/service/s3outposts/service_endpoints_gen_test.go +++ b/internal/service/s3outposts/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(s3outposts_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(s3outposts_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/s3outposts/service_package_gen.go b/internal/service/s3outposts/service_package_gen.go index 0071c7a290e..50b41b2ebde 100644 --- a/internal/service/s3outposts/service_package_gen.go +++ b/internal/service/s3outposts/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package s3outposts @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" s3outposts_sdkv1 "github.com/aws/aws-sdk-go/service/s3outposts" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -53,11 +52,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return s3outposts_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/sagemaker/service_endpoint_resolver_gen.go b/internal/service/sagemaker/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f6fe9d90139 --- /dev/null +++ b/internal/service/sagemaker/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package sagemaker + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/sagemaker/service_endpoints_gen_test.go b/internal/service/sagemaker/service_endpoints_gen_test.go index 225b319dfd1..cf13517d23f 100644 --- a/internal/service/sagemaker/service_endpoints_gen_test.go +++ b/internal/service/sagemaker/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(sagemaker_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(sagemaker_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/sagemaker/service_package_gen.go b/internal/service/sagemaker/service_package_gen.go index a8533b5b26a..fa620ff3602 100644 --- a/internal/service/sagemaker/service_package_gen.go +++ b/internal/service/sagemaker/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package sagemaker @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" sagemaker_sdkv1 "github.com/aws/aws-sdk-go/service/sagemaker" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -253,11 +252,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return sagemaker_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/scheduler/service_endpoint_resolver_gen.go b/internal/service/scheduler/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..44b5b63e288 --- /dev/null +++ b/internal/service/scheduler/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package scheduler + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + scheduler_sdkv2 "github.com/aws/aws-sdk-go-v2/service/scheduler" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ scheduler_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver scheduler_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: scheduler_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params scheduler_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up scheduler endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*scheduler_sdkv2.Options) { + return func(o *scheduler_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/scheduler/service_endpoints_gen_test.go b/internal/service/scheduler/service_endpoints_gen_test.go index 1215f07b26b..a4a51a32daf 100644 --- a/internal/service/scheduler/service_endpoints_gen_test.go +++ b/internal/service/scheduler/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := scheduler_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), scheduler_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := scheduler_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), scheduler_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/scheduler/service_package_gen.go b/internal/service/scheduler/service_package_gen.go index 5b9841bd3b8..ec194e82f3d 100644 --- a/internal/service/scheduler/service_package_gen.go +++ b/internal/service/scheduler/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package scheduler @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" scheduler_sdkv2 "github.com/aws/aws-sdk-go-v2/service/scheduler" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -52,19 +51,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*scheduler_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return scheduler_sdkv2.NewFromConfig(cfg, func(o *scheduler_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return scheduler_sdkv2.NewFromConfig(cfg, + scheduler_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/schemas/service_endpoint_resolver_gen.go b/internal/service/schemas/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..7cc298f1c7d --- /dev/null +++ b/internal/service/schemas/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package schemas + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + schemas_sdkv2 "github.com/aws/aws-sdk-go-v2/service/schemas" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ schemas_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver schemas_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: schemas_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params schemas_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up schemas endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*schemas_sdkv2.Options) { + return func(o *schemas_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/schemas/service_endpoints_gen_test.go b/internal/service/schemas/service_endpoints_gen_test.go index 91dd282436a..81388037caa 100644 --- a/internal/service/schemas/service_endpoints_gen_test.go +++ b/internal/service/schemas/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := schemas_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), schemas_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := schemas_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), schemas_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/schemas/service_package.go b/internal/service/schemas/service_package.go index 835a6b8c35f..7b949c08f55 100644 --- a/internal/service/schemas/service_package.go +++ b/internal/service/schemas/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/schemas" awstypes "github.com/aws/aws-sdk-go-v2/service/schemas/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*schemas.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return schemas.NewFromConfig(cfg, func(o *schemas.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsAErrorMessageContains[*awstypes.TooManyRequestsException](err, "Too Many Requests") { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return schemas.NewFromConfig(cfg, + schemas.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *schemas.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*awstypes.TooManyRequestsException](err, "Too Many Requests") { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/schemas/service_package_gen.go b/internal/service/schemas/service_package_gen.go index f3c5f3d266e..16633fbe0a4 100644 --- a/internal/service/schemas/service_package_gen.go +++ b/internal/service/schemas/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package schemas diff --git a/internal/service/secretsmanager/service_endpoint_resolver_gen.go b/internal/service/secretsmanager/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1bbe5694033 --- /dev/null +++ b/internal/service/secretsmanager/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package secretsmanager + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + secretsmanager_sdkv2 "github.com/aws/aws-sdk-go-v2/service/secretsmanager" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ secretsmanager_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver secretsmanager_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: secretsmanager_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params secretsmanager_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up secretsmanager endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*secretsmanager_sdkv2.Options) { + return func(o *secretsmanager_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/secretsmanager/service_endpoints_gen_test.go b/internal/service/secretsmanager/service_endpoints_gen_test.go index bec95418b18..c16b66c3db2 100644 --- a/internal/service/secretsmanager/service_endpoints_gen_test.go +++ b/internal/service/secretsmanager/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := secretsmanager_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), secretsmanager_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := secretsmanager_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), secretsmanager_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index d2bd84724c2..9606e9732fb 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package secretsmanager @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" secretsmanager_sdkv2 "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -92,19 +91,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*secretsmanager_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return secretsmanager_sdkv2.NewFromConfig(cfg, func(o *secretsmanager_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return secretsmanager_sdkv2.NewFromConfig(cfg, + secretsmanager_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/securityhub/service_endpoint_resolver_gen.go b/internal/service/securityhub/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..260276a3d68 --- /dev/null +++ b/internal/service/securityhub/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package securityhub + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + securityhub_sdkv2 "github.com/aws/aws-sdk-go-v2/service/securityhub" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ securityhub_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver securityhub_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: securityhub_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params securityhub_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up securityhub endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*securityhub_sdkv2.Options) { + return func(o *securityhub_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/securityhub/service_endpoints_gen_test.go b/internal/service/securityhub/service_endpoints_gen_test.go index 1a00849e38e..944ac88fa5b 100644 --- a/internal/service/securityhub/service_endpoints_gen_test.go +++ b/internal/service/securityhub/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := securityhub_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), securityhub_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := securityhub_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), securityhub_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/securityhub/service_package_gen.go b/internal/service/securityhub/service_package_gen.go index 74a3f26e8f2..60cac89f0bb 100644 --- a/internal/service/securityhub/service_package_gen.go +++ b/internal/service/securityhub/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package securityhub @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" securityhub_sdkv2 "github.com/aws/aws-sdk-go-v2/service/securityhub" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -113,19 +112,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*securityhub_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return securityhub_sdkv2.NewFromConfig(cfg, func(o *securityhub_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return securityhub_sdkv2.NewFromConfig(cfg, + securityhub_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/securitylake/service_endpoint_resolver_gen.go b/internal/service/securitylake/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..3b3ebacd62b --- /dev/null +++ b/internal/service/securitylake/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package securitylake + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + securitylake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/securitylake" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ securitylake_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver securitylake_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: securitylake_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params securitylake_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up securitylake endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*securitylake_sdkv2.Options) { + return func(o *securitylake_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/securitylake/service_endpoints_gen_test.go b/internal/service/securitylake/service_endpoints_gen_test.go index c1c150dfff9..5ae32c53f8d 100644 --- a/internal/service/securitylake/service_endpoints_gen_test.go +++ b/internal/service/securitylake/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := securitylake_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), securitylake_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := securitylake_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), securitylake_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/securitylake/service_package_gen.go b/internal/service/securitylake/service_package_gen.go index af67ea2acda..1e3b5cb5d1f 100644 --- a/internal/service/securitylake/service_package_gen.go +++ b/internal/service/securitylake/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package securitylake @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" securitylake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/securitylake" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -66,19 +65,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*securitylake_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return securitylake_sdkv2.NewFromConfig(cfg, func(o *securitylake_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return securitylake_sdkv2.NewFromConfig(cfg, + securitylake_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/serverlessrepo/service_endpoint_resolver_gen.go b/internal/service/serverlessrepo/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..fa10cf95508 --- /dev/null +++ b/internal/service/serverlessrepo/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package serverlessrepo + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/serverlessrepo/service_endpoints_gen_test.go b/internal/service/serverlessrepo/service_endpoints_gen_test.go index 7f6f71b8f95..c47e0c0ead2 100644 --- a/internal/service/serverlessrepo/service_endpoints_gen_test.go +++ b/internal/service/serverlessrepo/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -90,7 +91,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -330,7 +331,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -351,12 +352,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(serverlessapplicationrepository_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -365,17 +366,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(serverlessapplicationrepository_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -384,7 +385,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -466,16 +467,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/serverlessrepo/service_package_gen.go b/internal/service/serverlessrepo/service_package_gen.go index 261c14f2597..f96cff203bb 100644 --- a/internal/service/serverlessrepo/service_package_gen.go +++ b/internal/service/serverlessrepo/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package serverlessrepo @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" serverlessapplicationrepository_sdkv1 "github.com/aws/aws-sdk-go/service/serverlessapplicationrepository" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -60,11 +59,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return serverlessapplicationrepository_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/servicecatalog/service_endpoint_resolver_gen.go b/internal/service/servicecatalog/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..755ba5228f8 --- /dev/null +++ b/internal/service/servicecatalog/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package servicecatalog + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/servicecatalog/service_endpoints_gen_test.go b/internal/service/servicecatalog/service_endpoints_gen_test.go index 0bdec1330e5..8f361b45fc2 100644 --- a/internal/service/servicecatalog/service_endpoints_gen_test.go +++ b/internal/service/servicecatalog/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(servicecatalog_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(servicecatalog_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/servicecatalog/service_package_gen.go b/internal/service/servicecatalog/service_package_gen.go index 7b45ebd3169..3f91af76c0f 100644 --- a/internal/service/servicecatalog/service_package_gen.go +++ b/internal/service/servicecatalog/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package servicecatalog @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" servicecatalog_sdkv1 "github.com/aws/aws-sdk-go/service/servicecatalog" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -134,11 +133,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return servicecatalog_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/servicecatalogappregistry/service_endpoint_resolver_gen.go b/internal/service/servicecatalogappregistry/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f1bb6b26621 --- /dev/null +++ b/internal/service/servicecatalogappregistry/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package servicecatalogappregistry + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + servicecatalogappregistry_sdkv2 "github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ servicecatalogappregistry_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver servicecatalogappregistry_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: servicecatalogappregistry_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params servicecatalogappregistry_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up servicecatalogappregistry endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*servicecatalogappregistry_sdkv2.Options) { + return func(o *servicecatalogappregistry_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/servicecatalogappregistry/service_endpoints_gen_test.go b/internal/service/servicecatalogappregistry/service_endpoints_gen_test.go index 07a988a5a4a..66220fd8c54 100644 --- a/internal/service/servicecatalogappregistry/service_endpoints_gen_test.go +++ b/internal/service/servicecatalogappregistry/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := servicecatalogappregistry_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), servicecatalogappregistry_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := servicecatalogappregistry_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), servicecatalogappregistry_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/servicecatalogappregistry/service_package_gen.go b/internal/service/servicecatalogappregistry/service_package_gen.go index 9e75da24839..affcfd818e4 100644 --- a/internal/service/servicecatalogappregistry/service_package_gen.go +++ b/internal/service/servicecatalogappregistry/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package servicecatalogappregistry @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" servicecatalogappregistry_sdkv2 "github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -49,19 +48,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*servicecatalogappregistry_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return servicecatalogappregistry_sdkv2.NewFromConfig(cfg, func(o *servicecatalogappregistry_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return servicecatalogappregistry_sdkv2.NewFromConfig(cfg, + servicecatalogappregistry_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/servicediscovery/service_endpoint_resolver_gen.go b/internal/service/servicediscovery/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..55fb327fef9 --- /dev/null +++ b/internal/service/servicediscovery/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package servicediscovery + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + servicediscovery_sdkv2 "github.com/aws/aws-sdk-go-v2/service/servicediscovery" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ servicediscovery_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver servicediscovery_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: servicediscovery_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params servicediscovery_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up servicediscovery endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*servicediscovery_sdkv2.Options) { + return func(o *servicediscovery_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/servicediscovery/service_endpoints_gen_test.go b/internal/service/servicediscovery/service_endpoints_gen_test.go index b8d5b97bdf9..13c0161c27f 100644 --- a/internal/service/servicediscovery/service_endpoints_gen_test.go +++ b/internal/service/servicediscovery/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := servicediscovery_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), servicediscovery_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := servicediscovery_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), servicediscovery_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/servicediscovery/service_package_gen.go b/internal/service/servicediscovery/service_package_gen.go index 00be99ea9d5..a6a8c608190 100644 --- a/internal/service/servicediscovery/service_package_gen.go +++ b/internal/service/servicediscovery/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package servicediscovery @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" servicediscovery_sdkv2 "github.com/aws/aws-sdk-go-v2/service/servicediscovery" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -93,19 +92,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*servicediscovery_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return servicediscovery_sdkv2.NewFromConfig(cfg, func(o *servicediscovery_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return servicediscovery_sdkv2.NewFromConfig(cfg, + servicediscovery_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/servicequotas/service_endpoint_resolver_gen.go b/internal/service/servicequotas/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f461cb7eb56 --- /dev/null +++ b/internal/service/servicequotas/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package servicequotas + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + servicequotas_sdkv2 "github.com/aws/aws-sdk-go-v2/service/servicequotas" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ servicequotas_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver servicequotas_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: servicequotas_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params servicequotas_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up servicequotas endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*servicequotas_sdkv2.Options) { + return func(o *servicequotas_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/servicequotas/service_endpoints_gen_test.go b/internal/service/servicequotas/service_endpoints_gen_test.go index 8dce10beac3..172d188825f 100644 --- a/internal/service/servicequotas/service_endpoints_gen_test.go +++ b/internal/service/servicequotas/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := servicequotas_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), servicequotas_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := servicequotas_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), servicequotas_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/servicequotas/service_package_gen.go b/internal/service/servicequotas/service_package_gen.go index bed9668566e..7f1ccd410fb 100644 --- a/internal/service/servicequotas/service_package_gen.go +++ b/internal/service/servicequotas/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package servicequotas @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" servicequotas_sdkv2 "github.com/aws/aws-sdk-go-v2/service/servicequotas" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -67,19 +66,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*servicequotas_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return servicequotas_sdkv2.NewFromConfig(cfg, func(o *servicequotas_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return servicequotas_sdkv2.NewFromConfig(cfg, + servicequotas_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ses/service_endpoint_resolver_gen.go b/internal/service/ses/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..69e9facc483 --- /dev/null +++ b/internal/service/ses/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ses + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/ses/service_endpoints_gen_test.go b/internal/service/ses/service_endpoints_gen_test.go index 1bd03cc4090..622ec129fef 100644 --- a/internal/service/ses/service_endpoints_gen_test.go +++ b/internal/service/ses/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(ses_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(ses_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ses/service_package_gen.go b/internal/service/ses/service_package_gen.go index ad16942a1f7..b062a6b2a30 100644 --- a/internal/service/ses/service_package_gen.go +++ b/internal/service/ses/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ses @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" ses_sdkv1 "github.com/aws/aws-sdk-go/service/ses" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -118,11 +117,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return ses_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/sesv2/service_endpoint_resolver_gen.go b/internal/service/sesv2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..9ca7f81bec2 --- /dev/null +++ b/internal/service/sesv2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package sesv2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + sesv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sesv2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ sesv2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver sesv2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: sesv2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params sesv2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up sesv2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*sesv2_sdkv2.Options) { + return func(o *sesv2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/sesv2/service_endpoints_gen_test.go b/internal/service/sesv2/service_endpoints_gen_test.go index bebd1c41fcc..f95a22b454b 100644 --- a/internal/service/sesv2/service_endpoints_gen_test.go +++ b/internal/service/sesv2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := sesv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sesv2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := sesv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sesv2_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/sesv2/service_package_gen.go b/internal/service/sesv2/service_package_gen.go index fa74819686b..4fb43b1fecb 100644 --- a/internal/service/sesv2/service_package_gen.go +++ b/internal/service/sesv2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package sesv2 @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" sesv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sesv2" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -118,19 +117,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*sesv2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return sesv2_sdkv2.NewFromConfig(cfg, func(o *sesv2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return sesv2_sdkv2.NewFromConfig(cfg, + sesv2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/sfn/service_endpoint_resolver_gen.go b/internal/service/sfn/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..86fc99340c6 --- /dev/null +++ b/internal/service/sfn/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package sfn + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/sfn/service_endpoints_gen_test.go b/internal/service/sfn/service_endpoints_gen_test.go index 146be236e96..8ba9624aa47 100644 --- a/internal/service/sfn/service_endpoints_gen_test.go +++ b/internal/service/sfn/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -88,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -271,7 +272,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -292,12 +293,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(sfn_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -306,17 +307,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(sfn_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -325,7 +326,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -396,16 +397,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/sfn/service_package_gen.go b/internal/service/sfn/service_package_gen.go index 894c7ea6ac7..c99679407be 100644 --- a/internal/service/sfn/service_package_gen.go +++ b/internal/service/sfn/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package sfn @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" sfn_sdkv1 "github.com/aws/aws-sdk-go/service/sfn" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -86,11 +85,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return sfn_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/shield/service_endpoint_resolver_gen.go b/internal/service/shield/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..c5b364751a9 --- /dev/null +++ b/internal/service/shield/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package shield + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + shield_sdkv2 "github.com/aws/aws-sdk-go-v2/service/shield" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ shield_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver shield_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: shield_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params shield_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up shield endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*shield_sdkv2.Options) { + return func(o *shield_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/shield/service_endpoints_gen_test.go b/internal/service/shield/service_endpoints_gen_test.go index 9a6a0d0937f..b3b2acfbecd 100644 --- a/internal/service/shield/service_endpoints_gen_test.go +++ b/internal/service/shield/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := shield_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), shield_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := shield_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), shield_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/shield/service_package.go b/internal/service/shield/service_package.go index a4f0521be0f..675d3e9e449 100644 --- a/internal/service/shield/service_package.go +++ b/internal/service/shield/service_package.go @@ -16,22 +16,20 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*shield.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - // Force "global" services to correct Regions. - if config["partition"].(string) == names.StandardPartitionID { - cfg.Region = names.USEast1RegionID - } - - return shield.NewFromConfig(cfg, func(o *shield.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled + return shield.NewFromConfig(cfg, + shield.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *shield.Options) { + // Force "global" services to correct Regions. + if config["partition"].(string) == names.StandardPartitionID { + if cfg.Region != names.USEast1RegionID { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": names.USEast1RegionID, + }) + o.Region = names.USEast1RegionID + } } - } - }), nil + }, + ), nil } diff --git a/internal/service/shield/service_package_gen.go b/internal/service/shield/service_package_gen.go index 5ff95a39e3c..b68127ffff0 100644 --- a/internal/service/shield/service_package_gen.go +++ b/internal/service/shield/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package shield diff --git a/internal/service/signer/service_endpoint_resolver_gen.go b/internal/service/signer/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..298c6e9901e --- /dev/null +++ b/internal/service/signer/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package signer + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + signer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/signer" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ signer_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver signer_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: signer_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params signer_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up signer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*signer_sdkv2.Options) { + return func(o *signer_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/signer/service_endpoints_gen_test.go b/internal/service/signer/service_endpoints_gen_test.go index 8877c145270..4b785ccd0fc 100644 --- a/internal/service/signer/service_endpoints_gen_test.go +++ b/internal/service/signer/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := signer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), signer_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := signer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), signer_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/signer/service_package_gen.go b/internal/service/signer/service_package_gen.go index 7574543d6a9..b5629cb5327 100644 --- a/internal/service/signer/service_package_gen.go +++ b/internal/service/signer/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package signer @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" signer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/signer" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -65,19 +64,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*signer_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return signer_sdkv2.NewFromConfig(cfg, func(o *signer_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return signer_sdkv2.NewFromConfig(cfg, + signer_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/simpledb/service_endpoint_resolver_gen.go b/internal/service/simpledb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a046e07c6c9 --- /dev/null +++ b/internal/service/simpledb/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package simpledb + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/simpledb/service_endpoints_gen_test.go b/internal/service/simpledb/service_endpoints_gen_test.go index 65786f2819d..d8083cc2992 100644 --- a/internal/service/simpledb/service_endpoints_gen_test.go +++ b/internal/service/simpledb/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -88,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -271,7 +272,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -292,12 +293,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(simpledb_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -306,17 +307,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(simpledb_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -325,7 +326,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -396,16 +397,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/simpledb/service_package_gen.go b/internal/service/simpledb/service_package_gen.go index d3c1ecf5893..2f25ee7b39f 100644 --- a/internal/service/simpledb/service_package_gen.go +++ b/internal/service/simpledb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package simpledb @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" simpledb_sdkv1 "github.com/aws/aws-sdk-go/service/simpledb" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -52,11 +51,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return simpledb_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/sns/service_endpoint_resolver_gen.go b/internal/service/sns/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..2d7084ab7b6 --- /dev/null +++ b/internal/service/sns/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package sns + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + sns_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sns" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ sns_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver sns_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: sns_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params sns_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up sns endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*sns_sdkv2.Options) { + return func(o *sns_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/sns/service_endpoints_gen_test.go b/internal/service/sns/service_endpoints_gen_test.go index c0a08d95c41..cc432e099d6 100644 --- a/internal/service/sns/service_endpoints_gen_test.go +++ b/internal/service/sns/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := sns_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sns_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := sns_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sns_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/sns/service_package_gen.go b/internal/service/sns/service_package_gen.go index 8b643de6661..732d3b2a793 100644 --- a/internal/service/sns/service_package_gen.go +++ b/internal/service/sns/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package sns @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" sns_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sns" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -73,19 +72,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*sns_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return sns_sdkv2.NewFromConfig(cfg, func(o *sns_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return sns_sdkv2.NewFromConfig(cfg, + sns_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/sqs/service_endpoint_resolver_gen.go b/internal/service/sqs/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..cbbbf1ebfc7 --- /dev/null +++ b/internal/service/sqs/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package sqs + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + sqs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sqs" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ sqs_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver sqs_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: sqs_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params sqs_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up sqs endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*sqs_sdkv2.Options) { + return func(o *sqs_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/sqs/service_endpoints_gen_test.go b/internal/service/sqs/service_endpoints_gen_test.go index 540b319ec6f..f10a5421d62 100644 --- a/internal/service/sqs/service_endpoints_gen_test.go +++ b/internal/service/sqs/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := sqs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sqs_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := sqs_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sqs_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/sqs/service_package_gen.go b/internal/service/sqs/service_package_gen.go index d9af2ca4333..66485af9376 100644 --- a/internal/service/sqs/service_package_gen.go +++ b/internal/service/sqs/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package sqs @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" sqs_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sqs" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -72,19 +71,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*sqs_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return sqs_sdkv2.NewFromConfig(cfg, func(o *sqs_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return sqs_sdkv2.NewFromConfig(cfg, + sqs_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ssm/service_endpoint_resolver_gen.go b/internal/service/ssm/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e40aad9a4db --- /dev/null +++ b/internal/service/ssm/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ssm + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ssm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssm" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ssm_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ssm_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ssm_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ssm_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ssm endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ssm_sdkv2.Options) { + return func(o *ssm_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ssm/service_endpoints_gen_test.go b/internal/service/ssm/service_endpoints_gen_test.go index dc8de4b23d1..c325e7ec88d 100644 --- a/internal/service/ssm/service_endpoints_gen_test.go +++ b/internal/service/ssm/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ssm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssm_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ssm_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssm_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ssm/service_package_gen.go b/internal/service/ssm/service_package_gen.go index 9ffd8c4e99d..c5a58dabe7c 100644 --- a/internal/service/ssm/service_package_gen.go +++ b/internal/service/ssm/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ssm @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ssm_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssm" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -148,19 +147,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ssm_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ssm_sdkv2.NewFromConfig(cfg, func(o *ssm_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ssm_sdkv2.NewFromConfig(cfg, + ssm_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ssmcontacts/service_endpoint_resolver_gen.go b/internal/service/ssmcontacts/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..eb359b3c3bd --- /dev/null +++ b/internal/service/ssmcontacts/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ssmcontacts + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ssmcontacts_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssmcontacts" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ssmcontacts_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ssmcontacts_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ssmcontacts_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ssmcontacts_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ssmcontacts endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ssmcontacts_sdkv2.Options) { + return func(o *ssmcontacts_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ssmcontacts/service_endpoints_gen_test.go b/internal/service/ssmcontacts/service_endpoints_gen_test.go index b6f42a04648..e824fe850d8 100644 --- a/internal/service/ssmcontacts/service_endpoints_gen_test.go +++ b/internal/service/ssmcontacts/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ssmcontacts_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssmcontacts_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ssmcontacts_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssmcontacts_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ssmcontacts/service_package_gen.go b/internal/service/ssmcontacts/service_package_gen.go index 3800192a8e8..9211147a0f4 100644 --- a/internal/service/ssmcontacts/service_package_gen.go +++ b/internal/service/ssmcontacts/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ssmcontacts @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ssmcontacts_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssmcontacts" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -84,19 +83,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ssmcontacts_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ssmcontacts_sdkv2.NewFromConfig(cfg, func(o *ssmcontacts_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ssmcontacts_sdkv2.NewFromConfig(cfg, + ssmcontacts_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ssmincidents/service_endpoint_resolver_gen.go b/internal/service/ssmincidents/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..873f96d0978 --- /dev/null +++ b/internal/service/ssmincidents/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ssmincidents + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ssmincidents_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssmincidents" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ssmincidents_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ssmincidents_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ssmincidents_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ssmincidents_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ssmincidents endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ssmincidents_sdkv2.Options) { + return func(o *ssmincidents_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ssmincidents/service_endpoints_gen_test.go b/internal/service/ssmincidents/service_endpoints_gen_test.go index 7838c83f4f3..10a11fa8e26 100644 --- a/internal/service/ssmincidents/service_endpoints_gen_test.go +++ b/internal/service/ssmincidents/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ssmincidents_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssmincidents_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ssmincidents_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssmincidents_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ssmincidents/service_package_gen.go b/internal/service/ssmincidents/service_package_gen.go index 52ae518b8f5..af1214566f8 100644 --- a/internal/service/ssmincidents/service_package_gen.go +++ b/internal/service/ssmincidents/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ssmincidents @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ssmincidents_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssmincidents" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -65,19 +64,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ssmincidents_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ssmincidents_sdkv2.NewFromConfig(cfg, func(o *ssmincidents_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ssmincidents_sdkv2.NewFromConfig(cfg, + ssmincidents_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ssmsap/service_endpoint_resolver_gen.go b/internal/service/ssmsap/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b0849ab8fbd --- /dev/null +++ b/internal/service/ssmsap/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ssmsap + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ssmsap_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssmsap" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ssmsap_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ssmsap_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ssmsap_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ssmsap_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ssmsap endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ssmsap_sdkv2.Options) { + return func(o *ssmsap_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ssmsap/service_endpoints_gen_test.go b/internal/service/ssmsap/service_endpoints_gen_test.go index 4cf4aa2f168..1d313c57f4e 100644 --- a/internal/service/ssmsap/service_endpoints_gen_test.go +++ b/internal/service/ssmsap/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ssmsap_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssmsap_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ssmsap_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssmsap_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ssmsap/service_package_gen.go b/internal/service/ssmsap/service_package_gen.go index feb9f8e7c85..113b09ac754 100644 --- a/internal/service/ssmsap/service_package_gen.go +++ b/internal/service/ssmsap/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ssmsap @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" ssmsap_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssmsap" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ssmsap_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return ssmsap_sdkv2.NewFromConfig(cfg, func(o *ssmsap_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return ssmsap_sdkv2.NewFromConfig(cfg, + ssmsap_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/sso/service_endpoint_resolver_gen.go b/internal/service/sso/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a2318fec977 --- /dev/null +++ b/internal/service/sso/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package sso + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + sso_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sso" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ sso_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver sso_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: sso_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params sso_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up sso endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*sso_sdkv2.Options) { + return func(o *sso_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/sso/service_endpoints_gen_test.go b/internal/service/sso/service_endpoints_gen_test.go index 02c05f5a9f6..79d5f3e7e2c 100644 --- a/internal/service/sso/service_endpoints_gen_test.go +++ b/internal/service/sso/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := sso_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sso_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := sso_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sso_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/sso/service_package_gen.go b/internal/service/sso/service_package_gen.go index 2d6446fa84f..5ca1868e97b 100644 --- a/internal/service/sso/service_package_gen.go +++ b/internal/service/sso/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package sso @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" sso_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sso" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*sso_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return sso_sdkv2.NewFromConfig(cfg, func(o *sso_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return sso_sdkv2.NewFromConfig(cfg, + sso_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/ssoadmin/service_endpoint_resolver_gen.go b/internal/service/ssoadmin/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..01948c036ac --- /dev/null +++ b/internal/service/ssoadmin/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package ssoadmin + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + ssoadmin_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ssoadmin" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ ssoadmin_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver ssoadmin_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: ssoadmin_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params ssoadmin_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up ssoadmin endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*ssoadmin_sdkv2.Options) { + return func(o *ssoadmin_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/ssoadmin/service_endpoints_gen_test.go b/internal/service/ssoadmin/service_endpoints_gen_test.go index 38bc6ae7838..772732ce7b7 100644 --- a/internal/service/ssoadmin/service_endpoints_gen_test.go +++ b/internal/service/ssoadmin/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := ssoadmin_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssoadmin_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := ssoadmin_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), ssoadmin_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/ssoadmin/service_package.go b/internal/service/ssoadmin/service_package.go index 39e67981787..17763dd8e3b 100644 --- a/internal/service/ssoadmin/service_package.go +++ b/internal/service/ssoadmin/service_package.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/service/ssoadmin" "github.com/aws/aws-sdk-go-v2/service/ssoadmin/types" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/names" @@ -20,24 +19,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*ssoadmin.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return ssoadmin.NewFromConfig(cfg, func(o *ssoadmin.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled - } - } - - o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { - if errs.IsA[*types.ConflictException](err) || errs.IsA[*types.ThrottlingException](err) { - return aws.TrueTernary - } - return aws.UnknownTernary // Delegate to configured Retryer. - })) - }), nil + return ssoadmin.NewFromConfig(cfg, + ssoadmin.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *ssoadmin.Options) { + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsA[*types.ConflictException](err) || errs.IsA[*types.ThrottlingException](err) { + return aws.TrueTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + })) + }, + ), nil } diff --git a/internal/service/ssoadmin/service_package_gen.go b/internal/service/ssoadmin/service_package_gen.go index 1e9e6270764..36ad7d588d0 100644 --- a/internal/service/ssoadmin/service_package_gen.go +++ b/internal/service/ssoadmin/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package ssoadmin diff --git a/internal/service/storagegateway/service_endpoint_resolver_gen.go b/internal/service/storagegateway/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..d9b168c2ab4 --- /dev/null +++ b/internal/service/storagegateway/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package storagegateway + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/storagegateway/service_endpoints_gen_test.go b/internal/service/storagegateway/service_endpoints_gen_test.go index 35af5385d53..2cb9cbabdca 100644 --- a/internal/service/storagegateway/service_endpoints_gen_test.go +++ b/internal/service/storagegateway/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,12 +239,12 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(storagegateway_sdkv1.EndpointsID, region) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -252,17 +253,17 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(storagegateway_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -271,7 +272,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -323,16 +324,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/storagegateway/service_package_gen.go b/internal/service/storagegateway/service_package_gen.go index 3b41091f9e0..2c934e1c284 100644 --- a/internal/service/storagegateway/service_package_gen.go +++ b/internal/service/storagegateway/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package storagegateway @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" storagegateway_sdkv1 "github.com/aws/aws-sdk-go/service/storagegateway" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -126,11 +125,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*s "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return storagegateway_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/sts/service_endpoint_resolver_gen.go b/internal/service/sts/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ce9a1b1df5a --- /dev/null +++ b/internal/service/sts/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package sts + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + sts_sdkv2 "github.com/aws/aws-sdk-go-v2/service/sts" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ sts_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver sts_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: sts_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params sts_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up sts endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*sts_sdkv2.Options) { + return func(o *sts_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/sts/service_endpoints_gen_test.go b/internal/service/sts/service_endpoints_gen_test.go index c8e93c286ea..02ee4a6b853 100644 --- a/internal/service/sts/service_endpoints_gen_test.go +++ b/internal/service/sts/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -90,7 +92,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -330,7 +332,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -351,24 +353,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := sts_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sts_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := sts_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), sts_sdkv2.EndpointParameters{ @@ -376,14 +378,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -453,16 +455,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/sts/service_package.go b/internal/service/sts/service_package.go index dcc11b8d87f..803f30fb751 100644 --- a/internal/service/sts/service_package.go +++ b/internal/service/sts/service_package.go @@ -16,21 +16,16 @@ import ( func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*sts.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - return sts.NewFromConfig(cfg, func(o *sts.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled + return sts.NewFromConfig(cfg, + sts.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + func(o *sts.Options) { + if stsRegion := config["sts_region"].(string); stsRegion != "" { + tflog.Info(ctx, "overriding region", map[string]any{ + "original_region": cfg.Region, + "override_region": stsRegion, + }) + o.Region = stsRegion } - } - - if stsRegion := config["sts_region"].(string); stsRegion != "" { - o.Region = stsRegion - } - }), nil + }), nil } diff --git a/internal/service/sts/service_package_gen.go b/internal/service/sts/service_package_gen.go index 87d193deb30..0eb639c351f 100644 --- a/internal/service/sts/service_package_gen.go +++ b/internal/service/sts/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package sts diff --git a/internal/service/swf/service_endpoint_resolver_gen.go b/internal/service/swf/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..f5e0da6321d --- /dev/null +++ b/internal/service/swf/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package swf + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + swf_sdkv2 "github.com/aws/aws-sdk-go-v2/service/swf" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ swf_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver swf_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: swf_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params swf_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up swf endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*swf_sdkv2.Options) { + return func(o *swf_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/swf/service_endpoints_gen_test.go b/internal/service/swf/service_endpoints_gen_test.go index 4461f401cc8..229f7560033 100644 --- a/internal/service/swf/service_endpoints_gen_test.go +++ b/internal/service/swf/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := swf_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), swf_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := swf_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), swf_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -337,16 +339,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/swf/service_package_gen.go b/internal/service/swf/service_package_gen.go index 7e913624a00..86cefe5d9b0 100644 --- a/internal/service/swf/service_package_gen.go +++ b/internal/service/swf/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package swf @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" swf_sdkv2 "github.com/aws/aws-sdk-go-v2/service/swf" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,19 +47,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*swf_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return swf_sdkv2.NewFromConfig(cfg, func(o *swf_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return swf_sdkv2.NewFromConfig(cfg, + swf_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/synthetics/service_endpoint_resolver_gen.go b/internal/service/synthetics/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1d34dd22c25 --- /dev/null +++ b/internal/service/synthetics/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package synthetics + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + synthetics_sdkv2 "github.com/aws/aws-sdk-go-v2/service/synthetics" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ synthetics_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver synthetics_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: synthetics_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params synthetics_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up synthetics endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*synthetics_sdkv2.Options) { + return func(o *synthetics_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/synthetics/service_endpoints_gen_test.go b/internal/service/synthetics/service_endpoints_gen_test.go index cc19f54ca2b..6e4c177055d 100644 --- a/internal/service/synthetics/service_endpoints_gen_test.go +++ b/internal/service/synthetics/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := synthetics_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), synthetics_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := synthetics_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), synthetics_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/synthetics/service_package_gen.go b/internal/service/synthetics/service_package_gen.go index adb76a5a24e..4c7cc2c2e56 100644 --- a/internal/service/synthetics/service_package_gen.go +++ b/internal/service/synthetics/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package synthetics @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" synthetics_sdkv2 "github.com/aws/aws-sdk-go-v2/service/synthetics" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -61,19 +60,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*synthetics_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return synthetics_sdkv2.NewFromConfig(cfg, func(o *synthetics_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return synthetics_sdkv2.NewFromConfig(cfg, + synthetics_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/timestreaminfluxdb/service_endpoint_resolver_gen.go b/internal/service/timestreaminfluxdb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..1899dc095c1 --- /dev/null +++ b/internal/service/timestreaminfluxdb/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package timestreaminfluxdb + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + timestreaminfluxdb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ timestreaminfluxdb_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver timestreaminfluxdb_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: timestreaminfluxdb_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params timestreaminfluxdb_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up timestreaminfluxdb endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*timestreaminfluxdb_sdkv2.Options) { + return func(o *timestreaminfluxdb_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/timestreaminfluxdb/service_endpoints_gen_test.go b/internal/service/timestreaminfluxdb/service_endpoints_gen_test.go index 2c2dd1f5f57..5bb3383356d 100644 --- a/internal/service/timestreaminfluxdb/service_endpoints_gen_test.go +++ b/internal/service/timestreaminfluxdb/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := timestreaminfluxdb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), timestreaminfluxdb_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := timestreaminfluxdb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), timestreaminfluxdb_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/timestreaminfluxdb/service_package_gen.go b/internal/service/timestreaminfluxdb/service_package_gen.go index 20175d1c1e6..570f77d4e59 100644 --- a/internal/service/timestreaminfluxdb/service_package_gen.go +++ b/internal/service/timestreaminfluxdb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package timestreaminfluxdb @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" timestreaminfluxdb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*timestreaminfluxdb_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return timestreaminfluxdb_sdkv2.NewFromConfig(cfg, func(o *timestreaminfluxdb_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return timestreaminfluxdb_sdkv2.NewFromConfig(cfg, + timestreaminfluxdb_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/timestreamwrite/service_endpoint_resolver_gen.go b/internal/service/timestreamwrite/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..0c8cf804610 --- /dev/null +++ b/internal/service/timestreamwrite/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package timestreamwrite + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + timestreamwrite_sdkv2 "github.com/aws/aws-sdk-go-v2/service/timestreamwrite" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ timestreamwrite_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver timestreamwrite_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: timestreamwrite_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params timestreamwrite_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up timestreamwrite endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*timestreamwrite_sdkv2.Options) { + return func(o *timestreamwrite_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/timestreamwrite/service_package_gen.go b/internal/service/timestreamwrite/service_package_gen.go index 11cb503df41..3d55d96985c 100644 --- a/internal/service/timestreamwrite/service_package_gen.go +++ b/internal/service/timestreamwrite/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package timestreamwrite @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" timestreamwrite_sdkv2 "github.com/aws/aws-sdk-go-v2/service/timestreamwrite" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,19 +55,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*timestreamwrite_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return timestreamwrite_sdkv2.NewFromConfig(cfg, func(o *timestreamwrite_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return timestreamwrite_sdkv2.NewFromConfig(cfg, + timestreamwrite_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/transcribe/service_endpoint_resolver_gen.go b/internal/service/transcribe/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..d915cb32bd2 --- /dev/null +++ b/internal/service/transcribe/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package transcribe + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + transcribe_sdkv2 "github.com/aws/aws-sdk-go-v2/service/transcribe" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ transcribe_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver transcribe_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: transcribe_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params transcribe_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up transcribe endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*transcribe_sdkv2.Options) { + return func(o *transcribe_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/transcribe/service_endpoints_gen_test.go b/internal/service/transcribe/service_endpoints_gen_test.go index 4d039648644..9c97a6ad1ef 100644 --- a/internal/service/transcribe/service_endpoints_gen_test.go +++ b/internal/service/transcribe/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -91,7 +93,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -274,7 +276,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -295,24 +297,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := transcribe_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), transcribe_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := transcribe_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), transcribe_sdkv2.EndpointParameters{ @@ -320,14 +322,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -408,16 +410,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/transcribe/service_package_gen.go b/internal/service/transcribe/service_package_gen.go index 8bc4825bb5f..375ceab73d9 100644 --- a/internal/service/transcribe/service_package_gen.go +++ b/internal/service/transcribe/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package transcribe @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" transcribe_sdkv2 "github.com/aws/aws-sdk-go-v2/service/transcribe" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -72,19 +71,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*transcribe_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return transcribe_sdkv2.NewFromConfig(cfg, func(o *transcribe_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return transcribe_sdkv2.NewFromConfig(cfg, + transcribe_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/transfer/service_endpoint_resolver_gen.go b/internal/service/transfer/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..e2fe2f0ea22 --- /dev/null +++ b/internal/service/transfer/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package transfer + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + transfer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/transfer" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ transfer_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver transfer_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: transfer_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params transfer_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up transfer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*transfer_sdkv2.Options) { + return func(o *transfer_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/transfer/service_endpoints_gen_test.go b/internal/service/transfer/service_endpoints_gen_test.go index a1b3edba86f..b58358c921a 100644 --- a/internal/service/transfer/service_endpoints_gen_test.go +++ b/internal/service/transfer/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := transfer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), transfer_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := transfer_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), transfer_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/transfer/service_package_gen.go b/internal/service/transfer/service_package_gen.go index 80381821b97..b9375c1b49a 100644 --- a/internal/service/transfer/service_package_gen.go +++ b/internal/service/transfer/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package transfer @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" transfer_sdkv2 "github.com/aws/aws-sdk-go-v2/service/transfer" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -117,19 +116,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*transfer_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return transfer_sdkv2.NewFromConfig(cfg, func(o *transfer_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return transfer_sdkv2.NewFromConfig(cfg, + transfer_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/verifiedpermissions/service_endpoint_resolver_gen.go b/internal/service/verifiedpermissions/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..984e26718e7 --- /dev/null +++ b/internal/service/verifiedpermissions/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package verifiedpermissions + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + verifiedpermissions_sdkv2 "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ verifiedpermissions_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver verifiedpermissions_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: verifiedpermissions_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params verifiedpermissions_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up verifiedpermissions endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*verifiedpermissions_sdkv2.Options) { + return func(o *verifiedpermissions_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/verifiedpermissions/service_endpoints_gen_test.go b/internal/service/verifiedpermissions/service_endpoints_gen_test.go index 5c886acdc1e..140c9173c30 100644 --- a/internal/service/verifiedpermissions/service_endpoints_gen_test.go +++ b/internal/service/verifiedpermissions/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := verifiedpermissions_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), verifiedpermissions_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := verifiedpermissions_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), verifiedpermissions_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/verifiedpermissions/service_package_gen.go b/internal/service/verifiedpermissions/service_package_gen.go index d0a9c25f04a..2787f6e2c68 100644 --- a/internal/service/verifiedpermissions/service_package_gen.go +++ b/internal/service/verifiedpermissions/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package verifiedpermissions @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" verifiedpermissions_sdkv2 "github.com/aws/aws-sdk-go-v2/service/verifiedpermissions" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -61,19 +60,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*verifiedpermissions_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return verifiedpermissions_sdkv2.NewFromConfig(cfg, func(o *verifiedpermissions_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return verifiedpermissions_sdkv2.NewFromConfig(cfg, + verifiedpermissions_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/vpclattice/service_endpoint_resolver_gen.go b/internal/service/vpclattice/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..b517529cb12 --- /dev/null +++ b/internal/service/vpclattice/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package vpclattice + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + vpclattice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/vpclattice" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ vpclattice_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver vpclattice_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: vpclattice_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params vpclattice_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up vpclattice endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*vpclattice_sdkv2.Options) { + return func(o *vpclattice_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/vpclattice/service_endpoints_gen_test.go b/internal/service/vpclattice/service_endpoints_gen_test.go index 2697b713199..fb33b6f7025 100644 --- a/internal/service/vpclattice/service_endpoints_gen_test.go +++ b/internal/service/vpclattice/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := vpclattice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), vpclattice_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := vpclattice_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), vpclattice_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/vpclattice/service_package_gen.go b/internal/service/vpclattice/service_package_gen.go index 2d9dd98a4c5..db00c3d9673 100644 --- a/internal/service/vpclattice/service_package_gen.go +++ b/internal/service/vpclattice/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package vpclattice @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" vpclattice_sdkv2 "github.com/aws/aws-sdk-go-v2/service/vpclattice" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -144,19 +143,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*vpclattice_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return vpclattice_sdkv2.NewFromConfig(cfg, func(o *vpclattice_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return vpclattice_sdkv2.NewFromConfig(cfg, + vpclattice_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/waf/service_endpoint_resolver_gen.go b/internal/service/waf/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..cb4177efb49 --- /dev/null +++ b/internal/service/waf/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package waf + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + waf_sdkv2 "github.com/aws/aws-sdk-go-v2/service/waf" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ waf_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver waf_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: waf_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params waf_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up waf endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*waf_sdkv2.Options) { + return func(o *waf_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/waf/service_endpoints_gen_test.go b/internal/service/waf/service_endpoints_gen_test.go index b5cfcd1593e..642494e18e3 100644 --- a/internal/service/waf/service_endpoints_gen_test.go +++ b/internal/service/waf/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := waf_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), waf_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := waf_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), waf_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/waf/service_package_gen.go b/internal/service/waf/service_package_gen.go index d57b46ab753..65f1b78d43a 100644 --- a/internal/service/waf/service_package_gen.go +++ b/internal/service/waf/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package waf @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" waf_sdkv2 "github.com/aws/aws-sdk-go-v2/service/waf" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -138,19 +137,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*waf_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return waf_sdkv2.NewFromConfig(cfg, func(o *waf_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return waf_sdkv2.NewFromConfig(cfg, + waf_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/wafregional/service_endpoint_resolver_gen.go b/internal/service/wafregional/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..4b97d5e2387 --- /dev/null +++ b/internal/service/wafregional/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package wafregional + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + wafregional_sdkv2 "github.com/aws/aws-sdk-go-v2/service/wafregional" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ wafregional_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver wafregional_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: wafregional_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params wafregional_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up wafregional endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*wafregional_sdkv2.Options) { + return func(o *wafregional_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/wafregional/service_endpoints_gen_test.go b/internal/service/wafregional/service_endpoints_gen_test.go index 42bb5b8e233..afc55486bdd 100644 --- a/internal/service/wafregional/service_endpoints_gen_test.go +++ b/internal/service/wafregional/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := wafregional_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), wafregional_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := wafregional_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), wafregional_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/wafregional/service_package_gen.go b/internal/service/wafregional/service_package_gen.go index a4bb063ea04..73dd82adade 100644 --- a/internal/service/wafregional/service_package_gen.go +++ b/internal/service/wafregional/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package wafregional @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" wafregional_sdkv2 "github.com/aws/aws-sdk-go-v2/service/wafregional" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -143,19 +142,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*wafregional_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return wafregional_sdkv2.NewFromConfig(cfg, func(o *wafregional_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return wafregional_sdkv2.NewFromConfig(cfg, + wafregional_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/wafv2/service_endpoint_resolver_gen.go b/internal/service/wafv2/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..27df5d8997d --- /dev/null +++ b/internal/service/wafv2/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package wafv2 + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + wafv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/wafv2" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ wafv2_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver wafv2_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: wafv2_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params wafv2_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up wafv2 endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*wafv2_sdkv2.Options) { + return func(o *wafv2_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/wafv2/service_endpoints_gen_test.go b/internal/service/wafv2/service_endpoints_gen_test.go index a4ee77b6f83..e7cea21c794 100644 --- a/internal/service/wafv2/service_endpoints_gen_test.go +++ b/internal/service/wafv2/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -87,7 +89,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -221,7 +223,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -242,24 +244,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := wafv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), wafv2_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := wafv2_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), wafv2_sdkv2.EndpointParameters{ @@ -267,14 +269,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -338,16 +340,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/wafv2/service_package_gen.go b/internal/service/wafv2/service_package_gen.go index f04417739dd..cdf93312ee1 100644 --- a/internal/service/wafv2/service_package_gen.go +++ b/internal/service/wafv2/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package wafv2 @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" wafv2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/wafv2" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -103,19 +102,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*wafv2_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return wafv2_sdkv2.NewFromConfig(cfg, func(o *wafv2_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return wafv2_sdkv2.NewFromConfig(cfg, + wafv2_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/wellarchitected/service_endpoint_resolver_gen.go b/internal/service/wellarchitected/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..85faee69813 --- /dev/null +++ b/internal/service/wellarchitected/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package wellarchitected + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + wellarchitected_sdkv2 "github.com/aws/aws-sdk-go-v2/service/wellarchitected" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ wellarchitected_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver wellarchitected_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: wellarchitected_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params wellarchitected_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up wellarchitected endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*wellarchitected_sdkv2.Options) { + return func(o *wellarchitected_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/wellarchitected/service_endpoints_gen_test.go b/internal/service/wellarchitected/service_endpoints_gen_test.go index bf78c25d883..d2fecc3dafa 100644 --- a/internal/service/wellarchitected/service_endpoints_gen_test.go +++ b/internal/service/wellarchitected/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := wellarchitected_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), wellarchitected_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := wellarchitected_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), wellarchitected_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/wellarchitected/service_package_gen.go b/internal/service/wellarchitected/service_package_gen.go index 072f9d68488..5161d0e1870 100644 --- a/internal/service/wellarchitected/service_package_gen.go +++ b/internal/service/wellarchitected/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package wellarchitected @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" wellarchitected_sdkv2 "github.com/aws/aws-sdk-go-v2/service/wellarchitected" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*wellarchitected_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return wellarchitected_sdkv2.NewFromConfig(cfg, func(o *wellarchitected_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return wellarchitected_sdkv2.NewFromConfig(cfg, + wellarchitected_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/worklink/service_endpoint_resolver_gen.go b/internal/service/worklink/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..ebcde0dab1f --- /dev/null +++ b/internal/service/worklink/service_endpoint_resolver_gen.go @@ -0,0 +1,76 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package worklink + +import ( + "context" + "fmt" + "net" + "net/url" + + endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ endpoints_sdkv1.Resolver = resolverSDKv1{} + +type resolverSDKv1 struct { + ctx context.Context +} + +func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { + return resolverSDKv1{ + ctx: ctx, + } +} + +func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { + ctx := r.ctx + + var opt endpoints_sdkv1.Options + opt.Set(opts...) + + useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled + + defaultResolver := endpoints_sdkv1.DefaultResolver() + + if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = defaultResolver.EndpointFor(service, region, opts...) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URL, + }) + + var endpointURL *url.URL + endpointURL, err = url.Parse(endpoint.URL) + if err != nil { + return endpoint, err + } + + hostname := endpointURL.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + opts = append(opts, func(o *endpoints_sdkv1.Options) { + o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + }) + } else { + err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return defaultResolver.EndpointFor(service, region, opts...) +} diff --git a/internal/service/worklink/service_endpoints_gen_test.go b/internal/service/worklink/service_endpoints_gen_test.go index 09f25598c1a..26b34f193ae 100644 --- a/internal/service/worklink/service_endpoints_gen_test.go +++ b/internal/service/worklink/service_endpoints_gen_test.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "maps" + "net" "net/url" "os" "path/filepath" @@ -83,7 +84,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -217,7 +218,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -238,14 +239,14 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(worklink_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { opt.ResolveUnknownService = true }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -254,10 +255,10 @@ func defaultEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := endpoints.DefaultResolver() ep, err := r.EndpointFor(worklink_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { @@ -265,7 +266,7 @@ func defaultFIPSEndpoint(region string) string { opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled }) if err != nil { - return err.Error() + return url.URL{}, err } url, _ := url.Parse(ep.URL) @@ -274,7 +275,7 @@ func defaultFIPSEndpoint(region string) string { url.Path = "/" } - return url.String() + return *url, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -326,16 +327,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/worklink/service_package_gen.go b/internal/service/worklink/service_package_gen.go index 4b08f1a08d0..4ffb1afdf8b 100644 --- a/internal/service/worklink/service_package_gen.go +++ b/internal/service/worklink/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package worklink @@ -6,7 +6,6 @@ import ( "context" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" worklink_sdkv1 "github.com/aws/aws-sdk-go/service/worklink" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -57,11 +56,8 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*w "tf_aws.endpoint": endpoint, }) cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - } + } else { + cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) } return worklink_sdkv1.New(sess.Copy(&cfg)), nil diff --git a/internal/service/workspaces/service_endpoint_resolver_gen.go b/internal/service/workspaces/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..37a015e3e16 --- /dev/null +++ b/internal/service/workspaces/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package workspaces + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + workspaces_sdkv2 "github.com/aws/aws-sdk-go-v2/service/workspaces" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ workspaces_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver workspaces_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: workspaces_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params workspaces_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up workspaces endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*workspaces_sdkv2.Options) { + return func(o *workspaces_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/workspaces/service_endpoints_gen_test.go b/internal/service/workspaces/service_endpoints_gen_test.go index dfbc1131a1e..06582940149 100644 --- a/internal/service/workspaces/service_endpoints_gen_test.go +++ b/internal/service/workspaces/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := workspaces_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), workspaces_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := workspaces_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), workspaces_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/workspaces/service_package_gen.go b/internal/service/workspaces/service_package_gen.go index 2c61d9e5a3a..7a47eafcc0c 100644 --- a/internal/service/workspaces/service_package_gen.go +++ b/internal/service/workspaces/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package workspaces @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" workspaces_sdkv2 "github.com/aws/aws-sdk-go-v2/service/workspaces" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -89,19 +88,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*workspaces_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return workspaces_sdkv2.NewFromConfig(cfg, func(o *workspaces_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return workspaces_sdkv2.NewFromConfig(cfg, + workspaces_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/workspacesweb/service_endpoint_resolver_gen.go b/internal/service/workspacesweb/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..9775fb0a93d --- /dev/null +++ b/internal/service/workspacesweb/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package workspacesweb + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + workspacesweb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/workspacesweb" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ workspacesweb_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver workspacesweb_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: workspacesweb_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params workspacesweb_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up workspacesweb endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*workspacesweb_sdkv2.Options) { + return func(o *workspacesweb_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/workspacesweb/service_endpoints_gen_test.go b/internal/service/workspacesweb/service_endpoints_gen_test.go index 1a0770f1635..52862c977dd 100644 --- a/internal/service/workspacesweb/service_endpoints_gen_test.go +++ b/internal/service/workspacesweb/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := workspacesweb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), workspacesweb_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := workspacesweb_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), workspacesweb_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/workspacesweb/service_package_gen.go b/internal/service/workspacesweb/service_package_gen.go index 5372dc1ced8..7fb1a4e3d37 100644 --- a/internal/service/workspacesweb/service_package_gen.go +++ b/internal/service/workspacesweb/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package workspacesweb @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" workspacesweb_sdkv2 "github.com/aws/aws-sdk-go-v2/service/workspacesweb" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -39,19 +38,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*workspacesweb_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return workspacesweb_sdkv2.NewFromConfig(cfg, func(o *workspacesweb_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return workspacesweb_sdkv2.NewFromConfig(cfg, + workspacesweb_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/xray/service_endpoint_resolver_gen.go b/internal/service/xray/service_endpoint_resolver_gen.go new file mode 100644 index 00000000000..a2aa0dedb3f --- /dev/null +++ b/internal/service/xray/service_endpoint_resolver_gen.go @@ -0,0 +1,82 @@ +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. + +package xray + +import ( + "context" + "fmt" + "net" + + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + xray_sdkv2 "github.com/aws/aws-sdk-go-v2/service/xray" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/errs" +) + +var _ xray_sdkv2.EndpointResolverV2 = resolverSDKv2{} + +type resolverSDKv2 struct { + defaultResolver xray_sdkv2.EndpointResolverV2 +} + +func newEndpointResolverSDKv2() resolverSDKv2 { + return resolverSDKv2{ + defaultResolver: xray_sdkv2.NewDefaultEndpointResolverV2(), + } +} + +func (r resolverSDKv2) ResolveEndpoint(ctx context.Context, params xray_sdkv2.EndpointParameters) (endpoint smithyendpoints.Endpoint, err error) { + params = params.WithDefaults() + useFIPS := aws_sdkv2.ToBool(params.UseFIPS) + + if eps := params.Endpoint; aws_sdkv2.ToString(eps) != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + + if useFIPS { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + params.UseFIPS = aws_sdkv2.Bool(false) + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) + } else if useFIPS { + ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) + + endpoint, err = r.defaultResolver.ResolveEndpoint(ctx, params) + if err != nil { + return endpoint, err + } + + tflog.Debug(ctx, "endpoint resolved", map[string]any{ + "tf_aws.endpoint": endpoint.URI.String(), + }) + + hostname := endpoint.URI.Hostname() + _, err = net.LookupHost(hostname) + if err != nil { + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ + "tf_aws.hostname": hostname, + }) + params.UseFIPS = aws_sdkv2.Bool(false) + } else { + err = fmt.Errorf("looking up xray endpoint %q: %s", hostname, err) + return + } + } else { + return endpoint, err + } + } + + return r.defaultResolver.ResolveEndpoint(ctx, params) +} + +func withBaseEndpoint(endpoint string) func(*xray_sdkv2.Options) { + return func(o *xray_sdkv2.Options) { + if endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + } +} diff --git a/internal/service/xray/service_endpoints_gen_test.go b/internal/service/xray/service_endpoints_gen_test.go index a7b9fd795e1..ad1b3a8a0a3 100644 --- a/internal/service/xray/service_endpoints_gen_test.go +++ b/internal/service/xray/service_endpoints_gen_test.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "maps" + "net" + "net/url" "os" "path/filepath" "reflect" @@ -86,7 +88,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S testcases := map[string]endpointTestCase{ "no config": { with: []setupFunc{withNoConfig}, - expected: expectDefaultEndpoint(expectedEndpointRegion), + expected: expectDefaultEndpoint(t, expectedEndpointRegion), }, // Package name endpoint on Config @@ -220,7 +222,7 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S with: []setupFunc{ withUseFIPSInConfig, }, - expected: expectDefaultFIPSEndpoint(expectedEndpointRegion), + expected: expectDefaultFIPSEndpoint(t, expectedEndpointRegion), }, "use fips config with package name endpoint config": { @@ -241,24 +243,24 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } } -func defaultEndpoint(region string) string { +func defaultEndpoint(region string) (url.URL, error) { r := xray_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), xray_sdkv2.EndpointParameters{ Region: aws_sdkv2.String(region), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } -func defaultFIPSEndpoint(region string) string { +func defaultFIPSEndpoint(region string) (url.URL, error) { r := xray_sdkv2.NewDefaultEndpointResolverV2() ep, err := r.ResolveEndpoint(context.Background(), xray_sdkv2.EndpointParameters{ @@ -266,14 +268,14 @@ func defaultFIPSEndpoint(region string) string { UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { - return err.Error() + return url.URL{}, err } if ep.URI.Path == "" { ep.URI.Path = "/" } - return ep.URI.String() + return ep.URI, nil } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { @@ -335,16 +337,38 @@ func withUseFIPSInConfig(setup *caseSetup) { setup.config["use_fips_endpoint"] = true } -func expectDefaultEndpoint(region string) caseExpectations { +func expectDefaultEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer default endpoint: %s", err) + } + return caseExpectations{ - endpoint: defaultEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } -func expectDefaultFIPSEndpoint(region string) caseExpectations { +func expectDefaultFIPSEndpoint(t *testing.T, region string) caseExpectations { + t.Helper() + + endpoint, err := defaultFIPSEndpoint(region) + if err != nil { + t.Fatalf("resolving accessanalyzer FIPS endpoint: %s", err) + } + + hostname := endpoint.Hostname() + _, err = net.LookupHost(hostname) + if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { + return expectDefaultEndpoint(t, region) + } else if err != nil { + t.Fatalf("looking up accessanalyzer endpoint %q: %s", hostname, err) + } + return caseExpectations{ - endpoint: defaultFIPSEndpoint(region), + endpoint: endpoint.String(), region: expectedCallRegion, } } diff --git a/internal/service/xray/service_package_gen.go b/internal/service/xray/service_package_gen.go index 23cd0ef6361..71fd0136436 100644 --- a/internal/service/xray/service_package_gen.go +++ b/internal/service/xray/service_package_gen.go @@ -1,4 +1,4 @@ -// Code generated by internal/generate/servicepackages/main.go; DO NOT EDIT. +// Code generated by internal/generate/servicepackage/main.go; DO NOT EDIT. package xray @@ -7,7 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" xray_sdkv2 "github.com/aws/aws-sdk-go-v2/service/xray" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -60,19 +59,10 @@ func (p *servicePackage) ServicePackageName() string { func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*xray_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return xray_sdkv2.NewFromConfig(cfg, func(o *xray_sdkv2.Options) { - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - o.BaseEndpoint = aws_sdkv2.String(endpoint) - - if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled - } - } - }), nil + return xray_sdkv2.NewFromConfig(cfg, + xray_sdkv2.WithEndpointResolverV2(newEndpointResolverSDKv2()), + withBaseEndpoint(config[names.AttrEndpoint].(string)), + ), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/names/data/names_data.hcl b/names/data/names_data.hcl index 3880af55ab7..0cc0962628f 100644 --- a/names/data/names_data.hcl +++ b/names/data/names_data.hcl @@ -6124,7 +6124,7 @@ service "meta" { } client { - go_v1_client_typename = "" + skip_client_generate = true } resource_prefix {