diff --git a/.changelog/42708.txt b/.changelog/42708.txt new file mode 100644 index 000000000000..64d58e83abaf --- /dev/null +++ b/.changelog/42708.txt @@ -0,0 +1,7 @@ +```release-note:new-resource +aws_transfer_web_app +``` + +```release-note:new-resource +aws_transfer_web_app_customization +``` diff --git a/.changelog/43490.txt b/.changelog/43490.txt new file mode 100644 index 000000000000..dc27135c8836 --- /dev/null +++ b/.changelog/43490.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_kinesisanalyticsv2_application: Ensure that configured `application_configuration.run_configuration` values are respected during update +``` diff --git a/.changelog/43590.txt b/.changelog/43590.txt new file mode 100644 index 000000000000..e71fd45ddd74 --- /dev/null +++ b/.changelog/43590.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_s3_bucket_lifecycle_configuration: Do not warn if no filter element is set +``` diff --git a/.changelog/43825.txt b/.changelog/43825.txt new file mode 100644 index 000000000000..2c1ac5c6c8c1 --- /dev/null +++ b/.changelog/43825.txt @@ -0,0 +1,7 @@ +```release-note:new-data-source +aws_odb_gi_versions +``` + +```release-note:new-data-source +aws_odb_db_system_shapes +``` \ No newline at end of file diff --git a/.changelog/43996.txt b/.changelog/43996.txt new file mode 100644 index 000000000000..a4f317fb2a8c --- /dev/null +++ b/.changelog/43996.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_chatbot_slack_channel_configuration: Force resource replacement when `configuration_name` is modified +``` diff --git a/.changelog/44256.txt b/.changelog/44256.txt new file mode 100644 index 000000000000..167b590f4c4b --- /dev/null +++ b/.changelog/44256.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_prometheus_resource_policy +``` diff --git a/.changelog/44299.txt b/.changelog/44299.txt new file mode 100644 index 000000000000..cb782a0541e9 --- /dev/null +++ b/.changelog/44299.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_iam_service_specific_credential: Add support for Bedrock API keys with `credential_age_days`, `service_credential_alias`, `service_credential_secret`, `create_date`, and `expiration_date` attributes +``` \ No newline at end of file diff --git a/.changelog/44309.txt b/.changelog/44309.txt new file mode 100644 index 000000000000..1724a50ff893 --- /dev/null +++ b/.changelog/44309.txt @@ -0,0 +1,11 @@ +```release-note:enhancement +resource/aws_rds_proxy: Add `default_auth_scheme` argument +``` + +```release-note:enhancement +resource/aws_rds_proxy: Make `auth` configuration block optional +``` + +```release-note:enhancement +data-source/aws_rds_proxy: Add `default_auth_scheme` attribute +``` diff --git a/.changelog/44328.txt b/.changelog/44328.txt new file mode 100644 index 000000000000..a8956aaa2b81 --- /dev/null +++ b/.changelog/44328.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +data-source/aws_ec2_instance_type_offering: Add `location` attribute +``` diff --git a/.changelog/44362.txt b/.changelog/44362.txt new file mode 100644 index 000000000000..e71029f7d9a4 --- /dev/null +++ b/.changelog/44362.txt @@ -0,0 +1,7 @@ +```release-note:bug +resource/aws_vpc: Correctly set `ipv6_cidr_block` when the VPC has multiple associated IPv6 CIDRs +``` + +```release-note:bug +resource/aws_default_vpc: Correctly set `ipv6_cidr_block` when the VPC has multiple associated IPv6 CIDRs +``` \ No newline at end of file diff --git a/.changelog/44369.txt b/.changelog/44369.txt new file mode 100644 index 000000000000..e92edf1e60d8 --- /dev/null +++ b/.changelog/44369.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_ssmcontacts_contact_channel: Add resource identity support +``` \ No newline at end of file diff --git a/.changelog/44372.txt b/.changelog/44372.txt new file mode 100644 index 000000000000..e6916ba748e3 --- /dev/null +++ b/.changelog/44372.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_pinpointsmsvoicev2_phone_number: Update `two_way_channel_arn` argument to accept `connect.[region].amazonaws.com` in addition to ARNs +``` diff --git a/.changelog/44389.txt b/.changelog/44389.txt new file mode 100644 index 000000000000..c70b04a5ebfa --- /dev/null +++ b/.changelog/44389.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_dms_endpoint: Ensure that `postgres_settings` are updated +``` diff --git a/.changelog/44417.txt b/.changelog/44417.txt new file mode 100644 index 000000000000..0dee7d140817 --- /dev/null +++ b/.changelog/44417.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_opensearch_domain: Add `aiml_options` argument +``` diff --git a/.changelog/44435.txt b/.changelog/44435.txt new file mode 100644 index 000000000000..f8be24b041ac --- /dev/null +++ b/.changelog/44435.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_cleanrooms_configured_table: Add resource identity support +``` \ No newline at end of file diff --git a/.changelog/44442.txt b/.changelog/44442.txt new file mode 100644 index 000000000000..cf03d35ef168 --- /dev/null +++ b/.changelog/44442.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_s3_bucket_lifecycle_configuration: Allows unsetting `noncurrent_version_expiration.newer_noncurrent_versions` and `noncurrent_version_transition.newer_noncurrent_versions`. +``` diff --git a/.changelog/44444.txt b/.changelog/44444.txt new file mode 100644 index 000000000000..d434d1edf076 --- /dev/null +++ b/.changelog/44444.txt @@ -0,0 +1,3 @@ +```release-note:new-action +aws_codebuild_start_build +``` \ No newline at end of file diff --git a/.changelog/44445.txt b/.changelog/44445.txt new file mode 100644 index 000000000000..49041231ec1c --- /dev/null +++ b/.changelog/44445.txt @@ -0,0 +1,3 @@ +```release-note:new-action +aws_transcribe_start_transcription_job +``` diff --git a/.changelog/44449.txt b/.changelog/44449.txt new file mode 100644 index 000000000000..afb108849144 --- /dev/null +++ b/.changelog/44449.txt @@ -0,0 +1,3 @@ +```release-note:bug +data-source/aws_servicequotas_service_quota: Fixed a panic that occurred when a non-existing `quota_name` was provided +``` diff --git a/.changelog/44456.txt b/.changelog/44456.txt new file mode 100644 index 000000000000..ccefcf2b2929 --- /dev/null +++ b/.changelog/44456.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_fsx_lustre_file_system: Fixed to update `metadata_configuration` first to allow simultaneous increase of `metadata_configuration.iops` and `storage_capacity` +``` diff --git a/.changelog/44459.txt b/.changelog/44459.txt new file mode 100644 index 000000000000..043c058b8dd3 --- /dev/null +++ b/.changelog/44459.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_instance: Fix `interface conversion: interface {} is nil, not map[string]interface {}` panics when `capacity_reservation_target` is empty +``` \ No newline at end of file diff --git a/.changelog/44461.txt b/.changelog/44461.txt new file mode 100644 index 000000000000..9e985181801d --- /dev/null +++ b/.changelog/44461.txt @@ -0,0 +1,7 @@ +```release-note:bug +resource/aws_elastic_beanstalk_environment: Fix `inconsistent final plan` error in some cases with `setting` elements. +``` + +```release-note:bug +resource/aws_elastic_beanstalk_configuration_template: Fix `inconsistent final plan` error in some cases with `setting` elements. +``` diff --git a/.changelog/44463.txt b/.changelog/44463.txt new file mode 100644 index 000000000000..349eaf4382dd --- /dev/null +++ b/.changelog/44463.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_cloudfront_distribution: Add `ip_address_type` argument to `origin.custom_origin_config` block +``` diff --git a/.changelog/44464.txt b/.changelog/44464.txt new file mode 100644 index 000000000000..86d8e91298a3 --- /dev/null +++ b/.changelog/44464.txt @@ -0,0 +1,3 @@ +```release-note:new-action +aws_sfn_start_execution +``` \ No newline at end of file diff --git a/.changelog/44473.txt b/.changelog/44473.txt new file mode 100644 index 000000000000..cb4b7e735ef1 --- /dev/null +++ b/.changelog/44473.txt @@ -0,0 +1,11 @@ +```release-note:enhancement +resource/aws_route53recoverycontrolconfig_cluster: Add tagging support +``` + +```release-note:enhancement +resource/aws_route53recoverycontrolconfig_control_panel: Add tagging support +``` + +```release-note:enhancement +resource/aws_route53recoverycontrolconfig_safety_rule: Add tagging support +``` diff --git a/.changelog/44482.txt b/.changelog/44482.txt new file mode 100644 index 000000000000..26842547d5db --- /dev/null +++ b/.changelog/44482.txt @@ -0,0 +1,3 @@ +```release-note:bug +data-source/aws_networkfirewall_firewall_policy: Fix failure to retrieve multiple `firewall_policy.stateful_rule_group_reference` attributes +``` diff --git a/.changelog/44485.txt b/.changelog/44485.txt new file mode 100644 index 000000000000..442ec8f72b92 --- /dev/null +++ b/.changelog/44485.txt @@ -0,0 +1,3 @@ +```release-note:bug +data-source/aws_lb: Fix `Invalid address to set: []string{"secondary_ips_auto_assigned_per_subnet"}` errors +``` diff --git a/.changelog/44487.txt b/.changelog/44487.txt new file mode 100644 index 000000000000..98eb0eca07a4 --- /dev/null +++ b/.changelog/44487.txt @@ -0,0 +1,3 @@ +```release-note:new-action +aws_events_put_events +``` \ No newline at end of file diff --git a/.changelog/44489.txt b/.changelog/44489.txt new file mode 100644 index 000000000000..875d680e8eca --- /dev/null +++ b/.changelog/44489.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_cloudwatch_event_rule: Do not retry on `LimitExceededException` +``` diff --git a/.changelog/44491.txt b/.changelog/44491.txt new file mode 100644 index 000000000000..94840ce53c20 --- /dev/null +++ b/.changelog/44491.txt @@ -0,0 +1,39 @@ +```release-note:bug +resource/aws_datazone_environment: Prevents `unknown value` error when optional `account_identifier` is not specified. +``` + +```release-note:bug +resource/aws_datazone_environment: Prevents `unknown value` error when optional `account_region` is not specified. +``` + +```release-note:bug +resource/aws_datazone_environment: Properly passes `blueprint_identifier` on creation. +``` + +```release-note:bug +resource/aws_datazone_environment: Prevents error when updating. +``` + +```release-note:bug +resource/aws_datazone_environment: Prevents occasional `unexpected state` error when deleting. +``` + +```release-note:bug +resource/aws_datazone_environment: Sets values for `user_parameters` when importing. +``` + +```release-note:bug +resource/aws_datazone_environment: Values in `user_parameters` should not be updateable. +``` + +```release-note:bug +resource/aws_datazone_environment: Correctly updates `glossary_terms`. +``` + +```release-note:bug +resource/aws_datazone_project: No longer ignores errors when deleting. +``` + +```release-note:bug +resource/aws_datazone_project: No longer returns error when already deleting. +``` diff --git a/.changelog/44498.txt b/.changelog/44498.txt new file mode 100644 index 000000000000..19c706141ec5 --- /dev/null +++ b/.changelog/44498.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_odb_cloud_vm_cluster : Fixed planmodifier for data_storage_size_in_tbs. Marked it mandatory. Fixed gi-version issue during creation +``` \ No newline at end of file diff --git a/.changelog/44505.txt b/.changelog/44505.txt new file mode 100644 index 000000000000..1a133d88e6ae --- /dev/null +++ b/.changelog/44505.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_launch_template: `kms_key_id` validation now accepts key ID, alias, and alias ARN in addition to key ARN +``` diff --git a/.changelog/44509.txt b/.changelog/44509.txt new file mode 100644 index 000000000000..27714534ab9e --- /dev/null +++ b/.changelog/44509.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_ecs_capacity_provider: Make `auto_scaling_group_provider` optional +``` + +```release-note:enhancement +resource/aws_ecs_capacity_provider: Add `cluster` and `managed_instances_provider` arguments +``` \ No newline at end of file diff --git a/.changelog/44514.txt b/.changelog/44514.txt new file mode 100644 index 000000000000..1c77c7803876 --- /dev/null +++ b/.changelog/44514.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_ebs_volume: Update `throughput` maximum validation from 1000 to 2000 MiB/s for gp3 volumes +``` diff --git a/.changelog/44515.txt b/.changelog/44515.txt new file mode 100644 index 000000000000..9d37e28f970e --- /dev/null +++ b/.changelog/44515.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_networkfirewall_logging_configuration: Add `enable_monitoring_dashboard` argument +``` diff --git a/.changelog/44516.txt b/.changelog/44516.txt new file mode 100644 index 000000000000..86d121ee5762 --- /dev/null +++ b/.changelog/44516.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_dms_endpoint: Add `mysql_settings` configuration block +``` + +```release-note:enhancement +data-source/aws_dms_endpoint: Add `mysql_settings` attribute +``` diff --git a/.changelog/44522.txt b/.changelog/44522.txt new file mode 100644 index 000000000000..8f3434a84d00 --- /dev/null +++ b/.changelog/44522.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_cloudwatch_log_resource_policy: Do not retry on `LimitExceededException` +``` diff --git a/.changelog/44540.txt b/.changelog/44540.txt new file mode 100644 index 000000000000..f6020ac923e7 --- /dev/null +++ b/.changelog/44540.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_lambda_event_source_mapping: Add `schema_registry_config` configuration blocks to `amazon_managed_kafka_event_source_config` and `self_managed_kafka_event_source_config` blocks +``` diff --git a/.changelog/44548.txt b/.changelog/44548.txt new file mode 100644 index 000000000000..feaf5a906905 --- /dev/null +++ b/.changelog/44548.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_ssmcontacts_contact: Add resource identity support +``` \ No newline at end of file diff --git a/.changelog/44559.txt b/.changelog/44559.txt new file mode 100644 index 000000000000..4f91f775d80a --- /dev/null +++ b/.changelog/44559.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_transfer_host_key +``` \ No newline at end of file diff --git a/.changelog/44560.txt b/.changelog/44560.txt new file mode 100644 index 000000000000..a7f8a9bba496 --- /dev/null +++ b/.changelog/44560.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_vpclattice_resource_gateway: Add `ipv4_addresses_per_eni` argument +``` \ No newline at end of file diff --git a/.changelog/44573.txt b/.changelog/44573.txt new file mode 100644 index 000000000000..da07f59c7854 --- /dev/null +++ b/.changelog/44573.txt @@ -0,0 +1,3 @@ +```release-note:bug +provider: Correctly validate AWS European Sovereign Cloud Regions in ARNs +``` \ No newline at end of file diff --git a/.ci/providerlint/go.mod b/.ci/providerlint/go.mod index 22b0699c6ac0..e7629a631417 100644 --- a/.ci/providerlint/go.mod +++ b/.ci/providerlint/go.mod @@ -4,7 +4,7 @@ go 1.24.6 require ( github.com/bflad/tfproviderlint v0.31.0 - github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1 golang.org/x/tools v0.37.0 ) diff --git a/.ci/providerlint/go.sum b/.ci/providerlint/go.sum index f9703c009ae9..ecf289a0ce9b 100644 --- a/.ci/providerlint/go.sum +++ b/.ci/providerlint/go.sum @@ -54,8 +54,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 h1:HA6blfR0h6kGnw4oJ92tZzghubreIkWbQJ4NVNqS688= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66/go.mod h1:7kTJVbY5+igob9Q5N6KO81EGEKDNI9FpjujB31uI/n0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 h1:IS4mjtvkLHXWI5yn/t9ILOUiBqPePMFaO4IRh5pcMk4= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67/go.mod h1:l81jrdpcZSWUsJs4BGFfdGScefSYEFQRLMQRG3uyvT0= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -163,8 +163,8 @@ github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0 github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= diff --git a/.github/workflows/acctest-terraform-embedded-lint.yml b/.github/workflows/acctest-terraform-embedded-lint.yml index c17815f69856..9a901e64ae81 100644 --- a/.github/workflows/acctest-terraform-embedded-lint.yml +++ b/.github/workflows/acctest-terraform-embedded-lint.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -55,13 +55,13 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('go.sum') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 name: Cache plugin dir continue-on-error: true timeout-minutes: 2 diff --git a/.github/workflows/acctest-terraform-lint.yml b/.github/workflows/acctest-terraform-lint.yml index 2391fa67c039..27562381ec86 100644 --- a/.github/workflows/acctest-terraform-lint.yml +++ b/.github/workflows/acctest-terraform-lint.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -45,13 +45,13 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('go.sum') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 name: Cache plugin dir continue-on-error: true timeout-minutes: 2 diff --git a/.github/workflows/changelog_misspell.yml b/.github/workflows/changelog_misspell.yml index e6e5e50fbe53..6f2ef972bbb7 100644 --- a/.github/workflows/changelog_misspell.yml +++ b/.github/workflows/changelog_misspell.yml @@ -24,7 +24,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/copyright.yml b/.github/workflows/copyright.yml index efaef89efd7a..66811cdfa38a 100644 --- a/.github/workflows/copyright.yml +++ b/.github/workflows/copyright.yml @@ -32,13 +32,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 159053a92a31..0f3fec27bdf5 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -47,13 +47,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 5a7f3e4b377e..3a957c580103 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -47,7 +47,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5579726237e9..913f8237e98e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('go.sum') }} @@ -38,7 +38,7 @@ jobs: - name: install tflint run: cd .ci/tools && go install github.com/terraform-linters/tflint - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 name: Cache plugin dir with: path: ~/.tflint.d/plugins @@ -64,7 +64,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('go.sum') }} diff --git a/.github/workflows/modern_go.yml b/.github/workflows/modern_go.yml index 46bd17d9400b..650150d9d276 100644 --- a/.github/workflows/modern_go.yml +++ b/.github/workflows/modern_go.yml @@ -29,13 +29,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/provider.yml b/.github/workflows/provider.yml index bcb77747d5c9..3099b51321df 100644 --- a/.github/workflows/provider.yml +++ b/.github/workflows/provider.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true id: cache-go-pkg-mod timeout-minutes: 2 @@ -57,7 +57,7 @@ jobs: runs-on: custom-ubuntu-22.04-medium steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true id: cache-terraform-plugin-dir timeout-minutes: 2 @@ -74,12 +74,12 @@ jobs: run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - if: steps.cache-terraform-plugin-dir.outputs.cache-hit != 'true' || steps.cache-terraform-plugin-dir.outcome == 'failure' - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - if: steps.cache-terraform-plugin-dir.outputs.cache-hit != 'true' || steps.cache-terraform-plugin-dir.outcome == 'failure' - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('go.sum') }} @@ -100,13 +100,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -135,13 +135,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -162,13 +162,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -195,13 +195,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -217,7 +217,7 @@ jobs: (echo; echo "Expected `strings` to detect sweeper function names in sweeper binary."; exit 1) # Use cached provider or rebuild - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 continue-on-error: true id: cache-terraform-plugin-dir timeout-minutes: 2 @@ -244,7 +244,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true id: cache-terraform-providers-schema timeout-minutes: 2 @@ -252,7 +252,7 @@ jobs: path: terraform-providers-schema key: ${{ runner.os }}-terraform-providers-schema-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - if: steps.cache-terraform-providers-schema.outputs.cache-hit != 'true' || steps.cache-terraform-providers-schema.outcome == 'failure' - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 timeout-minutes: 2 with: path: terraform-plugin-dir @@ -286,14 +286,14 @@ jobs: with: terraform_version: ${{ env.TERRAFORM_VERSION }} terraform_wrapper: false - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('go.sum') }} - run: cd .ci/tools && go install github.com/YakDriver/tfproviderdocs - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 timeout-minutes: 2 with: path: terraform-providers-schema @@ -319,7 +319,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 3 with: diff --git a/.github/workflows/providerlint.yml b/.github/workflows/providerlint.yml index 65ac3a25ad8b..686c9582be95 100644 --- a/.github/workflows/providerlint.yml +++ b/.github/workflows/providerlint.yml @@ -29,13 +29,13 @@ jobs: go-version-file: go.mod - name: go env run: echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/pull_request_target.yml b/.github/workflows/pull_request_target.yml index 60ea4436cbff..725bbaa39c37 100644 --- a/.github/workflows/pull_request_target.yml +++ b/.github/workflows/pull_request_target.yml @@ -39,13 +39,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/readiness_comment.yml b/.github/workflows/readiness_comment.yml index 0acaaf9f3885..a1d4145c1b7c 100644 --- a/.github/workflows/readiness_comment.yml +++ b/.github/workflows/readiness_comment.yml @@ -149,7 +149,7 @@ jobs: - name: Check for Existing Comment id: prc - uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0 + uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0 with: issue-number: ${{ github.event.pull_request.number }} comment-author: "github-actions[bot]" @@ -168,7 +168,7 @@ jobs: if: | steps.start.outcome != 'skipped' || steps.corrected.outcome != 'skipped' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/semgrep-ci.yml b/.github/workflows/semgrep-ci.yml index 508c2c1f64ba..0319cb8684ad 100644 --- a/.github/workflows/semgrep-ci.yml +++ b/.github/workflows/semgrep-ci.yml @@ -28,7 +28,7 @@ jobs: name: Validate Code Quality Rules runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - run: | @@ -43,7 +43,7 @@ jobs: needs: [semgrep-validate] runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - run: | @@ -54,7 +54,7 @@ jobs: needs: [semgrep-test] runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - run: | @@ -74,7 +74,7 @@ jobs: name: Naming Scan Caps/AWS/EC2 runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" if: (github.action != 'dependabot[bot]') steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -85,7 +85,7 @@ jobs: name: Test Configs Scan runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" if: (github.action != 'dependabot[bot]') steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -96,7 +96,7 @@ jobs: name: Service Name Scan A-C runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" if: (github.action != 'dependabot[bot]') steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -107,7 +107,7 @@ jobs: name: Service Name Scan C-I runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" if: (github.action != 'dependabot[bot]') steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -118,7 +118,7 @@ jobs: name: Service Name Scan I-Q runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" if: (github.action != 'dependabot[bot]') steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -129,7 +129,7 @@ jobs: name: Service Name Scan Q-Z runs-on: ubuntu-latest container: - image: "returntocorp/semgrep:1.52.0" + image: "semgrep/semgrep:1.110.0" if: (github.action != 'dependabot[bot]') steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/.github/workflows/skaff.yml b/.github/workflows/skaff.yml index 2b95c6580d31..aeb4e3f45ab5 100644 --- a/.github/workflows/skaff.yml +++ b/.github/workflows/skaff.yml @@ -31,13 +31,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/smarterr.yml b/.github/workflows/smarterr.yml index 5634d7b4a26f..f573e4d7b1d1 100644 --- a/.github/workflows/smarterr.yml +++ b/.github/workflows/smarterr.yml @@ -29,13 +29,13 @@ jobs: - name: go env run: | echo "GOCACHE=$(go env GOCACHE)" >> $GITHUB_ENV - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: path: ${{ env.GOCACHE }} key: ${{ runner.os }}-GOCACHE-${{ hashFiles('go.sum') }}-${{ hashFiles('internal/**') }} - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 7c86fc0a099e..31e0a6f9d5bc 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 + - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 720 diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index de31e4441eec..840d08a0c433 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -90,7 +90,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: .ci/tools/go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -106,7 +106,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: .ci/tools/go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -124,7 +124,7 @@ jobs: - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: .ci/tools/go.mod - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 continue-on-error: true timeout-minutes: 2 with: @@ -134,7 +134,7 @@ jobs: - run: cd .ci/tools && go install github.com/katbyte/terrafmt - run: cd .ci/tools && go install github.com/terraform-linters/tflint - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 name: Cache plugin dir with: path: ~/.tflint.d/plugins diff --git a/.teamcity/scripts/provider_tests/acceptance_tests.sh b/.teamcity/scripts/provider_tests/acceptance_tests.sh index f42d935c248d..539ee5a129f8 100644 --- a/.teamcity/scripts/provider_tests/acceptance_tests.sh +++ b/.teamcity/scripts/provider_tests/acceptance_tests.sh @@ -34,6 +34,7 @@ fi TF_ACC=1 go test \ ./internal/acctest/... \ + ./internal/actionwait/... \ ./internal/attrmap/... \ ./internal/backoff/... \ ./internal/conns/... \ diff --git a/.teamcity/scripts/provider_tests/unit_tests.sh b/.teamcity/scripts/provider_tests/unit_tests.sh index 2f0072dc45e0..c3bf8454caf7 100644 --- a/.teamcity/scripts/provider_tests/unit_tests.sh +++ b/.teamcity/scripts/provider_tests/unit_tests.sh @@ -6,6 +6,7 @@ set -euo pipefail go test \ ./internal/acctest/... \ + ./internal/actionwait/... \ ./internal/attrmap/... \ ./internal/backoff/... \ ./internal/conns/... \ diff --git a/CHANGELOG.md b/CHANGELOG.md index b638851bf3d7..0b1194ac01a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,35 @@ -## 6.15.0 (Unreleased) +## 6.16.0 (Unreleased) + +FEATURES: + +* **New Action:** `aws_transcribe_start_transcription_job` ([#44445](https://github.com/hashicorp/terraform-provider-aws/issues/44445)) +* **New Resource:** `aws_prometheus_resource_policy` ([#44256](https://github.com/hashicorp/terraform-provider-aws/issues/44256)) +* **New Resource:** `aws_transfer_host_key` ([#44559](https://github.com/hashicorp/terraform-provider-aws/issues/44559)) +* **New Resource:** `aws_transfer_web_app` ([#42708](https://github.com/hashicorp/terraform-provider-aws/issues/42708)) +* **New Resource:** `aws_transfer_web_app_customization` ([#42708](https://github.com/hashicorp/terraform-provider-aws/issues/42708)) + +ENHANCEMENTS: + +* resource/aws_lambda_event_source_mapping: Add `schema_registry_config` configuration blocks to `amazon_managed_kafka_event_source_config` and `self_managed_kafka_event_source_config` blocks ([#44540](https://github.com/hashicorp/terraform-provider-aws/issues/44540)) +* resource/aws_ssmcontacts_contact: Add resource identity support ([#44548](https://github.com/hashicorp/terraform-provider-aws/issues/44548)) +* resource/aws_vpclattice_resource_gateway: Add `ipv4_addresses_per_eni` argument ([#44560](https://github.com/hashicorp/terraform-provider-aws/issues/44560)) + +BUG FIXES: + +* provider: Correctly validate AWS European Sovereign Cloud Regions in ARNs ([#44573](https://github.com/hashicorp/terraform-provider-aws/issues/44573)) +* resource/aws_datazone_environment: Correctly updates `glossary_terms`. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_environment: Prevents `unknown value` error when optional `account_identifier` is not specified. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_environment: Prevents `unknown value` error when optional `account_region` is not specified. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_environment: Prevents error when updating. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_environment: Prevents occasional `unexpected state` error when deleting. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_environment: Properly passes `blueprint_identifier` on creation. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_environment: Sets values for `user_parameters` when importing. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_environment: Values in `user_parameters` should not be updateable. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_project: No longer ignores errors when deleting. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_datazone_project: No longer returns error when already deleting. ([#44491](https://github.com/hashicorp/terraform-provider-aws/issues/44491)) +* resource/aws_launch_template: `kms_key_id` validation now accepts key ID, alias, and alias ARN in addition to key ARN ([#44505](https://github.com/hashicorp/terraform-provider-aws/issues/44505)) + +## 6.15.0 (October 2, 2025) BREAKING CHANGES: @@ -6,35 +37,76 @@ BREAKING CHANGES: FEATURES: +* **New Action:** `aws_codebuild_start_build` ([#44444](https://github.com/hashicorp/terraform-provider-aws/issues/44444)) +* **New Action:** `aws_events_put_events` ([#44487](https://github.com/hashicorp/terraform-provider-aws/issues/44487)) +* **New Action:** `aws_sfn_start_execution` ([#44464](https://github.com/hashicorp/terraform-provider-aws/issues/44464)) * **New Data Source:** `aws_appconfig_application` ([#44168](https://github.com/hashicorp/terraform-provider-aws/issues/44168)) * **New Data Source:** `aws_odb_db_node` ([#43792](https://github.com/hashicorp/terraform-provider-aws/issues/43792)) * **New Data Source:** `aws_odb_db_nodes` ([#43792](https://github.com/hashicorp/terraform-provider-aws/issues/43792)) * **New Data Source:** `aws_odb_db_server` ([#43792](https://github.com/hashicorp/terraform-provider-aws/issues/43792)) * **New Data Source:** `aws_odb_db_servers` ([#43792](https://github.com/hashicorp/terraform-provider-aws/issues/43792)) +* **New Data Source:** `aws_odb_db_system_shapes` ([#43825](https://github.com/hashicorp/terraform-provider-aws/issues/43825)) +* **New Data Source:** `aws_odb_gi_versions` ([#43825](https://github.com/hashicorp/terraform-provider-aws/issues/43825)) * **New Resource:** `aws_lakeformation_lf_tag_expression` ([#43883](https://github.com/hashicorp/terraform-provider-aws/issues/43883)) ENHANCEMENTS: +* data-source/aws_dms_endpoint: Add `mysql_settings` attribute ([#44516](https://github.com/hashicorp/terraform-provider-aws/issues/44516)) +* data-source/aws_ec2_instance_type_offering: Add `location` attribute ([#44328](https://github.com/hashicorp/terraform-provider-aws/issues/44328)) +* data-source/aws_rds_proxy: Add `default_auth_scheme` attribute ([#44309](https://github.com/hashicorp/terraform-provider-aws/issues/44309)) +* resource/aws_cleanrooms_configured_table: Add resource identity support ([#44435](https://github.com/hashicorp/terraform-provider-aws/issues/44435)) +* resource/aws_cloudfront_distribution: Add `ip_address_type` argument to `origin.custom_origin_config` block ([#44463](https://github.com/hashicorp/terraform-provider-aws/issues/44463)) * resource/aws_connect_instance: Add resource identity support ([#44346](https://github.com/hashicorp/terraform-provider-aws/issues/44346)) * resource/aws_connect_phone_number: Add resource identity support ([#44365](https://github.com/hashicorp/terraform-provider-aws/issues/44365)) +* resource/aws_dms_endpoint: Add `mysql_settings` configuration block ([#44516](https://github.com/hashicorp/terraform-provider-aws/issues/44516)) * resource/aws_dsql_cluster: Adds attribute `force_destroy`. ([#44406](https://github.com/hashicorp/terraform-provider-aws/issues/44406)) +* resource/aws_ebs_volume: Update `throughput` maximum validation from 1000 to 2000 MiB/s for gp3 volumes ([#44514](https://github.com/hashicorp/terraform-provider-aws/issues/44514)) +* resource/aws_ecs_capacity_provider: Add `cluster` and `managed_instances_provider` arguments ([#44509](https://github.com/hashicorp/terraform-provider-aws/issues/44509)) +* resource/aws_ecs_capacity_provider: Make `auto_scaling_group_provider` optional ([#44509](https://github.com/hashicorp/terraform-provider-aws/issues/44509)) +* resource/aws_iam_service_specific_credential: Add support for Bedrock API keys with `credential_age_days`, `service_credential_alias`, `service_credential_secret`, `create_date`, and `expiration_date` attributes ([#44299](https://github.com/hashicorp/terraform-provider-aws/issues/44299)) +* resource/aws_networkfirewall_logging_configuration: Add `enable_monitoring_dashboard` argument ([#44515](https://github.com/hashicorp/terraform-provider-aws/issues/44515)) +* resource/aws_opensearch_domain: Add `aiml_options` argument ([#44417](https://github.com/hashicorp/terraform-provider-aws/issues/44417)) +* resource/aws_pinpointsmsvoicev2_phone_number: Update `two_way_channel_arn` argument to accept `connect.[region].amazonaws.com` in addition to ARNs ([#44372](https://github.com/hashicorp/terraform-provider-aws/issues/44372)) +* resource/aws_rds_proxy: Add `default_auth_scheme` argument ([#44309](https://github.com/hashicorp/terraform-provider-aws/issues/44309)) +* resource/aws_rds_proxy: Make `auth` configuration block optional ([#44309](https://github.com/hashicorp/terraform-provider-aws/issues/44309)) * resource/aws_route53recoverycontrolconfig_cluster: Add `network_type` argument ([#44377](https://github.com/hashicorp/terraform-provider-aws/issues/44377)) +* resource/aws_route53recoverycontrolconfig_cluster: Add tagging support ([#44473](https://github.com/hashicorp/terraform-provider-aws/issues/44473)) +* resource/aws_route53recoverycontrolconfig_control_panel: Add tagging support ([#44473](https://github.com/hashicorp/terraform-provider-aws/issues/44473)) +* resource/aws_route53recoverycontrolconfig_safety_rule: Add tagging support ([#44473](https://github.com/hashicorp/terraform-provider-aws/issues/44473)) * resource/aws_s3control_bucket: Add resource identity support ([#44379](https://github.com/hashicorp/terraform-provider-aws/issues/44379)) * resource/aws_sfn_activity: Add `arn` argument ([#44408](https://github.com/hashicorp/terraform-provider-aws/issues/44408)) * resource/aws_sfn_activity: Add resource identity support ([#44408](https://github.com/hashicorp/terraform-provider-aws/issues/44408)) * resource/aws_sfn_alias: Add resource identity support ([#44408](https://github.com/hashicorp/terraform-provider-aws/issues/44408)) +* resource/aws_ssmcontacts_contact_channel: Add resource identity support ([#44369](https://github.com/hashicorp/terraform-provider-aws/issues/44369)) BUG FIXES: +* data-source/aws_lb: Fix `Invalid address to set: []string{"secondary_ips_auto_assigned_per_subnet"}` errors ([#44485](https://github.com/hashicorp/terraform-provider-aws/issues/44485)) +* data-source/aws_networkfirewall_firewall_policy: Fix failure to retrieve multiple `firewall_policy.stateful_rule_group_reference` attributes ([#44482](https://github.com/hashicorp/terraform-provider-aws/issues/44482)) +* data-source/aws_servicequotas_service_quota: Fixed a panic that occurred when a non-existing `quota_name` was provided ([#44449](https://github.com/hashicorp/terraform-provider-aws/issues/44449)) * resource/aws_bedrock_provisioned_model_throughput: Fix `AttributeName("arn") still remains in the path: could not find attribute or block "arn" in schema` errors when upgrading from a pre-v6.0.0 provider version ([#44434](https://github.com/hashicorp/terraform-provider-aws/issues/44434)) +* resource/aws_chatbot_slack_channel_configuration: Force resource replacement when `configuration_name` is modified ([#43996](https://github.com/hashicorp/terraform-provider-aws/issues/43996)) +* resource/aws_cloudwatch_event_rule: Do not retry on `LimitExceededException` ([#44489](https://github.com/hashicorp/terraform-provider-aws/issues/44489)) +* resource/aws_cloudwatch_log_resource_policy: Do not retry on `LimitExceededException` ([#44522](https://github.com/hashicorp/terraform-provider-aws/issues/44522)) +* resource/aws_default_vpc: Correctly set `ipv6_cidr_block` when the VPC has multiple associated IPv6 CIDRs ([#44362](https://github.com/hashicorp/terraform-provider-aws/issues/44362)) +* resource/aws_dms_endpoint: Ensure that `postgres_settings` are updated ([#44389](https://github.com/hashicorp/terraform-provider-aws/issues/44389)) * resource/aws_dsql_cluster: Prevents error when optional attribute `deletion_protection_enabled` not set. ([#44406](https://github.com/hashicorp/terraform-provider-aws/issues/44406)) * resource/aws_eks_cluster: Change `compute_config`, `kubernetes_network_config.elastic_load_balancing`, and `storage_config.` to Optional and Computed, allowing EKS Auto Mode settings to be enabled, disabled, and removed from configuration ([#44334](https://github.com/hashicorp/terraform-provider-aws/issues/44334)) +* resource/aws_elastic_beanstalk_configuration_template: Fix `inconsistent final plan` error in some cases with `setting` elements. ([#44461](https://github.com/hashicorp/terraform-provider-aws/issues/44461)) +* resource/aws_elastic_beanstalk_environment: Fix `inconsistent final plan` error in some cases with `setting` elements. ([#44461](https://github.com/hashicorp/terraform-provider-aws/issues/44461)) * resource/aws_elasticache_cluster: Fix `provider produced unexpected value` for `cache_usage_limits` argument. ([#43841](https://github.com/hashicorp/terraform-provider-aws/issues/43841)) +* resource/aws_fsx_lustre_file_system: Fixed to update `metadata_configuration` first to allow simultaneous increase of `metadata_configuration.iops` and `storage_capacity` ([#44456](https://github.com/hashicorp/terraform-provider-aws/issues/44456)) +* resource/aws_instance: Fix `interface conversion: interface {} is nil, not map[string]interface {}` panics when `capacity_reservation_target` is empty ([#44459](https://github.com/hashicorp/terraform-provider-aws/issues/44459)) +* resource/aws_kinesisanalyticsv2_application: Ensure that configured `application_configuration.run_configuration` values are respected during update ([#43490](https://github.com/hashicorp/terraform-provider-aws/issues/43490)) * resource/aws_odb_cloud_autonomous_vm_cluster : Fixed planmodifier for computed attribute. ([#44401](https://github.com/hashicorp/terraform-provider-aws/issues/44401)) * resource/aws_odb_cloud_vm_cluster : Fixed planmodifier for computed attribute. Fixed planmodifier from display_name attribute. ([#44401](https://github.com/hashicorp/terraform-provider-aws/issues/44401)) +* resource/aws_odb_cloud_vm_cluster : Fixed planmodifier for data_storage_size_in_tbs. Marked it mandatory. Fixed gi-version issue during creation ([#44498](https://github.com/hashicorp/terraform-provider-aws/issues/44498)) * resource/aws_odb_network_peering_connection : Fixed planmodifier for computed attribute. ([#44401](https://github.com/hashicorp/terraform-provider-aws/issues/44401)) * resource/aws_rds_cluster: Fixes error when setting `database_insights_mode` with `global_cluster_identifier`. ([#44404](https://github.com/hashicorp/terraform-provider-aws/issues/44404)) * resource/aws_route53_health_check: Fix `child_health_threshold` to properly accept explicitly specified zero value ([#44006](https://github.com/hashicorp/terraform-provider-aws/issues/44006)) +* resource/aws_s3_bucket_lifecycle_configuration: Allows unsetting `noncurrent_version_expiration.newer_noncurrent_versions` and `noncurrent_version_transition.newer_noncurrent_versions`. ([#44442](https://github.com/hashicorp/terraform-provider-aws/issues/44442)) +* resource/aws_s3_bucket_lifecycle_configuration: Do not warn if no filter element is set ([#43590](https://github.com/hashicorp/terraform-provider-aws/issues/43590)) +* resource/aws_vpc: Correctly set `ipv6_cidr_block` when the VPC has multiple associated IPv6 CIDRs ([#44362](https://github.com/hashicorp/terraform-provider-aws/issues/44362)) ## 6.14.1 (September 22, 2025) diff --git a/GNUmakefile b/GNUmakefile index 6f1a93f77ed0..5ad2bf48f756 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -414,6 +414,7 @@ provider-lint: ## [CI] ProviderLint Checks / providerlint quick-fix-heading: ## Just a heading for quick-fix @echo "make: Quick fixes..." + @echo "make: Multiple runs are needed if it finds errors (later targets not reached)" quick-fix: quick-fix-heading fmt testacc-lint-fix fix-imports modern-fix semgrep-fix website-terrafmt-fix ## Some quick fixes diff --git a/go.mod b/go.mod index 5f202ff83f99..6416af313b17 100644 --- a/go.mod +++ b/go.mod @@ -11,266 +11,266 @@ require ( github.com/YakDriver/go-version v0.1.0 github.com/YakDriver/regexache v0.24.0 github.com/YakDriver/smarterr v0.6.0 - github.com/aws/aws-sdk-go-v2 v1.39.1 - github.com/aws/aws-sdk-go-v2/config v1.31.10 - github.com/aws/aws-sdk-go-v2/credentials v1.18.14 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.8 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.8 - github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.5 - github.com/aws/aws-sdk-go-v2/service/account v1.28.5 - github.com/aws/aws-sdk-go-v2/service/acm v1.37.5 - github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.4 - github.com/aws/aws-sdk-go-v2/service/amp v1.40.2 - github.com/aws/aws-sdk-go-v2/service/amplify v1.37.4 - github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.5 - github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.5 - github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.5 - github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.5 - github.com/aws/aws-sdk-go-v2/service/appflow v1.50.5 - github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.5 - github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.4 - github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.4 - github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.15.7 - github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.5 - github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.6 - github.com/aws/aws-sdk-go-v2/service/appstream v1.49.5 - github.com/aws/aws-sdk-go-v2/service/appsync v1.51.5 - github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.7 - github.com/aws/aws-sdk-go-v2/service/athena v1.55.5 - github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.5 - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.2 - github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.4 - github.com/aws/aws-sdk-go-v2/service/backup v1.47.5 - github.com/aws/aws-sdk-go-v2/service/batch v1.57.9 - github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.7 - github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.1 - github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.5 - github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.5.1 - github.com/aws/aws-sdk-go-v2/service/billing v1.7.6 - github.com/aws/aws-sdk-go-v2/service/budgets v1.39.1 - github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.5 - github.com/aws/aws-sdk-go-v2/service/chime v1.40.4 - github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.5 - github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.26.4 - github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.34.0 - github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.4 - github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.5 - github.com/aws/aws-sdk-go-v2/service/cloudformation v1.66.3 - github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.3 - github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.7 - github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.4 - github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.5 - github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.5 - github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.50.2 - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.1 - github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.5 - github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.4 - github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.7 - github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.5 - github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.4 - github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.4 - github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.4 - github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.4 - github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.5 - github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.5 - github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.5 - github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.5 - github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.6 - github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.5 - github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.4 - github.com/aws/aws-sdk-go-v2/service/configservice v1.58.1 - github.com/aws/aws-sdk-go-v2/service/connect v1.140.1 - github.com/aws/aws-sdk-go-v2/service/connectcases v1.30.5 - github.com/aws/aws-sdk-go-v2/service/controltower v1.26.5 - github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.5 - github.com/aws/aws-sdk-go-v2/service/costexplorer v1.56.1 - github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.5 - github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.52.5 - github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.5 - github.com/aws/aws-sdk-go-v2/service/databrew v1.38.4 - github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.5 - github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.4 - github.com/aws/aws-sdk-go-v2/service/datasync v1.54.5 - github.com/aws/aws-sdk-go-v2/service/datazone v1.41.2 - github.com/aws/aws-sdk-go-v2/service/dax v1.28.5 - github.com/aws/aws-sdk-go-v2/service/detective v1.37.6 - github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.5 - github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.5 - github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.5 - github.com/aws/aws-sdk-go-v2/service/directoryservice v1.37.4 - github.com/aws/aws-sdk-go-v2/service/dlm v1.34.5 - github.com/aws/aws-sdk-go-v2/service/docdb v1.46.5 - github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.5 - github.com/aws/aws-sdk-go-v2/service/drs v1.35.5 - github.com/aws/aws-sdk-go-v2/service/dsql v1.9.7 - github.com/aws/aws-sdk-go-v2/service/dynamodb v1.50.4 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.0 - github.com/aws/aws-sdk-go-v2/service/ecr v1.50.4 - github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.5 - github.com/aws/aws-sdk-go-v2/service/ecs v1.64.1 - github.com/aws/aws-sdk-go-v2/service/efs v1.40.6 - github.com/aws/aws-sdk-go-v2/service/eks v1.74.1 - github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.4 - github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.6 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.5 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.5 - github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.5 - github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.5 - github.com/aws/aws-sdk-go-v2/service/emr v1.54.4 - github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.1 - github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.5 - github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.4 - github.com/aws/aws-sdk-go-v2/service/evidently v1.28.4 - github.com/aws/aws-sdk-go-v2/service/evs v1.5.1 - github.com/aws/aws-sdk-go-v2/service/finspace v1.33.5 - github.com/aws/aws-sdk-go-v2/service/firehose v1.41.5 - github.com/aws/aws-sdk-go-v2/service/fis v1.37.4 - github.com/aws/aws-sdk-go-v2/service/fms v1.44.4 - github.com/aws/aws-sdk-go-v2/service/fsx v1.61.5 - github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.5 - github.com/aws/aws-sdk-go-v2/service/glacier v1.31.5 - github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.5 - github.com/aws/aws-sdk-go-v2/service/glue v1.128.4 - github.com/aws/aws-sdk-go-v2/service/grafana v1.31.5 - github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.5 - github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.5 - github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.1 - github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.4 - github.com/aws/aws-sdk-go-v2/service/iam v1.47.6 - github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.5 - github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.47.1 - github.com/aws/aws-sdk-go-v2/service/inspector v1.30.4 - github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.5 - github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.4 - github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.7 - github.com/aws/aws-sdk-go-v2/service/iot v1.69.4 - github.com/aws/aws-sdk-go-v2/service/ivs v1.47.5 - github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.4 - github.com/aws/aws-sdk-go-v2/service/kafka v1.43.5 - github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.4 - github.com/aws/aws-sdk-go-v2/service/kendra v1.60.5 - github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.5 - github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.4 - github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.5 - github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.6 - github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.4 - github.com/aws/aws-sdk-go-v2/service/kms v1.45.4 - github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.4 - github.com/aws/aws-sdk-go-v2/service/lambda v1.77.5 - github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.5 - github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.4 - github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.5 - github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.5 - github.com/aws/aws-sdk-go-v2/service/lightsail v1.48.5 - github.com/aws/aws-sdk-go-v2/service/location v1.49.5 - github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.5 - github.com/aws/aws-sdk-go-v2/service/m2 v1.25.5 - github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.5 - github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.44.5 - github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.5 - github.com/aws/aws-sdk-go-v2/service/medialive v1.83.1 - github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.5 - github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.2 - github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.5 - github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.5 - github.com/aws/aws-sdk-go-v2/service/memorydb v1.31.5 - github.com/aws/aws-sdk-go-v2/service/mgn v1.37.4 - github.com/aws/aws-sdk-go-v2/service/mq v1.34.3 - github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.5 - github.com/aws/aws-sdk-go-v2/service/neptune v1.42.3 - github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.4 - github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.56.1 - github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.6 - github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.5 - github.com/aws/aws-sdk-go-v2/service/notifications v1.7.3 - github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.7 - github.com/aws/aws-sdk-go-v2/service/oam v1.22.4 - github.com/aws/aws-sdk-go-v2/service/odb v1.4.5 - github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.4 - github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.3 - github.com/aws/aws-sdk-go-v2/service/organizations v1.45.2 - github.com/aws/aws-sdk-go-v2/service/osis v1.20.1 - github.com/aws/aws-sdk-go-v2/service/outposts v1.56.6 - github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.1 - github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.5 - github.com/aws/aws-sdk-go-v2/service/pcs v1.13.1 - github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.5 - github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.4 - github.com/aws/aws-sdk-go-v2/service/pipes v1.23.4 - github.com/aws/aws-sdk-go-v2/service/polly v1.53.5 - github.com/aws/aws-sdk-go-v2/service/pricing v1.39.5 - github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.5 - github.com/aws/aws-sdk-go-v2/service/qldb v1.30.5 - github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.1 - github.com/aws/aws-sdk-go-v2/service/ram v1.34.5 - github.com/aws/aws-sdk-go-v2/service/rbin v1.26.5 - github.com/aws/aws-sdk-go-v2/service/rds v1.107.1 - github.com/aws/aws-sdk-go-v2/service/redshift v1.58.4 - github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.5 - github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.7 - github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.4 - github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.5 - github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.21.5 - github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.6 - github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.5 - github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.5 - github.com/aws/aws-sdk-go-v2/service/route53 v1.58.3 - github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.3 - github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.5 - github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.6 - github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.5 - github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.5 - github.com/aws/aws-sdk-go-v2/service/rum v1.28.6 - github.com/aws/aws-sdk-go-v2/service/s3 v1.88.2 - github.com/aws/aws-sdk-go-v2/service/s3control v1.66.1 - github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.5 - github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.4 - github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.7 - github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.2 - github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.4 - github.com/aws/aws-sdk-go-v2/service/schemas v1.33.4 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.5 - github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.3 - github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.5 - github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.5 - github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.5 - github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.5 - github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.8 - github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.4 - github.com/aws/aws-sdk-go-v2/service/ses v1.34.4 - github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.4 - github.com/aws/aws-sdk-go-v2/service/sfn v1.39.5 - github.com/aws/aws-sdk-go-v2/service/shield v1.34.5 - github.com/aws/aws-sdk-go-v2/service/signer v1.31.5 - github.com/aws/aws-sdk-go-v2/service/sns v1.38.4 - github.com/aws/aws-sdk-go-v2/service/sqs v1.42.7 - github.com/aws/aws-sdk-go-v2/service/ssm v1.65.0 - github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.7 - github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.4 - github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.5 - github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.4 - github.com/aws/aws-sdk-go-v2/service/sso v1.29.4 - github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.0 - github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.5 - github.com/aws/aws-sdk-go-v2/service/sts v1.38.5 - github.com/aws/aws-sdk-go-v2/service/swf v1.32.4 - github.com/aws/aws-sdk-go-v2/service/synthetics v1.40.5 - github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.5 - github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.5 - github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.4 - github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.4 - github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.5 - github.com/aws/aws-sdk-go-v2/service/transfer v1.65.6 - github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.3 - github.com/aws/aws-sdk-go-v2/service/vpclattice v1.18.4 - github.com/aws/aws-sdk-go-v2/service/waf v1.30.4 - github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.5 - github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.6 - github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.5 - github.com/aws/aws-sdk-go-v2/service/workmail v1.36.3 - github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.5 - github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.5 - github.com/aws/aws-sdk-go-v2/service/xray v1.36.3 + github.com/aws/aws-sdk-go-v2 v1.39.2 + github.com/aws/aws-sdk-go-v2/config v1.31.12 + github.com/aws/aws-sdk-go-v2/credentials v1.18.16 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.11 + github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.6 + github.com/aws/aws-sdk-go-v2/service/account v1.28.6 + github.com/aws/aws-sdk-go-v2/service/acm v1.37.6 + github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.5 + github.com/aws/aws-sdk-go-v2/service/amp v1.40.3 + github.com/aws/aws-sdk-go-v2/service/amplify v1.37.5 + github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.6 + github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.6 + github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.6 + github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.6 + github.com/aws/aws-sdk-go-v2/service/appflow v1.50.6 + github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.6 + github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.5 + github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.5 + github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.16.0 + github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.6 + github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.7 + github.com/aws/aws-sdk-go-v2/service/appstream v1.49.7 + github.com/aws/aws-sdk-go-v2/service/appsync v1.51.6 + github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.8 + github.com/aws/aws-sdk-go-v2/service/athena v1.55.6 + github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.6 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.3 + github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.5 + github.com/aws/aws-sdk-go-v2/service/backup v1.48.0 + github.com/aws/aws-sdk-go-v2/service/batch v1.57.10 + github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.8 + github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.2 + github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.6 + github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.7.0 + github.com/aws/aws-sdk-go-v2/service/billing v1.8.0 + github.com/aws/aws-sdk-go-v2/service/budgets v1.39.2 + github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.6 + github.com/aws/aws-sdk-go-v2/service/chime v1.40.5 + github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.6 + github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.27.0 + github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.36.0 + github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.5 + github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.6 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.67.0 + github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4 + github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.8 + github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.5 + github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.6 + github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.6 + github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.51.1 + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.2 + github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.6 + github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.5 + github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.8 + github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.6 + github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.5 + github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.5 + github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.5 + github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.5 + github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.6 + github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.6 + github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.6 + github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.6 + github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.7 + github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.6 + github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.5 + github.com/aws/aws-sdk-go-v2/service/configservice v1.58.2 + github.com/aws/aws-sdk-go-v2/service/connect v1.141.0 + github.com/aws/aws-sdk-go-v2/service/connectcases v1.32.0 + github.com/aws/aws-sdk-go-v2/service/controltower v1.26.6 + github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.6 + github.com/aws/aws-sdk-go-v2/service/costexplorer v1.57.0 + github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.6 + github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.53.0 + github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.7 + github.com/aws/aws-sdk-go-v2/service/databrew v1.38.5 + github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.6 + github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.5 + github.com/aws/aws-sdk-go-v2/service/datasync v1.55.0 + github.com/aws/aws-sdk-go-v2/service/datazone v1.42.0 + github.com/aws/aws-sdk-go-v2/service/dax v1.29.1 + github.com/aws/aws-sdk-go-v2/service/detective v1.37.7 + github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.6 + github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.6 + github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.6 + github.com/aws/aws-sdk-go-v2/service/directoryservice v1.38.0 + github.com/aws/aws-sdk-go-v2/service/dlm v1.34.6 + github.com/aws/aws-sdk-go-v2/service/docdb v1.46.6 + github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.6 + github.com/aws/aws-sdk-go-v2/service/drs v1.35.6 + github.com/aws/aws-sdk-go-v2/service/dsql v1.9.8 + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.51.0 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.1 + github.com/aws/aws-sdk-go-v2/service/ecr v1.50.5 + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.6 + github.com/aws/aws-sdk-go-v2/service/ecs v1.65.1 + github.com/aws/aws-sdk-go-v2/service/efs v1.40.8 + github.com/aws/aws-sdk-go-v2/service/eks v1.74.2 + github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.5 + github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.7 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.6 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.6 + github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.6 + github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.6 + github.com/aws/aws-sdk-go-v2/service/emr v1.54.5 + github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.2 + github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.6 + github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.5 + github.com/aws/aws-sdk-go-v2/service/evidently v1.28.5 + github.com/aws/aws-sdk-go-v2/service/evs v1.5.2 + github.com/aws/aws-sdk-go-v2/service/finspace v1.33.6 + github.com/aws/aws-sdk-go-v2/service/firehose v1.41.6 + github.com/aws/aws-sdk-go-v2/service/fis v1.37.5 + github.com/aws/aws-sdk-go-v2/service/fms v1.44.6 + github.com/aws/aws-sdk-go-v2/service/fsx v1.62.0 + github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.6 + github.com/aws/aws-sdk-go-v2/service/glacier v1.31.6 + github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.6 + github.com/aws/aws-sdk-go-v2/service/glue v1.130.0 + github.com/aws/aws-sdk-go-v2/service/grafana v1.31.6 + github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.6 + github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.6 + github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.3 + github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.5 + github.com/aws/aws-sdk-go-v2/service/iam v1.47.7 + github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.6 + github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.48.0 + github.com/aws/aws-sdk-go-v2/service/inspector v1.30.5 + github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.6 + github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.5 + github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.8 + github.com/aws/aws-sdk-go-v2/service/iot v1.69.5 + github.com/aws/aws-sdk-go-v2/service/ivs v1.47.6 + github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.5 + github.com/aws/aws-sdk-go-v2/service/kafka v1.43.6 + github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.5 + github.com/aws/aws-sdk-go-v2/service/kendra v1.60.6 + github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.6 + github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.5 + github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.6 + github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.7 + github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.5 + github.com/aws/aws-sdk-go-v2/service/kms v1.45.6 + github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.5 + github.com/aws/aws-sdk-go-v2/service/lambda v1.77.6 + github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.6 + github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.5 + github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.6 + github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.6 + github.com/aws/aws-sdk-go-v2/service/lightsail v1.49.1 + github.com/aws/aws-sdk-go-v2/service/location v1.49.6 + github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.6 + github.com/aws/aws-sdk-go-v2/service/m2 v1.25.6 + github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.6 + github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.45.0 + github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.6 + github.com/aws/aws-sdk-go-v2/service/medialive v1.84.0 + github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.6 + github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.3 + github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.6 + github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.6 + github.com/aws/aws-sdk-go-v2/service/memorydb v1.32.0 + github.com/aws/aws-sdk-go-v2/service/mgn v1.37.5 + github.com/aws/aws-sdk-go-v2/service/mq v1.34.4 + github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.6 + github.com/aws/aws-sdk-go-v2/service/neptune v1.42.5 + github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.5 + github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.57.1 + github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.7 + github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.6 + github.com/aws/aws-sdk-go-v2/service/notifications v1.7.4 + github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.8 + github.com/aws/aws-sdk-go-v2/service/oam v1.22.5 + github.com/aws/aws-sdk-go-v2/service/odb v1.4.6 + github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.5 + github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.4 + github.com/aws/aws-sdk-go-v2/service/organizations v1.45.3 + github.com/aws/aws-sdk-go-v2/service/osis v1.20.2 + github.com/aws/aws-sdk-go-v2/service/outposts v1.56.7 + github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.2 + github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.6 + github.com/aws/aws-sdk-go-v2/service/pcs v1.14.0 + github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.6 + github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.5 + github.com/aws/aws-sdk-go-v2/service/pipes v1.23.5 + github.com/aws/aws-sdk-go-v2/service/polly v1.53.6 + github.com/aws/aws-sdk-go-v2/service/pricing v1.39.6 + github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.6 + github.com/aws/aws-sdk-go-v2/service/qldb v1.30.6 + github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.4 + github.com/aws/aws-sdk-go-v2/service/ram v1.34.6 + github.com/aws/aws-sdk-go-v2/service/rbin v1.26.6 + github.com/aws/aws-sdk-go-v2/service/rds v1.108.1 + github.com/aws/aws-sdk-go-v2/service/redshift v1.59.0 + github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.6 + github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.8 + github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.5 + github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.6 + github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.22.0 + github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.7 + github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.6 + github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.6 + github.com/aws/aws-sdk-go-v2/service/route53 v1.58.4 + github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.4 + github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.6 + github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.7 + github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.6 + github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.6 + github.com/aws/aws-sdk-go-v2/service/rum v1.28.7 + github.com/aws/aws-sdk-go-v2/service/s3 v1.88.3 + github.com/aws/aws-sdk-go-v2/service/s3control v1.66.2 + github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.6 + github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.5 + github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.8 + github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.3 + github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.5 + github.com/aws/aws-sdk-go-v2/service/schemas v1.33.5 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.6 + github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.4 + github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.6 + github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.6 + github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.6 + github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.6 + github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.9 + github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.5 + github.com/aws/aws-sdk-go-v2/service/ses v1.34.5 + github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.5 + github.com/aws/aws-sdk-go-v2/service/sfn v1.39.6 + github.com/aws/aws-sdk-go-v2/service/shield v1.34.6 + github.com/aws/aws-sdk-go-v2/service/signer v1.31.6 + github.com/aws/aws-sdk-go-v2/service/sns v1.38.5 + github.com/aws/aws-sdk-go-v2/service/sqs v1.42.8 + github.com/aws/aws-sdk-go-v2/service/ssm v1.65.1 + github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.8 + github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.5 + github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.6 + github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.5 + github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 + github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.2 + github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.6 + github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 + github.com/aws/aws-sdk-go-v2/service/swf v1.32.5 + github.com/aws/aws-sdk-go-v2/service/synthetics v1.41.0 + github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.6 + github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.6 + github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.5 + github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.5 + github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.6 + github.com/aws/aws-sdk-go-v2/service/transfer v1.66.0 + github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.5 + github.com/aws/aws-sdk-go-v2/service/vpclattice v1.19.0 + github.com/aws/aws-sdk-go-v2/service/waf v1.30.5 + github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.6 + github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.7 + github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.6 + github.com/aws/aws-sdk-go-v2/service/workmail v1.36.4 + github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.6 + github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.6 + github.com/aws/aws-sdk-go-v2/service/xray v1.36.4 github.com/aws/smithy-go v1.23.0 github.com/beevik/etree v1.6.0 github.com/cedar-policy/cedar-go v1.2.6 @@ -280,7 +280,7 @@ require ( github.com/goccy/go-yaml v1.18.0 github.com/google/go-cmp v0.7.0 github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.23.0 - github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 github.com/hashicorp/awspolicyequivalence v1.7.0 github.com/hashicorp/cli v1.1.7 github.com/hashicorp/go-cleanhttp v0.5.2 @@ -301,7 +301,7 @@ require ( github.com/hashicorp/terraform-plugin-mux v0.21.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1 github.com/hashicorp/terraform-plugin-testing v1.14.0-beta.1 - github.com/jaswdr/faker/v2 v2.8.0 + github.com/jaswdr/faker/v2 v2.8.1 github.com/jmespath/go-jmespath v0.4.0 github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38 github.com/mitchellh/copystructure v1.2.0 @@ -324,16 +324,16 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.8 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/cloudflare/circl v1.6.1 // indirect @@ -369,7 +369,7 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/zclconf/go-cty v1.17.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.63.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect diff --git a/go.sum b/go.sum index 00c5e146c46f..1789fde81099 100644 --- a/go.sum +++ b/go.sum @@ -23,548 +23,548 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.39.1 h1:fWZhGAwVRK/fAN2tmt7ilH4PPAE11rDj7HytrmbZ2FE= -github.com/aws/aws-sdk-go-v2 v1.39.1/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= +github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I= +github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00= -github.com/aws/aws-sdk-go-v2/config v1.31.10 h1:7LllDZAegXU3yk41mwM6KcPu0wmjKGQB1bg99bNdQm4= -github.com/aws/aws-sdk-go-v2/config v1.31.10/go.mod h1:Ge6gzXPjqu4v0oHvgAwvGzYcK921GU0hQM25WF/Kl+8= -github.com/aws/aws-sdk-go-v2/credentials v1.18.14 h1:TxkI7QI+sFkTItN/6cJuMZEIVMFXeu2dI1ZffkXngKI= -github.com/aws/aws-sdk-go-v2/credentials v1.18.14/go.mod h1:12x4Uw/vijC11XkctTjy92TNCQ+UnNJkT7fzX0Yd93E= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.8 h1:gLD09eaJUdiszm7vd1btiQUYE0Hj+0I2b8AS+75z9AY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.8/go.mod h1:4RW3oMPt1POR74qVOC4SbubxAwdP4pCT0nSw3jycOU4= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.8 h1:QcAh/TNGM3MWe95ilMWwnieXWXsyM33Mb/RuTGlWLm4= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.8/go.mod h1:72m/ZCCgYpXJzsgI8uJFYMnXEjtZ4kkaolL9NRXLSnU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.8 h1:6bgAZgRyT4RoFWhxS+aoGMFyE0cD1bSzFnEEi4bFPGI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.8/go.mod h1:KcGkXFVU8U28qS4KvLEcPxytPZPBcRawaH2Pf/0jptE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.8 h1:HhJYoES3zOz34yWEpGENqJvRVPqpmJyR3+AFg9ybhdY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.8/go.mod h1:JnA+hPWeYAVbDssp83tv+ysAG8lTfLVXvSsyKg/7xNA= +github.com/aws/aws-sdk-go-v2/config v1.31.12 h1:pYM1Qgy0dKZLHX2cXslNacbcEFMkDMl+Bcj5ROuS6p8= +github.com/aws/aws-sdk-go-v2/config v1.31.12/go.mod h1:/MM0dyD7KSDPR+39p9ZNVKaHDLb9qnfDurvVS2KAhN8= +github.com/aws/aws-sdk-go-v2/credentials v1.18.16 h1:4JHirI4zp958zC026Sm+V4pSDwW4pwLefKrc0bF2lwI= +github.com/aws/aws-sdk-go-v2/credentials v1.18.16/go.mod h1:qQMtGx9OSw7ty1yLclzLxXCRbrkjWAM7JnObZjmCB7I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 h1:Mv4Bc0mWmv6oDuSWTKnk+wgeqPL5DRFu5bQL9BGPQ8Y= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9/go.mod h1:IKlKfRppK2a1y0gy1yH6zD+yX5uplJ6UuPlgd48dJiQ= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.11 h1:w4GjasReY0m9vZA/3YhoBUBi1ZIWUHYQRm61v0BKcZg= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.11/go.mod h1:IPS1CSYQ8lfLYGytpMEPW4erZmVFUdxLpC0RCI/RCn8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.8 h1:1/bT9kDdLQzfZ1e6J6hpW+SfNDd6xrV8F3M2CuGyUz8= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.8/go.mod h1:RbdwTONAIi59ej/+1H+QzZORt5bcyAtbrS7FQb2pvz0= -github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.5 h1:ahcmzpmxwWG+/G67+QVEZK7GBWywTSG6jDEJ4PzpYgo= -github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.5/go.mod h1:9usigGMimzM79Y4yFdqgqC1SasoUKDVTmwpeHBrw6yw= -github.com/aws/aws-sdk-go-v2/service/account v1.28.5 h1:VDhBmhdDYFqzT4jBo/+dlK8OQBzCNdxbbvmVFOxIGhE= -github.com/aws/aws-sdk-go-v2/service/account v1.28.5/go.mod h1:LhQR+JAtexjWOFlTHqdqTv/BTbvs9xY68KTzCEx8woo= -github.com/aws/aws-sdk-go-v2/service/acm v1.37.5 h1:vTmyvkmMJEKZgyhSuaEv8gZCJJlgNpSpYy/4CExjHoA= -github.com/aws/aws-sdk-go-v2/service/acm v1.37.5/go.mod h1:TmyW/AiLmFEXwFsm5hh2T86BpgFbcB1icshuzFu8LgY= -github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.4 h1:1SdrKkB7zWf/jzV1NCECWGaK/tW+hDFein1Bx+zlmM0= -github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.4/go.mod h1:fEljIacWp3QN6OhEeSdETPP1QAon5eqOFQNNU870EiQ= -github.com/aws/aws-sdk-go-v2/service/amp v1.40.2 h1:LeNARz0HYUAPNF9SvUE+7YuWH9EfVV6lXyDSS/IJGZk= -github.com/aws/aws-sdk-go-v2/service/amp v1.40.2/go.mod h1:FvXvxRCSJ+C4GXgypn3JO42MrQpuw/82xT/w+pgZ9eo= -github.com/aws/aws-sdk-go-v2/service/amplify v1.37.4 h1:8yMWsijdMvnkK2CY1JfVu5hV8r0yprDaecgiacf1jrM= -github.com/aws/aws-sdk-go-v2/service/amplify v1.37.4/go.mod h1:k2qW1S0NN8fi7hLuQjqOdQvMIbzFsvM3qm+oS1SfX60= -github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.5 h1:skBoXAddT8Kj8Hu6B/+rpDd8btytsDuQtV91j4yv9Kw= -github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.5/go.mod h1:17HIwZjGn7CtmiRV4Q2AO6srqQZRC0c+KlAiyAGK+uQ= -github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.5 h1:6XVaF2fTNZThz5n/3YObHIIFS1WaaGnbQI/6aJasdas= -github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.5/go.mod h1:MYkXmYhWdgLwkzyjfbRchnSf53boo7m6QAS3ZRXaZKg= -github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.5 h1:ZWyYnXjlZ+48zYLyzOZ9t6BrDCJlDzd3A8TnGtYjDRI= -github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.5/go.mod h1:LpxhBlp1oM7R0CErx8+KR9VpiSS1UUb9UEM0GivB5WM= -github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.5 h1:DK+9MD7xMUFGJiqW+kJiMSIxaGoO8F3KJL5tAXZbnWc= -github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.5/go.mod h1:2x1+Rk0RpGfGhYX3dWyA21YiF/v65J3Y6GywC4VxiWA= -github.com/aws/aws-sdk-go-v2/service/appflow v1.50.5 h1:G4mGauYPPnWffLrZGLSBHMlSVZmJ6hlyMlL0UhMWuJA= -github.com/aws/aws-sdk-go-v2/service/appflow v1.50.5/go.mod h1:DG3i/cd3uEHB6gWWLPhI2+GNOW5Mcq0zq+9jpmQ+uEE= -github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.5 h1:gL9t5HYLKImIwtSmYOT/mrmFei/9w0OHRaImNkqO8gg= -github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.5/go.mod h1:mpG4rVlLYCIRESFlZlKoTmzGkeSLLTiHPHJtbGS6xPk= -github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.4 h1:iO8udIPScJgk8U53hl8psGVig+HFFY513vFw+DvJTJ0= -github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.4/go.mod h1:ybHG1Hx4EKsZs9lfWeBrx6UJf59niCybxdJoUD6KjOg= -github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.4 h1:hxfrwha8FOWp1H7sVb4qIVSezWSMOgamUCadRR4S58o= -github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.4/go.mod h1:vU4xegG7YujyiBgOqPbx1IGg1OeijviwP1rAK/p5U6w= -github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.15.7 h1:zOvYvWJQUI0amCkaUhS9d6ObzYkBodn31G9GkbdMSRk= -github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.15.7/go.mod h1:FgQ2k88o4rBYovSJ0Vi9Qo6/0KdoCc9GEydhsOkhAn4= -github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.5 h1:8vAgM2KvQL63O335li4QwvVcrMaABAAr38bbi6cniNU= -github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.5/go.mod h1:/LON1mHNfDZfZDuPKjl7qCavUC4d/rBZnjDwLdkNJAQ= -github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.6 h1:4FqI5E/fw0pH6HgflI1eyn25Ss1BxtE8Vy1ubVzQpFY= -github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.6/go.mod h1:QBuxmH6jvBz+VbBZRabFZ2z7sdPYS32OwSzzcPSbFso= -github.com/aws/aws-sdk-go-v2/service/appstream v1.49.5 h1:gbc/S8roq3jl9hdaIDdEYnK7oOhU23ET+rjidn045R4= -github.com/aws/aws-sdk-go-v2/service/appstream v1.49.5/go.mod h1:VHqX7t1TFzCW6c0/baFjL+c/uTLHTve9QvGnIl2t68E= -github.com/aws/aws-sdk-go-v2/service/appsync v1.51.5 h1:pZACTcwJMzHYlmqnF5V9QHTeRvHqCcRoKBVRs1b8tKw= -github.com/aws/aws-sdk-go-v2/service/appsync v1.51.5/go.mod h1:9peX7FKIuilf8nao3Sj6HqSyxq1cyxyS8hGOowUgw0s= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.7 h1:9WFtb9NflqlsC9/qoMYSMuHTPjefC9QjztCiWXroprM= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.7/go.mod h1:3NAtNcNccpi/I1R0UPcvYhroarbJKfxCewqIq+skiow= -github.com/aws/aws-sdk-go-v2/service/athena v1.55.5 h1:rZi1Qid0n2V4gnzxfmn6FEMEU6zKtCmcUV3VL9UiuRM= -github.com/aws/aws-sdk-go-v2/service/athena v1.55.5/go.mod h1:aLJfNa+nondGTH2gZ16OWEs9shuG2R1kM8XAFeyzMp8= -github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.5 h1:uzwUV8J0g+/tbZvfZxC/n7l7hurf7jQN+ZWEHwj784Q= -github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.5/go.mod h1:uMLfGaVbHvrR9i6RbRV+tuLqb659g9kkMEWpqkSo+S8= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.2 h1:YOWVoIjUoiwAVIRVU3PG2yNldh9dQT5OegnO99RO4ls= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.2/go.mod h1:t08UbddtoRQcKiIW2ZTfxX5x6vRaTj6KrKcf1R0I4tw= -github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.4 h1:qwgy4hxeCZmoYKMoxvY0DYNKmtJXv9exHVeVr0UVE4s= -github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.4/go.mod h1:jzCzRhms7J54Vx+T+OzbAPXu66H967Kx2pDBcQp1ebM= -github.com/aws/aws-sdk-go-v2/service/backup v1.47.5 h1:hXI1ic7LxVqoLJSifY9NRynWgKOV8MBqzRwqqlN+I+g= -github.com/aws/aws-sdk-go-v2/service/backup v1.47.5/go.mod h1:wFR/78TqeXIgQoFqu8m0SmwFx+ofSV3Mg7j1pyVTX4s= -github.com/aws/aws-sdk-go-v2/service/batch v1.57.9 h1:4zrkNVi3V20XlQ3tYJ8gLUyYWTGl1uAdES74M+mM//o= -github.com/aws/aws-sdk-go-v2/service/batch v1.57.9/go.mod h1:fWHsie3W5XBYLYlamL+Jv/zPhbjaSnOwoX6/2XvgXBA= -github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.7 h1:392wLo7mSsuSpYK61ozSmvSDThF7Xn6DOZltb8SOQjo= -github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.7/go.mod h1:CnVBOLm1nyq4dbS1Xl44GpxfOGZf4DiNn4d8kBJlQ6A= -github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.1 h1:vAnqxsmlnEYUzKUQLFjfy+YhilvIGqhBACU5vZPuP6I= -github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.1/go.mod h1:q/R1CT6xFa6YcVvNQtenUSMEs7tVd4S1oLulUd8+RCw= -github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.5 h1:M7a27wtqblMxOE8RnsCKXPO2xnuU8IVLl7nWpLOy27o= -github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.5/go.mod h1:NcYZhLyy4mnuIweU0K4WmE3GcxRzD/X6VqR5+3L6K/M= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.5.1 h1:r5tPK5Z9S0GxQCkVu5uDfMKiJUKyhR75aoVV9sIw+Tw= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.5.1/go.mod h1:cX30dTXPoDwf1ZVgnZU2wWaCV7QJdQvjBoMoWiJsnt4= -github.com/aws/aws-sdk-go-v2/service/billing v1.7.6 h1:dXylOk+JWTe/L3qzumnwz5CwO7+YLD9eacHOCJhtizI= -github.com/aws/aws-sdk-go-v2/service/billing v1.7.6/go.mod h1:NBTn4pyQeXa4/QT+wch5FqSPbZ41VfMZQmiBBePsL7k= -github.com/aws/aws-sdk-go-v2/service/budgets v1.39.1 h1:grOdaAKovx1HngbE3uFDzLqUXtGmnfMJP3WAiHA0jBs= -github.com/aws/aws-sdk-go-v2/service/budgets v1.39.1/go.mod h1:EDsMEIAC4BXqdkY/iTme86MCHd12edsjk5whpNyO6Bw= -github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.5 h1:HYVk9Mcs5/UtGov0QFkbee6kiJpFj+AXNQuDbHUi0T0= -github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.5/go.mod h1:PGj+XRbKggjufbcjSgl+FduG4flALTsKtjeSkG6UpKE= -github.com/aws/aws-sdk-go-v2/service/chime v1.40.4 h1:1mQj+E0k1DX9EgHFlSZT7ECVJt7acH2ZsVOCB5H9jbI= -github.com/aws/aws-sdk-go-v2/service/chime v1.40.4/go.mod h1:kGoQl88Hso174Z29Q/dodAmfWDZ7EHhqRbO1i9E2Xx0= -github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.5 h1:26+20xlISJWcOldgHLNY+Yuxbu2Tk/oDhuty3Zyjlpo= -github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.5/go.mod h1:eYayIHn6FawTcUhAqXd30b/pP8z3p0zfhfyse2qGWqE= -github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.26.4 h1:jFefKM709nuyV6uAYg6z/gxe2PidH/Vk3yADnjwSw18= -github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.26.4/go.mod h1:MBoFrOMGcstb0S5dglAEQ7SpX4TL+6Hn5FYZqWZI6qQ= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.34.0 h1:7zhXcQjI6YmzEyXWFIpGQl4IF6JzQSvFxmHu/oUMDSw= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.34.0/go.mod h1:poFTlKjRrbKjBOYKNTqfqsqoA4yM47e8Mk5HYHOeZ/k= -github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.4 h1:nWw9IVwWMylobwf2hR5uBhOMQ8+lj+xWNk4jP7w2skE= -github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.4/go.mod h1:rxayeoxnwqMBBypasFD2HL0taPiqntanftVq/raOkh0= -github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.5 h1:P6orsPAkseLLWPvAnniFTnpUFT43PLKXUFMwzHz7RLI= -github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.5/go.mod h1:xBedDPPftxA9mt/zRNFA5EZEtqEmBJEtEYbW+qJo5tM= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.66.3 h1:P+Jr65DtpIuYme6a3pjsvDIpCfNDk8oCFVzGsfhWqz0= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.66.3/go.mod h1:J5tabKm/zD5b3Uz4LKdZytESCQu0MGEzxUX7XYOOhNw= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.3 h1:JgzZxb/9UhqBwkRXrEVyHZMeGsjyovdERq15L3U9A0I= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.3/go.mod h1:uaoE1dsE7W/qZbWnAAfX46QEKpB4rrbdfnp3HRN4dDI= -github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.7 h1:tHmNsJ/QUJqBeUUD2gtpCJi1lQgDVNNkSGMxeRbsb6g= -github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.7/go.mod h1:cjvhAmUH3dIWLzOfxG3oVomq1w5etRw8PhxMU1Bu3LU= -github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.4 h1:F0f5RWjICiTvM9h5BP6U8tsdP6VdfSsy7euvha3hHTQ= -github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.4/go.mod h1:yztjcwCBIa6NSm6P4akOysMegI8AG7zwk62BQGYTuxA= -github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.5 h1:OemDTmq9D69Ur8gTtEpkdcGuD8LHOjeHfVcq/Rb6Sz8= -github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.5/go.mod h1:PzvSXLkE8mlOqSJl5ayXr1nc8+kaic9okDKL0F3rvZQ= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.5 h1:o6/qcMBLZ4YAfoDnRsPwE/xeM3kAU0nnnGP9ZPy4kTs= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.5/go.mod h1:RUoiEWrOYweLJemA9hLIuCaaJSXFiZryzZqK/AA9DYs= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.50.2 h1:RJJSBxXt3gEcZiWUDzTl0sLtknsfzGj7GrpGtZ81bDI= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.50.2/go.mod h1:6TdW6zAw6JIlaGSgRb/kV6pX7k7JfxiqKbymr6qB7ko= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.1 h1:JMYpgsJ31l0wjJCerJtIBo39HznZJ/ENJJzOSTcJh68= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.1/go.mod h1:zqtpx8Y/EydPCFy5MA9AJJBfJ+mCQz8BNHj2CvDvaYA= -github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.5 h1:Et3l7Yne0ZoMiaDS0fbq75oe6PbTr7hA1N0YOuXkpjM= -github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.5/go.mod h1:IwqSdfgHrMtfVwW5FFv0xj9sq3HM6z06DD2e1kselpQ= -github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.4 h1:2N3W0bdr/SxLQDfUGi1SPIORcuRSZ6FKm6FWBqGDo9g= -github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.4/go.mod h1:Pwyp2lLtt5/LXi53uMbJ13TXEwo3VPyYnHGP6N3hZOk= -github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.7 h1:+YQlq7rUHLV7B2szK9NfGjAhjun+MLiBQkCRSra0LMk= -github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.7/go.mod h1:vqJ0MON1UMGvFB3A+2LIuvVGRHdU9BFA2IaCcLSZ7zg= -github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.5 h1:IFvx5VOZbggY1Bpd/dFkMs9H6YtzZ4rBdEnkRaWA9i8= -github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.5/go.mod h1:vNYxiEmvRccYA7JJHtH4L4FoOGMSRiOvrczqh2FgxZg= -github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.4 h1:+HtFvo99RMfpgJN2mh/hn67UOY65y5RNU0S2uy9T+VM= -github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.4/go.mod h1:6CwXuWejMnqXkWdf3uskATk0EQ+v23e2pvgEn1TdqPk= -github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.4 h1:Wutz+Xyb863LzHbqhHftHXeAvIC0wrwmBASQY6c9f/M= -github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.4/go.mod h1:6M1YeHkMmOWtutcNJpkQ6Pm2lTcJhk5HlxOAXmOGDRo= -github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.4 h1:9qMax0S94rKAHoAuF1NJrD+okFd1rtBwgtPzfBNuYyA= -github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.4/go.mod h1:Nbt0nq5uPu0ejS5anjrSI3tBkERY8SL8rhBBn8M32Is= -github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.4 h1:mHsv+CicazS3rB1bUNj/ffwKbjQiHdY3PiJYb8SXYyw= -github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.4/go.mod h1:ZqROoQ6lpqfswK4A7MP31WgIGZxNp2hclWYIutHSbG8= -github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.5 h1:N2pNKqg02mEXeD+IBkzBMusuD/hLBAXh9Lwtbrj4xJk= -github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.5/go.mod h1:Bz8cpvViXoCeAdnVq5Z/lx8aAdPFXrH/LVYAgtbUHOU= -github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.5 h1:evPerbXm4GHFvROmQx7WZkKpvaP4zV86avDtcNEUdnE= -github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.5/go.mod h1:klJRj93ROIhdBewNs4ELuTq4fpqLahtFxy9BdFSDhqs= -github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.5 h1:CCBfmIsF8sIHv1E9mn/GJPui/R3BW5IJ10TUH04hyDc= -github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.5/go.mod h1:ZvOQmePGGdpBFiLqccrxzge8ggjjtSa8qpxmf5p1duQ= -github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.5 h1:3nYmv9oWR0rrG2q9jDtikenvpSjX5/YUTfznhxsIPgc= -github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.5/go.mod h1:h2tMUR2y5anI0f4DkuVcBH8exNYTTZ8BrLVypoiv7+w= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.6 h1:/EOZnHaz44R8IUPqmvdmwrRGs3I3fRjEIR8pSlqz5cQ= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.6/go.mod h1:gOSEL+GyAVlcUMPbw8P7qBZknGEhp8ShMw6gizLngE0= -github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.5 h1:oBCJmk5ZtWKY7yevlVVpUNmUzGYA5XFNEf9TCB1h3Pk= -github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.5/go.mod h1:Ftk2FokqewDroksWg0P02kASc+uoYtqbV3oGgi3YQJM= -github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.4 h1:f3VPBDMuIEA76JDNRXQ823SXQ922L200q5va1o37lUU= -github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.4/go.mod h1:rKRZAKXwLgUZOdXrjHfB3ko1zYj8KoQK6bpXTpUjan8= -github.com/aws/aws-sdk-go-v2/service/configservice v1.58.1 h1:YjwT6oWNI0KJANny3bZpMMLg6hKZajPIkHbAJ8fgYkI= -github.com/aws/aws-sdk-go-v2/service/configservice v1.58.1/go.mod h1:TDu0is6KJd6igH/aLiMY3ePszwUUL9srFr4eOUHzLVs= -github.com/aws/aws-sdk-go-v2/service/connect v1.140.1 h1:0APQTulMHxW9co+fScETtA0qmdeuIfqCK28uWU6Lmak= -github.com/aws/aws-sdk-go-v2/service/connect v1.140.1/go.mod h1:zkPWvG+gvw5UGyP9Iu/6FPaFHiSX94f9Fhffw2kgcvY= -github.com/aws/aws-sdk-go-v2/service/connectcases v1.30.5 h1:dO/ryGBzpxLh1028JG19CzZBZ7oHowbHjzVLhD0vZS4= -github.com/aws/aws-sdk-go-v2/service/connectcases v1.30.5/go.mod h1:mk7Q8p+AcP4xjdwGmBQSdof1pM5PIm+H9BO8Q/uzCW4= -github.com/aws/aws-sdk-go-v2/service/controltower v1.26.5 h1:sbORD+4WSo4hvVdIpUbE4CU+RrsoqDCoqBkI7S7+hJM= -github.com/aws/aws-sdk-go-v2/service/controltower v1.26.5/go.mod h1:jgAoCJvvCNC/OOtzyIvl11BZPASz5ATSNCknbUonX+w= -github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.5 h1:RabBaEOLoAvWVdqDwQ2cW4PF8DwXMmgarl2c6iuVaEc= -github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.5/go.mod h1:xmuTn3EtMz3rL35w3iUzR1nmKuAlLT7SM8PftOkIugQ= -github.com/aws/aws-sdk-go-v2/service/costexplorer v1.56.1 h1:HLDIBVSZkgZUpulXq9qccFzuCNbRgw+Tw4P6fLN7BsQ= -github.com/aws/aws-sdk-go-v2/service/costexplorer v1.56.1/go.mod h1:7DTxZXKffJHHcbPp9+0sRwFcXj2KL0fGpqB6DduPLhE= -github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.5 h1:P4vBeJGUzeWHZpZdyMXVSiIDx+Zw5zTnL374tQsfhjk= -github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.5/go.mod h1:ylrE0RKseaqxY7ERcqvwwCzdK6pvD+LDNJZYpil5RhA= -github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.52.5 h1:HIe9Q4h2mBPI6AMk4pzEEEDjG8vAukh7U63H9jDbPFw= -github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.52.5/go.mod h1:Th5Y0G4TvOMYN6lyCVEYgsLDz059NJXdDqlUOaeYDuM= -github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.5 h1:6T/CR26/V53CC4VvAK3bJlD4ibeXOO6tbt+DA+U9yYQ= -github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.5/go.mod h1:mn/2X3QkGZ7JW7Tb3dMwPing2cTzkYGuhyKUJzVEX/Y= -github.com/aws/aws-sdk-go-v2/service/databrew v1.38.4 h1:JgImAlmECnFCkhvnH9TCd553pzNTIRfH2Ul4R+p3d8k= -github.com/aws/aws-sdk-go-v2/service/databrew v1.38.4/go.mod h1:mL62FXgGPTF/Q/hepi1Qxh3HXU8Q5yp0y1wIIWANiFo= -github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.5 h1:+yel2bZWZRuhBqKX8PWFfXwr2HlTOHgnHPwXE9beoQU= -github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.5/go.mod h1:2D4PoeboTeeNKZ479TsSjl3B1F2pcQ5+GkOCgAZnzrI= -github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.4 h1:9mkH/ONm9RWxi3Ixym6LL1kvV6vo8orYBxQWPp6oExc= -github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.4/go.mod h1:OlSaTD0J8/KjGDsM+DnPhHiJVBamykRGLsAAg8A/OcA= -github.com/aws/aws-sdk-go-v2/service/datasync v1.54.5 h1:8BsejEevu0F/XLzi1Hc2GyU9t2qHMBl7OacFpmi8Jc8= -github.com/aws/aws-sdk-go-v2/service/datasync v1.54.5/go.mod h1:F0aJUK0TTE5AQAyWj8Dv9COO0t6UMoAyMnFESeZ/O+Q= -github.com/aws/aws-sdk-go-v2/service/datazone v1.41.2 h1:KA+OaZ1boO6q/Da+1pO0t4sjt42K9/dL0qqXMRiZyr8= -github.com/aws/aws-sdk-go-v2/service/datazone v1.41.2/go.mod h1:759UsQUMGOf3cm1iz9vsL+Epj7Wlddq58sldKqtJCFQ= -github.com/aws/aws-sdk-go-v2/service/dax v1.28.5 h1:jXqWwWs49FSwlfdkiNXFT82ZVyTou3oRGnd2QdUqAQk= -github.com/aws/aws-sdk-go-v2/service/dax v1.28.5/go.mod h1:lowvEGtcFbTbtL639HA0sek1VtvMtoQsflFi0ttTy8c= -github.com/aws/aws-sdk-go-v2/service/detective v1.37.6 h1:VvwWzJpBk4sup+mSuzX7Vmm30sW3y64czrCGUES8JUE= -github.com/aws/aws-sdk-go-v2/service/detective v1.37.6/go.mod h1:jXwgyIaSOaRuri9AWmyMDU39dAMMJ61RZ+YblT2R/6w= -github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.5 h1:40nKr1dmfn9f0doUxmvgC76QPGJ2F/1Mwh0+BXQBd7A= -github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.5/go.mod h1:++N+f27/Ne2Slli6+Yd8xomkzODF/cewRZZcfLqYc54= -github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.5 h1:POEwKseaALiTsWq5+aSb+sNg8+HzKOkVpSUrBI7i7d4= -github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.5/go.mod h1:RvU+42eaaSBXjDf5Og9Pswu+Gft/0fqvrJpSWkSlv6E= -github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.5 h1:ZeG7A3l7aMJE4/nxr4f8JKkPpbmMvg5/5A8DBJ99Cdc= -github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.5/go.mod h1:SQFyOg6kGN9d8NENqgQ3zjdVX610JXzyt+uN446hkhg= -github.com/aws/aws-sdk-go-v2/service/directoryservice v1.37.4 h1:ZDouCjBOrNmXq+GCCwC1fhoOzBpXQ/Usx05SHVpskjI= -github.com/aws/aws-sdk-go-v2/service/directoryservice v1.37.4/go.mod h1:rEEFx+xIPrVlhzJXFJiu79o6N13mys3LUCtHvHIygVo= -github.com/aws/aws-sdk-go-v2/service/dlm v1.34.5 h1:INJ+fEUVw4LwKU86UQv5OFQLg7U7Df3IxXtWZ1HDDaI= -github.com/aws/aws-sdk-go-v2/service/dlm v1.34.5/go.mod h1:CofHoDNqn6ZWkAgE3QuCJdvylmgp+IWh7gRssUnNyV8= -github.com/aws/aws-sdk-go-v2/service/docdb v1.46.5 h1:m7u48GaFM9XvDdSJGwHaHA5cmnE4/ioVjIeP60iQMXc= -github.com/aws/aws-sdk-go-v2/service/docdb v1.46.5/go.mod h1:9IAjRrIMPh5LFnWo4S2r1ZN+xq7qgKkC6RW8abBN1Go= -github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.5 h1:6aD1/jZBwjstYgB2wGpnuIohUqspeRvRmh0RFe1MI9A= -github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.5/go.mod h1:stxVYTXiIoyTTq+Gd/e1tVbi8AwGuSqi3m+1Itn0pmc= -github.com/aws/aws-sdk-go-v2/service/drs v1.35.5 h1:9HJvlrlqXyVo/5xYtnz30U3f6MifAQQTe/h4J/5Uuvw= -github.com/aws/aws-sdk-go-v2/service/drs v1.35.5/go.mod h1:TGMcQ5H9FecvGjhZqT8ozXOAFO+6a8sSTyFCEZ1EJ7g= -github.com/aws/aws-sdk-go-v2/service/dsql v1.9.7 h1:rwSOOhEKZXWYAqtqGjvIdslUOdOnbTYGpn83HPXJoL0= -github.com/aws/aws-sdk-go-v2/service/dsql v1.9.7/go.mod h1:kkU1xXHdCh7alFRoZA1qZPbB41Yy/uAINV2K6D79UbQ= -github.com/aws/aws-sdk-go-v2/service/dynamodb v1.50.4 h1:3EE5TTeBHPTKQNNeIHdXcJ6ENDsN7c2rCQUtbdolwV8= -github.com/aws/aws-sdk-go-v2/service/dynamodb v1.50.4/go.mod h1:8rWv4Lq/jrlspgd/wpdFeKrxLByJlfpFEk9g0Tw5iOw= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.0 h1:fTLR6dLDTGChAjecRPlVrKeznT0rVdzR4yn9Z68MTGk= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.0/go.mod h1:V0jbRy1/IPapnkqgXSwVOFB+u5pnCwd9S+R3pKWULC4= -github.com/aws/aws-sdk-go-v2/service/ecr v1.50.4 h1:kPe1ZLqERYZxxDi6ysoX4oYavSJ6lkGaadsN1ogg3I8= -github.com/aws/aws-sdk-go-v2/service/ecr v1.50.4/go.mod h1:cAJR/1pLXISKFSSJsrsTZPw05PLL5xOIpbbzxM7GLiI= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.5 h1:98e3/QHaQ14WdBt3tZTFSyDGRh8BTVmGE6DICjN2iHo= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.5/go.mod h1:z8vly/P3m0RZ5CsZyKESSjcdmVvCjqKQUIfj5VwaLO0= -github.com/aws/aws-sdk-go-v2/service/ecs v1.64.1 h1:kAzHjjqQnu3ET5/cX1N5tKPqtExYk97wpD6MpRadq/A= -github.com/aws/aws-sdk-go-v2/service/ecs v1.64.1/go.mod h1:HIaZTpBD7+mgQEIv2wMzXYJw2T23sMFVNp2Mkw/ODFk= -github.com/aws/aws-sdk-go-v2/service/efs v1.40.6 h1:+Iry/PsJmm0m99bGpU00ubukGCG9G6N48Hqj5WMrvv4= -github.com/aws/aws-sdk-go-v2/service/efs v1.40.6/go.mod h1:6bFGewZgq0SC5QGUIBHl1BYZihIOi/ZPipEJMIBfbHs= -github.com/aws/aws-sdk-go-v2/service/eks v1.74.1 h1:/twnp/d6RQaccM/hEin33E5iYG0vLQY9DDRDleB6UGw= -github.com/aws/aws-sdk-go-v2/service/eks v1.74.1/go.mod h1:YfA/RHfplvaNVxukwg3e4KWJpsL7Ic7bfvCXhJnhbzQ= -github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.4 h1:9KuzJb9bUyMwNJyyh0pHfsTMR2OJZNtp9WTfcV2Vj3s= -github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.4/go.mod h1:2nKJzgK0+jae6diDJ7Fo9IyYkQMuE4U3LZotgLJZY3A= -github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.6 h1:NLE0iKGz29Oq45OQg+CkpaDP1BqftKmM74H/VX5HOkI= -github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.6/go.mod h1:+FEEAJlFxEGU5bYPE0/NhxMZGpMJ/TCmd7WicVc3Qhs= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.5 h1:3WQ2wo4l7zwu0IWzvbI5QVtzsN7+Eg42QR4D5qYkr2s= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.5/go.mod h1:7KZQYpEEZg47FYjzxWNz3Gc7xY0xYl0vGyXMltWplKE= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.5 h1:q7goP7oXfAvRlBxP7oMYlUzKUA8MpMpRkUxxmHEHNes= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.5/go.mod h1:BrvdV5vYXNjnsO5tM5CLWGkxj7pCa6E67wVVt+yXt1E= -github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.5 h1:HKdMcWFqzUlobL80o9WNMFNuOQsdE5xdf+qwQUUFco4= -github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.5/go.mod h1:ke8t2vaPfy1jzUrBCPaXSVww3uauW/VVd8CCzDxL16U= -github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.5 h1:Nc1bF38DmDyDwebbR7BgxxuIH1Yhl1EfPkPaKH0xQ1U= -github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.5/go.mod h1:9tF20YvxWfJ7WTYt5A45oqPUoLReFTjWITxDXnbAONA= -github.com/aws/aws-sdk-go-v2/service/emr v1.54.4 h1:ZC0c/fOSA9Yy/BXTGJlqv+QkvDgM7a/an0EhOmWAopY= -github.com/aws/aws-sdk-go-v2/service/emr v1.54.4/go.mod h1:yCZW7KzmSSuWxLKfLrrmriZxuE/rolBic2WsFZkfsIA= -github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.1 h1:fQQoDSorzE5J4jXsef/97ekcYODbvKaph3+rCzfnuZE= -github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.1/go.mod h1:QB1EyqZPQS8UKslM0as2eT3GXDkAgwTUQOR/iKzLI6k= -github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.5 h1:BobchIW2pMeagzST84A3ICzCZDwNjsYLopOKwsGioYE= -github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.5/go.mod h1:d5C/KgwOZXr7Mxf/ZymiwgwvutFEqQB9lMooWMp7Uww= -github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.4 h1:Qc0hIguje+lCQ78VSx70qVPG0nrajvWRbC5mkYc1W7Q= -github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.4/go.mod h1:bOMdhYMX+c/AQzi20lbWmO0U8hWRawDo9kNxvKutwSk= -github.com/aws/aws-sdk-go-v2/service/evidently v1.28.4 h1:iti9VdkeC7Z78qId7zw32Lo1RnsU9kjfJ8qSsIsWhCU= -github.com/aws/aws-sdk-go-v2/service/evidently v1.28.4/go.mod h1:cv8RDvuN+5Y2/qvtljWMR5grqefjkGhSivf/kot/IQY= -github.com/aws/aws-sdk-go-v2/service/evs v1.5.1 h1:Kvu09SgEie1SoW3MCGu7bsizpMZqFKrhZ0g2myl3MMQ= -github.com/aws/aws-sdk-go-v2/service/evs v1.5.1/go.mod h1:O7A46zFyZAePaEHIBWzpuxWBFAVxtaJkUDD/4FD2bG0= -github.com/aws/aws-sdk-go-v2/service/finspace v1.33.5 h1:SrudNTicBccapfNU3IKO1uW9A8WVRJH9h1pRI0hWt7Q= -github.com/aws/aws-sdk-go-v2/service/finspace v1.33.5/go.mod h1:BmK10iWdy5WqBV5G2hFIqqS8hszTg3gkdQQWK4Jw1s0= -github.com/aws/aws-sdk-go-v2/service/firehose v1.41.5 h1:Osa/8apMLAe2WY2yVaB8kTTPdrEfzXd13uKCJd7lt18= -github.com/aws/aws-sdk-go-v2/service/firehose v1.41.5/go.mod h1:K7ecJD6/1hejYb7lSc4JczwNS9leHGq9RMTLuyEg4ko= -github.com/aws/aws-sdk-go-v2/service/fis v1.37.4 h1:HmEC/I6kWPZ1gixODkajwr/M/vxZtjLT6o5z3mB2/5U= -github.com/aws/aws-sdk-go-v2/service/fis v1.37.4/go.mod h1:xqDZvBdIoE0FE35rljgotQyT/+I/Fvuc337dWyWApgk= -github.com/aws/aws-sdk-go-v2/service/fms v1.44.4 h1:rA6Q75idyG1SQYIUeTNYUQZ8oe3koEnqmceJRAuXDl8= -github.com/aws/aws-sdk-go-v2/service/fms v1.44.4/go.mod h1:Gy9MDI0yRrBenHa9Jzg1ud2u0ZI9yAThQTjX+0IamDg= -github.com/aws/aws-sdk-go-v2/service/fsx v1.61.5 h1:hIAuUn0uFjFnmg8WGncoEpyfxf7Y/t9eFhd8PpKnF18= -github.com/aws/aws-sdk-go-v2/service/fsx v1.61.5/go.mod h1:WO+0YogiUvQcY7FchHpdQ7vnBjNzl1v+rM34JpoSRaI= -github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.5 h1:dtYIF39DQ1IhFQBnDqGB1pes/UPfUjP0VgHoYMnX5Eg= -github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.5/go.mod h1:z2n/O9ruWRawdzCKHSwh0aFib/3q73aPYFXkoygmH7k= -github.com/aws/aws-sdk-go-v2/service/glacier v1.31.5 h1:SghWxcZVyI7Iu14jng5dColevrhl9sJGJWduQ/sD83w= -github.com/aws/aws-sdk-go-v2/service/glacier v1.31.5/go.mod h1:/CyArR40faf3oHIYTkXGqYOkSQ07i9/kJP8T1ghbgf0= -github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.5 h1:W2UcvAIYBFAkz7fsLLbRUIIyT0bT6L7aChxItt7Tes0= -github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.5/go.mod h1:O8zO9cNML7tuG38unyE/vO7z01stN90R4PKH/pPyw1o= -github.com/aws/aws-sdk-go-v2/service/glue v1.128.4 h1:kuB0Y0rBB8ktzMer1aAkRr97VcMOV3htrK5ozwk+IXY= -github.com/aws/aws-sdk-go-v2/service/glue v1.128.4/go.mod h1:hkEsN8mLtY+OlMapw83O6YPjKnBpV/Xrlaqk/HFmM1M= -github.com/aws/aws-sdk-go-v2/service/grafana v1.31.5 h1:p3uJu5V5c/o2PePeELynpedWi+zBv5HGyeJxhvuLqnQ= -github.com/aws/aws-sdk-go-v2/service/grafana v1.31.5/go.mod h1:kRsZsMlOY+IRQjl7ENV4zeJJeJVhUvNmnvGmDPaxovw= -github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.5 h1:8FCU0h/3dbf5ElK5wwbKNgt4tKPCIRIwmSjaY6sFeDI= -github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.5/go.mod h1:S8KznekVEeSHkKl+5NvxhSelRR5pT3MBsHXGfmMaKp8= -github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.5 h1:SlAT6W1uY0XW7s8x69OelXX2OWopTbCBqu/G98z1ikA= -github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.5/go.mod h1:Jccq9CeVAqBaeBppITbzWP/roisx1dj1fE0AmRhyJXg= -github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.1 h1:gjjiS2bSuqxmN3YZgyivU5bji7lhByp5x0yDNcCirbU= -github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.1/go.mod h1:N/9Md/EYVqAOUB93qUF+SAQKwNL3LCaeVF/Bf8Le4kY= -github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.4 h1:42woA14NMIht4st8dzBp8nJjlM7bRm6fEf2pIlUUUU8= -github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.4/go.mod h1:E0EosqrhvVN1kr4GTNPQ3S0B/+WJrzEjymQ7wI4ry6k= -github.com/aws/aws-sdk-go-v2/service/iam v1.47.6 h1:EWehQXACWr+6hzfZPwZChlfoVhiUCfLHE0Xh3kAfzWQ= -github.com/aws/aws-sdk-go-v2/service/iam v1.47.6/go.mod h1:qRXgEBWPIltrWHQwU+HkyBvwh1QgeigFcaCGCIVrWk0= -github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.5 h1:trORK1psQM+4hgsOt+Hm53bc/AABOl7nGTP7zQT4PzU= -github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.5/go.mod h1:yHjAOYH1Y+2Ne18ZyiRPETfmOuGovtZ7jKnieO4RPnw= -github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.47.1 h1:lfBxnqWxgeLoN7Nx48eoEPdwt+umHOvTM1SHLyexJ1U= -github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.47.1/go.mod h1:MyVok3M4Be3gH7wf1vu0hYAC91XR7XWkRvVaBfYAR/M= -github.com/aws/aws-sdk-go-v2/service/inspector v1.30.4 h1:jBy3o4eCas8qTF32sYjkVMDaPi5F91eRpyDaKE7Ldns= -github.com/aws/aws-sdk-go-v2/service/inspector v1.30.4/go.mod h1:BqgWCL5RDqMH9lO7CmPzOYH9I+F/WRus88PmRCBNBp4= -github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.5 h1:KTtccDNYtBmnJ00hz3pM8OndRMI+FTKZXs2KQ61xv80= -github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.5/go.mod h1:IhhaIu8jGcyQTTn7Yu8qJe9JeeH7l3ZGBVjduQEN7ho= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 h1:w9LnHqTq8MEdlnyhV4Bwfizd65lfNCNgdlNC6mM5paE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9/go.mod h1:LGEP6EK4nj+bwWNdrvX/FnDTFowdBNwcSPuZu/ouFys= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.6 h1:OXJuITvU8R/Npo5Wv2dgIFBYROm42kXAD16rk8qirs8= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.6/go.mod h1:PvvoZ5HHC38O5xDu4yKotP0ZLvnlbaJbHFOD8vppMQ8= +github.com/aws/aws-sdk-go-v2/service/account v1.28.6 h1:eEtL3V2CHjO4IDRwBelx1sZLRrz7vAsNUrDIb967FkI= +github.com/aws/aws-sdk-go-v2/service/account v1.28.6/go.mod h1:qi8Mmk5TSynuGi1KWkzrFIYfiKSaCv/lIxPPyPOlVfs= +github.com/aws/aws-sdk-go-v2/service/acm v1.37.6 h1:48oGbMpBSzihrU145gpjrxySIs+VNGCXu9kLTLAdJJg= +github.com/aws/aws-sdk-go-v2/service/acm v1.37.6/go.mod h1:4Xgg9iUMFMpWd19UokmUwBCU6fqNJ7LPo11YYt3/xl4= +github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.5 h1:0aROQbnQ6nGlI1idLYuxx/mv4s+2I02RFyOA5MOlMQk= +github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.5/go.mod h1:1whQS1vMFP9KQPLTc9dtqnJGjgJ6Sb80bkPoN8CPQ2k= +github.com/aws/aws-sdk-go-v2/service/amp v1.40.3 h1:pAbmvpyEwOX5OphEvNCjDMTZS+I4mNOBBK5Z6Ga6Zgo= +github.com/aws/aws-sdk-go-v2/service/amp v1.40.3/go.mod h1:Kaiyw5xthjYIWNvilHLlRiNwZa3owNXd+YgJs53hzDE= +github.com/aws/aws-sdk-go-v2/service/amplify v1.37.5 h1:mCxlw2Vuh5XZP6qwuUxr7bXWZ7drfbquJieS8VCIb+k= +github.com/aws/aws-sdk-go-v2/service/amplify v1.37.5/go.mod h1:HeH9qb/ftrO1k18S+BoWN3P/p83yS06x/Opny3ATXDs= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.6 h1:v8RqEs++cq7uAYUusuwrHLNEFACv0nlICCBwV11p5sY= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.6/go.mod h1:5EVcku5uDhMks5w1FwPL8hLKqJwCgIIbuF5th+vGQhE= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.6 h1:k78ulhtPtIqMiZqq8bPkpJlx66VN8DmDIeRgrYpzehc= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.6/go.mod h1:A5+OX0k1IIqRR4jR+zPgHpzKmEoLfpyY2xIrrJj8O98= +github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.6 h1:e81OBhEpYUKh7Wg3hHiRE5zHpYPTgB4Sja0YWCBMivU= +github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.6/go.mod h1:3lk8tz+bmjQEPEmdDF7zTDFHlqRFdn0zZvTa2cIe0r8= +github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.6 h1:L50VB8yUNNequjYNhUm+MCjFCxfN6KMaIcpLgo679y8= +github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.6/go.mod h1:v0gYYyI3wXm6R1nxhW068lcxbmh8wTBKIPafxXI7rf4= +github.com/aws/aws-sdk-go-v2/service/appflow v1.50.6 h1:Q30ADINfdo4matzYAGq4rPuQrjQKinuvdaHGnR9/Ksk= +github.com/aws/aws-sdk-go-v2/service/appflow v1.50.6/go.mod h1:2W0SilTCqSFglsMuZYKFmuZCOaBxGLnWvpik/GP+bT8= +github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.6 h1:kwnjEvDnDXPGC2yGF3ygvNs8EGnZFxzsX6bKWFA+j4c= +github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.6/go.mod h1:DqUWf8yC60AYaDfwq1zMLRxP9uT5R41FZwpZzIgEsWU= +github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.5 h1:0t/Dr8fwxkc5fkhoeuYRpGiPowbLKi424s3oeLCusRU= +github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.5/go.mod h1:NUciQYiEOln3pubY8iovZkWZdJrBTnoPPW3JTIk9QAI= +github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.5 h1:HWvL7MWRel0n6W5msGcS2BllKX8OEH168656YH8IRNg= +github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.5/go.mod h1:9jEkcPD8H2x5XTr4JKfuftpz4EoKAhrom5lQzLLCI6I= +github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.16.0 h1:k5Gds31CrXttYeulwB6VjflGSXnRegRG2jKiWLimgHo= +github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.16.0/go.mod h1:dB7ydHt6geh960yqkPjZZfA+qqLK577b0jifWU1ahy0= +github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.6 h1:Wupdnc/3bA0GPzEEZInLvu4FHEmkHNHsG/xahSggcGw= +github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.6/go.mod h1:yHte17Vasn4Ows3YO5zLC1MWX2Dw8by5KvgDm6XGSm8= +github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.7 h1:gJCGw8gwiTYjLeTpCdwHFE60SRPN7tH2m0ScVYUZ4+Y= +github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.7/go.mod h1:UiPYznwe6WwKIOwLlWgrjdKvfOVVQ7eaRzf+OC4BzM4= +github.com/aws/aws-sdk-go-v2/service/appstream v1.49.7 h1:RlPnZlTvnNxjOm9XuYxcUqzrcR4VoHrMHrrWoa3pj+w= +github.com/aws/aws-sdk-go-v2/service/appstream v1.49.7/go.mod h1:aPmkM5vZVr/vBeP+czUKCYWAlewa3QCaCZGh6gWZfm8= +github.com/aws/aws-sdk-go-v2/service/appsync v1.51.6 h1:YsjIVoljoczbCUYFzTUhNkYjJlEreqXeuicq2wyvO9A= +github.com/aws/aws-sdk-go-v2/service/appsync v1.51.6/go.mod h1:j4cEEClULtta5LEg7OgxqGTz4k0ipCAvue7P7GGRLQI= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.8 h1:01m2bIxzwrVbFB6XADodX2JwSSlpKfarYZWczIdYNSU= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.8/go.mod h1:h5EaGwLxZGbeUEkwE9BWg+4lPwv42YgTqqQ/SH2bbB0= +github.com/aws/aws-sdk-go-v2/service/athena v1.55.6 h1:OC3hqQ29uyNsftVHwdbfHpDopEBViNFypjy9N5eDsMw= +github.com/aws/aws-sdk-go-v2/service/athena v1.55.6/go.mod h1:I1paYl0qAaXc+6AmLtylg4ApBC0/HEs5myhVIcy4Nng= +github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.6 h1:QD02o1P75R198cYX9Nt3flwM5HmXxsmWAhG+8Wef2ig= +github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.6/go.mod h1:ZZh2P2Vy29z/3Occ3o40d0P4IuwkaZJPKrSD1gukI6Y= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.3 h1:2tVkkifL19ZmmCRJyOudUuTNRzA1SYN7D32iEkB8CvE= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.3/go.mod h1:/Utcw7rzRwiW7C9ypYInnEtgyU7Nr8eG3+RFUUvuE1o= +github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.5 h1:YUHawBzbCFAqJzMjyIwHYRNyCJ2cF3cNmqZZcm2/Zqc= +github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.5/go.mod h1:3YNMqOSRPyr23RKCv8RRQz2B2xflT/nk1bZuogMnO8g= +github.com/aws/aws-sdk-go-v2/service/backup v1.48.0 h1:o5T+4iVi6R+czsshTXZJoTpldwYWJw+kvO6lWPdmZeQ= +github.com/aws/aws-sdk-go-v2/service/backup v1.48.0/go.mod h1:5er5+2GO9YgfAvZ9VqDSf9HKrwKAtjVA5Fm83eXtkfM= +github.com/aws/aws-sdk-go-v2/service/batch v1.57.10 h1:C9unOW8pT063iGGpnNWonK+iRMnVR86iPnYdFaRmnqA= +github.com/aws/aws-sdk-go-v2/service/batch v1.57.10/go.mod h1:fl2yc8ac4mmMPh3ByJ6LRgdL25iPcQ3cUqhZl4R5chE= +github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.8 h1:4O1siNWkg2oMPNzma7AR1GZCQIkH233tl9bTtOaweUg= +github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.8/go.mod h1:Mm4OxLblLwMOAZjrNfDrltCqO/RKSa516DNDrapaZyw= +github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.2 h1:5Bq66lHNfiPHM9WBwzQfhqqctRTxXF3+Un1bm9ZyThE= +github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.2/go.mod h1:3sUHFSHdoib4v7JdqEGgxD2sIdTDikr4IpjBOgUAa0g= +github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.6 h1:SQcm5+AnLYVNJP0K8yFRWTfEifhQenCaF+aPfqXf+fk= +github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.6/go.mod h1:Jl3eDtXBZAze9w+aJO1oPzdk55CqOh+Tq9VhLTLQSRA= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.7.0 h1:g9JK8P5l42MhwGRwGT46vrDpPUtm1lQu7ojq7yq6ZX8= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.7.0/go.mod h1:Es+CYDVSPzyRIJaDDzxvoBNRc+AZbevIL8d+q1+3J5w= +github.com/aws/aws-sdk-go-v2/service/billing v1.8.0 h1:qffsTlqnTPtokF6Y4dlw4YUWPYtOw+PCQyv0gJ8o1PE= +github.com/aws/aws-sdk-go-v2/service/billing v1.8.0/go.mod h1:HaQjETFBieRL+1p0qWCYDzDe/JnI4oJM4UiO3qNEPTo= +github.com/aws/aws-sdk-go-v2/service/budgets v1.39.2 h1:HxSdjcZ9NPVG4ZdznJMUjqjR0DPBWSId0xKUbTfl/Eg= +github.com/aws/aws-sdk-go-v2/service/budgets v1.39.2/go.mod h1:+0hQkFGrrsp6x9hxk/n7EOscPVfwrBkTojUCthoHquM= +github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.6 h1:QWlDo8QuBHtT6LYYf5opmQtUY4ntkcU0mjmmmbZiMoM= +github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.6/go.mod h1:QSe+uEkQQHwIPKFfaZtbZWrNaRq5esdmdQspTPV4apY= +github.com/aws/aws-sdk-go-v2/service/chime v1.40.5 h1:kaAYFY5mvQHeyEX9pamOBly0Vx7f3Al3dCD9p3JJAnE= +github.com/aws/aws-sdk-go-v2/service/chime v1.40.5/go.mod h1:gXN/LFE/H9vql+trNeg5MwcHYB2brbgv4j0pnphrxXU= +github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.6 h1:JT7X1tDbHo/0D0UQh7zi2YlHbH8zaLTgH1zKEPx/kUo= +github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.6/go.mod h1:ROgSEKmD43CMB1KWQSPNovieWq6DPPSu/MCdVbwO6II= +github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.27.0 h1:NMNhVPuxmv+8l/XktsHQTqyk7vhVsqzKEzePMdQWvgE= +github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.27.0/go.mod h1:8y4H/7OXnf2YSf2ybz8aqQzxbl5pW/yiolNFSSaZ41g= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.36.0 h1:AI06e0v0FtjcNk3XNsJmp8fiAAOceRzErDjdwN0WPj8= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.36.0/go.mod h1:VyV0Il6a4RYvrqhA6tvNpV13LEBFk77Vu1FMTJs4qyA= +github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.5 h1:ZoUqKpdIPkGeGRY1v81GCaVoELHgtUYEV0WF67skUhk= +github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.5/go.mod h1:Q2RJfC6edAyk5hr3gJMS8WANFoTPGIo2SlAzQkZsT0A= +github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.6 h1:jqP2tyJOEj7qDoLyqyKGnDMAW+Lmi0WwNB2OruNao6w= +github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.6/go.mod h1:GIOHLcWXFDrHSzJJFMNRxLsfA++pOENXO2QVvMT0mJI= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.67.0 h1:dXbv06SZ39MYWL70KgFdMgFl9ZLfHe3AWIiTs0V2LAE= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.67.0/go.mod h1:/q63oDWCyO4xLLRiVYpwufJDwSkL0IbC5epFNJne8JQ= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4 h1:tVpbQcr1A0c+VTqtKEN9vfB0qer2SjfxX3LYojSGUq0= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4/go.mod h1:dYwFVhUsRZt7COcGP23ei0lY8gX8ZSHrbyX49VB93MA= +github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.8 h1:dlFZVF9TpiFvPsNO8uN20iHsrpJrALbQbwGbs7cVL9c= +github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.8/go.mod h1:MylnqogyYEsq0wODWlXmewzDOLXvDuhPpyAORIDSOOc= +github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.5 h1:vjOGGSctnKWctwndBRg6fnUQnXiIQ/zuf5km/L4q/zg= +github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.5/go.mod h1:WvZiU3vTIX6sm3FLFNHe05MWjKM4cqOPkfwT1lSj7hw= +github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.6 h1:WqphYeWJNaQRl5taLdy6ipI8EHsQGi8rxghXGvBSpkM= +github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.6/go.mod h1:pOvrSeFE/QezgirkaSVZcEtEo1UvlnZy/XlYo5pAJ8c= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.6 h1:lo/qOnIAmeBGsfXa92XpKFolYCEVRqxRYd2V171eU24= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.6/go.mod h1:q4HzizMPYR4kPnUmcY7sjTCdB0hoxw84mQTgtjJ50ug= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.51.1 h1:GqVafesryYki8Lw/yRzLcoSeaT06qSAIbLoZLqeY0ks= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.51.1/go.mod h1:Kg/y+WTU5U8KtZ8vYYz0CyiR8UCBbZkpsT7TeqIkQ2M= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.2 h1:JPW6ND8muLsBwALrf/VXikyokUmGWNKZa88qZWwFGWA= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.2/go.mod h1:3Dh12t3s/KrpEm7HNfg5RH+XWzi9LW2QI7velkc61ac= +github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.6 h1:adRnHtafjEL6BdPyNvVvsljxGlI3wQALwnTLDGDyu3o= +github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.6/go.mod h1:Jo4nWheCppk/3QfXOcYBouw3XfQSLS/lqXn7GQIhYEQ= +github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.5 h1:IjkLl7nLhE8w32Zv9NKBUdbB6YsFHIN0Y7qek4LO7wQ= +github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.5/go.mod h1:1ayIXbJj20GhTn4zvTQ5mKmDYMg5gs9ICsqR+WvjWrw= +github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.8 h1:ngiN4E8pNW15lffBIVfbO6IOSR/3NiRbBTL6XprV2UA= +github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.8/go.mod h1:u8qstOf0Jhr2PB2Xko0PirjruTv4Cp/Rwhw7ZGxgpcI= +github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.6 h1:11qvnjhmVnkb9UFQdagNFmAZV8CNb0hznYUGIEIVMZM= +github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.6/go.mod h1:RLtIEolTsnW3TOw3fHTAXb4H2xNjcpKa/b1nKsTmAh8= +github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.5 h1:wcDfIGYi7pNS33qRzewQhvAs1FGZA+GrypDce+5m3TU= +github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.5/go.mod h1:XVNEBA5S5hDvYpzK0//pWFemUsx2LKxYa9Ymkg62Z5E= +github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.5 h1:chybWfKqesOGi/JZosjMFCUzEQ5180xOZAfDs0iY1Yo= +github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.5/go.mod h1:00HnOuKp1Q/g5sCAzV8dDJWq6fts0D/1xC5DlLWjXwA= +github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.5 h1:sQevsmx5Sg8WkyR/P+Vq/tqpJCDzKr+tvZYhuP6lMtE= +github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.5/go.mod h1:6vjCrFSI1R02YCIFRqCqcKxOzKWSgib4Q9RPK8yhHS0= +github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.5 h1:WByNI1rera7rLq8qRSh+0uhQSVMDM228fZqOiUyeJb0= +github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.5/go.mod h1:oYDh1yjbugYgvcdCWMbsZcZmp8QQ1OBCqaX2qdXiPvI= +github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.6 h1:z/82UoTxxmA27/yygFEnx+uIdYY1zyK37vCPKZoXyb4= +github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.6/go.mod h1:8n32TPTWAAHJ0kAuD0z8TGR0z84ZfYFm9ILkHgkV5Do= +github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.6 h1:jSXTzwJsreMbTdUaBRhB0PnB+sWfq+awXxZJorfP8U8= +github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.6/go.mod h1:bkkAghnfsExMwlQ9u3NIoMbhUhpUDq1VL5vaaD6KrKI= +github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.6 h1:q0ma8a3t28BbHb0/DSMF6VXOouvdk42kqjLzP1YGMMM= +github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.6/go.mod h1:lOY7xQqacZtC8sN+BEH8S3NCBoSEvLSeMHBVZfCynsk= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.6 h1:75RJ5nNarn2EViDSYRPV18H4PXAkugQy1Xjr4HJ9R3M= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.6/go.mod h1:dN8D7VkYmVwbH+MVVxiqtldtkTO7ovQiVUkCWa8v6PU= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.7 h1:1LPBlVrceFenrbWOZBGu8KTmX8TTMpZfRxX0HCnSjz0= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.7/go.mod h1:l8KDrD4EZQwTuM69YK3LFZ4c9VbNHrzaQJjJsoIFqfo= +github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.6 h1:LtBU4r66PzkAdivreTlrlNWH/CQ6PG7sAKlrcdz1d4Y= +github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.6/go.mod h1:tbNB6UTE8b8fVgKsLl8IOc50jyxZ0fGqiVgQTWfNdLg= +github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.5 h1:dilS2NJ0F1Jwhi4A8NuZJAGq7HwFQ/GE4GJ+IoHWzx4= +github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.5/go.mod h1:GP4KTSWjdb7GofokIXNbVP9CQDIKTv13nfqSBiq2hnA= +github.com/aws/aws-sdk-go-v2/service/configservice v1.58.2 h1:sfLW2pTtZZHGM7Ksp3PdMqyoLjoD7dHzPblLLjcYnBk= +github.com/aws/aws-sdk-go-v2/service/configservice v1.58.2/go.mod h1:/+Y1FQ6hhvY+6moAqnf/lrSgNbckvrHoNmxTMJ5WhaU= +github.com/aws/aws-sdk-go-v2/service/connect v1.141.0 h1:n6229inzrafV1+2LIa3ltwi2PeGgsD76eLVg6sTW/iE= +github.com/aws/aws-sdk-go-v2/service/connect v1.141.0/go.mod h1:RlZrDWMyt5HH92j6fpBcBLjo5FiJw61jNAgTjCAQY5g= +github.com/aws/aws-sdk-go-v2/service/connectcases v1.32.0 h1:4nmhQ24WaJ4e38AKtFJzFSPvoiLDZCK0e2Edm7u+Tdk= +github.com/aws/aws-sdk-go-v2/service/connectcases v1.32.0/go.mod h1:pWZuObOfZSGHvL29N0S0JvGpsvk8xDlJPgX92QTxnTE= +github.com/aws/aws-sdk-go-v2/service/controltower v1.26.6 h1:xJchWovBC1h9lvvcysi4kjDT+ZxycuJc+jt/Y6YELho= +github.com/aws/aws-sdk-go-v2/service/controltower v1.26.6/go.mod h1:7T5FMpZ7QYi3p35ugZH2Wdebzw/bAAQ+HVsdtxT31LI= +github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.6 h1:Fy5Lp0Gn0aHairTF8nj3HNsml9NuLGuKFXsGlSCXMK0= +github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.6/go.mod h1:WjmUookbSIF13EUgmIm3iJbsOR4ig0BZtPtLojlmiEo= +github.com/aws/aws-sdk-go-v2/service/costexplorer v1.57.0 h1:OPm/yHm06nNtL47/ITE/TEUgB1yZV7GU20cmH4qUe2A= +github.com/aws/aws-sdk-go-v2/service/costexplorer v1.57.0/go.mod h1:5PEFaK4UypksO7xXX+aZ2zJkTA4WYOCaCJ7jfHtvlrs= +github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.6 h1:bm/4K9y+tPlOm7LCw7Oul6j4+twkYN9pMZgf6czWEIE= +github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.6/go.mod h1:Ind97CkUL/Sp8b9+eXlZoJzOyAjgSl+zX2NODYGl/5M= +github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.53.0 h1:MgnY9bNxeOQ2jPCwkQ5PdNVNJtdLlGWsql4BCEA3oKs= +github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.53.0/go.mod h1:Zp3IfPlmLCI1qU7It4GyqNKmTNLjNP33ZS9XdJSHY38= +github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.7 h1:ARnadIHN7MAAMkjNsBScWgV7pRhrhXtBnXMG8YDkDNE= +github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.7/go.mod h1:ct/KZc7aF1iJDdvVtIMUBjbZrIespvcZDXfiobANsVw= +github.com/aws/aws-sdk-go-v2/service/databrew v1.38.5 h1:uAyzLnETV1vpvVakHdGNOSnpYtmCPbc8F3e+rjooC+E= +github.com/aws/aws-sdk-go-v2/service/databrew v1.38.5/go.mod h1:TyoXF8AvpXcKkxjlW7E+Aax/FBDLoObTyby6zRffi14= +github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.6 h1:ywlBAsu4TUhGcocmioq7k6709WHhVZx6yHHcuAma1C8= +github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.6/go.mod h1:uu4l98l3f19G6MGsNf3EWcbrpRTwyErJ9PLvI/XaXwg= +github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.5 h1:lIw4H3QLLfAV6OFUFNf2rSQOD8ufSfN9sXciRpUIsv8= +github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.5/go.mod h1:lOMJLtcZ8roDJadGeAVnqdvva6RpG66Rzl3qmyHibQU= +github.com/aws/aws-sdk-go-v2/service/datasync v1.55.0 h1:K2gDOAe8OdZ6lnau8ran0va1vL97/JxANxJ1d5VYHz4= +github.com/aws/aws-sdk-go-v2/service/datasync v1.55.0/go.mod h1:GN+XSZ4Gv+QAfsCkBTEqLlmI766xItwX1KIsNJlPCJo= +github.com/aws/aws-sdk-go-v2/service/datazone v1.42.0 h1:RWvJP55ZGnWKuJadS8a/TjgYt5rrVg9YooDOLNHLbA8= +github.com/aws/aws-sdk-go-v2/service/datazone v1.42.0/go.mod h1:JtfS1guKOGCe3cKwSGrTm0grzQiMy1cfxfEAoMjygLM= +github.com/aws/aws-sdk-go-v2/service/dax v1.29.1 h1:sYEBub6ZSeElTUaelJkffTHj6HdmUsTF5H4B2XI/OiQ= +github.com/aws/aws-sdk-go-v2/service/dax v1.29.1/go.mod h1:FQ3H4KZGNJ7xNstwjgtKtWM99QtU1y2Y2vGdOSqEPZ8= +github.com/aws/aws-sdk-go-v2/service/detective v1.37.7 h1:VlbfflT4Weqvq2cRzhbGv3gKvG2T7rhdwLvl8QohkIU= +github.com/aws/aws-sdk-go-v2/service/detective v1.37.7/go.mod h1:JpUF7Kimgvqm5MBT3YiqVFmLRNqf+9xgzXzaJrCnlts= +github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.6 h1:HCNMZXY/HhpvwpesD0foAVzSqOqkK7QQdgRkIqrUbBM= +github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.6/go.mod h1:D2NbfDF3qEeaPwl+EDLGIhq5sD4jqoTkv8o1rw37IaE= +github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.6 h1:251cRFp3KrRyboVXOFhpurd9SlJ7GOk+lMxsRlfKb7Y= +github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.6/go.mod h1:XhFyJv1IDmCaKiPUwWlj9+gV1mgpoR4BspX8CpfRbR8= +github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.6 h1:xlqasn95WDPq8rFwMuLft8K6EXiBXA4gbElNy3k1qAE= +github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.6/go.mod h1:ihMttb6cmTsmRw8/jdBT0WSR2cmxP+IdU9gIBbDs5mc= +github.com/aws/aws-sdk-go-v2/service/directoryservice v1.38.0 h1:/SjJpaHDl2Tcjq7wu0BXBr3y+iVhJGCUySBd40C38dQ= +github.com/aws/aws-sdk-go-v2/service/directoryservice v1.38.0/go.mod h1:9OhFQ4k8x6wvJRY3T3qQe4F/YQLo0iZB0Opq+2Mh80o= +github.com/aws/aws-sdk-go-v2/service/dlm v1.34.6 h1:x1q9I5nwC6JBo/k0CHPRUOtLsMTBoKTYBWQXbS0s0lU= +github.com/aws/aws-sdk-go-v2/service/dlm v1.34.6/go.mod h1:GMoqS22ylKwRmUIqPv2yQiYyfi9p4sv7D345nawzTgk= +github.com/aws/aws-sdk-go-v2/service/docdb v1.46.6 h1:AJ8DEg97/hOGfCMjXH/bJpodMKR5ZyXDPNjPTjGHMAw= +github.com/aws/aws-sdk-go-v2/service/docdb v1.46.6/go.mod h1:yK1MzY7O/rmmti02gkvk+IdJZ/tCvKpcGZU2YxoWUPg= +github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.6 h1:ZDolNXobqGnz7sLKh1b8yI4T4BrMjFbtIbmZRKmMmrI= +github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.6/go.mod h1:oOz1QSkosu6fWaSQPmS9HYIkeqPs7FH+jugGa/bGQdA= +github.com/aws/aws-sdk-go-v2/service/drs v1.35.6 h1:awl8S++TupDDTsCRvrdNHUicQljM6liiHIBAJk+ej2w= +github.com/aws/aws-sdk-go-v2/service/drs v1.35.6/go.mod h1:p72nRrztE6ntt9W54vgPV3M5b520x8kbxqiDmHjFyjA= +github.com/aws/aws-sdk-go-v2/service/dsql v1.9.8 h1:9SzhOaXCRSMmyKariyaeP7hYcAdFkQk/1x3Z88V5t6o= +github.com/aws/aws-sdk-go-v2/service/dsql v1.9.8/go.mod h1:2Oz6G8F+PlNW4RK40ISLe8fTyLRvSlFOjdaWFcaFl9c= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.51.0 h1:TfglMkeRNYNGkyJ+XOTQJJ/RQb+MBlkiMn2H7DYuZok= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.51.0/go.mod h1:AdM9p8Ytg90UaNYrZIsOivYeC5cDvTPC2Mqw4/2f2aM= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.1 h1:7p9bJCZ/b3EJXXARW7JMEs2IhsnI4YFHpfXQfgMh0eg= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.1/go.mod h1:M8WWWIfXmxA4RgTXcI/5cSByxRqjgne32Sh0VIbrn0A= +github.com/aws/aws-sdk-go-v2/service/ecr v1.50.5 h1:jzjNyiIrXJHumV1hwofcQLpIZtcDw+vPQL00rLI3s4g= +github.com/aws/aws-sdk-go-v2/service/ecr v1.50.5/go.mod h1:UtPKcYVHY6RrV9EaaM1KZGNaf9dgviFdsT6xoFMLQsM= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.6 h1:pc4te9Px2oORmxWlJXaX/OkHQsdQ3RiPvuZU7525FZc= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.6/go.mod h1:BeseuedjcZNw+lGyqDIbapD3hvvsEVkjkISUIQLzem4= +github.com/aws/aws-sdk-go-v2/service/ecs v1.65.1 h1:pBbXc1fGRbrYl7NFujuubMmEFEp7CJiKTBsoDOIUkuk= +github.com/aws/aws-sdk-go-v2/service/ecs v1.65.1/go.mod h1:fu6WrWUHYyPRjzYO13UDXA7O6OShI8QbH5YSl9SOJwQ= +github.com/aws/aws-sdk-go-v2/service/efs v1.40.8 h1:vwqXyeluOHOgkonTOxvFqGgMNh0y5H6r23+8RA5ifZo= +github.com/aws/aws-sdk-go-v2/service/efs v1.40.8/go.mod h1:xJFehblB1voatQStn4hPPTnr+ueQ3UKxjSCro66JliE= +github.com/aws/aws-sdk-go-v2/service/eks v1.74.2 h1:GKqBur7gp6rnYbMZXh2+89f8g+/bu26ZKwpXfXrno80= +github.com/aws/aws-sdk-go-v2/service/eks v1.74.2/go.mod h1:f1/1x766rRjLVUk94exobjhggT1MR3vO4wxglqOvpY4= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.5 h1:VEdPmtEs1EzHXOcKmKwaN6rwwatgw4k12n08U7qML5w= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.5/go.mod h1:venvSIu8icYqJTZ2meX3NIQypX5t4R2E6Cr9wdgHCQ8= +github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.7 h1:zWmgdRblU92HDqT37r+kvORdWAZCiG3z6SvPKcE2D8M= +github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.7/go.mod h1:6hnLvLpLNgqMXL2uaEf/FacDYErGspeQHZn/3U+6H6k= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.6 h1:+YIp+dygyeHjUd7u9kv2MluNwnbiNeUITH4aZ4UgiPs= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.6/go.mod h1:iyqISGdbs/IFj3D7GyiRcVjNnbEYcF3NZrRlZnp7IWs= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.6 h1:qhVfq2WIqvxPTywVrznCkX1ad+5p6E85XTEjXpQN7RM= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.6/go.mod h1:RuZwE3p8IrWqK1kZhwH2TymlHLPuiI/taBMb8vrD39Q= +github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.6 h1:+f1A4QwqPiWy71nr5qlvLMeaR7UjpzDgCAG2MhhmJeo= +github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.6/go.mod h1:pFAUfULfSY46LfS7WPd9q6IcdM/tWm3qTpEZhCSgtKI= +github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.6 h1:81IE+qNRipRKlwOUZzVI3NSOtewZnLqUqOA5UGAV3ME= +github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.6/go.mod h1:k9An7RySCxNbERamBuwDoXaXMTWXQqEusn3/eAoyN94= +github.com/aws/aws-sdk-go-v2/service/emr v1.54.5 h1:tA10GZKqcDLOD5JfeRTpu72X5KqxBDJBqWnn720HhzA= +github.com/aws/aws-sdk-go-v2/service/emr v1.54.5/go.mod h1:zESYrv3WuVUTyMIXwR8OoRAkcgj941Mdp154AXjONAY= +github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.2 h1:DXc0q23esbZXny49LUg289Yoy6Vjd58z0TV6jsGdKgM= +github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.2/go.mod h1:btaFcfwXxksqE0d6wBhIy3VopO0dWw1KWctELo7P+wk= +github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.6 h1:jBV+JfRW8laF4hQrPoVj7Xxd45hrXg6fvNn0/nOEm3s= +github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.6/go.mod h1:6jyzPmx8zLW3K5oP/CBMH3VFhQyf3G6vPR1vaz3HsTI= +github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.5 h1:MoTJpDDOR1gmfIC6Qc7gS+uS0hlqF7RcphMqAfp8r2U= +github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.5/go.mod h1:fgyvv0FpfhbcmGgcgyDltW9K2UMs1DOBBjnkyX9JC1I= +github.com/aws/aws-sdk-go-v2/service/evidently v1.28.5 h1:TCJCjCNhQ79VvthLKT3r4Ku3SU19rGpoAovI6rydRIs= +github.com/aws/aws-sdk-go-v2/service/evidently v1.28.5/go.mod h1:UOLThVkUgc5apzB1G4oemgrigr3BYpQEbD183CX1k5s= +github.com/aws/aws-sdk-go-v2/service/evs v1.5.2 h1:RrUB7uEIO4LYwaqRwK7KL+zH7irCQDfFOueZCHXFig8= +github.com/aws/aws-sdk-go-v2/service/evs v1.5.2/go.mod h1:0j+d5nDYF1oBpk7MWqkl5VIWnSNhWD9KiWTj+t/U7Y4= +github.com/aws/aws-sdk-go-v2/service/finspace v1.33.6 h1:H3llnOFZFz/g5v4cAA6gUQ54XUJf74SQCyKuLlCZfi4= +github.com/aws/aws-sdk-go-v2/service/finspace v1.33.6/go.mod h1:a2D/sV/YKWlPNmGYZ0OVmX2typzjwO7IwZ2NUfBgaEI= +github.com/aws/aws-sdk-go-v2/service/firehose v1.41.6 h1:BaLiLj0REx6fAxK6KYTeHXv9njpyqnLqrARYC8QhkLQ= +github.com/aws/aws-sdk-go-v2/service/firehose v1.41.6/go.mod h1:kKWlKjg9gI2uOLNQG1GnTBaYfBVQKJC0z99GIPQLFXw= +github.com/aws/aws-sdk-go-v2/service/fis v1.37.5 h1:yqaWoYLetwAKcnR74PvZjgaFRabbWDnllrFOYu6EEV0= +github.com/aws/aws-sdk-go-v2/service/fis v1.37.5/go.mod h1:htMJekf0GQU+ZgqHm5nkrpGrFQk9Sd/VX3mazLer3M4= +github.com/aws/aws-sdk-go-v2/service/fms v1.44.6 h1:Kkp6omiLoa7KDN8I/YesQzQ+Czi8a7iFsz18a2I0avE= +github.com/aws/aws-sdk-go-v2/service/fms v1.44.6/go.mod h1:0MmE+RS7FFf+ld2RVTLQSJumC56UPfnYj20jwC0F7IA= +github.com/aws/aws-sdk-go-v2/service/fsx v1.62.0 h1:by2Uy4YkY+kddlqUXziLUo+ORa5d5Zba7+9tDyB+nSc= +github.com/aws/aws-sdk-go-v2/service/fsx v1.62.0/go.mod h1:IYOHN0ZkhnOc76Wq3jA9p7EBmcyUrD7ovglUA7thwAA= +github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.6 h1:gbD+Jd5bKvfkeieI9nBk4pyBEGUCKGuC3uubBcnfjPQ= +github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.6/go.mod h1:qG2t3ko7BtX5Ix+c9V8xNiQbHyMhL3Cci8NemnNGU9M= +github.com/aws/aws-sdk-go-v2/service/glacier v1.31.6 h1:iwc7B/ZCzm8dhAunHXYU3ppf+OKjtxQmFaVWAi0KVCw= +github.com/aws/aws-sdk-go-v2/service/glacier v1.31.6/go.mod h1:diGbfsRR7oW+2CZPfdR/IC1LC9Vt33OVKHbSmmKaUo8= +github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.6 h1:1up3eQrlvZ0FEzNLFCpRa06ZnBO+w43MqgGjeQJVoXI= +github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.6/go.mod h1:z4vejjg7HKiZPR12s6irgnDOpFw0hTJukQm/tkwmgJU= +github.com/aws/aws-sdk-go-v2/service/glue v1.130.0 h1:Sbrmxv4PODlzPR70fbX8rnlpU00EVv6U5eihZsXmr1A= +github.com/aws/aws-sdk-go-v2/service/glue v1.130.0/go.mod h1:iH5M4d6X8IdmFUwOVdnoCEt7eqhjYZuw4gEI0ebsQjs= +github.com/aws/aws-sdk-go-v2/service/grafana v1.31.6 h1:SoVlnBHm+Gq5LI4Z4tIxLAfOG1wCFA5puE1vwB/ldHA= +github.com/aws/aws-sdk-go-v2/service/grafana v1.31.6/go.mod h1:ABsoTppDCXrP8CFfMIkaoYdC87U51t0mMxZbDFZGKkQ= +github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.6 h1:olwkT6lMeGYJ18lPObZKMaXOS3a69GoecEtGmR2Umyc= +github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.6/go.mod h1:GS2vTGoqO4jHpYqP0avBbcVmkojcOYKtiBvCrVCg8Pc= +github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.6 h1:LhXUztHSIjfmUHkahRMI+NeYBwv5XcFMyXAcw1+/5W0= +github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.6/go.mod h1:h6rk6CTK+SoxaYWtdwyrjgWI01Q2+figfhS4fLJCtD4= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.3 h1:vp2qkFD6u3TN3ACRLFshg1/lWIx0+ZnQc5vIAeKmtic= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.3/go.mod h1:0cFCtC9mK9eNAHpKNc5/A59dqjYdwPnE1vL5STupNsk= +github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.5 h1:FP9XMTzx31mocJLJjPJEpaQIDy9cAfYRdclIV/YfRVw= +github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.5/go.mod h1:kVyA+EB5+V1zoCKEd7DR2isRChxswqaafB3kFl5eM0Q= +github.com/aws/aws-sdk-go-v2/service/iam v1.47.7 h1:0EDAdmMTzsgXl++8a0JZ+Yx0/dOqT8o/EONknxlQK94= +github.com/aws/aws-sdk-go-v2/service/iam v1.47.7/go.mod h1:NkNbn/8/mFrPUq0Kg6EM6c0+GaTLG+aPzXxwB7RF5xo= +github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.6 h1:yJG8OLDpUK/U/BDClI+McQi5zzcIxV+kf1q2WxjWzNo= +github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.6/go.mod h1:4xOhHo77B1qfs09L1DJq5luMO2cSILnc+8UkLvzvtHw= +github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.48.0 h1:F3LuF59HfxqQqWA8lrjZmRwvScpfc6pvkrzHwFZwryA= +github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.48.0/go.mod h1:B44b3XYDjkYgLbEpyTWrK+0k8+N1PZoBO8PdJUF4Cn4= +github.com/aws/aws-sdk-go-v2/service/inspector v1.30.5 h1:a9Yl3PlsRSiOlfg7qCpAPTnL/yhfsEFrPuyMjnnmUkA= +github.com/aws/aws-sdk-go-v2/service/inspector v1.30.5/go.mod h1:WPIOZddPJtTqr0mjtd6YfwXyKJiSlOCb6ZWZ3f3xIac= +github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.6 h1:G3SqMciqPsatTbPmq2lLebpGjanwqfkBGCKStf4nSbE= +github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.6/go.mod h1:idr72RZY3+DwomnH2ZTYE0Y/+rwKdtdneJWWGLlylmU= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.8 h1:tIN8MFT1z5STK5kTdOT1TCfMN/bn5fSEnlKsTL8qBOU= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.8/go.mod h1:VKS56txtNWjKI8FqD/hliL0BcshyF4ZaLBa1rm2Y+5s= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.8 h1:0lJ7+zL81zesTu1nd1ocKpEoYi6BqDppjoAJLn18Vr0= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.8/go.mod h1:5t+iImUczd3RYSVnc20t/ohBrmrkpdcy89pm62BSDQo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.8 h1:M6JI2aGFEzYxsF6CXIuRBnkge9Wf9a2xU39rNeXgu10= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.8/go.mod h1:Fw+MyTwlwjFsSTE31mH211Np+CUslml8mzc0AFEG09s= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.8 h1:AgYCo1Rb8XChJXA871BXHDNxNWOTAr6V5YdsRIBbgv0= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.8/go.mod h1:Au9dvIGm1Hbqnt29d3VakOCQuN9l0WrkDDTRq8biWS4= -github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.4 h1:pqXQW3DS4n+LvhbMnI0dYu48/ezMZHyQ3hgZmqppWDA= -github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.4/go.mod h1:LlNojdmrHYdc58JiW4d1iiVauXMR67I6w7AOuNO/7QM= -github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.7 h1:ZwuNG7d6j3BIelPU/cjuU2WnbPPPr6HzTtkQHhCfVDg= -github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.7/go.mod h1:ro6V5D4DB4GTNjElv465FEbFLkArIZk8dfwlQu0CDVk= -github.com/aws/aws-sdk-go-v2/service/iot v1.69.4 h1:aE6flqYMH7oN70XXJ8NAzM6jsTK6dwv5DlYU/tTO9iE= -github.com/aws/aws-sdk-go-v2/service/iot v1.69.4/go.mod h1:JlM6Y9/lpdIu6Nbm2PHKsWBl4pEEjzeKcIwaceNzI8A= -github.com/aws/aws-sdk-go-v2/service/ivs v1.47.5 h1:aJ1AE3Dt/mwkFcR3Ak8HGJ8ack7sD21r3/oJJ1CzvIo= -github.com/aws/aws-sdk-go-v2/service/ivs v1.47.5/go.mod h1:ulDEMSCfB7GJPlDkbN8VZTQwuY+gzQS7uMhkPKc08Xk= -github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.4 h1:sRozLJvRu6LW2LNdjI7vNGz85BaHDTgrpnlxg0kjWfo= -github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.4/go.mod h1:Zz8GTvGWBPnle4TVu0fWZrWnEJM/ohy1AEvz72Q8T0o= -github.com/aws/aws-sdk-go-v2/service/kafka v1.43.5 h1:GD6O4rGwvpuXMW3G+LGmcAisxwEJ/qWTEHVh2EJ9YAg= -github.com/aws/aws-sdk-go-v2/service/kafka v1.43.5/go.mod h1:3JzaPchevdU28xVcUGvZihkHEgcxj6mc1M0jmIPBZCk= -github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.4 h1:sqxHUxLuh47E1yfvyIpqJ3Rlq86/Zp+qY3qdg1CwZls= -github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.4/go.mod h1:WD/XxqAT+x1ALiZh2mFgSZ2w7hhK1bgJyxrGczg5FeY= -github.com/aws/aws-sdk-go-v2/service/kendra v1.60.5 h1:wl1Jvy+LnplN3DA63LvFaiNRKAQQ/RJWJxNMhNc6uvk= -github.com/aws/aws-sdk-go-v2/service/kendra v1.60.5/go.mod h1:z6MqqmaBB0jB7j6TtqU74wZX43HuOAjW+xcPhlVtcLU= -github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.5 h1:WbkAo6akNMmDSY14aTX2P5JfLBPYaky3KowtTpUu+Dg= -github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.5/go.mod h1:V5N6Q6xPxATXIYhnINepbmj8v7SFjH/RvcR2tvwemqc= -github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.4 h1:EklnkOC4Hvk0qz7JEyj1lUQwuzhxNQwoWGzn+B9p/SQ= -github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.4/go.mod h1:P3rzrvQKKDJdr8DSQ+HrnPe0vZHObzGArI8VjS8TD/c= -github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.5 h1:rtFOjsNi/FF/ccQOWKJJ0DLJUmAjYHhrtKd21Vgis1k= -github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.5/go.mod h1:s5gBWn3mAmbzP1VH4gKCrZ8cvoPT3O4PFf2iqgnFv7o= -github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.6 h1:JqYFrkvba3uTBNT9SnHX3zY8xwAMIf67AAE9gKM6Wqg= -github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.6/go.mod h1:blmPmauXqE222j/1bBnWbnu5HmOFKaq57TDVEp5TY6E= -github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.4 h1:AtXxx3T2m3MtsOx6RYECZ9CY/xR+bs9IBpRcWjfYm7k= -github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.4/go.mod h1:Jw474eZ6bJAkOCNDip0lAwPIpGhaPumFuZ3WBftEZAI= -github.com/aws/aws-sdk-go-v2/service/kms v1.45.4 h1:6gzIbiRNs6o/K/WaLta0Vwac0bI9ou3gfx8ASSMf3wU= -github.com/aws/aws-sdk-go-v2/service/kms v1.45.4/go.mod h1:ooAdc5n3rjgEznIXncCYY6V9+YQDcJAYyZDJ4TwLSDM= -github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.4 h1:SkLIob+eQ2x917Dm6J8ZYBOKJQcubfnDvlFtBDTj3HA= -github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.4/go.mod h1:Llzlro6KcIlCQ9XlF67XWmWwB/SiSQ4E3+FAW9MF2P0= -github.com/aws/aws-sdk-go-v2/service/lambda v1.77.5 h1:rKc5Ad3PJlXGo5pigWii+m/hSPgxbNJtOicEP5nbV2E= -github.com/aws/aws-sdk-go-v2/service/lambda v1.77.5/go.mod h1:fPYDox6U6puh6xhMyWpUWd19QIIqMlcQ6iCdC1jk2cE= -github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.5 h1:kzVE1YGQzh2EsH2/2rru9KlTT1EcnyzPFh/ziT0bjmA= -github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.5/go.mod h1:Cj8DwO1GPQM1am9utweFWdc1l/hIPacK5NHukImj0/I= -github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.4 h1:4EXJ0zche8Tcb459h2JGnYTxBY5ipAWttvV+2UcPDn4= -github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.4/go.mod h1:fJv0jAIV2g4lLrIol3kE/2zt6P8l+66L2UFGMtD8I1Y= -github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.5 h1:0T2rzgz1a/snpBVTIen7eSwnGhWvAPd6437/yZ99tss= -github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.5/go.mod h1:E4DRF4KQX1XZN8t28fSq5W+BMksVqnV6U2ce2A4gXUQ= -github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.5 h1:0O5ABLP0OFZzFvj28caDllk2YH4mc1fP6i+4HuNfHek= -github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.5/go.mod h1:nxxXvBLZEm+j3hsKeTQ+nWnXlgHRaI9WDiagMPeT59M= -github.com/aws/aws-sdk-go-v2/service/lightsail v1.48.5 h1:w5f4GFD4VPp92gw8Lu+5bLNta8PQpi1Uc5TZCR05F6g= -github.com/aws/aws-sdk-go-v2/service/lightsail v1.48.5/go.mod h1:PYBtpUhvxpPQcFHNezTW+7S2q0EMm1tHmMxZ8EL17IA= -github.com/aws/aws-sdk-go-v2/service/location v1.49.5 h1:cRtSrpvv27SdsdAPlol8T2nnM3O66VdenjcPCKSIXHA= -github.com/aws/aws-sdk-go-v2/service/location v1.49.5/go.mod h1:Y+SWwVf3QLr3rW2ys+e4EdaXKfVkzXskNqdRda6XOJ0= -github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.5 h1:ETYc5MpIm5WSDShGfbSYTmklAB76FFuuxGfOsX+M+nc= -github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.5/go.mod h1:9orzVPgSp0QB6sBj7bJ14uA5p+/4JmpoFMZEST2WeWU= -github.com/aws/aws-sdk-go-v2/service/m2 v1.25.5 h1:ZdpvRHcAsuS+r68qUCpC/J9jeVr2hjQupXHej5pdp5Y= -github.com/aws/aws-sdk-go-v2/service/m2 v1.25.5/go.mod h1:mkXvkEK6xuq9HQyMcb+8OxFN08JEIHUiSLYZtvIUynk= -github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.5 h1:gc6xw799PWQwqSPiCUjSUeJFwktPxdu4EEv/JjtbaHg= -github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.5/go.mod h1:SJrA0S1rZf+hJZ8A14qyGSKEfo0+xgcHybOMuso4pGo= -github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.44.5 h1:SlM5+NZGTGDle6ttbPKF/WHJcwxbj3oEgdzDZ9Qw3Qw= -github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.44.5/go.mod h1:Qf4V6X3IK9jRR830+XweeOn1xjewIeLn2D3e2NCkobA= -github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.5 h1:FhZZhB3XgafXOd7GRTDPNie3n/HrF3Zv8bB4LBn/tuM= -github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.5/go.mod h1:jdqkPR7VkqoYZSFDaWNJO5117OB5ahm1OsdpL3N+FMA= -github.com/aws/aws-sdk-go-v2/service/medialive v1.83.1 h1:8uRoFG6r/9RxWNPpuyHj508tMBvZThOWzNFN6ulTt30= -github.com/aws/aws-sdk-go-v2/service/medialive v1.83.1/go.mod h1:QkW7SVV35Eq52NiDipbbq5Fdjprxdt0BevJGMOSI3cg= -github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.5 h1:cqAHLMgzD7lRgev2a1Mo+Yx1lrbQeUMrdYMG0tXTHDQ= -github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.5/go.mod h1:anm0e41ZROI5kucwbWCuL9Nuk/gIBhh+bOnwEKnyPaI= -github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.2 h1:bJf3EQ7U9YhLX0LZ/mWb2Ca4VDB0RHMXn7JHv9H1H+o= -github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.2/go.mod h1:3iKCnq745r5o1cK5T8sWPdBlca92hkOV9MRjkyLSoPs= -github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.5 h1:NpMBTC1/EUDCiR1QsAaJx5B5aQxfRAa3LI3o8o/ygzg= -github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.5/go.mod h1:ClEQ25nOCArJXha4xw1SKmNRBqokGa5wUWrY0CSljQc= -github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.5 h1:z8YzBokMM+ACy+VAt9ML6t15bl4PWg2Qa+gLZxSMzsI= -github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.5/go.mod h1:pX/zpqdhpMeXOgf4IaTj0R7huKhqmrz4Ycmqgd0OBVM= -github.com/aws/aws-sdk-go-v2/service/memorydb v1.31.5 h1:2RFdzA+rAgOh+pvBPniDT0SApO5klmNUHUFegbxq924= -github.com/aws/aws-sdk-go-v2/service/memorydb v1.31.5/go.mod h1:XFXsu3EXiGwEG4R64MkML234uPPXQBxcAY7qUXCyHaM= -github.com/aws/aws-sdk-go-v2/service/mgn v1.37.4 h1:g2h94C45Mqi88liuvo0IcH2eSL/FwgKOBXTVgp0Zy7U= -github.com/aws/aws-sdk-go-v2/service/mgn v1.37.4/go.mod h1:jSgQjRJnBdoNJEGHnpQ2PgOLys7ohNJkQKmzBQ8FYw4= -github.com/aws/aws-sdk-go-v2/service/mq v1.34.3 h1:Rz/lroysK+RqrcTY7J6psFC0EG0+lc/wDNITYhyZqS8= -github.com/aws/aws-sdk-go-v2/service/mq v1.34.3/go.mod h1:Xii/g+EJLpxVHa4A1dbKfp+beF9dbqFVwtsmcYoRjnk= -github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.5 h1:Nf2+SGxaMZ3KfRZ+DIYjrzWWhBUICOUG5+RrvdTNttQ= -github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.5/go.mod h1:T1nupRx4k6E8GYN/fqcV9e+Ezn8s6RyrDxcyBd0ylH4= -github.com/aws/aws-sdk-go-v2/service/neptune v1.42.3 h1:wQZ3ZoxMhSWeI+Gx04TdnPGVyiyse0JbnU8H/RnHVmc= -github.com/aws/aws-sdk-go-v2/service/neptune v1.42.3/go.mod h1:GrbX2ileXVUAUK8aqjYOpf7XsmkMwhtM5FL6L08REDs= -github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.4 h1:BwUXxuGTkfCJBxSeCyj9FGXzAORVGpW1vJeNDuljzaU= -github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.4/go.mod h1:63FrdK0c39o4iZR2SXgRVm5HAR4UO52U3aUAtsyiCFU= -github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.56.1 h1:9C74Am5h6+Zq8MFuq/LS8Kd6le8Jqoy/W2BES5HMnWY= -github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.56.1/go.mod h1:fdoS8BPmAwWCsz/T5z4Gj6rzgAJjSAsf88e+Qic7cQs= -github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.6 h1:gkW089f1iICPJKVq0UbtK57znJBbyLv0ryYpC3d3nHw= -github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.6/go.mod h1:u3gTjlgiO+GaYHD7mjiXTHEAkHzmv1jlqA27JaJCLAQ= -github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.5 h1:LVzNnDazY/+KJQfmzmy296vHVAsjt+KlBXKvK3RLAP4= -github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.5/go.mod h1:72XMlkVojEDuZTW9InSxprH/s18r6tOI/p3/Rjxd/e8= -github.com/aws/aws-sdk-go-v2/service/notifications v1.7.3 h1:yKNPjCC/kINzsM6V//q4gKeBkXjko3DOlLZ5XvvkW0w= -github.com/aws/aws-sdk-go-v2/service/notifications v1.7.3/go.mod h1:3JeNkPARZA8cQWkggggJRAWfn8YYL7IyR/Ng9fi8QWk= -github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.7 h1:LXBCZlJsWU9P/2wQJG+aOEBzzVkeqytNvVSP/AiM2xo= -github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.7/go.mod h1:1/9XnEIGQt6i7wFXCBTaFNBj2vmzc7g5O0YrrOoLZcM= -github.com/aws/aws-sdk-go-v2/service/oam v1.22.4 h1:hc6vhGJR/Oo3wUirrCdk2kcjUEbaAgKY/MaUoHdR7dc= -github.com/aws/aws-sdk-go-v2/service/oam v1.22.4/go.mod h1:yJfcx5ndz1LTXA3WQ7qZWmPQXOtE3d4Rx7fwF9CMeAs= -github.com/aws/aws-sdk-go-v2/service/odb v1.4.5 h1:g3WQYf6RoN7x0dqdf9edQROEw13c+rhU6ztseY3cfuo= -github.com/aws/aws-sdk-go-v2/service/odb v1.4.5/go.mod h1:YcfGEDn5kPX/cObRuQbLj0kaGgfJ62mg6vKwk261gY0= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.4 h1:dFR3ire/PYB9qIdAKes2dsIWSPSbmXDR+hYoWBOSvNM= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.4/go.mod h1:aglzJEixBNrJcfZkRFo9zUIiqgqau71VgMUpNF9aq20= -github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.3 h1:FcB0JD+m42HH2xQebadyl1w4nBsaXy3CezzLotSW5U0= -github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.3/go.mod h1:Kq0rlqHHSo8NhLze+I63WipfRDQ8RE5xwmUD6CbhRYI= -github.com/aws/aws-sdk-go-v2/service/organizations v1.45.2 h1:UrgNIo7nnNcJ41RSZ8I6mz0t5j6M19KPzb+XW9QF5U0= -github.com/aws/aws-sdk-go-v2/service/organizations v1.45.2/go.mod h1:g24aovax3vUoQp2D3+XAOPlJ7VeeM3MdI+3k/U2gg2s= -github.com/aws/aws-sdk-go-v2/service/osis v1.20.1 h1:iNDGJwuGrWFQgaUYSZ5V+0bqBGy91HrZYmvAVsPvdMg= -github.com/aws/aws-sdk-go-v2/service/osis v1.20.1/go.mod h1:WtOr7MJmClnNHHimDVC3uknN7UKiT8bnjnowP7DDPDM= -github.com/aws/aws-sdk-go-v2/service/outposts v1.56.6 h1:XcTh52znPsNYzIWyozFwu8Uu+XLkoGxL6grXNwxMAKs= -github.com/aws/aws-sdk-go-v2/service/outposts v1.56.6/go.mod h1:ffRwILonyjECbO5dHGK5HOXMUVmKX23X0PUOBecZeRo= -github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.1 h1:ko0VIzCAX4cT3gcoh0XE8GIzQNjYYwXVJfcbiCmJ1mM= -github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.1/go.mod h1:Rl6JV2tdH5DbnBiRzu2+N8Q3nnZaUofdvk+9EpRH/0A= -github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.5 h1:RPJr4Eavdpw9lrcKzcmWBaButkGxdZHXYLKuhhNDTcs= -github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.5/go.mod h1:ziQOjxhY7/5u/s50cq/rIixwBY4pFvuMz2WZfDGWvAg= -github.com/aws/aws-sdk-go-v2/service/pcs v1.13.1 h1:Dj5rB1dYKFBGbCC1ju0XnNnc/ww4MYOGu6NKCDkcSRQ= -github.com/aws/aws-sdk-go-v2/service/pcs v1.13.1/go.mod h1:/koo7XUOt4SD7GWfe+aJmVvQRFWc3qxg/V3J7GSKwtQ= -github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.5 h1:1w+7cQ8xLV5HHqXLsU951goCUuoMSz5LOUpmzCwC6As= -github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.5/go.mod h1:ioCORBoHu2o16hJpLFZg/e4S0f0yuPB9W+JjYMMNfu0= -github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.4 h1:f8GjAtK/4vlm8smVV6rJxlbYhzUfkGu1/BTPcFYRZwY= -github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.4/go.mod h1:X3wPHDPz8ned4UQ+a+kViPTNlIkY4Ccm6XpcN71/et8= -github.com/aws/aws-sdk-go-v2/service/pipes v1.23.4 h1:b7/6w7OW1h1OdpiJbtRTDxB1cNVBOEjm8iHWcRVCsws= -github.com/aws/aws-sdk-go-v2/service/pipes v1.23.4/go.mod h1:8SPFrFynF5Wn1iU2w4scParKYA9jDimBHFeDbyoGQTE= -github.com/aws/aws-sdk-go-v2/service/polly v1.53.5 h1:B8FqAPzKZYuTSF+iWzOdh2yuayZqDaz0rHeY7r7+Czw= -github.com/aws/aws-sdk-go-v2/service/polly v1.53.5/go.mod h1:sMQztn8/ymRqblrKqYi8Tp5WR2u75rDJsnmm23F+y6I= -github.com/aws/aws-sdk-go-v2/service/pricing v1.39.5 h1:6XZD3eQtNzrLQGjs5afZn1lW2TZRDWVfA/3SaQB412Y= -github.com/aws/aws-sdk-go-v2/service/pricing v1.39.5/go.mod h1:9AbXh+nl1DAjTjoSiDYz6IeKO5xeGJ05H/JIjb1Siwk= -github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.5 h1:2yXmH6W2446BciTlCzYlGEZeBt4IwwqIgkaXR5Q3i7U= -github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.5/go.mod h1:thMIBdJa0cHBOpqpUXjZVKJItdp5nYvAtd0OwtxUc30= -github.com/aws/aws-sdk-go-v2/service/qldb v1.30.5 h1:1s/KnPcDCWFcESJe5kg9Insc1cpM7kOJZxbmHF8Yy5w= -github.com/aws/aws-sdk-go-v2/service/qldb v1.30.5/go.mod h1:MuSf1hpqGEl5HzjSV2p5N1uJMykHP8YmX/QS0mugRTo= -github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.1 h1:O7hHDZF/5+DN4oPRQq1u3zd1SHnxwDgpvvxThUhP1+Q= -github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.1/go.mod h1:/Mot6Jj1Qd2/B8WxiOwOkxRv8nVtu7TVTCKgQcpgbJk= -github.com/aws/aws-sdk-go-v2/service/ram v1.34.5 h1:PvZedq8Nr3QiAOx3tXbZhD3uqvijB7AqgtjSK9HH1vE= -github.com/aws/aws-sdk-go-v2/service/ram v1.34.5/go.mod h1:6T048C/TFPVH5LDnuB27uZiWz4neaMX/k4PQuwsSGYI= -github.com/aws/aws-sdk-go-v2/service/rbin v1.26.5 h1:cIKPk2ps8dwc5Eb16VZnYMKQW+9FMbz+qDRgTzglXPU= -github.com/aws/aws-sdk-go-v2/service/rbin v1.26.5/go.mod h1:COEStyfI/PSW8awNT1HoHlRgYQqVjCdRhJZ1Sw7qpjI= -github.com/aws/aws-sdk-go-v2/service/rds v1.107.1 h1:j7GQZWF0CbHCObPEZUK6QuP3yUQwjBJmlaojHPRZ6f8= -github.com/aws/aws-sdk-go-v2/service/rds v1.107.1/go.mod h1:OW/mwGWAs6l1HnZpJupatcUFt1V0y6OiUMUp+Wd0DEc= -github.com/aws/aws-sdk-go-v2/service/redshift v1.58.4 h1:3/K+FgsR6//ZSK/Uv2QTeb8Ug1IdKjNgwb7205a4n4M= -github.com/aws/aws-sdk-go-v2/service/redshift v1.58.4/go.mod h1:t+6WfvYqxtwQ0MDg56sYFfH07EKT+Jz+NHamFAulkwg= -github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.5 h1:2hyuttSMbpJzTdpPAA6pbsmdcQSb3t7AQPGYKb8Pbw8= -github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.5/go.mod h1:l8JdskDXH9DHRDCXrUQeLwJMmuViPtTz/iz+MvBnSCc= -github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.7 h1:7ISSWB8eMzpZt4X3KeDd5yF0sOPQKbFaYikeElWgzIM= -github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.7/go.mod h1:o1kE7Aq8tpQm0aalh8i0wcwK0Yhrj/JB9FfvBAnbwjQ= -github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.4 h1:A0+WSnZw5q6HRbmql7OLmHuUHnaWUXgjmjSv4xshn8Y= -github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.4/go.mod h1:mxURAM325+JC3eHlWei2+mzWCxNZ5feN1uoRzT8miTs= -github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.5 h1:7ibWyVXWXpXoqaeoxRBl6FWKvDAYxpCEmjpjSQGum7M= -github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.5/go.mod h1:gBH/5F+DqH6XdzzHk3cmKGWmQbea1+nQM25S0dNKBFw= -github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.21.5 h1:/osdwwAdfwUJslToz4OetbXS1IZdNK0uYJ7UvhuJTIY= -github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.21.5/go.mod h1:47z4n+dkh/oTmOlaWxSy6RT3x7GkR9K7NCNHSN97NBk= -github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.6 h1:3jUHJ+wceveycmaOrwQXZSBv/7XRhtv68sLoQ+/zj4M= -github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.6/go.mod h1:ScoN6z1s8UGadFNYNsTYwXgztfW0r7+FyINMkmJmOgo= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.5 h1:UA3sejPQHzCKU16k1VY+AnTDr4FCWWQxLYKxlslKEU0= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.5/go.mod h1:yyo15Q/sYN7ztaSSP/kpAx+DdMNaQO0mP4GGBAm7BRw= -github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.5 h1:dVj+l4NIKnDsOMtlW1e1tWM1s1jO51Pm2QStoU13Y68= -github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.5/go.mod h1:doLe0bLdFnLMfaF9JacaeWritZRGLW9Nm6p+bNDUpRg= -github.com/aws/aws-sdk-go-v2/service/route53 v1.58.3 h1:jQzRC+0eI/l5mFXVoPTyyolrqyZtKIYaKHSuKJoIJKs= -github.com/aws/aws-sdk-go-v2/service/route53 v1.58.3/go.mod h1:1GNaojT/gG4Ru9tT39ton6kRZ3FvptJ/QRKBoqUOVX4= -github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.3 h1:sfRAFot/FdWktEsGAPS2sUFOjd7FJM8FQiRr7F3bNmo= -github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.3/go.mod h1:Fu3cGFzUxs17sZS5NJnaBPZTrZufyRDDPQX/D1erARA= -github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.5 h1:2jOEIGAK54GVbprEefZL9TtcIIdN3XAnzYvqn6NuGME= -github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.5/go.mod h1:nHZv5ixEJObIzWNp61Gg69rUPd2pCkrgOJB5Rvx2MXY= -github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.6 h1:oHhQ63HSIH6LNwMMdE/vo/DgXB8ro3H8x1DgNb8x62Q= -github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.6/go.mod h1:4nDaomeiHh3Se3hq0dNOKJFU5hmomS0F66afMsuYq2o= -github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.5 h1:SIyhgC6Yn9AepbdFEXYA9+NyM0M++QhUNVLAjZdMZMk= -github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.5/go.mod h1:NYmSbafb2MHeTQiQC0de+czBefxkM+5+6MthkmZTI4Y= -github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.5 h1:s4bVZWDzxzbZI0n943TUlvUoPLdUKUeBknowTUKWS0Q= -github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.5/go.mod h1:zsGRe0oBLauYWlFrj6FHK1mNhR4NCbuqj+JQelGFC3M= -github.com/aws/aws-sdk-go-v2/service/rum v1.28.6 h1:vYgurgqbwV9vkW34/bYqIfEahxe1vScs9ttre2nYEw8= -github.com/aws/aws-sdk-go-v2/service/rum v1.28.6/go.mod h1:qzw/AMuwYDbiaF31RS28qwtaDENs6uDk/KpgV8OBS0k= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.2 h1:T7b3qniouutV5Wwa9B1q7gW+Y8s1B3g9RE9qa7zLBIM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.2/go.mod h1:tW9TsLb6t1eaTdBE6LITyJW1m/+DjQPU78Q/jT2FJu8= -github.com/aws/aws-sdk-go-v2/service/s3control v1.66.1 h1:E2w689yRS6Goe3khBmlBrJvH1EdXKRbPajF28qvlus8= -github.com/aws/aws-sdk-go-v2/service/s3control v1.66.1/go.mod h1:R+UodcuiGX37eSCau+g8HfeOU8eINOYBmUF5F2Bh1K4= -github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.5 h1:F1yNtV8GCt4R1sN4eM0HxS1g4yFypBdN1jg8f8Y7wdI= -github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.5/go.mod h1:o9uktj0GTuXRPjzlf6LL8bYe5Maf/2efObAwtqBanhI= -github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.4 h1:unOY5Zy8JPGTto/ceP+fWbBRJbR+nv0iVmgQxzhl/MU= -github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.4/go.mod h1:n67J7pPexZgufeaQNdYrEugPZAWB5cPo7T1Z5aiZAN4= -github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.7 h1:gCinGWsye9fd57h+ZUrqJU2D0HEVwAOa4Y300Hilzwo= -github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.7/go.mod h1:gWGWfs4Firg447Gr4VnPcCpGzof+8+HEQTmJJGIj2nM= -github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.2 h1:3PzLhyagzne3V9s0lcYr9rwqmhFMuwa3IboGUai+s58= -github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.2/go.mod h1:nEk9o0OcHc6ZtCS9hYSHdnMVzUZLVr2M6VeWpKA7NQY= -github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.4 h1:YMt6+3drr9IcU4SUyG7O5+kIEjbR17xhis7QyGelHcg= -github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.4/go.mod h1:X026FtKGqEZm6e5Cgj8uus2v0EJEMU3h+YjGwUHYGGQ= -github.com/aws/aws-sdk-go-v2/service/schemas v1.33.4 h1:PHjUXL8ySNGYVl6ro54FXwu8BgdNsm/xjwySpqA+I4k= -github.com/aws/aws-sdk-go-v2/service/schemas v1.33.4/go.mod h1:z1T3zem9JVEVUsMtBoFf9CI6UVqO+bZCYAARD3mLWH8= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.5 h1:ssRo1z8FdFaoZc1AWz1R6/amdsxy56akVPql15/AYSs= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.5/go.mod h1:ut4ISJEOb5t2M1DNfx1787tF3UJGlwF3Q97uEulV/lU= -github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.3 h1:6o8+ze30fwnc4V/nhto/0fBYoiws9v78g7M9LbqofrU= -github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.3/go.mod h1:OGz8b7RoqQTdMhzy5fdiaRkOwyOV0yEg/aO9uAnkb+I= -github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.5 h1:JBJfUR1njXvmK9d3ZqC6K3WkttWAkbRf7+9XoIaPy/E= -github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.5/go.mod h1:QOVKb80l0cIaF3MwnX4V8rnHwHdnBJSC8jYGxeP9Bfs= -github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.5 h1:MVnXAF5vPF26AkAe+Fo6z78Oou8E0bZ+ms6hT/u0hoc= -github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.5/go.mod h1:qGotrkSA9OGOZVFQWedkzOzLDGcrUT2EnbCWCivBGX0= -github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.5 h1:ENz/xNI5OSdTobZSyfTxlXZlMS23/tH/sFVTl/Wvwuc= -github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.5/go.mod h1:7W1TBwi28cH8groqlEvrmXU/ezEIGG09HjBBsmGDB+c= -github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.5 h1:zsPa71rrBoG4oc60Nc9jmvNwQnwX5rMZZUzxAR3nIXc= -github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.5/go.mod h1:zQylvlg2uShkf/uj9nrOmdbwBH4+jGfvzDAeH6zQlq8= -github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.8 h1:iu7ZfkC7lZbkLFiiJ3Znl/YXuKNk3XTmwYMHaXXsPUo= -github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.8/go.mod h1:gcmimEFXc7ksrkBtLR2f7JYT9ANpQanofvwP1bq39Sw= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.4 h1:TJYHJY/TEOtWAyaI1p00lGRPQXx6DPLLmna8BjoCwrk= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.4/go.mod h1:gtv4gMhWF+201MWqog46V/fNHgUSddtt9IU6qYgZ4CQ= -github.com/aws/aws-sdk-go-v2/service/ses v1.34.4 h1:0GQy17zYn0U1CHXLh9rEbPZW3zSusSqiGbVBUYDJ2qs= -github.com/aws/aws-sdk-go-v2/service/ses v1.34.4/go.mod h1:NS7mQGFRialwnzHj/bVn8eurbcAGM4xKgPiIk/rwri4= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.4 h1:0T0pWRMBsWSP32FvuCmK/p7ufoEZitS+PODM3+aOTKA= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.4/go.mod h1:yKXc38qs9onyyKCBnH0QFkozi96GqVZGu6//HwpqMP8= -github.com/aws/aws-sdk-go-v2/service/sfn v1.39.5 h1:/HaGWiHdPxAxgwsYY+ZhEz47IOjcQcofFNk7Gd3yLbY= -github.com/aws/aws-sdk-go-v2/service/sfn v1.39.5/go.mod h1:OEmM4ipS3JRTTZxoU8TOLHirsqNHifZUwNciT76xZQ0= -github.com/aws/aws-sdk-go-v2/service/shield v1.34.5 h1:n7OaaYO5Id90TbZStXxd10ZHgzJP/dsmVrUkTvnX7f4= -github.com/aws/aws-sdk-go-v2/service/shield v1.34.5/go.mod h1:5yZs0QTVUBzFVcdmznzUlhvnJFe6ByjGa0L7X71GaRo= -github.com/aws/aws-sdk-go-v2/service/signer v1.31.5 h1:CPMtYBeWQ6SHfp47/6VnA6MoNs4OQDetNqt3/Nf7Z5s= -github.com/aws/aws-sdk-go-v2/service/signer v1.31.5/go.mod h1:wn4LhsujYbBhJyfdeAsLFJmuBGH3Ux6SodfoBjh0r28= -github.com/aws/aws-sdk-go-v2/service/sns v1.38.4 h1:MkaMcZGwW9vt0cW+N2i5JSF/zkxKyDqpGCP1VWip3YM= -github.com/aws/aws-sdk-go-v2/service/sns v1.38.4/go.mod h1:S0rwG+VHP1/jKoT6xJDe8f8Apz9HO42dUI8DmnOzYYU= -github.com/aws/aws-sdk-go-v2/service/sqs v1.42.7 h1:KZldI+77SMG8vHDE55HYSjPcKSeOy2WIRo+HtIz2IY8= -github.com/aws/aws-sdk-go-v2/service/sqs v1.42.7/go.mod h1:wbgNsM9psd+xQtLSDUAICjFCT/HXNZIgx3qyjqQNt88= -github.com/aws/aws-sdk-go-v2/service/ssm v1.65.0 h1:6bPuMpky+qG4L7VQ1RyYVkBrEix1JRC/JPweTRfRDko= -github.com/aws/aws-sdk-go-v2/service/ssm v1.65.0/go.mod h1:mbnkxOJSgkV4YHA5dWSlLolvC1EuxNcaGfn0Gf4e9UU= -github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.7 h1:kz/8Mw8HrNrGlZjh5LIGMNeg/h7wtFMu/zXzbNEJ+z4= -github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.7/go.mod h1:gNXImFj9hXsjX5tgtgH+3GAhzJ1gkwXKVl8cu448dVA= -github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.4 h1:HT2hU7SaHSz7RINT8vRz++MEdDUGvbrrBEOiDtIleQ0= -github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.4/go.mod h1:pdKXsrQEqtzcuFgy/9dbDBCdznCECK0fs826ODHAaD8= -github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.5 h1:joNgSFjCVcqO4ChehYL1g7P8zC3WfjD0lggqFyVbUlE= -github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.5/go.mod h1:H67jYNIX7T7SLe5iZVDMwAtoA8TabGpFW2f/NrPUP0s= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.4 h1:SuE/GiqX4BmG1RJ/SXCuiGX6y4XP4tRkAGSn6wpmgPQ= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.4/go.mod h1:ixryFI/P2+QSLHiT2KLmg1Fl4uZ+SZe9Hj+YdRFMNgg= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.4 h1:FTdEN9dtWPB0EOURNtDPmwGp6GGvMqRJCAihkSl/1No= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.4/go.mod h1:mYubxV9Ff42fZH4kexj43gFPhgc/LyC7KqvUKt1watc= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.0 h1:zW0XCIX3weYJpbbE+8GIWK+ewISjcm9XuItb/+90UDc= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.0/go.mod h1:33Y0SLyIseFE7x9sk4TwQTGZLvKCEoQNMaBIyRc6S8E= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.0 h1:I7ghctfGXrscr7r1Ga/mDqSJKm7Fkpl5Mwq79Z+rZqU= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.0/go.mod h1:Zo9id81XP6jbayIFWNuDpA6lMBWhsVy+3ou2jLa4JnA= -github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.5 h1:66xiSm2c+yKfW89ZCuSUGSpjhlXrnnujYVzMTvlBn9U= -github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.5/go.mod h1:h9W8UyJy3tqo2JUZJKDCzms5P6nAdfctF5AE6wbih8Y= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.5 h1:+LVB0xBqEgjQoqr9bGZbRzvg212B0f17JdflleJRNR4= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.5/go.mod h1:xoaxeqnnUaZjPjaICgIy5B+MHCSb/ZSOn4MvkFNOUA0= -github.com/aws/aws-sdk-go-v2/service/swf v1.32.4 h1:8Vir3v5ofhVSyq+uQsZbhHv5gDmeFB8MOHOBbBTQtic= -github.com/aws/aws-sdk-go-v2/service/swf v1.32.4/go.mod h1:Dn78lVa2sYo1frnLV2Y/VGjPf1cU2AZaXbCskYmRGgM= -github.com/aws/aws-sdk-go-v2/service/synthetics v1.40.5 h1:QFbPjZPYsHIvEfH2IgmmJ5RKLzcxdYAFom2NDtdH9Wg= -github.com/aws/aws-sdk-go-v2/service/synthetics v1.40.5/go.mod h1:UY4GoG7FjIRXEFEy1xI8C2tfq50rwbsmIS3sf5C7pn0= -github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.5 h1:aCsvthnYzQUhclNnOnY6y98GE/5QcSDiJKnZ/O6cM8E= -github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.5/go.mod h1:hEQ9Hci23FipEndGjVf13gKknP1iou0u8v+YZyFwzfE= -github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.5 h1:ULU5NJasc33+18uhZCaxfnENf5S9u8fmLWGtpoR/cng= -github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.5/go.mod h1:UUCLRjt77Mi12nID7LOXKiaHp7tBlS8QSLNNNHv2YVk= -github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.4 h1:jBCvWkHfU0CDXr88Jk2iDP/2w/Ix7N0yoW5JRXHWb4I= -github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.4/go.mod h1:csNEYpo3KmbQvPBGvSvOyRESGHhWn4H2dnuhYTGBH94= -github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.4 h1:lCEmLYq7SKuAovCyT2tVVaRuYvuq/DCOBIiEYhUNiYw= -github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.4/go.mod h1:xzj/HUCYOPwWxjymulevwAu5aEd14h1DbrgD3xcmpE8= -github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.5 h1:+53FqSqWDrlmPr784MGo4uOMS21NJwUJVGtdliCb9tg= -github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.5/go.mod h1:Z72GfN19PJCKpKKQU7/9Rj3dzcK9EScyUj5xd4GwqOc= -github.com/aws/aws-sdk-go-v2/service/transfer v1.65.6 h1:gxMSPqweeuO+f/UswVu13fLU/A5NGilUascqtivEwbU= -github.com/aws/aws-sdk-go-v2/service/transfer v1.65.6/go.mod h1:G3NKnR/n/5iL2FX3ETW10cDnMcs21yaxCgbFoOq8EYU= -github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.3 h1:gArDyF9h3/Ae7cjsaCeb27qrfQ2TTZpXeFQnTOc8rOU= -github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.3/go.mod h1:QhnmLIvllivoSp0DNBF2rJwKrZqSCUhlbF5aHOkTl2c= -github.com/aws/aws-sdk-go-v2/service/vpclattice v1.18.4 h1:rSH+7J2CYam9KjTnP/McEBXGKek3ZKmPIjxzbg9JccY= -github.com/aws/aws-sdk-go-v2/service/vpclattice v1.18.4/go.mod h1:8kiKl6iX78tF/zC2Xre57+tIzyqUgss5EC4XTYbTGsg= -github.com/aws/aws-sdk-go-v2/service/waf v1.30.4 h1:I8iRy0FZaIzvKQbYd+so9dwHjfTH7gJStIto9jVdyGo= -github.com/aws/aws-sdk-go-v2/service/waf v1.30.4/go.mod h1:lX0RUUJZv3o0i7eJpOb5v8U/b1nLXOSrDw+5IDfeQ2k= -github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.5 h1:IsxWqce1g3oinoU7IrhMLHBC9fjU2bsa4a9uB+04ZXk= -github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.5/go.mod h1:cXlfX/JQZm571jLbsJ2KwSkWNL519cIuEGvHRhE00nU= -github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.6 h1:/1GODXDwDC0VajRPSOM7WEB/lt1nHf4EFGq3tek1mfo= -github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.6/go.mod h1:q1Vkk7vOGe+ZOVoAPF40G79KmvIA4PUopJX7MoX02wY= -github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.5 h1:edH2U4T6OVZ3oSF1RQJd5uUkYT5qXsv///5eNbjtctA= -github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.5/go.mod h1:MH8WKWPx4mST1eiSCzfnbM/WnbYAYBjquREGQoXiw1k= -github.com/aws/aws-sdk-go-v2/service/workmail v1.36.3 h1:4fr59LE0V+wHppPzH6KcXnPjYsTnSrOmLfg0fCesPSo= -github.com/aws/aws-sdk-go-v2/service/workmail v1.36.3/go.mod h1:CxGZ2aCZsgLJ5joHnUdydAZnGseF8J+k9Q95dQmslCY= -github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.5 h1:csqxgZrn2tPvnasMPNxIaLCTy6lSXAPMYGks7JkrvzE= -github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.5/go.mod h1:xNd6H5yqIyFcoOwDuJZjR0o6doMVIABzTJ/s6KpVnok= -github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.5 h1:niTF0DKSzYbSwHbqvfgkTGDjCc4KS9AomYar+FtG4Q8= -github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.5/go.mod h1:oOqgO8CM0jBAailzE/c7Y578WoNGZkge1MW/HZ3M0Co= -github.com/aws/aws-sdk-go-v2/service/xray v1.36.3 h1:4EA/KYvUBptDbTt8aWyyasx8ae4ofSkwX4f2EEG3y7k= -github.com/aws/aws-sdk-go-v2/service/xray v1.36.3/go.mod h1:Gb+Fn+VUhd4TJvFpqn7l/+ny0suOK0IZAA+eE7+9oGo= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.9 h1:by3nYZLR9l8bUH7kgaMU4dJgYFjyRdFEfORlDpPILB4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.9/go.mod h1:IWjQYlqw4EX9jw2g3qnEPPWvCE6bS8fKzhMed1OK7c8= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.9 h1:7ILIzhRlYbHmZDdkF15B+RGEO8sGbdSe0RelD0RcV6M= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.9/go.mod h1:6LLPgzztobazqK65Q5qYsFnxwsN0v6cktuIvLC5M7DM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 h1:5r34CgVOD4WZudeEKZ9/iKpiT6cM1JyEROpXjOcdWv8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9/go.mod h1:dB12CEbNWPbzO2uC6QSWHteqOg4JfBVJOojbAoAUb5I= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 h1:wuZ5uW2uhJR63zwNlqWH2W4aL4ZjeJP3o92/W+odDY4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9/go.mod h1:/G58M2fGszCrOzvJUkDdY8O9kycodunH4VdT5oBAqls= +github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.5 h1:1bnvwYxuKCTMiF/MavITDTRnCCOdCbmNWyFbfKMw2wA= +github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.5/go.mod h1:Ok83qcqfCvpkKU655IHorvYG0NMPr30P5H8ng9uNaQk= +github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.8 h1:rdiHnyg2/1Wu3/BVCY0o4a5RGs/bF5NTjqscInYWGJ4= +github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.8/go.mod h1:TniL6d9prBubA9ZcfCJo9Q9r2cyh2c4C9csZMUDYuBw= +github.com/aws/aws-sdk-go-v2/service/iot v1.69.5 h1:ufbRtUcNLpfKjE4MXGnqNwF2gXh5s9CUlgfL3nDyd5I= +github.com/aws/aws-sdk-go-v2/service/iot v1.69.5/go.mod h1:xkUGPoYRFoe0i19cUfIMeocCOWG5Ona7MWMeMqqL8eE= +github.com/aws/aws-sdk-go-v2/service/ivs v1.47.6 h1:L4uWqGDzaapkNiPW1LUnHVGkrjynMG5vyGeu+YATgio= +github.com/aws/aws-sdk-go-v2/service/ivs v1.47.6/go.mod h1:i6n4c/4w7kw455UViuMob7/0YoWB24uXkzal1udFz8g= +github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.5 h1:pwetfaLlSr67dBmlJtVNUsBgSdOzk02NfAo1MDqhyQM= +github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.5/go.mod h1:mbBWB0NzEUOjY8FarIsbCWo6DXqylv1mf+B77uT/xlQ= +github.com/aws/aws-sdk-go-v2/service/kafka v1.43.6 h1:gd9n9V4YTRcg5VJfDYBRVJHQBaUMpbKOKWzAhHzyhcA= +github.com/aws/aws-sdk-go-v2/service/kafka v1.43.6/go.mod h1:061TSd3Z7fxrRzFbo8VniS3VErBjATTfC7+HsSUW11g= +github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.5 h1:6lT7GqiBAkuL2bPGUjJDqm4DoPpRom/BhvIokHPLPB4= +github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.5/go.mod h1:Z9w9e4XGxePy+tPjsgNKYiJZXPTFysEbKqpc72dzhO0= +github.com/aws/aws-sdk-go-v2/service/kendra v1.60.6 h1:rGhNWcIhP7DqFve8zlZItzX8UslsM26aSCRTC6M2hGs= +github.com/aws/aws-sdk-go-v2/service/kendra v1.60.6/go.mod h1:3Amyw8Cu+M3VliBNu6PkOvVLLGS9eyzmkwBBYIygr60= +github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.6 h1:VvcHwWDWJs6sbM62LI1UKo3ONVBXSP+sPiYduTOZ5Ug= +github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.6/go.mod h1:YjFnZVw57O46J972EzA4Ny7HObGqymOoFCymCiLXdDE= +github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.5 h1:GWAVIxhYlkFX76WGG2gus5eyonXaKPv00VpiSqHzXDo= +github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.5/go.mod h1:u/oFMSASsn9QNBRop5lrIpuNwHZwEXjYxNQp7sHFSxc= +github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.6 h1:OL3s9Y927XoMxO4Jod29/eIl1vyS5NDnDesJaLkhjeE= +github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.6/go.mod h1:1szjTKn1bM+Ce2Pf2g57WqudQXi+YZodbrYMZY2Awzw= +github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.7 h1:lePrOEBRe3FMsApDx6QNfiVsUR0ePYdeE+KkIMM6vp0= +github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.7/go.mod h1:AUtvJ7STwd00cd5mT3Vt9WH0LjF56nOWAZzPx+T5wUg= +github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.5 h1:8oO+Su+tqdsF1wll/Zm0eenGi/0lXQljG5sFerZvFXQ= +github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.5/go.mod h1:Mu9FDrPD7xsAZf9KhiL+WFEtnEgO7x6Kf8OJceaiJRU= +github.com/aws/aws-sdk-go-v2/service/kms v1.45.6 h1:Br3kil4j7RPW+7LoLVkYt8SuhIWlg6ylmbmzXJ7PgXY= +github.com/aws/aws-sdk-go-v2/service/kms v1.45.6/go.mod h1:FKXkHzw1fJZtg1P1qoAIiwen5thz/cDRTTDCIu8ljxc= +github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.5 h1:YlhZqR9Ma0x7q83cNpis7YJ1w4u532+ohJ7MSHqZno0= +github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.5/go.mod h1:e+RSq7q4W1pe3kt1kFBWQLvCsF3LEa6YF695iPjwUqo= +github.com/aws/aws-sdk-go-v2/service/lambda v1.77.6 h1:bU48NwA1e9jFkng1qYUVQjdJFEIv0oxhDO/Zz57M5IU= +github.com/aws/aws-sdk-go-v2/service/lambda v1.77.6/go.mod h1:LFNm6TvaFI2Li7U18hJB++k+qH5nK3TveIFD7x9TFHc= +github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.6 h1:aZ8MXpLB17q6THeWkvpYVheZTf2oOMgaeXYxQLfq8vY= +github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.6/go.mod h1:5IsG5hZ0YnGeIsZvB88ALqptUB5TmyA68Vh2JtOuolQ= +github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.5 h1:ArkKQMxVIaauILktZS/FMc9u52qGpC3OSAA9AQAnvgU= +github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.5/go.mod h1:LRYpBu4UZPuBggAl0Q62MaDRDlDYYE/DR/Q3Nr5HnTQ= +github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.6 h1:Ujpm8Qr81ge34jboS6NQu4WK/gpuwjNQI/cW8G2w1+g= +github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.6/go.mod h1:xiuNneOma5q5l0VtLAR6MuQ3K5sJlUCz51HB0IdJgvc= +github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.6 h1:jSPCSRdv3Ad2BZtaCO3PWJQmoOe6WXqrG79IoHrTpl4= +github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.6/go.mod h1:E+dz2RTwFIOG6cKRJiln5khKJmROa6RvP7DKiEEPCFE= +github.com/aws/aws-sdk-go-v2/service/lightsail v1.49.1 h1:J1A0VJlt5HgUX6s11Obe9zrBDECeE2uhQc7Dwhdei9o= +github.com/aws/aws-sdk-go-v2/service/lightsail v1.49.1/go.mod h1:WEOSRNyfIfvgrD9MuSIGrogKyuFahaVMziVq1pHI0NQ= +github.com/aws/aws-sdk-go-v2/service/location v1.49.6 h1:hNRkhRPvAHAqZapl7BPcjls1BAnykokUkF71E0iYgPU= +github.com/aws/aws-sdk-go-v2/service/location v1.49.6/go.mod h1:aRLVKgDTnlsf0moRfee8FTWv9SghW/x3W0W33Y//ZDY= +github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.6 h1:9yP3vAUac8JYDnenwuOuPmpIRBgCVidxWN6hZvab1lE= +github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.6/go.mod h1:A6750m3A2OebBhSwoXKosN5Vciq/JiY2piPsmZauiwc= +github.com/aws/aws-sdk-go-v2/service/m2 v1.25.6 h1:1pA10Dziy1XrpFNf6aND3Y43imaLL9w6U6lfMBUNR0E= +github.com/aws/aws-sdk-go-v2/service/m2 v1.25.6/go.mod h1:X3NB31GJKffp5h+SnU4aMKMarKd9Bd7jRFs2y/Ihve8= +github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.6 h1:0lg+Mhd61q16NUpxwnNpAhP7sxSOO5H5/l+QxerZuIc= +github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.6/go.mod h1:hAUjN7Dlx1i1Sjbx67uumWB7iwXOA/PM8kNOiw4ygjY= +github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.45.0 h1:4cBXNlo8XYFq/leCpTVuZX2qAp779SIg3wkMPd5FDjo= +github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.45.0/go.mod h1:pyFeP6f26HHtJJeNU4LqcD3R1Zh9RMwZjiluEsgZlYE= +github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.6 h1:gk0yVOnKaRKGyWifpqw3aGeEGB4EO77UYGXnucl93Ek= +github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.6/go.mod h1:YZeaUGHZihZA8/pC2hi248p8Y8S4oPMZLXso2RF4hsQ= +github.com/aws/aws-sdk-go-v2/service/medialive v1.84.0 h1:4VnT0CicQgGzIkzbfIz9FcCvl/A25JclsZ/jkkP2sGs= +github.com/aws/aws-sdk-go-v2/service/medialive v1.84.0/go.mod h1:ZWOvuk7slOmdlSnDIY7gr00d/HUEKAYT15oPc2oMprw= +github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.6 h1:xF2FWETQbjkGKK8fcmaJ2bO7i53wwRbsnExg5uTswyI= +github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.6/go.mod h1:hSlgOOXXYOtXOH8PUE07ZctOeDR9doOvtvpM6oR7z54= +github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.3 h1:Tbh1uS0VAEw75762wftgeXlrpK2AO2tZjObiilryUCQ= +github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.3/go.mod h1:5w01h9/Nmf0FUimiQGY9bYPU/of1Nz9oxiGbNxzUYT8= +github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.6 h1:8QUyNYiWzhsbQJITt/v+SNwdA/wH7B8YnDO/9GLeX2g= +github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.6/go.mod h1:QHMKOy8M9YcyxacWIIije66JGOPn0Uv911y3QN5xvOE= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.6 h1:iafXeKlVqhC8/ScR2CzQlWzDm+B3BNcQD7SzZ+gE1LM= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.6/go.mod h1:pyztXbSyAGD+TmvQhGva28W3KgwEsjZ39d/tM5E3WLk= +github.com/aws/aws-sdk-go-v2/service/memorydb v1.32.0 h1:R+jvAaitNKrnuBDpAxM/Pi/1JD5cRqwL3cQolngYf+M= +github.com/aws/aws-sdk-go-v2/service/memorydb v1.32.0/go.mod h1:ls5Htz+L0oFjuS/8Md/RLSLCFUpGkvlnZ2GLZ4NZguw= +github.com/aws/aws-sdk-go-v2/service/mgn v1.37.5 h1:BMu425Ntx40waGQ0/g6BeX1F/sYvKdIcO+ABys5Jv9s= +github.com/aws/aws-sdk-go-v2/service/mgn v1.37.5/go.mod h1:F3YMviBP/8gRnYBh8j+6MUw/c3ID0l3IMS37kHAo22Y= +github.com/aws/aws-sdk-go-v2/service/mq v1.34.4 h1:Oo18RmcBezamgeYgLQs0TvQte9qnBsT/h0FXaVR/su0= +github.com/aws/aws-sdk-go-v2/service/mq v1.34.4/go.mod h1:Ix0YBjTUQkaENu7moWEIOuRPvSXCankc9G8+6tCHPFE= +github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.6 h1:E2/4c34w/DlacnWCB00i5vK84Q+R4THQekMFYKEQ6EU= +github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.6/go.mod h1:VGfnBe0/1AmUklInis8fWYCsX1sytShIyJaAskYui8k= +github.com/aws/aws-sdk-go-v2/service/neptune v1.42.5 h1:tfn0wZ5FFDV8USRyR1pbwVuMjc/8lxCXGiXtj4pGP2Y= +github.com/aws/aws-sdk-go-v2/service/neptune v1.42.5/go.mod h1:31tyZ8ZVqFkyO8beZNHcEOQZGn/BkuSpj92xz0DV47M= +github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.5 h1:M6POQvRc86IBNXMGMnigORWW7TuI4DQw6w9/7a22AmE= +github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.5/go.mod h1:SDNZtDXmPLQgX3rhJKQilrATByCSvfefeGBzmyHWV9A= +github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.57.1 h1:ft8fBc54sf9RPLzZ9C3R2ICWlsJI7gNXzhe4KM6hcMU= +github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.57.1/go.mod h1:aR3+jhGdmzkcu69LUu3uEfWSz48rSWZpRZ1UiW1brzY= +github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.7 h1:UqDxJzpwgrEi/AuVaXCqN3g0zysr0K/RPY7kxj3kAFs= +github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.7/go.mod h1:2lpNczbmNGrUPnMa04jr4J2BxQ3jv2pYErTQlELWESg= +github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.6 h1:5MKZrK70vz0m3A/IbE00XgWdX6VARrQMe/lTtlh1VIc= +github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.6/go.mod h1:r99VUsxYLupfRyaZ517RoASgRyspKDvj+T3Ec2bsJLg= +github.com/aws/aws-sdk-go-v2/service/notifications v1.7.4 h1:Ur4HSvZrzDevCVcXHLzj/VYKLYznFsIuXXzsqggt0HE= +github.com/aws/aws-sdk-go-v2/service/notifications v1.7.4/go.mod h1:jp/DVjlMmlD2RaRCAYs0IRy2k5XkppwVNc9wo4oYkkQ= +github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.8 h1:SoLCt2Ig7kir4Vv8VtFVqADtaE1iSrC/f2U9vVgCe4M= +github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.8/go.mod h1:TqON/FD1E56TNUpLtwI6m1PbjmuZRhrvbo1ZGOIbzto= +github.com/aws/aws-sdk-go-v2/service/oam v1.22.5 h1:To+7SakfElByzTR10RrFGAXRH2uWBDvMPTFOYQY0Wrw= +github.com/aws/aws-sdk-go-v2/service/oam v1.22.5/go.mod h1:huNDbI1vKiFhIuo8Q4hK09wk1kN+RFdbxrrjSsCZtCQ= +github.com/aws/aws-sdk-go-v2/service/odb v1.4.6 h1:AV9JZ+ErtkFZFJAOao1CSSPdcJzY/onnQU5K5wdiV/8= +github.com/aws/aws-sdk-go-v2/service/odb v1.4.6/go.mod h1:sNgPICtv0QshuEoMhFiRT5rBWnpXMFvLhly/Hu0MqYw= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.5 h1:gkLP1OOn0/gBPD125+Ax+9DKuGGsu9TwvbZJ4bBgcsY= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.5/go.mod h1:c1RKL9jCAUP+7ZtY+99yWcWxRFBsQ3LG5Klkj5PEoJs= +github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.4 h1:46xDV+bDfEaoI4CFYA/SASoD17PhdIfRcnybENoeA68= +github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.4/go.mod h1:a+I7XPLBv75d9aI6TvmcMn2osIxiZ8rxjSy/OZQQAlw= +github.com/aws/aws-sdk-go-v2/service/organizations v1.45.3 h1:JcKtlBBVZpu01E+WS5s6MerJezxVNW0arRinXwd8eMg= +github.com/aws/aws-sdk-go-v2/service/organizations v1.45.3/go.mod h1:oiUEFEALhJA54ODqgmRr3o5rZ+SOXARVOj4Gl3d935M= +github.com/aws/aws-sdk-go-v2/service/osis v1.20.2 h1:fmH/ayvn5AcQ2jnFMtbd57CwTtuOKcZLdfl3eGZP7oc= +github.com/aws/aws-sdk-go-v2/service/osis v1.20.2/go.mod h1:t3KwhHJvvtof6DJzL7JtGY4+cxPsQumV1snXgg0+aww= +github.com/aws/aws-sdk-go-v2/service/outposts v1.56.7 h1:q/y5yHOR3CmvBO7G3dQKE8IT2PrfWSorN8iP51qVOHY= +github.com/aws/aws-sdk-go-v2/service/outposts v1.56.7/go.mod h1:AX2swwJXvwgCE0695M12Vw8p/JU2PQNC/5J9ur1Zd9s= +github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.2 h1:jAVEnaD69Jhc3ePMMuKLj7Y6NNRNN4s1X/UT+SMlXag= +github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.2/go.mod h1:LtAy3qbryUglXiyAYdn+OCltWbMMMvYoUK6hAiFc73k= +github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.6 h1:tZK9NedvW1WYWf+eZ437hUNETq4+eofZ9ja32FtFHLQ= +github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.6/go.mod h1:fRBVcoZiTYjTywau+UcyTXAjtLxz20Jsaz0XXdG2950= +github.com/aws/aws-sdk-go-v2/service/pcs v1.14.0 h1:Dk/dj8EBPQBPawPMR2M9+tijanojSdoxJDSA5clenZo= +github.com/aws/aws-sdk-go-v2/service/pcs v1.14.0/go.mod h1:wyFACwTlB5ZUiOQAqs+5m7gj4xUCbojoUTaZYxa7BjM= +github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.6 h1:6vjEH7AL5aYC49apXto1dHgMBNDdZLh2L3Bve0vkE2o= +github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.6/go.mod h1:oNyevxM/xQifmv2yk482sM2isWXgloHLrOLoeOrOPHQ= +github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.5 h1:S/QLsL7GTbrtjrALjKWdab+UBUB7LIHnEJtMvdD9khk= +github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.5/go.mod h1:TlvbcCoDxToksnKXX+nmSi70Kn0aMcPo3qr2hgbO+yo= +github.com/aws/aws-sdk-go-v2/service/pipes v1.23.5 h1:QrMb0weKCfbPmFM8Z3tHXGDd8b/g5kkbYSGELgYteOE= +github.com/aws/aws-sdk-go-v2/service/pipes v1.23.5/go.mod h1:OYOBK8E3mCVkk/6bCQk+J0R2JgLYotiBd10P07i6CTk= +github.com/aws/aws-sdk-go-v2/service/polly v1.53.6 h1:ltnQaTs2saOP3REJZlNGbujWoF0/O/uWsKtW5aRs+0o= +github.com/aws/aws-sdk-go-v2/service/polly v1.53.6/go.mod h1:4xoAju2Su1TJ1Q5Y6hxNFLb3kBzYOtgUN05dQj3VTp4= +github.com/aws/aws-sdk-go-v2/service/pricing v1.39.6 h1:SapAI7aLrvLNUCBeBhhR6cU7TFIrRC5KNeaj72hV+fc= +github.com/aws/aws-sdk-go-v2/service/pricing v1.39.6/go.mod h1:TtNWNQGg2WmSIS+j/ZqyJD3xY6zyAuYHBDGxFYQftjU= +github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.6 h1:kLTYFvi4+nsETUZpwqPcVVOfOX/lD7OvQ4aU+TSNGVE= +github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.6/go.mod h1:XxU8fY4XHMpkvrCDaylvGiaz1PSU1nntX3XasTEomDQ= +github.com/aws/aws-sdk-go-v2/service/qldb v1.30.6 h1:5FBEiFjL83odCokDLGauL1g5Noiapq8jRsqKN2/YaF8= +github.com/aws/aws-sdk-go-v2/service/qldb v1.30.6/go.mod h1:FZR8mKbaQK8xEyQmtZKEPYj6Rxgi3iLKFi7MutHzYNI= +github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.4 h1:NYaNLjesQC14fZR15t25Wws4znd0NsuvZfUWJAtaYA8= +github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.4/go.mod h1:aJPu5hqpBhcV4gXqbAuZhBiIZ+dXHrvJ176qTPADa2A= +github.com/aws/aws-sdk-go-v2/service/ram v1.34.6 h1:S/BivEPJDOKDEaLQuodznRu/9VscK2n24Oi464ySkao= +github.com/aws/aws-sdk-go-v2/service/ram v1.34.6/go.mod h1:IjW9GK9av7d2rdmmi3uze2erokbWAxUtMwDc1YOj+9M= +github.com/aws/aws-sdk-go-v2/service/rbin v1.26.6 h1:wKVcl95mVcHW1rJMsf5SsA9T2zrfOmC5WyDrqpFVnVE= +github.com/aws/aws-sdk-go-v2/service/rbin v1.26.6/go.mod h1:LCbTwbuAosB0UYOB4eMr7CmzwKPaO5ZD+UXEhJ6TPn4= +github.com/aws/aws-sdk-go-v2/service/rds v1.108.1 h1:Felh4W55+rsAjcg+EsRUdCWxXXyy3N9UJz4Ej5tLCC4= +github.com/aws/aws-sdk-go-v2/service/rds v1.108.1/go.mod h1:VOBL5tbhS7AF0m5YpfwLuRBpb5QVp4EWSPizUr/D6iE= +github.com/aws/aws-sdk-go-v2/service/redshift v1.59.0 h1:MtE4oUVeljvF2CWPZwzWERizY5uhZV7os1eJC9oA8BI= +github.com/aws/aws-sdk-go-v2/service/redshift v1.59.0/go.mod h1:ARgrCFhclWArEevJ/GAn+UBBVc9+f9oFurQlyjx262I= +github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.6 h1:PC5iIPcOwMMqAocH4fuiyLKbEOKr9t75zhp7yysK0NY= +github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.6/go.mod h1:u8BCO9VvZZqxHaCk4i17Js9WSGR45KPN35k/Gi79hng= +github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.8 h1:YJixVrWNAJYfCXcMVMppPA1RQaPtZ0oXGrLDRf5FHIU= +github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.8/go.mod h1:1T8W8J3Xiwhtikj4yLUXTFwOB6cWvukAzncJUV9A5uw= +github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.5 h1:7XEUHyj3NhDxz8ogR9Zqj8SRA/5J2OJ+u4lpGu+qmJ0= +github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.5/go.mod h1:2lepPReuRVIackBiaSO6c5ch3HXIROzHFxCCpMQgKJc= +github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.6 h1:LvBVCmxDLAp3tNkAXNvedPjNw2DFJ9W0mwOpbkjaSUE= +github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.6/go.mod h1:ZBunG0PHHt5TwsVfGyDpPtAeqmCnlo8SjVRsS/me+5Y= +github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.22.0 h1:+vdGkeg7koJ0MtMui392lmmF2gKISzqiUryQuq8HumQ= +github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.22.0/go.mod h1:WeUb0leMU6VjQkjVzmUa/DBuqgaMCgcaWoWNJy4Hg5M= +github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.7 h1:aJEEtqhpU2Vr2zFQ6jJT3z6ryqNSJjQ3UqEUKIsCdU4= +github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.7/go.mod h1:RD/9wH7u81Og53+2Vt7qAOA6PstpLcyiud5wCv0R/ds= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.6 h1:c1gIOTNJ6gkocnL33DP1St++uv+f7ClFiUjR5/Pm40o= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.6/go.mod h1:KJZ2lPXqxMULgTX/ldDAa2WeLAR2qz7vGqLEJLCP1RM= +github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.6 h1:1n0OZvoccoCuMn8GYI8/A78sWc0NKc3VTgTyO3fmasY= +github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.6/go.mod h1:+X3mqbUeamf2ANy4ppudqH0s6tuH2pFl04Cq8gFAikc= +github.com/aws/aws-sdk-go-v2/service/route53 v1.58.4 h1:KycXrohD5OxAZ5h02YechO2gevvoHfAPAaJM5l8zqb0= +github.com/aws/aws-sdk-go-v2/service/route53 v1.58.4/go.mod h1:xNLZLn4SusktBQ5moqUOgiDKGz3a7vHwF4W0KD+WBPc= +github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.4 h1:mQ7ZPMQ2Dz4dl//dgMOWmApKXGZ9f9cHza7Qh9tnqSM= +github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.4/go.mod h1:7q323bgF8xAtY1+rN/WVtUsbtSPZWWOVsIID9zAI5KA= +github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.6 h1:Tx7z/TsZ+OdtDtUeZFrzAU//NhnFMiGRxeAEEeTIZOI= +github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.6/go.mod h1:d46EQzstY7ltSyackMoYMJGzq+TrF1RYr3DU15t0mCo= +github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.7 h1:JztKalb2lLUv07Ls1J4ePVmg0RUgyRBx1/k8maIkawE= +github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.7/go.mod h1:PJXGu3IjcUbdL8taf9Zl9vB6ZmigpjAq+gFz6hDBmGc= +github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.6 h1:dT53/rvqKgu4MMOzwhv6HVtxgrWp9SgYwkviQIBbmeQ= +github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.6/go.mod h1:6d6uDK4yLgR+5jLqWdYejxBE2yS5NV/4FrOmNZclrm0= +github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.6 h1:lhnQ2Nkm3liKRxl4j3A18DYzGkxaixaSNF0fgXhtZDI= +github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.6/go.mod h1:hFCmtJyNyNNKxzX43Skr+l4JTpV/w8x470hIJBedcO0= +github.com/aws/aws-sdk-go-v2/service/rum v1.28.7 h1:WD3KNbMhPNIo6NeWIKvH+JyB+nlxA+3FP8T6AeoC8zY= +github.com/aws/aws-sdk-go-v2/service/rum v1.28.7/go.mod h1:d1TetEj0rCx4wEye6LeIjDCgHUkIIS/6cXu8UaI1aP8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.88.3 h1:P18I4ipbk+b/3dZNq5YYh+Hq6XC0vp5RWkLp1tJldDA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.88.3/go.mod h1:Rm3gw2Jov6e6kDuamDvyIlZJDMYk97VeCZ82wz/mVZ0= +github.com/aws/aws-sdk-go-v2/service/s3control v1.66.2 h1:/ZonyP9GF0PKVTCLvnce+muPdS8REakUTHwkP8cyFFU= +github.com/aws/aws-sdk-go-v2/service/s3control v1.66.2/go.mod h1:m5ZEef7/rUTT4ed1B22b+MhYKWnp8Qkj4iIp465G6J0= +github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.6 h1:ISvhq3XY67cCOhHQNuERigQBjUNkr4gjM7f0MFRq9P0= +github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.6/go.mod h1:rLtMvFVwJRG+in5WrAQxgzDU2KBsenSsNrpLbRa0Xrw= +github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.5 h1:lvhu7h0CC9vsL0kxghR6OeGJwF5VsXDHfeGEAwl6XWE= +github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.5/go.mod h1:ZPE8QxN4+WylqmPew7p7G+J+h1qQo/pbBNLGKr/GJ/o= +github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.8 h1:ERb8DDNjGcCkDHblpHkSNzEs1ONBk+rCITYA6z+Yd1w= +github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.8/go.mod h1:gSvTmSFxwjt2k+U9eP8LQpR3sDYpwA/desV1WjaEGJ8= +github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.3 h1:7QukmIiqAnEoVfduk36whgv8YGtKjcZc1hilfxZxqYQ= +github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.3/go.mod h1:BSg+goTRoWiHkPwaU91RjaWtCB4+BAcbj6X6Ihvs8I8= +github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.5 h1:QaBANQbMZMyyZ8UmuOaa533NCkgjtwuKyfJqd6fziUQ= +github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.5/go.mod h1:9ulCU1KqL8XYYCu7Zj15WB2lSlSAb1sDzmwVl9LuMGI= +github.com/aws/aws-sdk-go-v2/service/schemas v1.33.5 h1:f94foSb0xp3flzTDe0qHRl/kwsp5RnUvMGH9jYophXc= +github.com/aws/aws-sdk-go-v2/service/schemas v1.33.5/go.mod h1:StI8kLU7UqwT4GUIyHwd4cmLXxglmNbT+faOZltSlA4= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.6 h1:9PWl450XOG+m5lKv+qg5BXso1eLxpsZLqq7VPug5km0= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.6/go.mod h1:hwt7auGsDcaNQ8pzLgE2kCNyIWouYlAKSjuUu5Dqr7I= +github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.4 h1:56LRTpQSA6dqo2inwUwICUgnlCe3kAddCOhWggdDsYQ= +github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.4/go.mod h1:whhpbyK81XOJWOiCmN4SbYv3X+kgNlMgHOQAnEMRXsM= +github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.6 h1:HDDXTIW91VHxTgu+05f8n5HzJrDAUDqbjX1v3H2KV9Y= +github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.6/go.mod h1:MY0oQdCHOaepsEJoN/WoaCHNoksmhrBrBlDvjUQYJmY= +github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.6 h1:70PEH4oDsU+YER8KUfSedHGlRBVihtcXxah3rokT9S0= +github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.6/go.mod h1:spm5LxERJz0IOpYf9fH6lBDDGgB3OXSwrV0Oj+fL7xU= +github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.6 h1:ZGvb2y036q8v5bZhuqzmDnqdpo85u/3/B+9NnbYPcXE= +github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.6/go.mod h1:eNS1O7ALYB0n1K6UJASh8kgw1KYGg26wHxx35VZgjFs= +github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.6 h1:OFmbZQixBI0tnwxxoiZtdlGZSOqaOHq7wkxJGLcOIsk= +github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.6/go.mod h1:zOpRzlMssUTM/YZ/JVuztNnGUMGTvOUHTCtyLEtOUnU= +github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.9 h1:snXikqd2A2wiFwFoEjWVLE1p2hbRaVkSxHCcV/vxibg= +github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.9/go.mod h1:D+QXio/b/Fxee/lnsYvajiEuWcPzCIc2B04YzIHX0/M= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.5 h1:yaKAIVuVWtqDkiGV+gQKYt6gfYxbcnbfL5lv4lEawU4= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.5/go.mod h1:OzKW+2JATYOrFN/hai+5/4SezjqbEeLeZrQqNPLPe+s= +github.com/aws/aws-sdk-go-v2/service/ses v1.34.5 h1:NwOeuOFrWoh4xWKINrmaAK4Vh75jmmY0RAuNjQ6W5Es= +github.com/aws/aws-sdk-go-v2/service/ses v1.34.5/go.mod h1:m3BsMJZD0eqjGIniBzwrNUqG9ZUPquC4hY9FyE2qNFo= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.5 h1:ZHBssvFtrtfNCm5APnzFrkdCX4KPDKlSGZ2NbfPmISY= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.5/go.mod h1:eJP5lLTdqKwiQB5mKKaSjjJlLB0xcT3pTFF576PbdP0= +github.com/aws/aws-sdk-go-v2/service/sfn v1.39.6 h1:0kpMhSSBrZmYeeKmyM4RftA4XeiC0PDVcbUg3gXNqfk= +github.com/aws/aws-sdk-go-v2/service/sfn v1.39.6/go.mod h1:XyrAUQxv//wWMFyh2mvvTZL9vaYdpjM3Rg5A5QOFOaE= +github.com/aws/aws-sdk-go-v2/service/shield v1.34.6 h1:AWKt4pVqiqzLIT3xoOThd0xT6dY1lSB+7yDcn0N3I48= +github.com/aws/aws-sdk-go-v2/service/shield v1.34.6/go.mod h1:Io5NYTndCqsmL+vdfoQEkInZkbZn8gLloqEjGvng+7M= +github.com/aws/aws-sdk-go-v2/service/signer v1.31.6 h1:TnlG33tsUOBnu7rMicF8YFIC0pxkJdBJwo2R0W5L6Fw= +github.com/aws/aws-sdk-go-v2/service/signer v1.31.6/go.mod h1:a6U0A/LNWknEIS7Fmf4McuUwImMlo6qrKkhbEpSczP8= +github.com/aws/aws-sdk-go-v2/service/sns v1.38.5 h1:c0hINjMfDQvQLJJxfNNcIaLYVLC7E0W2zOQOVVKLnnU= +github.com/aws/aws-sdk-go-v2/service/sns v1.38.5/go.mod h1:E427ZzdOMWh/4KtD48AGfbWLX14iyw9URVOdIwtv80o= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.8 h1:cWiY+//XL5QOYKJyf4Pvt+oE/5wSIi095+bS+ME2lGw= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.8/go.mod h1:sLvnKf0p0sMQ33nkJGP2NpYyWHMojpL0O9neiCGc9lc= +github.com/aws/aws-sdk-go-v2/service/ssm v1.65.1 h1:TFg6XiS7EsHN0/jpV3eVNczZi/sPIVP5jxIs+euIESQ= +github.com/aws/aws-sdk-go-v2/service/ssm v1.65.1/go.mod h1:OIezd9K0sM/64DDP4kXx/i0NdgXu6R5KE6SCsIPJsjc= +github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.8 h1:Nqsc8EhmXUwGCLLxB1cCt/8sDyVUDaS9zpkXyd8zcD0= +github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.8/go.mod h1:AGjoKT5weHZ8oo4sFEorNVKsg9noEmEBiXsA5e9veEE= +github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.5 h1:oGUMJl6Wf7vZWiaCRE4MPjtnet6aEjnpF/1WxoKlJ+A= +github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.5/go.mod h1:5TeCNbB10rN3TUR7NWFdRWFLfrjebhMvvE0lQKS30aE= +github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.6 h1:sGhOo5CZV1QV1gsAcrwXJVm2EcVaTCVLhEIr29eaihA= +github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.6/go.mod h1:Y07XpBl1TPJFFfYf4OD1PPmui8rFba8k2u3gAH1H5YM= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.5 h1:D2bijFgTDf26Oizhsj5X6X1B8ibIaZVHgonPeLnNTlQ= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.5/go.mod h1:11+FpRI0DIr3RuA3pRCDwVA22LP4vymQB7MCTMCApKw= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 h1:A1oRkiSQOWstGh61y4Wc/yQ04sqrQZr1Si/oAXj20/s= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.6/go.mod h1:5PfYspyCU5Vw1wNPsxi15LZovOnULudOQuVxphSflQA= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.2 h1:4O5fAx9BpoX5c+5BxUgOLJM7kS0K20JebxzLzfu+JIk= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.2/go.mod h1:7iR/6+xIFUPl0LnAZ0RSBQ4A4R6CyA7WrxKyB9QncWc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 h1:5fm5RTONng73/QA73LhCNR7UT9RpFH3hR6HWL6bIgVY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1/go.mod h1:xBEjWD13h+6nq+z4AkqSfSvqRKFgDIQeaMguAJndOWo= +github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.6 h1:fkyLQiPCNKi7eerHV4m+uM4ljlw6BQjQW2sLh4xVaew= +github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.6/go.mod h1:e5HFdmxGXdN1LQ/a+twPR3PuQyvI/aPK38MWVU17QHc= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 h1:p3jIvqYwUZgu/XYeI48bJxOhvm47hZb5HUQ0tn6Q9kA= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.6/go.mod h1:WtKK+ppze5yKPkZ0XwqIVWD4beCwv056ZbPQNoeHqM8= +github.com/aws/aws-sdk-go-v2/service/swf v1.32.5 h1:uGf0//B3vB5y2gqeP7qUtyKh8A+MrhWgGXlisdsCCsk= +github.com/aws/aws-sdk-go-v2/service/swf v1.32.5/go.mod h1:jY8XhNSBjSezBEJA5pEM9sW7nqBc6EDmHwIJ1hj5pq4= +github.com/aws/aws-sdk-go-v2/service/synthetics v1.41.0 h1:PhrW72CcuCEhPNItPyE7eO/gE5fx4QJiNQ2Hwo6gqRM= +github.com/aws/aws-sdk-go-v2/service/synthetics v1.41.0/go.mod h1:eCpO7DjOFxysY+P8dEFJMWCTnpMLt7IGbIhSk5yHDMA= +github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.6 h1:RS2HB6ey9KpPETo2pWoPNcedvZY6E6+TETJ+3qHmrVA= +github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.6/go.mod h1:f2PHOYOjNlFxzDo6eR6Zf89XmUancu6ORaoTVURTY7g= +github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.6 h1:dVOI+vU8QsWJba4VfeZlNObkL76HlZQRjts+HqgfqcI= +github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.6/go.mod h1:7ObjtSvjDRJVBRhd9zxh6kgxYMbA9vtBQ24+RNjUdao= +github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.5 h1:ivzKU64lfi9F5VwBLIEcoqQMtXKrn7iUHOmhU8I88pA= +github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.5/go.mod h1:cSU9wIi0AjMmlo0ydUD839k1yh7fNnTdCZokIwol5Qg= +github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.5 h1:BjJ8HypXtGM+O5HP2rPfbxq50UuecvoZpRPdTAnILOM= +github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.5/go.mod h1:rnOKv/DJpfdiPPOyAdsHSommMuIHW6bmP2rrQJJYPdU= +github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.6 h1:tzRDA4lO/j9nzQiUDxOyshXZ7hrz1bF41+48Sn8rvHo= +github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.6/go.mod h1:ZZN5Hh+s7Cr845LY5cWKJiCplzW/vZwpnpjxifgo4Ko= +github.com/aws/aws-sdk-go-v2/service/transfer v1.66.0 h1:MmwixdCnBGaaOHJHDgkvfB8Z/OmtNdof3pXa6JJjgos= +github.com/aws/aws-sdk-go-v2/service/transfer v1.66.0/go.mod h1:28XXFJKdD8UJP9USN1DMtNNJpSt06CyozE/UaPbgjGA= +github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.5 h1:U7NFjnobEmEFqF9DB4tMLqSIJmciwcGYajpOOJgRdgY= +github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.5/go.mod h1:BkoBrVIzx/RT4x6XqY1o5iUqq9Hh62PKnBC9YBClDvk= +github.com/aws/aws-sdk-go-v2/service/vpclattice v1.19.0 h1:3OyM+OTHo2c5u3lWQijbwDGF7jmnpZwya+IOAywsQQw= +github.com/aws/aws-sdk-go-v2/service/vpclattice v1.19.0/go.mod h1:DjBHb+rO7d7WLJKX73dO6fULvhHdJrXfv+k3Kkiespc= +github.com/aws/aws-sdk-go-v2/service/waf v1.30.5 h1:JUQsG3CPBtXGGdAril5Fois4wiFE1Z3Z/mkvkjd4TCQ= +github.com/aws/aws-sdk-go-v2/service/waf v1.30.5/go.mod h1:sRusTwVAJQtNy6vsrAHGXtd2WIgBGusW2waE6Kgc/So= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.6 h1:DqojtTvnVwuylF6Ru08okb9UGNrq3qc67mZ8Gpz9sVk= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.6/go.mod h1:uo8gzm2uqf+gYYa2blt1ITjIl59iTzOznUGaajPfT+g= +github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.7 h1:inakpEsI7NPyC3VP2EbPA4gFcCnaFNu0JNQ01s0u5nE= +github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.7/go.mod h1:maJyEaarDIirG/MA0EYIxWc1ctk4sbc4+cEUVCIgorI= +github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.6 h1:0vFMsxhs4763afIR7366ricWl+w1sVOeroRkMOV9BGA= +github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.6/go.mod h1:zmHAn01szsTI7D4u2qgUs0CMklmz2af4EU12bDOWZrM= +github.com/aws/aws-sdk-go-v2/service/workmail v1.36.4 h1:hVmkAUyvH4OZkiW0HmNYYeDjVL7jyj3kCN/3r6nPiW4= +github.com/aws/aws-sdk-go-v2/service/workmail v1.36.4/go.mod h1:RlfJYDlvfjkqFAf3Fim2a5ryz6/gOYQJXJLJV5/c/xU= +github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.6 h1:QHAuU6Tfq2k6Okb8cdZ98BkXzmUZflfKG64Fc44CnQQ= +github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.6/go.mod h1:LTdwIWneoBQ7vVoD1gAGXvcNWq1gkgQqbCoKg1iDUZ0= +github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.6 h1:h8PGWVBIctOlbBpupw4CorUI8gCtX7d5o2lSHi12XgM= +github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.6/go.mod h1:nUz45LzKA733mQl1wIKcWK87SkJWXo+TiLYC5NUZf3M= +github.com/aws/aws-sdk-go-v2/service/xray v1.36.4 h1:G5VZW+21OPiOGoAFM+gBWPLKyuRaB2dC/RdYgL82ZS8= +github.com/aws/aws-sdk-go-v2/service/xray v1.36.4/go.mod h1:FYhPO/0+3jtQ10m0K1DnBTrJkNgXsrYhSHOt3/mCOnE= github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE= github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= @@ -629,8 +629,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.23.0 h1:l16/Vrl0+x+HjHJWEjcKPwHYoxN9EC78gAFXKlH6m84= github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.23.0/go.mod h1:HAmscHyzSOfB1Dr16KLc177KNbn83wscnZC+N7WyaM8= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 h1:HA6blfR0h6kGnw4oJ92tZzghubreIkWbQJ4NVNqS688= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66/go.mod h1:7kTJVbY5+igob9Q5N6KO81EGEKDNI9FpjujB31uI/n0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 h1:IS4mjtvkLHXWI5yn/t9ILOUiBqPePMFaO4IRh5pcMk4= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67/go.mod h1:l81jrdpcZSWUsJs4BGFfdGScefSYEFQRLMQRG3uyvT0= github.com/hashicorp/awspolicyequivalence v1.7.0 h1:HxwPEw2/31BqQa73PinGciTfG2uJ/ATelvDG8X1gScU= github.com/hashicorp/awspolicyequivalence v1.7.0/go.mod h1:+oCTxQEYt+GcRalqrqTCBcJf100SQYiWQ4aENNYxYe0= github.com/hashicorp/cli v1.1.7 h1:/fZJ+hNdwfTSfsxMBa9WWMlfjUZbX8/LnUxgAd7lCVU= @@ -698,8 +698,8 @@ github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/jaswdr/faker/v2 v2.8.0 h1:3AxdXW9U7dJmWckh/P0YgRbNlCcVsTyrUNUnLVP9b3Q= -github.com/jaswdr/faker/v2 v2.8.0/go.mod h1:jZq+qzNQr8/P+5fHd9t3txe2GNPnthrTfohtnJ7B+68= +github.com/jaswdr/faker/v2 v2.8.1 h1:2AcPgHDBXYQregFUH9LgVZKfFupc4SIquYhp29sf5wQ= +github.com/jaswdr/faker/v2 v2.8.1/go.mod h1:jZq+qzNQr8/P+5fHd9t3txe2GNPnthrTfohtnJ7B+68= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -794,8 +794,8 @@ github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0 github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.63.0 h1:0W0GZvzQe514c3igO063tR0cFVStoABt1agKqlYToL8= go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.63.0/go.mod h1:wIvTiRUU7Pbfqas/5JVjGZcftBeSAGSYVMOHWzWG0qE= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= diff --git a/internal/actionwait/errors.go b/internal/actionwait/errors.go new file mode 100644 index 000000000000..58e440763b88 --- /dev/null +++ b/internal/actionwait/errors.go @@ -0,0 +1,70 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actionwait + +import ( + "errors" + "strings" + "time" +) + +// TimeoutError is returned when the operation does not reach a success state within Timeout. +type TimeoutError struct { + LastStatus Status + Timeout time.Duration +} + +func (e *TimeoutError) Error() string { + return "timeout waiting for target status after " + e.Timeout.String() +} + +// FailureStateError indicates the operation entered a declared failure state. +type FailureStateError struct { + Status Status +} + +func (e *FailureStateError) Error() string { + return "operation entered failure state: " + string(e.Status) +} + +// UnexpectedStateError indicates the operation entered a state outside success/transitional/failure sets. +type UnexpectedStateError struct { + Status Status + Allowed []Status +} + +func (e *UnexpectedStateError) Error() string { + if len(e.Allowed) == 0 { + return "operation entered unexpected state: " + string(e.Status) + } + allowedStr := make([]string, len(e.Allowed)) + for i, s := range e.Allowed { + allowedStr[i] = string(s) + } + return "operation entered unexpected state: " + string(e.Status) + " (allowed: " + + strings.Join(allowedStr, ", ") + ")" +} + +// Error type assertions for compile-time verification +var ( + _ error = (*TimeoutError)(nil) + _ error = (*FailureStateError)(nil) + _ error = (*UnexpectedStateError)(nil) +) + +// Helper functions for error type checking +func IsTimeout(err error) bool { + var timeoutErr *TimeoutError + return errors.As(err, &timeoutErr) +} + +func IsFailureState(err error) bool { + var failureErr *FailureStateError + return errors.As(err, &failureErr) +} + +func IsUnexpectedState(err error) bool { + var unexpectedErr *UnexpectedStateError + return errors.As(err, &unexpectedErr) +} diff --git a/internal/actionwait/errors_test.go b/internal/actionwait/errors_test.go new file mode 100644 index 000000000000..c7379df86521 --- /dev/null +++ b/internal/actionwait/errors_test.go @@ -0,0 +1,283 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actionwait + +import ( + "errors" + "strings" + "testing" + "time" +) + +func TestTimeoutError(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + err *TimeoutError + wantMsg string + wantType string + }{ + { + name: "with last status", + err: &TimeoutError{ + LastStatus: "CREATING", + Timeout: 5 * time.Minute, + }, + wantMsg: "timeout waiting for target status after 5m0s", + wantType: "*actionwait.TimeoutError", + }, + { + name: "with empty status", + err: &TimeoutError{ + LastStatus: "", + Timeout: 30 * time.Second, + }, + wantMsg: "timeout waiting for target status after 30s", + wantType: "*actionwait.TimeoutError", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + if got := tt.err.Error(); got != tt.wantMsg { + t.Errorf("TimeoutError.Error() = %q, want %q", got, tt.wantMsg) + } + + // Verify it implements error interface + var err error = tt.err + if got := err.Error(); got != tt.wantMsg { + t.Errorf("TimeoutError as error.Error() = %q, want %q", got, tt.wantMsg) + } + }) + } +} + +func TestFailureStateError(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + err *FailureStateError + wantMsg string + }{ + { + name: "with status", + err: &FailureStateError{ + Status: "FAILED", + }, + wantMsg: "operation entered failure state: FAILED", + }, + { + name: "with empty status", + err: &FailureStateError{ + Status: "", + }, + wantMsg: "operation entered failure state: ", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + if got := tt.err.Error(); got != tt.wantMsg { + t.Errorf("FailureStateError.Error() = %q, want %q", got, tt.wantMsg) + } + }) + } +} + +func TestUnexpectedStateError(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + err *UnexpectedStateError + wantMsg string + }{ + { + name: "no allowed states", + err: &UnexpectedStateError{ + Status: "UNKNOWN", + Allowed: nil, + }, + wantMsg: "operation entered unexpected state: UNKNOWN", + }, + { + name: "empty allowed states", + err: &UnexpectedStateError{ + Status: "UNKNOWN", + Allowed: []Status{}, + }, + wantMsg: "operation entered unexpected state: UNKNOWN", + }, + { + name: "single allowed state", + err: &UnexpectedStateError{ + Status: "UNKNOWN", + Allowed: []Status{"AVAILABLE"}, + }, + wantMsg: "operation entered unexpected state: UNKNOWN (allowed: AVAILABLE)", + }, + { + name: "multiple allowed states", + err: &UnexpectedStateError{ + Status: "UNKNOWN", + Allowed: []Status{"CREATING", "AVAILABLE", "UPDATING"}, + }, + wantMsg: "operation entered unexpected state: UNKNOWN (allowed: CREATING, AVAILABLE, UPDATING)", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + if got := tt.err.Error(); got != tt.wantMsg { + t.Errorf("UnexpectedStateError.Error() = %q, want %q", got, tt.wantMsg) + } + }) + } +} + +func TestErrorTypeChecking(t *testing.T) { + t.Parallel() + + // Create instances of each error type + timeoutErr := &TimeoutError{LastStatus: "CREATING", Timeout: time.Minute} + failureErr := &FailureStateError{Status: "FAILED"} + unexpectedErr := &UnexpectedStateError{Status: "UNKNOWN", Allowed: []Status{"AVAILABLE"}} + genericErr := errors.New("generic error") + + tests := []struct { + name string + err error + wantIsTimeout bool + wantIsFailure bool + wantIsUnexpected bool + }{ + { + name: "TimeoutError", + err: timeoutErr, + wantIsTimeout: true, + wantIsFailure: false, + wantIsUnexpected: false, + }, + { + name: "FailureStateError", + err: failureErr, + wantIsTimeout: false, + wantIsFailure: true, + wantIsUnexpected: false, + }, + { + name: "UnexpectedStateError", + err: unexpectedErr, + wantIsTimeout: false, + wantIsFailure: false, + wantIsUnexpected: true, + }, + { + name: "generic error", + err: genericErr, + wantIsTimeout: false, + wantIsFailure: false, + wantIsUnexpected: false, + }, + { + name: "nil error", + err: nil, + wantIsTimeout: false, + wantIsFailure: false, + wantIsUnexpected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + if got := IsTimeout(tt.err); got != tt.wantIsTimeout { + t.Errorf("IsTimeout(%v) = %v, want %v", tt.err, got, tt.wantIsTimeout) + } + + if got := IsFailureState(tt.err); got != tt.wantIsFailure { + t.Errorf("IsFailureState(%v) = %v, want %v", tt.err, got, tt.wantIsFailure) + } + + if got := IsUnexpectedState(tt.err); got != tt.wantIsUnexpected { + t.Errorf("IsUnexpectedState(%v) = %v, want %v", tt.err, got, tt.wantIsUnexpected) + } + }) + } +} + +func TestWrappedErrors(t *testing.T) { + t.Parallel() + + // Test that error type checking works with wrapped errors + baseErr := &TimeoutError{LastStatus: "CREATING", Timeout: time.Minute} + wrappedErr := errors.New("wrapped: " + baseErr.Error()) + + // Direct error should be detected + if !IsTimeout(baseErr) { + t.Errorf("IsTimeout should detect direct TimeoutError") + } + + // Wrapped string error should NOT be detected (this is expected behavior) + if IsTimeout(wrappedErr) { + t.Errorf("IsTimeout should not detect string-wrapped error") + } + + // But wrapped with errors.Join should work + joinedErr := errors.Join(baseErr, errors.New("additional context")) + if !IsTimeout(joinedErr) { + t.Errorf("IsTimeout should detect error in errors.Join") + } +} + +func TestErrorMessages(t *testing.T) { + t.Parallel() + + // Verify error messages contain expected components for debugging + timeoutErr := &TimeoutError{ + LastStatus: "PENDING", + Timeout: 2 * time.Minute, + } + + msg := timeoutErr.Error() + if !strings.Contains(msg, "timeout") { + t.Errorf("TimeoutError message should contain 'timeout', got: %q", msg) + } + if !strings.Contains(msg, "2m0s") { + t.Errorf("TimeoutError message should contain timeout duration, got: %q", msg) + } + + failureErr := &FailureStateError{Status: "ERROR"} + msg = failureErr.Error() + if !strings.Contains(msg, "failure state") { + t.Errorf("FailureStateError message should contain 'failure state', got: %q", msg) + } + if !strings.Contains(msg, "ERROR") { + t.Errorf("FailureStateError message should contain status, got: %q", msg) + } + + unexpectedErr := &UnexpectedStateError{ + Status: "WEIRD", + Allowed: []Status{"GOOD", "BETTER"}, + } + msg = unexpectedErr.Error() + if !strings.Contains(msg, "unexpected state") { + t.Errorf("UnexpectedStateError message should contain 'unexpected state', got: %q", msg) + } + if !strings.Contains(msg, "WEIRD") { + t.Errorf("UnexpectedStateError message should contain actual status, got: %q", msg) + } + if !strings.Contains(msg, "GOOD, BETTER") { + t.Errorf("UnexpectedStateError message should contain allowed states, got: %q", msg) + } +} diff --git a/internal/actionwait/wait.go b/internal/actionwait/wait.go new file mode 100644 index 000000000000..1f095f7deef0 --- /dev/null +++ b/internal/actionwait/wait.go @@ -0,0 +1,254 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Package actionwait provides a lightweight, action-focused polling helper +// for imperative Terraform actions which need to await asynchronous AWS +// operation completion with periodic user progress events. +package actionwait + +import ( + "context" + "errors" + "slices" + "time" + + "github.com/hashicorp/terraform-provider-aws/internal/backoff" +) + +// DefaultPollInterval is the default fixed polling interval used when no custom IntervalStrategy is provided. +const DefaultPollInterval = 30 * time.Second + +// Status represents a string status value returned from a polled API. +type Status string + +// FetchResult wraps the latest status (and optional value) from a poll attempt. +// Value may be a richer SDK structure (pointer) or zero for simple cases. +type FetchResult[T any] struct { + Status Status + Value T +} + +// FetchFunc retrieves the latest state of an asynchronous operation. +// It should be side-effect free aside from the remote read. +type FetchFunc[T any] func(context.Context) (FetchResult[T], error) + +// IntervalStrategy allows pluggable poll interval behavior (fixed, backoff, etc.). +type IntervalStrategy interface { //nolint:interfacebloat // single method interface (tiny intentional interface) + NextPoll(attempt uint) time.Duration +} + +// FixedInterval implements IntervalStrategy with a constant delay. +type FixedInterval time.Duration + +// NextPoll returns the fixed duration. +func (fi FixedInterval) NextPoll(uint) time.Duration { return time.Duration(fi) } + +// BackoffInterval implements IntervalStrategy using a backoff.Delay strategy. +// This allows actionwait to leverage sophisticated backoff algorithms while +// maintaining the declarative status-based polling approach. +type BackoffInterval struct { + delay backoff.Delay +} + +// NextPoll returns the next polling interval using the wrapped backoff delay strategy. +func (bi BackoffInterval) NextPoll(attempt uint) time.Duration { + return bi.delay.Next(attempt) +} + +// WithBackoffDelay creates an IntervalStrategy that uses the provided backoff.Delay. +// This bridges actionwait's IntervalStrategy interface with the backoff package's +// delay strategies (fixed, exponential, SDK-compatible, etc.). +// +// Example usage: +// +// opts := actionwait.Options[MyType]{ +// Interval: actionwait.WithBackoffDelay(backoff.FixedDelay(time.Second)), +// // ... other options +// } +func WithBackoffDelay(delay backoff.Delay) IntervalStrategy { + return BackoffInterval{delay: delay} +} + +// Options configure the WaitForStatus loop. +type Options[T any] struct { + Timeout time.Duration // Required total timeout. + Interval IntervalStrategy // Poll interval strategy (default: 30s fixed). + ProgressInterval time.Duration // Throttle for ProgressSink (default: disabled if <=0). + SuccessStates []Status // Required (>=1) terminal success states. + TransitionalStates []Status // Optional allowed in-flight states. + FailureStates []Status // Optional explicit failure states. + ConsecutiveSuccess int // Number of consecutive successes required (default 1). + ProgressSink func(fr FetchResult[any], meta ProgressMeta) +} + +// ProgressMeta supplies metadata for progress callbacks. +type ProgressMeta struct { + Attempt uint + Elapsed time.Duration + Remaining time.Duration + Deadline time.Time + NextPollIn time.Duration +} + +// WaitForStatus polls using fetch until a success state, failure state, timeout, unexpected state, +// context cancellation, or fetch error occurs. +// On success, the final FetchResult is returned with nil error. +func WaitForStatus[T any](ctx context.Context, fetch FetchFunc[T], opts Options[T]) (FetchResult[T], error) { //nolint:cyclop // complexity driven by classification/state machine; readability preferred + if err := validateOptions(opts); err != nil { + var zero FetchResult[T] + return zero, err + } + + normalizeOptions(&opts) + + start := time.Now() + deadline := start.Add(opts.Timeout) + var lastProgress time.Time + var attempt uint + var successStreak int + var last FetchResult[T] + + // Precompute allowed states for unexpected classification (success + transitional + failure) + // Failure states are excluded from Allowed to ensure they classify distinctly. + allowedTransient := append([]Status{}, opts.SuccessStates...) + allowedTransient = append(allowedTransient, opts.TransitionalStates...) + + for { + // Early return: context cancelled + if ctx.Err() != nil { + return last, ctx.Err() + } + + // Early return: timeout exceeded + if time.Now().After(deadline) { + return last, &TimeoutError{LastStatus: last.Status, Timeout: opts.Timeout} + } + + // Fetch current status + fr, err := fetch(ctx) + if err != nil { + return fr, err // Early return: fetch error + } + last = fr + + // Classify status and determine if we should terminate + isTerminal, classifyErr := classifyStatus(fr, opts, &successStreak, allowedTransient) + if isTerminal { + return fr, classifyErr // Early return: terminal state (success or failure) + } + + // Handle progress reporting + handleProgressReport(opts, fr, start, deadline, attempt, &lastProgress) + + // Sleep until next attempt, with context cancellation check + if err := sleepWithContext(ctx, opts.Interval.NextPoll(attempt)); err != nil { + return last, err // Early return: context cancelled during sleep + } + + attempt++ + } +} + +// anyFetchResult converts a typed FetchResult[T] into FetchResult[any] for ProgressSink. +func anyFetchResult[T any](fr FetchResult[T]) FetchResult[any] { + return FetchResult[any]{Status: fr.Status, Value: any(fr.Value)} +} + +func maxDuration(a, b time.Duration) time.Duration { + if a > b { + return a + } + return b +} + +// validateOptions performs early validation of required options. +func validateOptions[T any](opts Options[T]) error { + if opts.Timeout <= 0 { + return errors.New("actionwait: Timeout must be > 0") + } + if len(opts.SuccessStates) == 0 { + return errors.New("actionwait: at least one SuccessState required") + } + if opts.ConsecutiveSuccess < 0 { + return errors.New("actionwait: ConsecutiveSuccess cannot be negative") + } + if opts.ProgressInterval < 0 { + return errors.New("actionwait: ProgressInterval cannot be negative") + } + return nil +} + +// normalizeOptions sets defaults for optional configuration. +func normalizeOptions[T any](opts *Options[T]) { + if opts.ConsecutiveSuccess <= 0 { + opts.ConsecutiveSuccess = 1 + } + if opts.Interval == nil { + opts.Interval = FixedInterval(DefaultPollInterval) + } +} + +// classifyStatus determines the next action based on the current status. +// Returns: (isTerminal, error) - if isTerminal is true, polling should stop. +func classifyStatus[T any](fr FetchResult[T], opts Options[T], successStreak *int, allowedTransient []Status) (bool, error) { + // Classification precedence: failure -> success -> transitional -> unexpected + if slices.Contains(opts.FailureStates, fr.Status) { + return true, &FailureStateError{Status: fr.Status} + } + + if slices.Contains(opts.SuccessStates, fr.Status) { + *successStreak++ + if *successStreak >= opts.ConsecutiveSuccess { + return true, nil // Success! + } + return false, nil // Continue polling for consecutive successes + } + + // Not a success state, reset streak + *successStreak = 0 + + // Check if transitional state is allowed + // If TransitionalStates is specified, status must be in that list + // If TransitionalStates is empty, any non-success/non-failure state is allowed + if len(opts.TransitionalStates) > 0 && !slices.Contains(opts.TransitionalStates, fr.Status) { + return true, &UnexpectedStateError{Status: fr.Status, Allowed: allowedTransient} + } + + return false, nil // Continue polling +} + +// handleProgressReport sends progress updates if conditions are met. +func handleProgressReport[T any](opts Options[T], fr FetchResult[T], start time.Time, deadline time.Time, attempt uint, lastProgress *time.Time) { + if opts.ProgressSink == nil || opts.ProgressInterval <= 0 { + return + } + + if lastProgress.IsZero() || time.Since(*lastProgress) >= opts.ProgressInterval { + nextPoll := opts.Interval.NextPoll(attempt) + opts.ProgressSink(anyFetchResult(fr), ProgressMeta{ + Attempt: attempt, + Elapsed: time.Since(start), + Remaining: maxDuration(0, time.Until(deadline)), + Deadline: deadline, + NextPollIn: nextPoll, + }) + *lastProgress = time.Now() + } +} + +// sleepWithContext sleeps for the specified duration while respecting context cancellation. +func sleepWithContext(ctx context.Context, duration time.Duration) error { + if duration <= 0 { + return nil + } + + timer := time.NewTimer(duration) + defer timer.Stop() + + select { + case <-ctx.Done(): + return ctx.Err() + case <-timer.C: + return nil + } +} diff --git a/internal/actionwait/wait_test.go b/internal/actionwait/wait_test.go new file mode 100644 index 000000000000..22096adb77f3 --- /dev/null +++ b/internal/actionwait/wait_test.go @@ -0,0 +1,423 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actionwait + +import ( + "context" + "errors" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/hashicorp/terraform-provider-aws/internal/backoff" +) + +// fastFixedInterval returns a very small fixed interval to speed tests. +const fastFixedInterval = 5 * time.Millisecond + +// makeCtx creates a context with generous overall test timeout safeguard. +func makeCtx(t *testing.T) context.Context { // test helper + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + t.Cleanup(cancel) + return ctx +} + +func TestWaitForStatus_ValidationErrors(t *testing.T) { + t.Parallel() + // Subtests parallelized; each uses its own context with timeout. + cases := map[string]Options[struct{}]{ + "missing timeout": {SuccessStates: []Status{"ok"}}, + "missing success": {Timeout: time.Second}, + "negative consecutive": {Timeout: time.Second, SuccessStates: []Status{"ok"}, ConsecutiveSuccess: -1}, + "negative progress interval": {Timeout: time.Second, SuccessStates: []Status{"ok"}, ProgressInterval: -time.Second}, + } + + for name, opts := range cases { + t.Run(name, func(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + _, err := WaitForStatus(ctx, func(context.Context) (FetchResult[struct{}], error) { + return FetchResult[struct{}]{Status: "irrelevant"}, nil + }, opts) + if err == nil { + t.Fatalf("expected validation error") + } + }) + } +} + +func TestWaitForStatus_SuccessImmediate(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + fr, err := WaitForStatus(ctx, func(context.Context) (FetchResult[int], error) { + return FetchResult[int]{Status: "DONE", Value: 42}, nil + }, Options[int]{ + Timeout: 250 * time.Millisecond, + SuccessStates: []Status{"DONE"}, + Interval: FixedInterval(fastFixedInterval), + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if fr.Value != 42 || fr.Status != "DONE" { + t.Fatalf("unexpected result: %#v", fr) + } +} + +func TestWaitForStatus_SuccessAfterTransitions(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + var calls int32 + fr, err := WaitForStatus(ctx, func(context.Context) (FetchResult[string], error) { + c := atomic.AddInt32(&calls, 1) + switch c { + case 1, 2: + return FetchResult[string]{Status: "IN_PROGRESS", Value: "step"}, nil + default: + return FetchResult[string]{Status: "COMPLETE", Value: "done"}, nil + } + }, Options[string]{ + Timeout: 500 * time.Millisecond, + SuccessStates: []Status{"COMPLETE"}, + TransitionalStates: []Status{"IN_PROGRESS"}, + Interval: FixedInterval(fastFixedInterval), + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if fr.Status != "COMPLETE" || fr.Value != "done" { + t.Fatalf("unexpected final result: %#v", fr) + } +} + +func TestWaitForStatus_FailureState(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + fr, err := WaitForStatus(ctx, func(context.Context) (FetchResult[struct{}], error) { + return FetchResult[struct{}]{Status: "FAILED"}, nil + }, Options[struct{}]{ + Timeout: 200 * time.Millisecond, + SuccessStates: []Status{"SUCCEEDED"}, + FailureStates: []Status{"FAILED"}, + Interval: FixedInterval(fastFixedInterval), + }) + if err == nil { + t.Fatal("expected failure error") + } + if _, ok := err.(*FailureStateError); !ok { //nolint:errorlint // direct type assertion adequate in tests + t.Fatalf("expected FailureStateError, got %T", err) + } + if fr.Status != "FAILED" { + t.Fatalf("unexpected status: %v", fr.Status) + } +} + +func TestWaitForStatus_UnexpectedState_WithTransitional(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + _, err := WaitForStatus(ctx, func(context.Context) (FetchResult[int], error) { + return FetchResult[int]{Status: "UNKNOWN"}, nil + }, Options[int]{ + Timeout: 200 * time.Millisecond, + SuccessStates: []Status{"OK"}, + TransitionalStates: []Status{"PENDING"}, + Interval: FixedInterval(fastFixedInterval), + }) + if err == nil { + t.Fatal("expected unexpected state error") + } + if _, ok := err.(*UnexpectedStateError); !ok { //nolint:errorlint // direct type assertion adequate in tests + t.Fatalf("expected UnexpectedStateError, got %T", err) + } +} + +func TestWaitForStatus_NoTransitionalListAllowsAnyUntilTimeout(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + start := time.Now() + _, err := WaitForStatus(ctx, func(context.Context) (FetchResult[struct{}], error) { + return FetchResult[struct{}]{Status: "WHATEVER"}, nil + }, Options[struct{}]{ + Timeout: 50 * time.Millisecond, + SuccessStates: []Status{"DONE"}, + Interval: FixedInterval(10 * time.Millisecond), + }) + if err == nil { + t.Fatal("expected timeout error") + } + if _, ok := err.(*TimeoutError); !ok { //nolint:errorlint // direct type assertion adequate in tests + t.Fatalf("expected TimeoutError, got %T", err) + } + if time.Since(start) < 40*time.Millisecond { // sanity that we actually waited + t.Fatalf("timeout returned too early") + } +} + +func TestWaitForStatus_ContextCancel(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(makeCtx(t)) + go func() { + time.Sleep(20 * time.Millisecond) + cancel() + }() + _, err := WaitForStatus(ctx, func(context.Context) (FetchResult[struct{}], error) { + return FetchResult[struct{}]{Status: "PENDING"}, nil + }, Options[struct{}]{ + Timeout: 500 * time.Millisecond, + SuccessStates: []Status{"DONE"}, + Interval: FixedInterval(fastFixedInterval), + }) + if !errors.Is(err, context.Canceled) { + t.Fatalf("expected context.Canceled, got %v", err) + } +} + +func TestWaitForStatus_FetchErrorPropagation(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + testErr := errors.New("boom") + _, err := WaitForStatus(ctx, func(context.Context) (FetchResult[int], error) { + return FetchResult[int]{}, testErr + }, Options[int]{ + Timeout: 200 * time.Millisecond, + SuccessStates: []Status{"OK"}, + Interval: FixedInterval(fastFixedInterval), + }) + if !errors.Is(err, testErr) { + t.Fatalf("expected fetch error, got %v", err) + } +} + +func TestWaitForStatus_ConsecutiveSuccess(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + var toggle int32 + // alternate success / transitional until two consecutive successes happen + fr, err := WaitForStatus(ctx, func(context.Context) (FetchResult[string], error) { + n := atomic.AddInt32(&toggle, 1) + // Pattern: BUILDING, READY, READY, READY ... ensures at least two consecutive successes by third attempt + if n == 1 { + return FetchResult[string]{Status: "BUILDING", Value: "val"}, nil + } + return FetchResult[string]{Status: "READY", Value: "val"}, nil + }, Options[string]{ + Timeout: 750 * time.Millisecond, + SuccessStates: []Status{"READY"}, + TransitionalStates: []Status{"BUILDING"}, + ConsecutiveSuccess: 2, + Interval: FixedInterval(2 * time.Millisecond), + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if fr.Status != "READY" { + t.Fatalf("expected READY, got %v", fr.Status) + } + if atomic.LoadInt32(&toggle) < 3 { // at least three fetches required (BUILDING, READY, READY) + t.Fatalf("expected multiple attempts, got %d", toggle) + } +} + +func TestWaitForStatus_ProgressSinkThrottling(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + var progressCalls int32 + var fetchCalls int32 + _, _ = WaitForStatus(ctx, func(context.Context) (FetchResult[int], error) { + atomic.AddInt32(&fetchCalls, 1) + if fetchCalls >= 5 { + return FetchResult[int]{Status: "DONE"}, nil + } + return FetchResult[int]{Status: "WORKING"}, nil + }, Options[int]{ + Timeout: 500 * time.Millisecond, + SuccessStates: []Status{"DONE"}, + TransitionalStates: []Status{"WORKING"}, + Interval: FixedInterval(5 * time.Millisecond), + ProgressInterval: 15 * time.Millisecond, // should group roughly 3 polls + ProgressSink: func(fr FetchResult[any], meta ProgressMeta) { + atomic.AddInt32(&progressCalls, 1) + if fr.Status != "WORKING" && fr.Status != "DONE" { + t.Fatalf("unexpected status in progress sink: %v", fr.Status) + } + if meta.NextPollIn <= 0 { + t.Fatalf("expected positive NextPollIn") + } + }, + }) + // With 5 fetch calls and 15ms progress vs 5ms poll, expect fewer progress events than fetches + if progressCalls <= 1 || progressCalls >= fetchCalls { + t.Fatalf("unexpected progress call count: %d (fetches %d)", progressCalls, fetchCalls) + } +} + +func TestWaitForStatus_ConsecutiveSuccessDefault(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + fr, err := WaitForStatus(ctx, func(context.Context) (FetchResult[struct{}], error) { + return FetchResult[struct{}]{Status: "READY"}, nil + }, Options[struct{}]{ + Timeout: 100 * time.Millisecond, + SuccessStates: []Status{"READY"}, + Interval: FixedInterval(fastFixedInterval), + // ConsecutiveSuccess left zero to trigger defaulting logic + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if fr.Status != "READY" { + t.Fatalf("unexpected status: %v", fr.Status) + } +} + +func TestWaitForStatus_ProgressSinkDisabled(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + var progressCalls int32 + _, err := WaitForStatus(ctx, func(context.Context) (FetchResult[int], error) { + return FetchResult[int]{Status: "DONE"}, nil + }, Options[int]{ + Timeout: 100 * time.Millisecond, + SuccessStates: []Status{"DONE"}, + Interval: FixedInterval(fastFixedInterval), + ProgressInterval: 0, // disabled + ProgressSink: func(FetchResult[any], ProgressMeta) { + atomic.AddInt32(&progressCalls, 1) + }, + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if progressCalls != 0 { // should not be invoked when ProgressInterval <= 0 + t.Fatalf("expected zero progress sink calls, got %d", progressCalls) + } +} + +func TestWaitForStatus_UnexpectedStateErrorMessage(t *testing.T) { + t.Parallel() + ctx := makeCtx(t) + _, err := WaitForStatus(ctx, func(context.Context) (FetchResult[int], error) { + return FetchResult[int]{Status: "UNKNOWN"}, nil + }, Options[int]{ + Timeout: 200 * time.Millisecond, + SuccessStates: []Status{"OK"}, + TransitionalStates: []Status{"PENDING", "IN_PROGRESS"}, + Interval: FixedInterval(fastFixedInterval), + }) + if err == nil { + t.Fatal("expected unexpected state error") + } + var unexpectedErr *UnexpectedStateError + if !errors.As(err, &unexpectedErr) { + t.Fatalf("expected UnexpectedStateError, got %T", err) + } + errMsg := unexpectedErr.Error() + if !strings.Contains(errMsg, "UNKNOWN") { + t.Errorf("error message should contain status 'UNKNOWN', got: %s", errMsg) + } + if !strings.Contains(errMsg, "allowed:") { + t.Errorf("error message should list allowed states, got: %s", errMsg) + } + if !strings.Contains(errMsg, "PENDING") { + t.Errorf("error message should contain allowed state 'PENDING', got: %s", errMsg) + } +} + +func TestBackoffInterval(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + delay backoff.Delay + attempts []uint + expectedDurations []time.Duration + }{ + { + name: "fixed delay", + delay: backoff.FixedDelay(100 * time.Millisecond), + attempts: []uint{0, 1, 2, 3}, + expectedDurations: []time.Duration{0, 100 * time.Millisecond, 100 * time.Millisecond, 100 * time.Millisecond}, + }, + { + name: "zero delay", + delay: backoff.ZeroDelay, + attempts: []uint{0, 1, 2}, + expectedDurations: []time.Duration{0, 0, 0}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + interval := BackoffInterval{delay: tt.delay} + + for i, attempt := range tt.attempts { + got := interval.NextPoll(attempt) + want := tt.expectedDurations[i] + if got != want { + t.Errorf("NextPoll(%d) = %v, want %v", attempt, got, want) + } + } + }) + } +} + +func TestWithBackoffDelay(t *testing.T) { + t.Parallel() + + delay := backoff.FixedDelay(50 * time.Millisecond) + interval := WithBackoffDelay(delay) + + // Test that it wraps the delay correctly + if got := interval.NextPoll(0); got != 0 { + t.Errorf("NextPoll(0) = %v, want 0", got) + } + if got := interval.NextPoll(1); got != 50*time.Millisecond { + t.Errorf("NextPoll(1) = %v, want 50ms", got) + } +} + +func TestBackoffIntegration(t *testing.T) { + t.Parallel() + + ctx := makeCtx(t) + + var callCount atomic.Int32 + fetch := func(context.Context) (FetchResult[string], error) { + count := callCount.Add(1) + switch count { + case 1: + return FetchResult[string]{Status: "CREATING", Value: "attempt1"}, nil + case 2: + return FetchResult[string]{Status: "AVAILABLE", Value: "success"}, nil + default: + t.Errorf("unexpected call count: %d", count) + return FetchResult[string]{}, errors.New("too many calls") + } + } + + opts := Options[string]{ + Timeout: 2 * time.Second, + Interval: WithBackoffDelay(backoff.FixedDelay(fastFixedInterval)), + SuccessStates: []Status{"AVAILABLE"}, + TransitionalStates: []Status{"CREATING"}, + } + + result, err := WaitForStatus(ctx, fetch, opts) + if err != nil { + t.Fatalf("WaitForStatus() error = %v", err) + } + + if result.Status != "AVAILABLE" { + t.Errorf("result.Status = %q, want %q", result.Status, "AVAILABLE") + } + if result.Value != "success" { + t.Errorf("result.Value = %q, want %q", result.Value, "success") + } + if callCount.Load() != 2 { + t.Errorf("expected 2 fetch calls, got %d", callCount.Load()) + } +} diff --git a/internal/framework/flex/auto_expand.go b/internal/framework/flex/auto_expand.go index 33ce1725d7fb..59694e20e9ec 100644 --- a/internal/framework/flex/auto_expand.go +++ b/internal/framework/flex/auto_expand.go @@ -1165,7 +1165,7 @@ func expandStruct(ctx context.Context, sourcePath path.Path, from any, targetPat fromFieldName := fromField.Name _, fromFieldOpts := autoflexTags(fromField) - toField, ok := findFieldFuzzy(ctx, fromFieldName, typeFrom, typeTo, flexer) + toField, ok := (&fuzzyFieldFinder{}).findField(ctx, fromFieldName, typeFrom, typeTo, flexer) if !ok { // Corresponding field not found in to. tflog.SubsystemDebug(ctx, subsystemName, "No corresponding field", map[string]any{ diff --git a/internal/framework/flex/auto_expand_test.go b/internal/framework/flex/auto_expand_test.go index f50b4593d5b5..20673aa7d92c 100644 --- a/internal/framework/flex/auto_expand_test.go +++ b/internal/framework/flex/auto_expand_test.go @@ -5958,3 +5958,88 @@ func runAutoExpandTestCases(t *testing.T, testCases autoFlexTestCases) { }) } } + +func TestFindFieldFuzzy_Combinations(t *testing.T) { + t.Parallel() + + type builder func() (typeFrom reflect.Type, typeTo reflect.Type, fieldNameFrom string, expectedFieldName string) + + cases := map[string]struct { + prefix string + suffix string + build builder + }{ + // 1) suffix-only on target; source has neither + "suffix on target only (prefix configured but not applied)": { + prefix: "Cluster", + suffix: "Input", + build: func() (reflect.Type, reflect.Type, string, string) { + type source struct{ ExecutionConfig string } + type target struct{ ExecutionConfigInput string } + return reflect.TypeFor[source](), reflect.TypeFor[target](), "ExecutionConfig", "ExecutionConfigInput" + }, + }, + // 2) trim prefix on source, then add suffix + "trim prefix on source then add suffix": { + prefix: "Cluster", + suffix: "Input", + build: func() (reflect.Type, reflect.Type, string, string) { + type source struct{ ClusterExecutionConfig string } + type target struct{ ExecutionConfigInput string } + return reflect.TypeFor[source](), reflect.TypeFor[target](), "ClusterExecutionConfig", "ExecutionConfigInput" + }, + }, + // 3) add prefix and suffix on target (source has neither) + "add prefix and suffix on target": { + prefix: "Cluster", + suffix: "Input", + build: func() (reflect.Type, reflect.Type, string, string) { + type source struct{ ExecutionConfig string } + type target struct{ ClusterExecutionConfigInput string } + return reflect.TypeFor[source](), reflect.TypeFor[target](), "ExecutionConfig", "ClusterExecutionConfigInput" + }, + }, + // 4) trim suffix on source (target has neither) + "trim suffix on source": { + prefix: "Cluster", + suffix: "Input", + build: func() (reflect.Type, reflect.Type, string, string) { + type source struct{ ExecutionConfigInput string } + type target struct{ ExecutionConfig string } + return reflect.TypeFor[source](), reflect.TypeFor[target](), "ExecutionConfigInput", "ExecutionConfig" + }, + }, + // 5) trim both on source (target has neither) + "trim both prefix and suffix on source": { + prefix: "Cluster", + suffix: "Input", + build: func() (reflect.Type, reflect.Type, string, string) { + type source struct{ ClusterExecutionConfigInput string } + type target struct{ ExecutionConfig string } + return reflect.TypeFor[source](), reflect.TypeFor[target](), "ClusterExecutionConfigInput", "ExecutionConfig" + }, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + typeFrom, typeTo, fieldNameFrom, expected := tc.build() + ctx := context.Background() + opts := []AutoFlexOptionsFunc{ + WithFieldNamePrefix(tc.prefix), + WithFieldNameSuffix(tc.suffix), + } + flexer := newAutoExpander(opts) + + field, found := (&fuzzyFieldFinder{}).findField(ctx, fieldNameFrom, typeFrom, typeTo, flexer) + if !found { + t.Fatalf("expected to find field, but found==false") + } + if field.Name != expected { + t.Fatalf("expected field name %q, got %q", expected, field.Name) + } + }) + } +} diff --git a/internal/framework/flex/auto_flatten.go b/internal/framework/flex/auto_flatten.go index 8aca49b42210..a74b3ba93772 100644 --- a/internal/framework/flex/auto_flatten.go +++ b/internal/framework/flex/auto_flatten.go @@ -1512,7 +1512,7 @@ func flattenStruct(ctx context.Context, sourcePath path.Path, from any, targetPa for fromField := range flattenSourceFields(ctx, typeFrom, flexer.getOptions()) { fromFieldName := fromField.Name - toField, ok := findFieldFuzzy(ctx, fromFieldName, typeFrom, typeTo, flexer) + toField, ok := (&fuzzyFieldFinder{}).findField(ctx, fromFieldName, typeFrom, typeTo, flexer) if !ok { // Corresponding field not found in to. tflog.SubsystemDebug(ctx, subsystemName, "No corresponding field", map[string]any{ diff --git a/internal/framework/flex/autoflex.go b/internal/framework/flex/autoflex.go index aa941f275265..dce7baf563c5 100644 --- a/internal/framework/flex/autoflex.go +++ b/internal/framework/flex/autoflex.go @@ -17,12 +17,7 @@ import ( tfreflect "github.com/hashicorp/terraform-provider-aws/internal/reflect" ) -type fieldNamePrefixCtxKey string - const ( - fieldNamePrefixRecurse fieldNamePrefixCtxKey = "FIELD_NAME_PREFIX_RECURSE" - fieldNameSuffixRecurse fieldNamePrefixCtxKey = "FIELD_NAME_SUFFIX_RECURSE" - mapBlockKeyFieldName = "MapBlockKey" ) @@ -74,7 +69,12 @@ var ( plural = pluralize.NewClient() ) -func findFieldFuzzy(ctx context.Context, fieldNameFrom string, typeFrom reflect.Type, typeTo reflect.Type, flexer autoFlexer) (reflect.StructField, bool) { +type fuzzyFieldFinder struct { + prefixRecursionDepth int + suffixRecursionDepth int +} + +func (fff *fuzzyFieldFinder) findField(ctx context.Context, fieldNameFrom string, typeFrom reflect.Type, typeTo reflect.Type, flexer autoFlexer) (reflect.StructField, bool) { //nolint:unparam // first precedence is exact match (case sensitive) if fieldTo, ok := typeTo.FieldByName(fieldNameFrom); ok { return fieldTo, true @@ -117,26 +117,38 @@ func findFieldFuzzy(ctx context.Context, fieldNameFrom string, typeFrom reflect. // fourth precedence is using field name prefix if v := opts.fieldNamePrefix; v != "" { v = strings.ReplaceAll(v, " ", "") - if ctx.Value(fieldNamePrefixRecurse) == nil { + if fff.prefixRecursionDepth == 0 { // so it will only recurse once - ctx = context.WithValue(ctx, fieldNamePrefixRecurse, true) + fff.prefixRecursionDepth++ if trimmed, ok := strings.CutPrefix(fieldNameFrom, v); ok { - return findFieldFuzzy(ctx, trimmed, typeFrom, typeTo, flexer) + if fieldTo, ok := fff.findField(ctx, trimmed, typeFrom, typeTo, flexer); ok { + fff.prefixRecursionDepth-- + return fieldTo, true + } + } else { + if fieldTo, ok := fff.findField(ctx, v+fieldNameFrom, typeFrom, typeTo, flexer); ok { + fff.prefixRecursionDepth-- + return fieldTo, true + } } - return findFieldFuzzy(ctx, v+fieldNameFrom, typeFrom, typeTo, flexer) + // no match via prefix mutation; fall through to suffix handling on the original name } } // fifth precedence is using field name suffix if v := opts.fieldNameSuffix; v != "" { v = strings.ReplaceAll(v, " ", "") - if ctx.Value(fieldNameSuffixRecurse) == nil { + if fff.suffixRecursionDepth == 0 { // so it will only recurse once - ctx = context.WithValue(ctx, fieldNameSuffixRecurse, true) + fff.suffixRecursionDepth++ if strings.HasSuffix(fieldNameFrom, v) { - return findFieldFuzzy(ctx, strings.TrimSuffix(fieldNameFrom, v), typeFrom, typeTo, flexer) + fieldTo, ok := fff.findField(ctx, strings.TrimSuffix(fieldNameFrom, v), typeFrom, typeTo, flexer) + fff.suffixRecursionDepth-- + return fieldTo, ok } - return findFieldFuzzy(ctx, fieldNameFrom+v, typeFrom, typeTo, flexer) + fieldTo, ok := fff.findField(ctx, fieldNameFrom+v, typeFrom, typeTo, flexer) + fff.suffixRecursionDepth-- + return fieldTo, ok } } diff --git a/internal/framework/planmodifiers/int32planmodifier/null_value.go b/internal/framework/planmodifiers/int32planmodifier/null_value.go deleted file mode 100644 index cbb7f1800dbd..000000000000 --- a/internal/framework/planmodifiers/int32planmodifier/null_value.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package int32planmodifier - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/types" -) - -// LegacyValue returns a plan modifier that prevents `known after apply` during creation plans for -// attributes that must be `Computed,Optional` for legacy value reasons. -func NullValue() planmodifier.Int32 { - return nullValueModifier{} -} - -type nullValueModifier struct{} - -func (m nullValueModifier) Description(_ context.Context) string { - return "" -} - -func (m nullValueModifier) MarkdownDescription(ctx context.Context) string { - return m.Description(ctx) -} - -func (m nullValueModifier) PlanModifyInt32(ctx context.Context, req planmodifier.Int32Request, resp *planmodifier.Int32Response) { - // Use value from Config if set - if !req.ConfigValue.IsNull() { - return - } - - // Exit if another planmodifier has set the value - if !req.PlanValue.IsUnknown() { - return - } - - // Do nothing if there is an unknown configuration value, otherwise interpolation gets messed up. - if req.ConfigValue.IsUnknown() { - return - } - - if req.StateValue.IsNull() { - resp.PlanValue = types.Int32Null() - return - } -} diff --git a/internal/framework/planmodifiers/stringplanmodifier/requires_replace_wo.go b/internal/framework/planmodifiers/stringplanmodifier/requires_replace_wo.go new file mode 100644 index 000000000000..2e39af574ae8 --- /dev/null +++ b/internal/framework/planmodifiers/stringplanmodifier/requires_replace_wo.go @@ -0,0 +1,65 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package stringplanmodifier + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-provider-aws/internal/framework/privatestate" +) + +// RequiresReplaceWO returns a plan modifier that forces resource replacement +// if a write-only value changes. +func RequiresReplaceWO(privateStateKey string) planmodifier.String { + return requiresReplaceWO{ + privateStateKey: privateStateKey, + } +} + +type requiresReplaceWO struct { + privateStateKey string +} + +func (m requiresReplaceWO) Description(ctx context.Context) string { + return m.MarkdownDescription(ctx) +} + +func (m requiresReplaceWO) MarkdownDescription(context.Context) string { + return "If the value of this write-only attribute changes, Terraform will destroy and recreate the resource." +} + +func (m requiresReplaceWO) PlanModifyString(ctx context.Context, request planmodifier.StringRequest, response *planmodifier.StringResponse) { + newValue := request.ConfigValue + newValueExists := !newValue.IsNull() + + woStore := privatestate.NewWriteOnlyValueStore(request.Private, m.privateStateKey) + oldValueExists, diags := woStore.HasValue(ctx) + response.Diagnostics.Append(diags...) + if response.Diagnostics.HasError() { + return + } + + if !newValueExists { + if oldValueExists { + response.RequiresReplace = true + } + return + } + + if !oldValueExists { + response.RequiresReplace = true + return + } + + equal, diags := woStore.EqualValue(ctx, newValue) + response.Diagnostics.Append(diags...) + if response.Diagnostics.HasError() { + return + } + + if !equal { + response.RequiresReplace = true + } +} diff --git a/internal/framework/privatestate/private_state.go b/internal/framework/privatestate/private_state.go new file mode 100644 index 000000000000..584c9509680f --- /dev/null +++ b/internal/framework/privatestate/private_state.go @@ -0,0 +1,18 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package privatestate + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/diag" +) + +// PrivateState defines an interface for managing provider-defined resource private state data. +type PrivateState interface { + // GetKey returns the private state data associated with the given key. + GetKey(context.Context, string) ([]byte, diag.Diagnostics) + // SetKey sets the private state data at the given key. + SetKey(context.Context, string, []byte) diag.Diagnostics +} diff --git a/internal/framework/privatestate/write_only.go b/internal/framework/privatestate/write_only.go new file mode 100644 index 000000000000..9b7503f5611f --- /dev/null +++ b/internal/framework/privatestate/write_only.go @@ -0,0 +1,61 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package privatestate + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "strconv" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + tfjson "github.com/hashicorp/terraform-provider-aws/internal/json" +) + +func NewWriteOnlyValueStore(private PrivateState, key string) *WriteOnlyValueStore { + return &WriteOnlyValueStore{ + key: key, + private: private, + } +} + +type WriteOnlyValueStore struct { + key string + private PrivateState +} + +func (w *WriteOnlyValueStore) EqualValue(ctx context.Context, value types.String) (bool, diag.Diagnostics) { + bytes, diags := w.private.GetKey(ctx, w.key) + if diags.HasError() { + return false, diags + } + + var s string + if err := tfjson.DecodeFromBytes(bytes, &s); err != nil { + diags.AddError("decoding private state", err.Error()) + return false, diags + } + + return s == sha256Hash(value.ValueString()), diags +} + +func (w *WriteOnlyValueStore) HasValue(ctx context.Context) (bool, diag.Diagnostics) { + bytes, diags := w.private.GetKey(ctx, w.key) + return len(bytes) > 0, diags +} + +func (w *WriteOnlyValueStore) SetValue(ctx context.Context, val types.String) diag.Diagnostics { + if val.IsNull() { + return w.private.SetKey(ctx, w.key, []byte("")) + } + + return w.private.SetKey(ctx, w.key, []byte(strconv.Quote(sha256Hash(val.ValueString())))) +} + +func sha256Hash(data string) string { + hash := sha256.New() + hash.Write([]byte(data)) + return hex.EncodeToString(hash.Sum(nil)) +} diff --git a/internal/framework/privatestate/write_only_test.go b/internal/framework/privatestate/write_only_test.go new file mode 100644 index 000000000000..ea44d17b8672 --- /dev/null +++ b/internal/framework/privatestate/write_only_test.go @@ -0,0 +1,112 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package privatestate_test + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/framework/privatestate" +) + +func TestWriteOnlyValueStore_HasValue(t *testing.T) { + t.Parallel() + + ctx := t.Context() + store1 := privatestate.NewWriteOnlyValueStore(&privateState{}, "key") + store2 := privatestate.NewWriteOnlyValueStore(&privateState{}, "key") + store2.SetValue(ctx, types.StringValue("value1")) + + testCases := []struct { + testName string + store *privatestate.WriteOnlyValueStore + wantValue bool + }{ + { + testName: "empty state", + store: store1, + }, + { + testName: "has value", + store: store2, + wantValue: true, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.testName, func(t *testing.T) { + t.Parallel() + gotValue, diags := testCase.store.HasValue(ctx) + if diags.HasError() { + t.Fatal("unexpected error") + } + if got, want := gotValue, testCase.wantValue; !cmp.Equal(got, want) { + t.Errorf("got %t, want %t", got, want) + } + }) + } +} + +func TestWriteOnlyValueStore_EqualValue(t *testing.T) { + t.Parallel() + + ctx := t.Context() + store1 := privatestate.NewWriteOnlyValueStore(&privateState{}, "key") + store1.SetValue(ctx, types.StringValue("value1")) + store2 := privatestate.NewWriteOnlyValueStore(&privateState{}, "key") + store2.SetValue(ctx, types.StringValue("value2")) + + testCases := []struct { + testName string + store *privatestate.WriteOnlyValueStore + wantEqual bool + }{ + { + testName: "equal", + store: store1, + wantEqual: true, + }, + { + testName: "not equal", + store: store2, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.testName, func(t *testing.T) { + t.Parallel() + gotEqual, diags := testCase.store.EqualValue(ctx, types.StringValue("value1")) + if diags.HasError() { + t.Fatal("unexpected error") + } + if got, want := gotEqual, testCase.wantEqual; !cmp.Equal(got, want) { + t.Errorf("got %t, want %t", got, want) + } + }) + } +} + +type privateState struct { + data map[string][]byte +} + +func (p *privateState) GetKey(_ context.Context, key string) ([]byte, diag.Diagnostics) { + var diags diag.Diagnostics + bytes := p.data[key] + return bytes, diags +} + +func (p *privateState) SetKey(_ context.Context, key string, value []byte) diag.Diagnostics { + var diags diag.Diagnostics + + if p.data == nil { + p.data = make(map[string][]byte) + } + + p.data[key] = value + return diags +} diff --git a/internal/generate/identitytests/resource_test.go.gtpl b/internal/generate/identitytests/resource_test.go.gtpl index 64c8bfd296c4..61ce4279329e 100644 --- a/internal/generate/identitytests/resource_test.go.gtpl +++ b/internal/generate/identitytests/resource_test.go.gtpl @@ -227,8 +227,9 @@ func {{ template "testname" . }}_IdentitySerial(t *testing.T) { {{- end }} testCases := map[string]func(t *testing.T){ - acctest.CtBasic: {{ template "testname" . }}_Identity_Basic, - "ExistingResource": {{ template "testname" . }}_Identity_ExistingResource, + acctest.CtBasic: {{ template "testname" . }}_Identity_Basic, + "ExistingResource": {{ template "testname" . }}_Identity_ExistingResource, + "ExistingResourceNoRefresh": {{ template "testname" . }}_Identity_ExistingResource_NoRefresh_NoChange, {{ if .GenerateRegionOverrideTest -}} "RegionOverride": {{ template "testname" . }}_Identity_RegionOverride, {{ end -}} diff --git a/internal/provider/framework/wrap.go b/internal/provider/framework/wrap.go index d5f56a5adb93..ad7554ed08c7 100644 --- a/internal/provider/framework/wrap.go +++ b/internal/provider/framework/wrap.go @@ -550,13 +550,20 @@ func newWrappedResource(spec *inttypes.ServicePackageFrameworkResource, serviceP inner, _ := spec.Factory(context.TODO()) - if len(spec.Identity.Attributes) > 0 { - interceptors = append(interceptors, newIdentityInterceptor(spec.Identity.Attributes)) - if v, ok := inner.(framework.Identityer); ok { - v.SetIdentitySpec(spec.Identity) + if len(spec.Identity.Attributes) == 0 { + return &wrappedResource{ + inner: inner, + servicePackageName: servicePackageName, + spec: spec, + interceptors: interceptors, } } + interceptors = append(interceptors, newIdentityInterceptor(spec.Identity.Attributes)) + if v, ok := inner.(framework.Identityer); ok { + v.SetIdentitySpec(spec.Identity) + } + if spec.Import.WrappedImport { if v, ok := inner.(framework.ImportByIdentityer); ok { v.SetImportSpec(spec.Import) @@ -564,11 +571,14 @@ func newWrappedResource(spec *inttypes.ServicePackageFrameworkResource, serviceP // If the resource does not implement framework.ImportByIdentityer, // it will be caught by `validateResourceSchemas`, so we can ignore it here. } - return &wrappedResource{ - inner: inner, - servicePackageName: servicePackageName, - spec: spec, - interceptors: interceptors, + + return &wrappedResourceWithIdentity{ + wrappedResource: wrappedResource{ + inner: inner, + servicePackageName: servicePackageName, + spec: spec, + interceptors: interceptors, + }, } } @@ -788,7 +798,11 @@ func (w *wrappedResource) MoveState(ctx context.Context) []resource.StateMover { return nil } -func (w *wrappedResource) IdentitySchema(ctx context.Context, req resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) { +type wrappedResourceWithIdentity struct { + wrappedResource +} + +func (w *wrappedResourceWithIdentity) IdentitySchema(ctx context.Context, req resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) { if len(w.spec.Identity.Attributes) > 0 { resp.IdentitySchema = identity.NewIdentitySchema(w.spec.Identity) } diff --git a/internal/sdkv2/state.go b/internal/sdkv2/state.go index 1d74322091e9..0a826cb735dd 100644 --- a/internal/sdkv2/state.go +++ b/internal/sdkv2/state.go @@ -24,3 +24,8 @@ func ToLowerSchemaStateFunc(v any) string { func ToUpperSchemaStateFunc(v any) string { return strings.ToUpper(v.(string)) } + +// TrimSpaceSchemaStateFunc removes all leading and trailing white space from a string value before storing it in state. +func TrimSpaceSchemaStateFunc(v any) string { + return strings.TrimSpace(v.(string)) +} diff --git a/internal/sdkv2/state_test.go b/internal/sdkv2/state_test.go index 844355e685da..ffc9e5b66369 100644 --- a/internal/sdkv2/state_test.go +++ b/internal/sdkv2/state_test.go @@ -47,3 +47,16 @@ func TestToUpperSchemaStateFunc(t *testing.T) { t.Errorf("unexpected diff (+want, -got): %s", diff) } } + +func TestTrimSpaceSchemaStateFunc(t *testing.T) { + t.Parallel() + + var input any = " in-state " + want := "in-state" + + got := TrimSpaceSchemaStateFunc(input) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("unexpected diff (+want, -got): %s", diff) + } +} diff --git a/internal/service/amp/exports_test.go b/internal/service/amp/exports_test.go index a5487cdace04..6c3679851176 100644 --- a/internal/service/amp/exports_test.go +++ b/internal/service/amp/exports_test.go @@ -10,9 +10,11 @@ var ( ResourceRuleGroupNamespace = resourceRuleGroupNamespace ResourceScraper = newScraperResource ResourceWorkspace = resourceWorkspace + ResourceResourcePolicy = newResourcePolicyResource FindAlertManagerDefinitionByID = findAlertManagerDefinitionByID FindQueryLoggingConfigurationByID = findQueryLoggingConfigurationByID + FindResourcePolicyByWorkspaceID = findResourcePolicyByWorkspaceID FindRuleGroupNamespaceByARN = findRuleGroupNamespaceByARN FindScraperByID = findScraperByID FindWorkspaceByID = findWorkspaceByID diff --git a/internal/service/amp/resource_policy.go b/internal/service/amp/resource_policy.go new file mode 100644 index 000000000000..0b083e82940c --- /dev/null +++ b/internal/service/amp/resource_policy.go @@ -0,0 +1,333 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package amp + +import ( + "context" + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/amp" + awstypes "github.com/aws/aws-sdk-go-v2/service/amp/types" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + sdkid "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource("aws_prometheus_resource_policy", name="Resource Policy") +// @Testing(existsType="github.com/aws/aws-sdk-go-v2/service/amp;amp.DescribeResourcePolicyOutput") +func newResourcePolicyResource(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourcePolicyResource{} + + r.SetDefaultCreateTimeout(5 * time.Minute) + r.SetDefaultDeleteTimeout(5 * time.Minute) + r.SetDefaultUpdateTimeout(5 * time.Minute) + + return r, nil +} + +type resourcePolicyResource struct { + framework.ResourceWithModel[resourcePolicyResourceModel] + framework.WithTimeouts +} + +func (r *resourcePolicyResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "policy_document": schema.StringAttribute{ + CustomType: fwtypes.IAMPolicyType, + Required: true, + }, + "revision_id": schema.StringAttribute{ + Computed: true, + Optional: true, + }, + "workspace_id": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + }, + Blocks: map[string]schema.Block{ + names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{ + Create: true, + Delete: true, + Update: true, + }), + }, + } +} + +func (r *resourcePolicyResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var data resourcePolicyResourceModel + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().AMPClient(ctx) + + workspaceID := fwflex.StringValueFromFramework(ctx, data.WorkspaceID) + input := amp.PutResourcePolicyInput{ + ClientToken: aws.String(sdkid.UniqueId()), + PolicyDocument: fwflex.StringFromFramework(ctx, data.PolicyDocument), + WorkspaceId: aws.String(workspaceID), + } + + if !data.RevisionID.IsNull() { + input.RevisionId = fwflex.StringFromFramework(ctx, data.RevisionID) + } + + output, err := conn.PutResourcePolicy(ctx, &input) + + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("creating Prometheus Workspace (%s) Resource Policy", workspaceID), err.Error()) + return + } + + // Set values for unknowns. + data.RevisionID = fwflex.StringToFramework(ctx, output.RevisionId) + + if _, err := waitResourcePolicyCreated(ctx, conn, workspaceID, r.CreateTimeout(ctx, data.Timeouts)); err != nil { + response.Diagnostics.AddError(fmt.Sprintf("waiting for Prometheus Workspace (%s) Resource Policy create", workspaceID), err.Error()) + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} + +func (r *resourcePolicyResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var data resourcePolicyResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().AMPClient(ctx) + + workspaceID := fwflex.StringValueFromFramework(ctx, data.WorkspaceID) + output, err := findResourcePolicyByWorkspaceID(ctx, conn, workspaceID) + + if tfresource.NotFound(err) { + response.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) + response.State.RemoveResource(ctx) + return + } + + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("reading Prometheus Workspace (%s) Resource Policy", workspaceID), err.Error()) + return + } + + // Set attributes for import. + response.Diagnostics.Append(fwflex.Flatten(ctx, output, &data)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} + +func (r *resourcePolicyResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var new, old resourcePolicyResourceModel + response.Diagnostics.Append(request.Plan.Get(ctx, &new)...) + if response.Diagnostics.HasError() { + return + } + response.Diagnostics.Append(request.State.Get(ctx, &old)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().AMPClient(ctx) + + if !new.PolicyDocument.Equal(old.PolicyDocument) || !new.RevisionID.Equal(old.RevisionID) { + workspaceID := fwflex.StringValueFromFramework(ctx, new.WorkspaceID) + input := amp.PutResourcePolicyInput{ + ClientToken: aws.String(sdkid.UniqueId()), + PolicyDocument: fwflex.StringFromFramework(ctx, new.PolicyDocument), + WorkspaceId: aws.String(workspaceID), + } + + if !new.RevisionID.IsNull() { + input.RevisionId = fwflex.StringFromFramework(ctx, new.RevisionID) + } + + output, err := conn.PutResourcePolicy(ctx, &input) + + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("updating Prometheus Workspace (%s) Resource Policy", workspaceID), err.Error()) + return + } + + new.RevisionID = fwflex.StringToFramework(ctx, output.RevisionId) + + if _, err := waitResourcePolicyUpdated(ctx, conn, workspaceID, r.UpdateTimeout(ctx, new.Timeouts)); err != nil { + response.Diagnostics.AddError(fmt.Sprintf("waiting for Prometheus Workspace (%s) Resource Policy update", workspaceID), err.Error()) + return + } + } + + response.Diagnostics.Append(response.State.Set(ctx, &new)...) +} + +func (r *resourcePolicyResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data resourcePolicyResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().AMPClient(ctx) + + workspaceID := fwflex.StringValueFromFramework(ctx, data.WorkspaceID) + input := amp.DeleteResourcePolicyInput{ + ClientToken: aws.String(sdkid.UniqueId()), + WorkspaceId: aws.String(workspaceID), + } + + if !data.RevisionID.IsNull() { + input.RevisionId = fwflex.StringFromFramework(ctx, data.RevisionID) + } + + _, err := conn.DeleteResourcePolicy(ctx, &input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("deleting Prometheus Workspace (%s) Resource Policy", workspaceID), err.Error()) + return + } + + if _, err := waitResourcePolicyDeleted(ctx, conn, workspaceID, r.DeleteTimeout(ctx, data.Timeouts)); err != nil { + response.Diagnostics.AddError(fmt.Sprintf("waiting for Prometheus Workspace (%s) Resource Policy delete", workspaceID), err.Error()) + return + } +} + +func (r *resourcePolicyResource) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("workspace_id"), request, response) +} + +type resourcePolicyResourceModel struct { + framework.WithRegionModel + PolicyDocument fwtypes.IAMPolicy `tfsdk:"policy_document"` + RevisionID types.String `tfsdk:"revision_id"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + WorkspaceID types.String `tfsdk:"workspace_id"` +} + +func findResourcePolicyByWorkspaceID(ctx context.Context, conn *amp.Client, workspaceID string) (*amp.DescribeResourcePolicyOutput, error) { + input := amp.DescribeResourcePolicyInput{ + WorkspaceId: aws.String(workspaceID), + } + + return findResourcePolicy(ctx, conn, &input) +} + +func findResourcePolicy(ctx context.Context, conn *amp.Client, input *amp.DescribeResourcePolicyInput) (*amp.DescribeResourcePolicyOutput, error) { + output, err := conn.DescribeResourcePolicy(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.PolicyDocument == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} + +func statusResourcePolicy(ctx context.Context, conn *amp.Client, workspaceID string) retry.StateRefreshFunc { + return func() (any, string, error) { + output, err := findResourcePolicyByWorkspaceID(ctx, conn, workspaceID) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, string(output.PolicyStatus), nil + } +} + +func waitResourcePolicyCreated(ctx context.Context, conn *amp.Client, workspaceID string, timeout time.Duration) (*amp.DescribeResourcePolicyOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.WorkspacePolicyStatusCodeCreating), + Target: enum.Slice(awstypes.WorkspacePolicyStatusCodeActive), + Refresh: statusResourcePolicy(ctx, conn, workspaceID), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*amp.DescribeResourcePolicyOutput); ok { + return output, err + } + + return nil, err +} + +func waitResourcePolicyUpdated(ctx context.Context, conn *amp.Client, workspaceID string, timeout time.Duration) (*amp.DescribeResourcePolicyOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.WorkspacePolicyStatusCodeUpdating), + Target: enum.Slice(awstypes.WorkspacePolicyStatusCodeActive), + Refresh: statusResourcePolicy(ctx, conn, workspaceID), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*amp.DescribeResourcePolicyOutput); ok { + return output, err + } + + return nil, err +} + +func waitResourcePolicyDeleted(ctx context.Context, conn *amp.Client, workspaceID string, timeout time.Duration) (*amp.DescribeResourcePolicyOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.WorkspacePolicyStatusCodeDeleting, awstypes.WorkspacePolicyStatusCodeActive), + Target: []string{}, + Refresh: statusResourcePolicy(ctx, conn, workspaceID), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*amp.DescribeResourcePolicyOutput); ok { + return output, err + } + + return nil, err +} diff --git a/internal/service/amp/resource_policy_test.go b/internal/service/amp/resource_policy_test.go new file mode 100644 index 000000000000..d5aba4a989f1 --- /dev/null +++ b/internal/service/amp/resource_policy_test.go @@ -0,0 +1,262 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package amp_test + +import ( + "context" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/amp" + awstypes "github.com/aws/aws-sdk-go-v2/service/amp/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + tfamp "github.com/hashicorp/terraform-provider-aws/internal/service/amp" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccAMPResourcePolicy_basic(t *testing.T) { + ctx := acctest.Context(t) + var policy amp.DescribeResourcePolicyOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_prometheus_resource_policy.test" + workspaceResourceName := "aws_prometheus_workspace.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.AMPEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.AMPServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckResourcePolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccResourcePolicyConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourcePolicyExists(ctx, resourceName, &policy), + resource.TestCheckResourceAttrPair(resourceName, "workspace_id", workspaceResourceName, names.AttrID), + resource.TestCheckResourceAttrSet(resourceName, "revision_id"), + resource.TestCheckResourceAttrSet(resourceName, "policy_document"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: acctest.AttrImportStateIdFunc(resourceName, "workspace_id"), + ImportStateVerifyIdentifierAttribute: "workspace_id", + ImportStateVerifyIgnore: []string{"policy_document"}, + }, + }, + }) +} + +func TestAccAMPResourcePolicy_update(t *testing.T) { + ctx := acctest.Context(t) + var policy1, policy2 amp.DescribeResourcePolicyOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_prometheus_resource_policy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.AMPEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.AMPServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckResourcePolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccResourcePolicyConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourcePolicyExists(ctx, resourceName, &policy1), + ), + }, + { + Config: testAccResourcePolicyConfig_updated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourcePolicyExists(ctx, resourceName, &policy2), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: acctest.AttrImportStateIdFunc(resourceName, "workspace_id"), + ImportStateVerifyIdentifierAttribute: "workspace_id", + ImportStateVerifyIgnore: []string{"policy_document"}, + }, + }, + }) +} + +func TestAccAMPResourcePolicy_disappears(t *testing.T) { + ctx := acctest.Context(t) + var policy amp.DescribeResourcePolicyOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_prometheus_resource_policy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.AMPEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.AMPServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckResourcePolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccResourcePolicyConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourcePolicyExists(ctx, resourceName, &policy), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfamp.ResourceResourcePolicy, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAMPResourcePolicy_disappears_Workspace(t *testing.T) { + ctx := acctest.Context(t) + var policy amp.DescribeResourcePolicyOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_prometheus_resource_policy.test" + workspaceResourceName := "aws_prometheus_workspace.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.AMPEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.AMPServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckResourcePolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccResourcePolicyConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourcePolicyExists(ctx, resourceName, &policy), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfamp.ResourceWorkspace(), workspaceResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckResourcePolicyDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).AMPClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_prometheus_resource_policy" { + continue + } + + _, err := tfamp.FindResourcePolicyByWorkspaceID(ctx, conn, rs.Primary.Attributes["workspace_id"]) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("Prometheus Workspace Resource Policy %s still exists", rs.Primary.Attributes["workspace_id"]) + } + + return nil + } +} + +func testAccCheckResourcePolicyExists(ctx context.Context, n string, v *amp.DescribeResourcePolicyOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).AMPClient(ctx) + + output, err := tfamp.FindResourcePolicyByWorkspaceID(ctx, conn, rs.Primary.Attributes["workspace_id"]) + + if err != nil { + return err + } + + *v = *output + + return nil + } +} + +func testAccResourcePolicyConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_prometheus_workspace" "test" { + alias = %[1]q +} + +data "aws_caller_identity" "current" {} + +data "aws_iam_policy_document" "test" { + statement { + effect = "Allow" + principals { + type = "AWS" + identifiers = [data.aws_caller_identity.current.account_id] + } + actions = [ + "aps:RemoteWrite", + "aps:QueryMetrics", + "aps:GetSeries", + "aps:GetLabels", + "aps:GetMetricMetadata" + ] + resources = [aws_prometheus_workspace.test.arn] + } +} + +resource "aws_prometheus_resource_policy" "test" { + workspace_id = aws_prometheus_workspace.test.id + policy_document = data.aws_iam_policy_document.test.json +} +`, rName) +} + +func testAccResourcePolicyConfig_updated(rName string) string { + return fmt.Sprintf(` +resource "aws_prometheus_workspace" "test" { + alias = %[1]q +} + +data "aws_caller_identity" "current" {} + +data "aws_iam_policy_document" "test" { + statement { + effect = "Allow" + principals { + type = "AWS" + identifiers = [data.aws_caller_identity.current.account_id] + } + actions = [ + "aps:RemoteWrite", + "aps:QueryMetrics" + ] + resources = [aws_prometheus_workspace.test.arn] + } +} + +resource "aws_prometheus_resource_policy" "test" { + workspace_id = aws_prometheus_workspace.test.id + policy_document = data.aws_iam_policy_document.test.json +} +`, rName) +} diff --git a/internal/service/amp/service_package_gen.go b/internal/service/amp/service_package_gen.go index 7b355d6015da..05d4bed3fba5 100644 --- a/internal/service/amp/service_package_gen.go +++ b/internal/service/amp/service_package_gen.go @@ -36,6 +36,12 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*inttypes.Ser Name: "QueryLoggingConfiguration", Region: unique.Make(inttypes.ResourceRegionDefault()), }, + { + Factory: newResourcePolicyResource, + TypeName: "aws_prometheus_resource_policy", + Name: "Resource Policy", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, { Factory: newScraperResource, TypeName: "aws_prometheus_scraper", diff --git a/internal/service/appfabric/app_bundle_identity_gen_test.go b/internal/service/appfabric/app_bundle_identity_gen_test.go index 3dc1d6d717e7..4e3013c4b694 100644 --- a/internal/service/appfabric/app_bundle_identity_gen_test.go +++ b/internal/service/appfabric/app_bundle_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccAppFabricAppBundle_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccAppFabricAppBundle_Identity_Basic, - "ExistingResource": testAccAppFabricAppBundle_Identity_ExistingResource, - "RegionOverride": testAccAppFabricAppBundle_Identity_RegionOverride, + acctest.CtBasic: testAccAppFabricAppBundle_Identity_Basic, + "ExistingResource": testAccAppFabricAppBundle_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccAppFabricAppBundle_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccAppFabricAppBundle_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/auditmanager/account_registration_identity_gen_test.go b/internal/service/auditmanager/account_registration_identity_gen_test.go index 563c74662f59..067c3b9f93be 100644 --- a/internal/service/auditmanager/account_registration_identity_gen_test.go +++ b/internal/service/auditmanager/account_registration_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccAuditManagerAccountRegistration_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccAuditManagerAccountRegistration_Identity_Basic, - "ExistingResource": testAccAuditManagerAccountRegistration_Identity_ExistingResource, - "RegionOverride": testAccAuditManagerAccountRegistration_Identity_RegionOverride, + acctest.CtBasic: testAccAuditManagerAccountRegistration_Identity_Basic, + "ExistingResource": testAccAuditManagerAccountRegistration_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccAuditManagerAccountRegistration_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccAuditManagerAccountRegistration_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/backup/region_settings_identity_gen_test.go b/internal/service/backup/region_settings_identity_gen_test.go index 6f6c5ade8db4..8f9fd397a106 100644 --- a/internal/service/backup/region_settings_identity_gen_test.go +++ b/internal/service/backup/region_settings_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccBackupRegionSettings_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccBackupRegionSettings_Identity_Basic, - "ExistingResource": testAccBackupRegionSettings_Identity_ExistingResource, - "RegionOverride": testAccBackupRegionSettings_Identity_RegionOverride, + acctest.CtBasic: testAccBackupRegionSettings_Identity_Basic, + "ExistingResource": testAccBackupRegionSettings_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccBackupRegionSettings_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccBackupRegionSettings_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/bedrock/custom_model_identity_gen_test.go b/internal/service/bedrock/custom_model_identity_gen_test.go index 442a2d09be56..75a009b71dcc 100644 --- a/internal/service/bedrock/custom_model_identity_gen_test.go +++ b/internal/service/bedrock/custom_model_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccBedrockCustomModel_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccBedrockCustomModel_Identity_Basic, - "ExistingResource": testAccBedrockCustomModel_Identity_ExistingResource, - "RegionOverride": testAccBedrockCustomModel_Identity_RegionOverride, + acctest.CtBasic: testAccBedrockCustomModel_Identity_Basic, + "ExistingResource": testAccBedrockCustomModel_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccBedrockCustomModel_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccBedrockCustomModel_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/bedrock/model_invocation_logging_configuration_identity_gen_test.go b/internal/service/bedrock/model_invocation_logging_configuration_identity_gen_test.go index 75a0337a352c..9139c65f5f1b 100644 --- a/internal/service/bedrock/model_invocation_logging_configuration_identity_gen_test.go +++ b/internal/service/bedrock/model_invocation_logging_configuration_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccBedrockModelInvocationLoggingConfiguration_IdentitySerial(t *testing t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccBedrockModelInvocationLoggingConfiguration_Identity_Basic, - "ExistingResource": testAccBedrockModelInvocationLoggingConfiguration_Identity_ExistingResource, - "RegionOverride": testAccBedrockModelInvocationLoggingConfiguration_Identity_RegionOverride, + acctest.CtBasic: testAccBedrockModelInvocationLoggingConfiguration_Identity_Basic, + "ExistingResource": testAccBedrockModelInvocationLoggingConfiguration_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccBedrockModelInvocationLoggingConfiguration_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccBedrockModelInvocationLoggingConfiguration_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/bedrockagentcore/generate.go b/internal/service/bedrockagentcore/generate.go index 81cf8cd03548..e6b7d78ed653 100644 --- a/internal/service/bedrockagentcore/generate.go +++ b/internal/service/bedrockagentcore/generate.go @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 //go:generate go run ../../generate/servicepackage/main.go +//go:generate go run ../../generate/tags/main.go -ServiceTagsMap -KVTValues -ListTags -UpdateTags // ONLY generate directives and package declaration! Do not add anything else to this file. package bedrockagentcore diff --git a/internal/service/bedrockagentcore/tags_gen.go b/internal/service/bedrockagentcore/tags_gen.go new file mode 100644 index 000000000000..3ed4e7ef14a1 --- /dev/null +++ b/internal/service/bedrockagentcore/tags_gen.go @@ -0,0 +1,128 @@ +// Code generated by internal/generate/tags/main.go; DO NOT EDIT. +package bedrockagentcore + +import ( + "context" + + "github.com/YakDriver/smarterr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/logging" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/types/option" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// listTags lists bedrockagentcore service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func listTags(ctx context.Context, conn *bedrockagentcorecontrol.Client, identifier string, optFns ...func(*bedrockagentcorecontrol.Options)) (tftags.KeyValueTags, error) { + input := bedrockagentcorecontrol.ListTagsForResourceInput{ + ResourceArn: aws.String(identifier), + } + + output, err := conn.ListTagsForResource(ctx, &input, optFns...) + + if err != nil { + return tftags.New(ctx, nil), smarterr.NewError(err) + } + + return keyValueTags(ctx, output.Tags), nil +} + +// ListTags lists bedrockagentcore service tags and set them in Context. +// It is called from outside this package. +func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { + tags, err := listTags(ctx, meta.(*conns.AWSClient).BedrockAgentCoreClient(ctx), identifier) + + if err != nil { + return smarterr.NewError(err) + } + + if inContext, ok := tftags.FromContext(ctx); ok { + inContext.TagsOut = option.Some(tags) + } + + return nil +} + +// map[string]string handling + +// svcTags returns bedrockagentcore service tags. +func svcTags(tags tftags.KeyValueTags) map[string]string { + return tags.Map() +} + +// keyValueTags creates tftags.KeyValueTags from bedrockagentcore service tags. +func keyValueTags(ctx context.Context, tags map[string]string) tftags.KeyValueTags { + return tftags.New(ctx, tags) +} + +// getTagsIn returns bedrockagentcore service tags from Context. +// nil is returned if there are no input tags. +func getTagsIn(ctx context.Context) map[string]string { + if inContext, ok := tftags.FromContext(ctx); ok { + if tags := svcTags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { + return tags + } + } + + return nil +} + +// setTagsOut sets bedrockagentcore service tags in Context. +func setTagsOut(ctx context.Context, tags map[string]string) { + if inContext, ok := tftags.FromContext(ctx); ok { + inContext.TagsOut = option.Some(keyValueTags(ctx, tags)) + } +} + +// updateTags updates bedrockagentcore service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func updateTags(ctx context.Context, conn *bedrockagentcorecontrol.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*bedrockagentcorecontrol.Options)) error { + oldTags := tftags.New(ctx, oldTagsMap) + newTags := tftags.New(ctx, newTagsMap) + + ctx = tflog.SetField(ctx, logging.KeyResourceId, identifier) + + removedTags := oldTags.Removed(newTags) + removedTags = removedTags.IgnoreSystem(names.BedrockAgentCore) + if len(removedTags) > 0 { + input := bedrockagentcorecontrol.UntagResourceInput{ + ResourceArn: aws.String(identifier), + TagKeys: removedTags.Keys(), + } + + _, err := conn.UntagResource(ctx, &input, optFns...) + + if err != nil { + return smarterr.NewError(err) + } + } + + updatedTags := oldTags.Updated(newTags) + updatedTags = updatedTags.IgnoreSystem(names.BedrockAgentCore) + if len(updatedTags) > 0 { + input := bedrockagentcorecontrol.TagResourceInput{ + ResourceArn: aws.String(identifier), + Tags: svcTags(updatedTags), + } + + _, err := conn.TagResource(ctx, &input, optFns...) + + if err != nil { + return smarterr.NewError(err) + } + } + + return nil +} + +// UpdateTags updates bedrockagentcore service tags. +// It is called from outside this package. +func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { + return updateTags(ctx, meta.(*conns.AWSClient).BedrockAgentCoreClient(ctx), identifier, oldTags, newTags) +} diff --git a/internal/service/chatbot/slack_channel_configuration.go b/internal/service/chatbot/slack_channel_configuration.go index f10f03fd6bc4..63d5a40aa9b4 100644 --- a/internal/service/chatbot/slack_channel_configuration.go +++ b/internal/service/chatbot/slack_channel_configuration.go @@ -59,6 +59,9 @@ func (r *slackChannelConfigurationResource) Schema(ctx context.Context, request "chat_configuration_arn": framework.ARNAttributeComputedOnly(), "configuration_name": schema.StringAttribute{ Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, }, "guardrail_policy_arns": schema.ListAttribute{ CustomType: fwtypes.ListOfStringType, diff --git a/internal/service/chatbot/slack_channel_configuration_test.go b/internal/service/chatbot/slack_channel_configuration_test.go index f9a1652316f9..d461a18c1af7 100644 --- a/internal/service/chatbot/slack_channel_configuration_test.go +++ b/internal/service/chatbot/slack_channel_configuration_test.go @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/chatbot/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -46,6 +47,8 @@ func testAccSlackChannelConfiguration_basic(t *testing.T) { var slackchannelconfiguration types.SlackChannelConfiguration rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rNameUpdated := rName + "-updated" + resourceName := testResourceSlackChannelConfiguration // The slack workspace must be created via the AWS Console. It cannot be created via APIs or Terraform. // Once it is created, export the name of the workspace in the env variable for this test @@ -81,6 +84,24 @@ func testAccSlackChannelConfiguration_basic(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIdentifierAttribute: "chat_configuration_arn", }, + { + Config: testAccSlackChannelConfigurationConfig_basic(rNameUpdated, channelID, teamID), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionDestroyBeforeCreate), + }, + }, + Check: resource.ComposeTestCheckFunc( + testAccCheckSlackChannelConfigurationExists(ctx, testResourceSlackChannelConfiguration, &slackchannelconfiguration), + resource.TestCheckResourceAttr(testResourceSlackChannelConfiguration, "configuration_name", rNameUpdated), + acctest.MatchResourceAttrGlobalARN(ctx, testResourceSlackChannelConfiguration, "chat_configuration_arn", "chatbot", regexache.MustCompile(fmt.Sprintf(`chat-configuration/slack-channel/%s`, rName))), + resource.TestCheckResourceAttrPair(testResourceSlackChannelConfiguration, names.AttrIAMRoleARN, "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(testResourceSlackChannelConfiguration, "slack_channel_id", channelID), + resource.TestCheckResourceAttrSet(testResourceSlackChannelConfiguration, "slack_channel_name"), + resource.TestCheckResourceAttr(testResourceSlackChannelConfiguration, "slack_team_id", teamID), + resource.TestCheckResourceAttrSet(testResourceSlackChannelConfiguration, "slack_team_name"), + ), + }, }, }) } diff --git a/internal/service/cleanrooms/configured_table.go b/internal/service/cleanrooms/configured_table.go index f723a905697b..f3d27bc56da7 100644 --- a/internal/service/cleanrooms/configured_table.go +++ b/internal/service/cleanrooms/configured_table.go @@ -29,6 +29,9 @@ import ( // @SDKResource("aws_cleanrooms_configured_table", name="Configured Table") // @Tags(identifierAttribute="arn") // @Testing(tagsTest=false) +// @IdentityAttribute("id") +// @Testing(preIdentityVersion="v6.14.1") +// @Testing(existsType="github.com/aws/aws-sdk-go-v2/service/cleanrooms;cleanrooms.GetConfiguredTableOutput") func ResourceConfiguredTable() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceConfiguredTableCreate, @@ -36,10 +39,6 @@ func ResourceConfiguredTable() *schema.Resource { UpdateWithoutTimeout: resourceConfiguredTableUpdate, DeleteWithoutTimeout: resourceConfiguredTableDelete, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(1 * time.Minute), Update: schema.DefaultTimeout(1 * time.Minute), diff --git a/internal/service/cleanrooms/configured_table_identity_gen_test.go b/internal/service/cleanrooms/configured_table_identity_gen_test.go new file mode 100644 index 000000000000..4eefe6892be7 --- /dev/null +++ b/internal/service/cleanrooms/configured_table_identity_gen_test.go @@ -0,0 +1,309 @@ +// Code generated by internal/generate/identitytests/main.go; DO NOT EDIT. + +package cleanrooms_test + +import ( + "testing" + + "github.com/aws/aws-sdk-go-v2/service/cleanrooms" + "github.com/hashicorp/terraform-plugin-testing/config" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + tfknownvalue "github.com/hashicorp/terraform-provider-aws/internal/acctest/knownvalue" + tfstatecheck "github.com/hashicorp/terraform-provider-aws/internal/acctest/statecheck" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccCleanRoomsConfiguredTable_Identity_Basic(t *testing.T) { + ctx := acctest.Context(t) + + var v cleanrooms.GetConfiguredTableOutput + resourceName := "aws_cleanrooms_configured_table.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.ParallelTest(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.CleanRoomsServiceID), + CheckDestroy: testAccCheckConfiguredTableDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + // Step 1: Setup + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfiguredTableExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + statecheck.ExpectIdentity(resourceName, map[string]knownvalue.Check{ + names.AttrAccountID: tfknownvalue.AccountID(), + names.AttrRegion: knownvalue.StringExact(acctest.Region()), + names.AttrID: knownvalue.NotNull(), + }), + statecheck.ExpectIdentityValueMatchesState(resourceName, tfjsonpath.New(names.AttrID)), + }, + }, + + // Step 2: Import command + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ImportStateKind: resource.ImportCommandWithID, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + + // Step 3: Import block with Import ID + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithID, + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + }, + }, + }, + + // Step 4: Import block with Resource Identity + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + }, + }, + }, + }, + }) +} + +func TestAccCleanRoomsConfiguredTable_Identity_RegionOverride(t *testing.T) { + ctx := acctest.Context(t) + + resourceName := "aws_cleanrooms_configured_table.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.ParallelTest(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.CleanRoomsServiceID), + CheckDestroy: acctest.CheckDestroyNoop, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + // Step 1: Setup + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/region_override/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "region": config.StringVariable(acctest.AlternateRegion()), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.AlternateRegion())), + statecheck.ExpectIdentity(resourceName, map[string]knownvalue.Check{ + names.AttrAccountID: tfknownvalue.AccountID(), + names.AttrRegion: knownvalue.StringExact(acctest.AlternateRegion()), + names.AttrID: knownvalue.NotNull(), + }), + statecheck.ExpectIdentityValueMatchesState(resourceName, tfjsonpath.New(names.AttrID)), + }, + }, + + // Step 2: Import command + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/region_override/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "region": config.StringVariable(acctest.AlternateRegion()), + }, + ImportStateKind: resource.ImportCommandWithID, + ImportStateIdFunc: acctest.CrossRegionImportStateIdFunc(resourceName), + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + + // Step 3: Import block with Import ID + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/region_override/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "region": config.StringVariable(acctest.AlternateRegion()), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithID, + ImportStateIdFunc: acctest.CrossRegionImportStateIdFunc(resourceName), + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.AlternateRegion())), + }, + }, + }, + + // Step 4: Import block with Resource Identity + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/region_override/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "region": config.StringVariable(acctest.AlternateRegion()), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.AlternateRegion())), + }, + }, + }, + }, + }) +} + +// Resource Identity was added after v6.14.1 +func TestAccCleanRoomsConfiguredTable_Identity_ExistingResource(t *testing.T) { + ctx := acctest.Context(t) + + var v cleanrooms.GetConfiguredTableOutput + resourceName := "aws_cleanrooms_configured_table.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.ParallelTest(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.CleanRoomsServiceID), + CheckDestroy: testAccCheckConfiguredTableDestroy(ctx), + Steps: []resource.TestStep{ + // Step 1: Create pre-Identity + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic_v6.14.1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfiguredTableExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + + // Step 2: Current version + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectIdentity(resourceName, map[string]knownvalue.Check{ + names.AttrAccountID: tfknownvalue.AccountID(), + names.AttrRegion: knownvalue.StringExact(acctest.Region()), + names.AttrID: knownvalue.NotNull(), + }), + statecheck.ExpectIdentityValueMatchesState(resourceName, tfjsonpath.New(names.AttrID)), + }, + }, + }, + }) +} + +// Resource Identity was added after v6.14.1 +func TestAccCleanRoomsConfiguredTable_Identity_ExistingResource_NoRefresh_NoChange(t *testing.T) { + ctx := acctest.Context(t) + + var v cleanrooms.GetConfiguredTableOutput + resourceName := "aws_cleanrooms_configured_table.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.ParallelTest(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.CleanRoomsServiceID), + CheckDestroy: testAccCheckConfiguredTableDestroy(ctx), + AdditionalCLIOptions: &resource.AdditionalCLIOptions{ + Plan: resource.PlanOptions{ + NoRefresh: true, + }, + }, + Steps: []resource.TestStep{ + // Step 1: Create pre-Identity + { + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic_v6.14.1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfiguredTableExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + + // Step 2: Current version + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/ConfiguredTable/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + }, + }) +} diff --git a/internal/service/cleanrooms/generate.go b/internal/service/cleanrooms/generate.go index 95d208f6d857..3fa2f819ec37 100644 --- a/internal/service/cleanrooms/generate.go +++ b/internal/service/cleanrooms/generate.go @@ -4,6 +4,7 @@ //go:generate go run ../../generate/servicepackage/main.go //go:generate go run ../../generate/tags/main.go -ListTags -ServiceTagsMap -UpdateTags -TagTypeKeyElem=key -TagTypeValElem=value -KVTValues //go:generate go run ../../generate/tagstests/main.go +//go:generate go run ../../generate/identitytests/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. package cleanrooms diff --git a/internal/service/cleanrooms/service_package_gen.go b/internal/service/cleanrooms/service_package_gen.go index 6aac145772ab..273fd0c733ac 100644 --- a/internal/service/cleanrooms/service_package_gen.go +++ b/internal/service/cleanrooms/service_package_gen.go @@ -57,7 +57,11 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*inttypes.ServicePa Tags: unique.Make(inttypes.ServicePackageResourceTags{ IdentifierAttribute: names.AttrARN, }), - Region: unique.Make(inttypes.ResourceRegionDefault()), + Region: unique.Make(inttypes.ResourceRegionDefault()), + Identity: inttypes.RegionalSingleParameterIdentity(names.AttrID), + Import: inttypes.SDKv2Import{ + WrappedImport: true, + }, }, } } diff --git a/internal/service/cleanrooms/testdata/ConfiguredTable/basic/main_gen.tf b/internal/service/cleanrooms/testdata/ConfiguredTable/basic/main_gen.tf new file mode 100644 index 000000000000..cea5e1d62ea5 --- /dev/null +++ b/internal/service/cleanrooms/testdata/ConfiguredTable/basic/main_gen.tf @@ -0,0 +1,49 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_s3_bucket" "test" { + bucket = var.rName +} + +resource "aws_glue_catalog_database" "test" { + name = var.rName +} + +resource "aws_glue_catalog_table" "test" { + name = var.rName + database_name = var.rName + + storage_descriptor { + location = "s3://${aws_s3_bucket.test.bucket}" + + columns { + name = "my_column_1" + type = "string" + } + + columns { + name = "my_column_2" + type = "string" + } + } +} + +resource "aws_cleanrooms_configured_table" "test" { + name = "test-name" + description = "test description" + analysis_method = "DIRECT_QUERY" + allowed_columns = ["my_column_1", "my_column_2"] + + table_reference { + database_name = var.rName + table_name = var.rName + } + + depends_on = [aws_glue_catalog_table.test] +} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} diff --git a/internal/service/cleanrooms/testdata/ConfiguredTable/basic_v6.14.1/main_gen.tf b/internal/service/cleanrooms/testdata/ConfiguredTable/basic_v6.14.1/main_gen.tf new file mode 100644 index 000000000000..3c4c26f0a6bb --- /dev/null +++ b/internal/service/cleanrooms/testdata/ConfiguredTable/basic_v6.14.1/main_gen.tf @@ -0,0 +1,59 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_s3_bucket" "test" { + bucket = var.rName +} + +resource "aws_glue_catalog_database" "test" { + name = var.rName +} + +resource "aws_glue_catalog_table" "test" { + name = var.rName + database_name = var.rName + + storage_descriptor { + location = "s3://${aws_s3_bucket.test.bucket}" + + columns { + name = "my_column_1" + type = "string" + } + + columns { + name = "my_column_2" + type = "string" + } + } +} + +resource "aws_cleanrooms_configured_table" "test" { + name = "test-name" + description = "test description" + analysis_method = "DIRECT_QUERY" + allowed_columns = ["my_column_1", "my_column_2"] + + table_reference { + database_name = var.rName + table_name = var.rName + } + + depends_on = [aws_glue_catalog_table.test] +} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "6.14.1" + } + } +} + +provider "aws" {} diff --git a/internal/service/cleanrooms/testdata/ConfiguredTable/region_override/main_gen.tf b/internal/service/cleanrooms/testdata/ConfiguredTable/region_override/main_gen.tf new file mode 100644 index 000000000000..b5ab494c7668 --- /dev/null +++ b/internal/service/cleanrooms/testdata/ConfiguredTable/region_override/main_gen.tf @@ -0,0 +1,63 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_s3_bucket" "test" { + region = var.region + + bucket = var.rName +} + +resource "aws_glue_catalog_database" "test" { + region = var.region + + name = var.rName +} + +resource "aws_glue_catalog_table" "test" { + region = var.region + + name = var.rName + database_name = var.rName + + storage_descriptor { + location = "s3://${aws_s3_bucket.test.bucket}" + + columns { + name = "my_column_1" + type = "string" + } + + columns { + name = "my_column_2" + type = "string" + } + } +} + +resource "aws_cleanrooms_configured_table" "test" { + region = var.region + + name = "test-name" + description = "test description" + analysis_method = "DIRECT_QUERY" + allowed_columns = ["my_column_1", "my_column_2"] + + table_reference { + database_name = var.rName + table_name = var.rName + } + + depends_on = [aws_glue_catalog_table.test] +} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} + +variable "region" { + description = "Region to deploy resource in" + type = string + nullable = false +} diff --git a/internal/service/cleanrooms/testdata/tmpl/configured_table_tags.gtpl b/internal/service/cleanrooms/testdata/tmpl/configured_table_tags.gtpl new file mode 100644 index 000000000000..de5b2533f159 --- /dev/null +++ b/internal/service/cleanrooms/testdata/tmpl/configured_table_tags.gtpl @@ -0,0 +1,45 @@ +resource "aws_s3_bucket" "test" { +{{- template "region" }} + bucket = var.rName +} + +resource "aws_glue_catalog_database" "test" { +{{- template "region" }} + name = var.rName +} + +resource "aws_glue_catalog_table" "test" { +{{- template "region" }} + name = var.rName + database_name = var.rName + + storage_descriptor { + location = "s3://${aws_s3_bucket.test.bucket}" + + columns { + name = "my_column_1" + type = "string" + } + + columns { + name = "my_column_2" + type = "string" + } + } +} + +resource "aws_cleanrooms_configured_table" "test" { +{{- template "region" }} + name = "test-name" + description = "test description" + analysis_method = "DIRECT_QUERY" + allowed_columns = ["my_column_1", "my_column_2"] + + table_reference { + database_name = var.rName + table_name = var.rName + } +{{- template "tags" }} + + depends_on = [aws_glue_catalog_table.test] +} diff --git a/internal/service/cloudfront/create_invalidation_action.go b/internal/service/cloudfront/create_invalidation_action.go index 0cd271486ef5..1f8275ce5dd1 100644 --- a/internal/service/cloudfront/create_invalidation_action.go +++ b/internal/service/cloudfront/create_invalidation_action.go @@ -5,8 +5,8 @@ package cloudfront import ( "context" + "errors" "fmt" - "slices" "time" "github.com/YakDriver/regexache" @@ -23,6 +23,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-provider-aws/internal/actionwait" "github.com/hashicorp/terraform-provider-aws/internal/framework" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -216,13 +217,51 @@ func (a *createInvalidationAction) Invoke(ctx context.Context, req action.Invoke Message: fmt.Sprintf("Invalidation %s created, waiting for completion...", invalidationID), }) - // Wait for invalidation to complete with periodic progress updates - err = a.waitForInvalidationComplete(ctx, conn, distributionID, invalidationID, timeout, resp) + // Wait for invalidation to complete with periodic progress updates using actionwait + // Use fixed interval since CloudFront invalidations have predictable timing and + // don't benefit from exponential backoff - status changes are infrequent and consistent + _, err = actionwait.WaitForStatus(ctx, func(ctx context.Context) (actionwait.FetchResult[struct{}], error) { + input := cloudfront.GetInvalidationInput{ + DistributionId: aws.String(distributionID), + Id: aws.String(invalidationID), + } + output, gerr := conn.GetInvalidation(ctx, &input) + if gerr != nil { + return actionwait.FetchResult[struct{}]{}, fmt.Errorf("getting invalidation status: %w", gerr) + } + status := aws.ToString(output.Invalidation.Status) + return actionwait.FetchResult[struct{}]{Status: actionwait.Status(status)}, nil + }, actionwait.Options[struct{}]{ + Timeout: timeout, + Interval: actionwait.FixedInterval(actionwait.DefaultPollInterval), + ProgressInterval: 60 * time.Second, + SuccessStates: []actionwait.Status{"Completed"}, + TransitionalStates: []actionwait.Status{ + "InProgress", + }, + ProgressSink: func(fr actionwait.FetchResult[any], meta actionwait.ProgressMeta) { + resp.SendProgress(action.InvokeProgressEvent{Message: fmt.Sprintf("Invalidation %s is currently '%s', continuing to wait for completion...", invalidationID, fr.Status)}) + }, + }) if err != nil { - resp.Diagnostics.AddError( - "Timeout Waiting for Invalidation to Complete", - fmt.Sprintf("CloudFront invalidation %s did not complete within %s: %s", invalidationID, timeout, err), - ) + var timeoutErr *actionwait.TimeoutError + var unexpectedErr *actionwait.UnexpectedStateError + if errors.As(err, &timeoutErr) { + resp.Diagnostics.AddError( + "Timeout Waiting for Invalidation to Complete", + fmt.Sprintf("CloudFront invalidation %s did not complete within %s: %s", invalidationID, timeout, err), + ) + } else if errors.As(err, &unexpectedErr) { + resp.Diagnostics.AddError( + "Invalid Invalidation State", + fmt.Sprintf("CloudFront invalidation %s entered unexpected state: %s", invalidationID, err), + ) + } else { + resp.Diagnostics.AddError( + "Failed While Waiting for Invalidation", + fmt.Sprintf("Error waiting for CloudFront invalidation %s: %s", invalidationID, err), + ) + } return } @@ -237,64 +276,3 @@ func (a *createInvalidationAction) Invoke(ctx context.Context, req action.Invoke "paths": paths, }) } - -// waitForInvalidationComplete waits for an invalidation to complete with progress updates -func (a *createInvalidationAction) waitForInvalidationComplete(ctx context.Context, conn *cloudfront.Client, distributionID, invalidationID string, timeout time.Duration, resp *action.InvokeResponse) error { - const ( - pollInterval = 30 * time.Second - progressInterval = 60 * time.Second - ) - - deadline := time.Now().Add(timeout) - lastProgressUpdate := time.Now() - - for { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - // Check if we've exceeded the timeout - if time.Now().After(deadline) { - return fmt.Errorf("timeout after %s", timeout) - } - - // Get current invalidation status - input := &cloudfront.GetInvalidationInput{ - DistributionId: aws.String(distributionID), - Id: aws.String(invalidationID), - } - - output, err := conn.GetInvalidation(ctx, input) - if err != nil { - return fmt.Errorf("getting invalidation status: %w", err) - } - - currentStatus := aws.ToString(output.Invalidation.Status) - - // Send progress update every 60 seconds - if time.Since(lastProgressUpdate) >= progressInterval { - resp.SendProgress(action.InvokeProgressEvent{ - Message: fmt.Sprintf("Invalidation %s is currently '%s', continuing to wait for completion...", invalidationID, currentStatus), - }) - lastProgressUpdate = time.Now() - } - - // Check if we've reached completion - if aws.ToString(output.Invalidation.Status) == "Completed" { - return nil - } - - // Check if we're in an unexpected state - validStatuses := []string{ - "InProgress", - } - if !slices.Contains(validStatuses, currentStatus) && currentStatus != "Completed" { - return fmt.Errorf("invalidation entered unexpected status: %s", currentStatus) - } - - // Wait before next poll - time.Sleep(pollInterval) - } -} diff --git a/internal/service/cloudfront/distribution.go b/internal/service/cloudfront/distribution.go index 9ebf8837c4c2..c52549b0dea4 100644 --- a/internal/service/cloudfront/distribution.go +++ b/internal/service/cloudfront/distribution.go @@ -628,6 +628,11 @@ func resourceDistribution() *schema.Resource { Type: schema.TypeInt, Required: true, }, + names.AttrIPAddressType: { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.IpAddressType](), + }, "origin_keepalive_timeout": { Type: schema.TypeInt, Optional: true, @@ -2446,6 +2451,10 @@ func expandCustomOriginConfig(tfMap map[string]any) *awstypes.CustomOriginConfig OriginSslProtocols: expandCustomOriginConfigSSL(tfMap["origin_ssl_protocols"].(*schema.Set).List()), } + if v, ok := tfMap[names.AttrIPAddressType]; ok && v.(string) != "" { + apiObject.IpAddressType = awstypes.IpAddressType(v.(string)) + } + return apiObject } @@ -2463,6 +2472,10 @@ func flattenCustomOriginConfig(apiObject *awstypes.CustomOriginConfig) map[strin "origin_ssl_protocols": flattenCustomOriginConfigSSL(apiObject.OriginSslProtocols), } + if apiObject.IpAddressType != "" { + tfMap[names.AttrIPAddressType] = apiObject.IpAddressType + } + return tfMap } diff --git a/internal/service/cloudfront/distribution_test.go b/internal/service/cloudfront/distribution_test.go index 1ba78e3b72ab..943432b81de4 100644 --- a/internal/service/cloudfront/distribution_test.go +++ b/internal/service/cloudfront/distribution_test.go @@ -180,6 +180,7 @@ func TestAccCloudFrontDistribution_customOrigin(t *testing.T) { var distribution awstypes.Distribution rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_cloudfront_distribution.custom_distribution" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) }, @@ -190,7 +191,48 @@ func TestAccCloudFrontDistribution_customOrigin(t *testing.T) { { Config: testAccDistributionConfig_custom(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckDistributionExists(ctx, "aws_cloudfront_distribution.custom_distribution", &distribution), + testAccCheckDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, "origin.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_origin_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_origin_config.0.ip_address_type", ""), + ), + }, + { + ResourceName: "aws_cloudfront_distribution.custom_distribution", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "retain_on_delete", + "wait_for_deployment", + }, + }, + }, + }) +} + +func TestAccCloudFrontDistribution_customOriginIPAddressType(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var distribution awstypes.Distribution + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_cloudfront_distribution.custom_distribution" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDistributionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDistributionConfig_customIPAddressType(rName, string(awstypes.IpAddressTypeIpv6)), + Check: resource.ComposeTestCheckFunc( + testAccCheckDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, "origin.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_origin_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_origin_config.0.ip_address_type", string(awstypes.IpAddressTypeIpv6)), ), }, { @@ -202,6 +244,15 @@ func TestAccCloudFrontDistribution_customOrigin(t *testing.T) { "wait_for_deployment", }, }, + { + Config: testAccDistributionConfig_customIPAddressType(rName, string(awstypes.IpAddressTypeDualStack)), + Check: resource.ComposeTestCheckFunc( + testAccCheckDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, "origin.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_origin_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_origin_config.0.ip_address_type", string(awstypes.IpAddressTypeDualStack)), + ), + }, }, }) } @@ -2050,6 +2101,76 @@ resource "aws_cloudfront_distribution" "custom_distribution" { `, testAccDistributionRetainConfig())) } +func testAccDistributionConfig_customIPAddressType(rName, ipAddressType string) string { + return acctest.ConfigCompose( + logBucket(rName), + fmt.Sprintf(` +resource "aws_cloudfront_distribution" "custom_distribution" { + depends_on = [aws_s3_bucket_acl.s3_bucket_logs_acl] + + origin { + domain_name = "www.example.com" + origin_id = "myCustomOrigin" + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "http-only" + origin_ssl_protocols = ["SSLv3", "TLSv1"] + origin_read_timeout = 30 + origin_keepalive_timeout = 5 + ip_address_type = %[2]q + } + } + + enabled = true + comment = "Some comment" + default_root_object = "index.html" + + logging_config { + include_cookies = false + bucket = aws_s3_bucket.s3_bucket_logs.bucket_regional_domain_name + prefix = "myprefix" + } + + default_cache_behavior { + allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD"] + target_origin_id = "myCustomOrigin" + smooth_streaming = false + + forwarded_values { + query_string = false + + cookies { + forward = "all" + } + } + + viewer_protocol_policy = "allow-all" + min_ttl = 0 + default_ttl = 3600 + max_ttl = 86400 + } + + price_class = "PriceClass_200" + + restrictions { + geo_restriction { + restriction_type = "whitelist" + locations = ["US", "CA", "GB", "DE"] + } + } + + viewer_certificate { + cloudfront_default_certificate = true + } + + %[1]s +} +`, testAccDistributionRetainConfig(), ipAddressType)) +} + func testAccDistributionConfig_originRequestPolicyDefault(rName string) string { return acctest.ConfigCompose( logBucket(rName), diff --git a/internal/service/cloudtrail/trail_identity_gen_test.go b/internal/service/cloudtrail/trail_identity_gen_test.go index df25b8614ec4..16382e6797bb 100644 --- a/internal/service/cloudtrail/trail_identity_gen_test.go +++ b/internal/service/cloudtrail/trail_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccCloudTrailTrail_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccCloudTrailTrail_Identity_Basic, - "ExistingResource": testAccCloudTrailTrail_Identity_ExistingResource, - "RegionOverride": testAccCloudTrailTrail_Identity_RegionOverride, + acctest.CtBasic: testAccCloudTrailTrail_Identity_Basic, + "ExistingResource": testAccCloudTrailTrail_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccCloudTrailTrail_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccCloudTrailTrail_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/codeartifact/domain_identity_gen_test.go b/internal/service/codeartifact/domain_identity_gen_test.go index 10d72ece764d..4c3feef38662 100644 --- a/internal/service/codeartifact/domain_identity_gen_test.go +++ b/internal/service/codeartifact/domain_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccCodeArtifactDomain_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccCodeArtifactDomain_Identity_Basic, - "ExistingResource": testAccCodeArtifactDomain_Identity_ExistingResource, - "RegionOverride": testAccCodeArtifactDomain_Identity_RegionOverride, + acctest.CtBasic: testAccCodeArtifactDomain_Identity_Basic, + "ExistingResource": testAccCodeArtifactDomain_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccCodeArtifactDomain_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccCodeArtifactDomain_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/codeartifact/domain_permissions_policy_identity_gen_test.go b/internal/service/codeartifact/domain_permissions_policy_identity_gen_test.go index e6726bd1c475..e331d30a15c1 100644 --- a/internal/service/codeartifact/domain_permissions_policy_identity_gen_test.go +++ b/internal/service/codeartifact/domain_permissions_policy_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccCodeArtifactDomainPermissionsPolicy_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccCodeArtifactDomainPermissionsPolicy_Identity_Basic, - "ExistingResource": testAccCodeArtifactDomainPermissionsPolicy_Identity_ExistingResource, - "RegionOverride": testAccCodeArtifactDomainPermissionsPolicy_Identity_RegionOverride, + acctest.CtBasic: testAccCodeArtifactDomainPermissionsPolicy_Identity_Basic, + "ExistingResource": testAccCodeArtifactDomainPermissionsPolicy_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccCodeArtifactDomainPermissionsPolicy_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccCodeArtifactDomainPermissionsPolicy_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/codeartifact/repository_identity_gen_test.go b/internal/service/codeartifact/repository_identity_gen_test.go index 195e5a3c9587..b0543bc96902 100644 --- a/internal/service/codeartifact/repository_identity_gen_test.go +++ b/internal/service/codeartifact/repository_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccCodeArtifactRepository_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccCodeArtifactRepository_Identity_Basic, - "ExistingResource": testAccCodeArtifactRepository_Identity_ExistingResource, - "RegionOverride": testAccCodeArtifactRepository_Identity_RegionOverride, + acctest.CtBasic: testAccCodeArtifactRepository_Identity_Basic, + "ExistingResource": testAccCodeArtifactRepository_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccCodeArtifactRepository_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccCodeArtifactRepository_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/codeartifact/repository_permissions_policy_identity_gen_test.go b/internal/service/codeartifact/repository_permissions_policy_identity_gen_test.go index 9e8a04165a96..a0c3a0f8f311 100644 --- a/internal/service/codeartifact/repository_permissions_policy_identity_gen_test.go +++ b/internal/service/codeartifact/repository_permissions_policy_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccCodeArtifactRepositoryPermissionsPolicy_IdentitySerial(t *testing.T) t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccCodeArtifactRepositoryPermissionsPolicy_Identity_Basic, - "ExistingResource": testAccCodeArtifactRepositoryPermissionsPolicy_Identity_ExistingResource, - "RegionOverride": testAccCodeArtifactRepositoryPermissionsPolicy_Identity_RegionOverride, + acctest.CtBasic: testAccCodeArtifactRepositoryPermissionsPolicy_Identity_Basic, + "ExistingResource": testAccCodeArtifactRepositoryPermissionsPolicy_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccCodeArtifactRepositoryPermissionsPolicy_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccCodeArtifactRepositoryPermissionsPolicy_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/codebuild/service_package_gen.go b/internal/service/codebuild/service_package_gen.go index 50c655fe1ac1..68d1abad9c9a 100644 --- a/internal/service/codebuild/service_package_gen.go +++ b/internal/service/codebuild/service_package_gen.go @@ -17,6 +17,17 @@ import ( type servicePackage struct{} +func (p *servicePackage) Actions(ctx context.Context) []*inttypes.ServicePackageAction { + return []*inttypes.ServicePackageAction{ + { + Factory: newStartBuildAction, + TypeName: "aws_codebuild_start_build", + Name: "CodeBuild Start Build", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, + } +} + func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*inttypes.ServicePackageFrameworkDataSource { return []*inttypes.ServicePackageFrameworkDataSource{} } diff --git a/internal/service/codebuild/start_build_action.go b/internal/service/codebuild/start_build_action.go new file mode 100644 index 000000000000..a67229b96030 --- /dev/null +++ b/internal/service/codebuild/start_build_action.go @@ -0,0 +1,187 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package codebuild + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/codebuild" + awstypes "github.com/aws/aws-sdk-go-v2/service/codebuild/types" + "github.com/hashicorp/terraform-plugin-framework/action" + "github.com/hashicorp/terraform-plugin-framework/action/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/actionwait" + "github.com/hashicorp/terraform-provider-aws/internal/backoff" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @Action(aws_codebuild_start_build, name="CodeBuild Start Build") +func newStartBuildAction(context.Context) (action.ActionWithConfigure, error) { + return &startBuildAction{}, nil +} + +type startBuildAction struct { + framework.ActionWithModel[startBuildActionModel] +} + +type startBuildActionModel struct { + framework.WithRegionModel + ProjectName types.String `tfsdk:"project_name"` + SourceVersion types.String `tfsdk:"source_version"` + Timeout types.Int64 `tfsdk:"timeout"` + EnvironmentVariablesOverride fwtypes.ListNestedObjectValueOf[environmentVariableModel] `tfsdk:"environment_variables_override"` + BuildID types.String `tfsdk:"build_id"` +} + +type environmentVariableModel struct { + Name types.String `tfsdk:"name"` + Value types.String `tfsdk:"value"` + Type types.String `tfsdk:"type"` +} + +func (a *startBuildAction) Schema(ctx context.Context, req action.SchemaRequest, resp *action.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Starts a CodeBuild project build", + Attributes: map[string]schema.Attribute{ + "project_name": schema.StringAttribute{ + Description: "Name of the CodeBuild project", + Required: true, + }, + "source_version": schema.StringAttribute{ + Description: "Version of the build input to be built", + Optional: true, + }, + names.AttrTimeout: schema.Int64Attribute{ + Description: "Timeout in seconds for the build operation", + Optional: true, + }, + "build_id": schema.StringAttribute{ + Description: "ID of the started build", + Optional: true, + }, + }, + Blocks: map[string]schema.Block{ + "environment_variables_override": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[environmentVariableModel](ctx), + Description: "Environment variables to override for this build", + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + names.AttrName: schema.StringAttribute{ + Description: "Environment variable name", + Required: true, + }, + names.AttrValue: schema.StringAttribute{ + Description: "Environment variable value", + Required: true, + }, + names.AttrType: schema.StringAttribute{ + Description: "Environment variable type", + Optional: true, + }, + }, + }, + }, + }, + } +} + +func (a *startBuildAction) Invoke(ctx context.Context, req action.InvokeRequest, resp *action.InvokeResponse) { + var model startBuildActionModel + resp.Diagnostics.Append(req.Config.Get(ctx, &model)...) + if resp.Diagnostics.HasError() { + return + } + + conn := a.Meta().CodeBuildClient(ctx) + + timeout := 30 * time.Minute + if !model.Timeout.IsNull() { + timeout = time.Duration(model.Timeout.ValueInt64()) * time.Second + } + + tflog.Info(ctx, "Starting CodeBuild project build", map[string]any{ + "project_name": model.ProjectName.ValueString(), + }) + + resp.SendProgress(action.InvokeProgressEvent{ + Message: "Starting CodeBuild project build...", + }) + + var input codebuild.StartBuildInput + resp.Diagnostics.Append(fwflex.Expand(ctx, model, &input)...) + if resp.Diagnostics.HasError() { + return + } + + output, err := conn.StartBuild(ctx, &input) + if err != nil { + resp.Diagnostics.AddError("Starting CodeBuild project build", err.Error()) + return + } + + buildID := aws.ToString(output.Build.Id) + model.BuildID = types.StringValue(buildID) + + resp.SendProgress(action.InvokeProgressEvent{ + Message: "Build started, waiting for completion...", + }) + + // Poll for build completion using actionwait with backoff strategy + // Use backoff since builds can take a long time and status changes less frequently + // as the build progresses - start with frequent polling then back off + _, err = actionwait.WaitForStatus(ctx, func(ctx context.Context) (actionwait.FetchResult[*awstypes.Build], error) { + input := codebuild.BatchGetBuildsInput{Ids: []string{buildID}} + batch, berr := conn.BatchGetBuilds(ctx, &input) + if berr != nil { + return actionwait.FetchResult[*awstypes.Build]{}, berr + } + if len(batch.Builds) == 0 { + return actionwait.FetchResult[*awstypes.Build]{}, fmt.Errorf("build not found in BatchGetBuilds response") + } + b := batch.Builds[0] + return actionwait.FetchResult[*awstypes.Build]{Status: actionwait.Status(b.BuildStatus), Value: &b}, nil + }, actionwait.Options[*awstypes.Build]{ + Timeout: timeout, + Interval: actionwait.WithBackoffDelay(backoff.DefaultSDKv2HelperRetryCompatibleDelay()), + ProgressInterval: 2 * time.Minute, + SuccessStates: []actionwait.Status{actionwait.Status(awstypes.StatusTypeSucceeded)}, + TransitionalStates: []actionwait.Status{ + actionwait.Status(awstypes.StatusTypeInProgress), + }, + FailureStates: []actionwait.Status{ + actionwait.Status(awstypes.StatusTypeFailed), + actionwait.Status(awstypes.StatusTypeFault), + actionwait.Status(awstypes.StatusTypeStopped), + actionwait.Status(awstypes.StatusTypeTimedOut), + }, + ProgressSink: func(fr actionwait.FetchResult[any], meta actionwait.ProgressMeta) { + resp.SendProgress(action.InvokeProgressEvent{Message: "Build currently in state: " + string(fr.Status)}) + }, + }) + if err != nil { + var timeoutErr *actionwait.TimeoutError + var failureErr *actionwait.FailureStateError + var unexpectedErr *actionwait.UnexpectedStateError + if errors.As(err, &timeoutErr) { + resp.Diagnostics.AddError("Build timeout", "Build did not complete within the specified timeout") + } else if errors.As(err, &failureErr) { + resp.Diagnostics.AddError("Build failed", "Build completed with status: "+err.Error()) + } else if errors.As(err, &unexpectedErr) { + resp.Diagnostics.AddError("Unexpected build status", err.Error()) + } else { + resp.Diagnostics.AddError("Error waiting for build", err.Error()) + } + return + } + + resp.SendProgress(action.InvokeProgressEvent{Message: "Build completed successfully"}) +} diff --git a/internal/service/codebuild/start_build_action_test.go b/internal/service/codebuild/start_build_action_test.go new file mode 100644 index 000000000000..9c8e4153d56f --- /dev/null +++ b/internal/service/codebuild/start_build_action_test.go @@ -0,0 +1,277 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package codebuild_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/aws/aws-sdk-go-v2/service/codebuild" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccCodeBuildStartBuildAction_basic(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.CodeBuildServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: testAccCheckProjectDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccStartBuildActionConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBuildStarted(ctx, rName), + ), + }, + }, + }) +} + +func TestAccCodeBuildStartBuildAction_withEnvironmentVariables(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.CodeBuildServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: testAccCheckProjectDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccStartBuildActionConfig_withEnvironmentVariables(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckBuildStarted(ctx, rName), + ), + }, + }, + }) +} + +func testAccCheckBuildStarted(ctx context.Context, projectName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).CodeBuildClient(ctx) + + // List builds for the project + input := &codebuild.ListBuildsForProjectInput{ + ProjectName: &projectName, + } + + timeout := time.After(5 * time.Minute) + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + + for { + select { + case <-timeout: + return fmt.Errorf("timeout waiting for build to be started for project %s", projectName) + case <-ticker.C: + output, err := conn.ListBuildsForProject(ctx, input) + if err != nil { + continue + } + + if len(output.Ids) == 0 { + continue + } + + // Get build details + batchInput := &codebuild.BatchGetBuildsInput{ + Ids: output.Ids[:1], // Check most recent build + } + batchOutput, err := conn.BatchGetBuilds(ctx, batchInput) + if err != nil { + continue + } + + if len(batchOutput.Builds) > 0 { + build := batchOutput.Builds[0] + // Verify build was started (any status other than not found) + if build.BuildStatus != "" { + return nil + } + } + } + } + } +} + +func testAccStartBuildActionConfig_basic(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "codebuild.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_role_policy" "test" { + role = aws_iam_role.test.name + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + Resource = "arn:${data.aws_partition.current.partition}:logs:*:*:*" + } + ] + }) +} + +resource "aws_codebuild_project" "test" { + name = %[1]q + service_role = aws_iam_role.test.arn + + artifacts { + type = "NO_ARTIFACTS" + } + + environment { + compute_type = "BUILD_GENERAL1_SMALL" + image = "aws/codebuild/amazonlinux2-x86_64-standard:3.0" + type = "LINUX_CONTAINER" + } + + source { + type = "NO_SOURCE" + buildspec = "version: 0.2\nphases:\n build:\n commands:\n - echo 'Hello World'" + } +} + +action "aws_codebuild_start_build" "test" { + config { + project_name = aws_codebuild_project.test.name + } +} + +resource "terraform_data" "trigger" { + lifecycle { + action_trigger { + events = [after_create] + actions = [action.aws_codebuild_start_build.test] + } + } + + depends_on = [aws_codebuild_project.test] +} +`, rName) +} + +func testAccStartBuildActionConfig_withEnvironmentVariables(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "codebuild.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_role_policy" "test" { + role = aws_iam_role.test.name + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + Resource = "arn:${data.aws_partition.current.partition}:logs:*:*:*" + } + ] + }) +} + +resource "aws_codebuild_project" "test" { + name = %[1]q + service_role = aws_iam_role.test.arn + + artifacts { + type = "NO_ARTIFACTS" + } + + environment { + compute_type = "BUILD_GENERAL1_SMALL" + image = "aws/codebuild/amazonlinux2-x86_64-standard:3.0" + type = "LINUX_CONTAINER" + } + + source { + type = "NO_SOURCE" + buildspec = "version: 0.2\nphases:\n build:\n commands:\n - echo \"TEST_VAR is $TEST_VAR\"" + } +} + +action "aws_codebuild_start_build" "test" { + config { + project_name = aws_codebuild_project.test.name + + environment_variables_override { + name = "TEST_VAR" + value = "test_value" + type = "PLAINTEXT" + } + } +} + +resource "terraform_data" "trigger" { + lifecycle { + action_trigger { + events = [after_create] + actions = [action.aws_codebuild_start_build.test] + } + } + + depends_on = [aws_codebuild_project.test] +} +`, rName) +} diff --git a/internal/service/connect/instance_identity_gen_test.go b/internal/service/connect/instance_identity_gen_test.go index dc999e2c54c9..d17dfba217d3 100644 --- a/internal/service/connect/instance_identity_gen_test.go +++ b/internal/service/connect/instance_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccConnectInstance_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccConnectInstance_Identity_Basic, - "ExistingResource": testAccConnectInstance_Identity_ExistingResource, - "RegionOverride": testAccConnectInstance_Identity_RegionOverride, + acctest.CtBasic: testAccConnectInstance_Identity_Basic, + "ExistingResource": testAccConnectInstance_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccConnectInstance_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccConnectInstance_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/connect/phone_number_identity_gen_test.go b/internal/service/connect/phone_number_identity_gen_test.go index 8cacf22b0ad0..d91e19aa8f47 100644 --- a/internal/service/connect/phone_number_identity_gen_test.go +++ b/internal/service/connect/phone_number_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccConnectPhoneNumber_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccConnectPhoneNumber_Identity_Basic, - "ExistingResource": testAccConnectPhoneNumber_Identity_ExistingResource, - "RegionOverride": testAccConnectPhoneNumber_Identity_RegionOverride, + acctest.CtBasic: testAccConnectPhoneNumber_Identity_Basic, + "ExistingResource": testAccConnectPhoneNumber_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccConnectPhoneNumber_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccConnectPhoneNumber_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/datazone/asset_type_test.go b/internal/service/datazone/asset_type_test.go index a706f323ec4e..39d7d12111ae 100644 --- a/internal/service/datazone/asset_type_test.go +++ b/internal/service/datazone/asset_type_test.go @@ -31,8 +31,6 @@ func TestAccDataZoneAssetType_basic(t *testing.T) { var assettype datazone.GetAssetTypeOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_asset_type.test" projectName := "aws_datazone_project.test" domainName := "aws_datazone_domain.test" @@ -48,7 +46,7 @@ func TestAccDataZoneAssetType_basic(t *testing.T) { CheckDestroy: testAccCheckAssetTypeDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccAssetTypeConfig_basic(rName, pName, dName), + Config: testAccAssetTypeConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAssetTypeExists(ctx, resourceName, &assettype), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), @@ -79,8 +77,6 @@ func TestAccDataZoneAssetType_disappears(t *testing.T) { var assettype datazone.GetAssetTypeOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_asset_type.test" resource.ParallelTest(t, resource.TestCase{ @@ -94,7 +90,7 @@ func TestAccDataZoneAssetType_disappears(t *testing.T) { CheckDestroy: testAccCheckAssetTypeDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccAssetTypeConfig_basic(rName, pName, dName), + Config: testAccAssetTypeConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAssetTypeExists(ctx, resourceName, &assettype), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceAssetType, resourceName), @@ -164,8 +160,8 @@ func testAccAssetTypeImportStateIdFunc(resourceName string) resource.ImportState } } -func testAccAssetTypeConfig_basic(rName, pName, dName string) string { - return acctest.ConfigCompose(testAccProjectConfig_basic(pName, dName), fmt.Sprintf(` +func testAccAssetTypeConfig_basic(rName string) string { + return acctest.ConfigCompose(testAccProjectConfig_basic(rName), fmt.Sprintf(` resource "aws_datazone_asset_type" "test" { description = %[1]q domain_identifier = aws_datazone_domain.test.id diff --git a/internal/service/datazone/datazone_test.go b/internal/service/datazone/datazone_test.go deleted file mode 100644 index 1d0f50f9cd1d..000000000000 --- a/internal/service/datazone/datazone_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package datazone_test - -import ( - "testing" - - "github.com/hashicorp/terraform-provider-aws/internal/acctest" -) - -func TestAccDataZone_serial(t *testing.T) { - t.Parallel() - - testCases := map[string]map[string]func(t *testing.T){ - "Environment": { - acctest.CtBasic: testAccEnvironment_basic, - acctest.CtDisappears: testAccEnvironment_disappears, - "update": testAccEnvironment_update, - }, - } - - acctest.RunSerialTests2Levels(t, testCases, 0) -} diff --git a/internal/service/datazone/environment.go b/internal/service/datazone/environment.go index 08469ca4557a..ae1f4938df05 100644 --- a/internal/service/datazone/environment.go +++ b/internal/service/datazone/environment.go @@ -15,6 +15,7 @@ import ( awstypes "github.com/aws/aws-sdk-go-v2/service/datazone/types" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -142,6 +143,7 @@ func (r *environmentResource) Schema(ctx context.Context, req resource.SchemaReq CustomType: fwtypes.NewListNestedObjectTypeOf[resourceUserParametersData](ctx), PlanModifiers: []planmodifier.List{ listplanmodifier.UseStateForUnknown(), + listplanmodifier.RequiresReplace(), }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ @@ -219,7 +221,7 @@ func (r *environmentResource) Create(ctx context.Context, req resource.CreateReq return } - resp.Diagnostics.Append(fwflex.Flatten(ctx, output, &state, fwflex.WithIgnoredFieldNames([]string{"UserParameters"}))...) + flattenEnvironment(ctx, output, &state, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } @@ -252,21 +254,14 @@ func (r *environmentResource) Read(ctx context.Context, req resource.ReadRequest return } - resp.Diagnostics.Append(fwflex.Flatten(ctx, out, &state, fwflex.WithIgnoredFieldNamesAppend("UserParameters"), - fwflex.WithFieldNamePrefix("Environment"), - )...) - + flattenEnvironment(ctx, out, &state, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - state.AccountIdentifier = fwflex.StringToFramework(ctx, out.AwsAccountId) - state.AccountRegion = fwflex.StringToFramework(ctx, out.AwsAccountRegion) - state.ProjectIdentifier = fwflex.StringToFramework(ctx, out.ProjectId) - state.ProfileIdentifier = fwflex.StringToFramework(ctx, out.EnvironmentProfileId) - resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } + func (r *environmentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { conn := r.Meta().DataZoneClient(ctx) @@ -277,18 +272,35 @@ func (r *environmentResource) Update(ctx context.Context, req resource.UpdateReq return } - if !plan.Name.Equal(state.Name) || - !plan.Description.Equal(state.Description) || - !plan.GlossaryTerms.Equal(state.GlossaryTerms) { - in := &datazone.UpdateEnvironmentInput{} - resp.Diagnostics.Append(fwflex.Expand(ctx, plan, in)...) + var ( + needsUpdate bool + ) + input := datazone.UpdateEnvironmentInput{ + DomainIdentifier: plan.DomainIdentifier.ValueStringPointer(), + Identifier: plan.Id.ValueStringPointer(), + } + + if !plan.Name.Equal(state.Name) { + needsUpdate = true + input.Name = plan.Name.ValueStringPointer() + } - if resp.Diagnostics.HasError() { + if !plan.Description.Equal(state.Description) { + needsUpdate = true + input.Description = plan.Description.ValueStringPointer() + } + + if !plan.GlossaryTerms.Equal(state.GlossaryTerms) { + needsUpdate = true + d := fwflex.Expand(ctx, &plan.GlossaryTerms, &input.GlossaryTerms) + resp.Diagnostics.Append(d...) + if d.HasError() { return } - in.Identifier = state.Id.ValueStringPointer() + } - out, err := conn.UpdateEnvironment(ctx, in) + if needsUpdate { + out, err := conn.UpdateEnvironment(ctx, &input) if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.DataZone, create.ErrActionUpdating, ResNameEnvironment, plan.Id.String(), err), @@ -306,7 +318,7 @@ func (r *environmentResource) Update(ctx context.Context, req resource.UpdateReq } updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) - _, err = waitEnvironmentUpdated(ctx, conn, plan.DomainIdentifier.ValueString(), plan.Id.ValueString(), updateTimeout) + output, err := waitEnvironmentUpdated(ctx, conn, plan.DomainIdentifier.ValueString(), plan.Id.ValueString(), updateTimeout) if err != nil { resp.Diagnostics.AddError( @@ -315,6 +327,11 @@ func (r *environmentResource) Update(ctx context.Context, req resource.UpdateReq ) return } + + flattenEnvironment(ctx, output, &plan, &resp.Diagnostics) + if resp.Diagnostics.HasError() { + return + } } resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) @@ -375,8 +392,8 @@ func (r *environmentResource) ImportState(ctx context.Context, req resource.Impo func waitEnvironmentCreated(ctx context.Context, conn *datazone.Client, domainId string, id string, timeout time.Duration) (*datazone.GetEnvironmentOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: enum.Slice[awstypes.EnvironmentStatus](awstypes.EnvironmentStatusCreating), - Target: enum.Slice[awstypes.EnvironmentStatus](awstypes.EnvironmentStatusActive), + Pending: enum.Slice(awstypes.EnvironmentStatusCreating), + Target: enum.Slice(awstypes.EnvironmentStatusActive), Refresh: statusEnvironment(ctx, conn, domainId, id), Timeout: timeout, NotFoundChecks: 20, @@ -385,7 +402,7 @@ func waitEnvironmentCreated(ctx context.Context, conn *datazone.Client, domainId outputRaw, err := stateConf.WaitForStateContext(ctx) if out, ok := outputRaw.(*datazone.GetEnvironmentOutput); ok { - if status, deployment := out.Status, out.LastDeployment; status == awstypes.EnvironmentStatusCreateFailed && deployment != nil { + if status, deployment := out.Status, out.LastDeployment; (status == awstypes.EnvironmentStatusCreateFailed || status == awstypes.EnvironmentStatusValidationFailed) && deployment != nil { tfresource.SetLastError(err, fmt.Errorf("%s: %s", status, aws.ToString(deployment.FailureReason.Message))) } return out, err @@ -396,8 +413,8 @@ func waitEnvironmentCreated(ctx context.Context, conn *datazone.Client, domainId func waitEnvironmentUpdated(ctx context.Context, conn *datazone.Client, domainId string, id string, timeout time.Duration) (*datazone.GetEnvironmentOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: enum.Slice[awstypes.EnvironmentStatus](awstypes.EnvironmentStatusUpdating), - Target: enum.Slice[awstypes.EnvironmentStatus](awstypes.EnvironmentStatusActive), + Pending: enum.Slice(awstypes.EnvironmentStatusUpdating), + Target: enum.Slice(awstypes.EnvironmentStatusActive), Refresh: statusEnvironment(ctx, conn, domainId, id), Timeout: timeout, NotFoundChecks: 20, @@ -417,10 +434,12 @@ func waitEnvironmentUpdated(ctx context.Context, conn *datazone.Client, domainId func waitEnvironmentDeleted(ctx context.Context, conn *datazone.Client, domainId string, id string, timeout time.Duration) (*datazone.GetEnvironmentOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: enum.Slice(awstypes.EnvironmentStatusDeleting, awstypes.EnvironmentStatusActive), - Target: []string{}, - Refresh: statusEnvironment(ctx, conn, domainId, id), - Timeout: timeout, + Pending: enum.Slice(awstypes.EnvironmentStatusActive, awstypes.EnvironmentStatusDeleting, awstypes.EnvironmentStatusDeleted), + Target: []string{}, + Refresh: statusEnvironment(ctx, conn, domainId, id), + Timeout: timeout, + Delay: 10 * time.Second, + PollInterval: 5 * time.Second, } outputRaw, err := stateConf.WaitForStateContext(ctx) @@ -479,7 +498,7 @@ type environmentResourceModel struct { framework.WithRegionModel AccountIdentifier types.String `tfsdk:"account_identifier"` AccountRegion types.String `tfsdk:"account_region"` - BlueprintId types.String `tfsdk:"blueprint_identifier"` + BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"` CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` CreatedBy types.String `tfsdk:"created_by"` Description types.String `tfsdk:"description"` @@ -496,6 +515,23 @@ type environmentResourceModel struct { UserParameters fwtypes.ListNestedObjectValueOf[resourceUserParametersData] `tfsdk:"user_parameters"` } +// nosemgrep:ci.semgrep.framework.manual-flattener-functions +func flattenEnvironment(ctx context.Context, apiObject *datazone.GetEnvironmentOutput, model *environmentResourceModel, diags *diag.Diagnostics) { + diags.Append(fwflex.Flatten(ctx, apiObject, model, fwflex.WithIgnoredFieldNamesAppend("UserParameters"))...) + + model.AccountIdentifier = fwflex.StringToFramework(ctx, apiObject.AwsAccountId) + model.AccountRegion = fwflex.StringToFramework(ctx, apiObject.AwsAccountRegion) + model.BlueprintIdentifier = fwflex.StringToFramework(ctx, apiObject.EnvironmentBlueprintId) + model.ProfileIdentifier = fwflex.StringToFramework(ctx, apiObject.EnvironmentProfileId) + model.ProjectIdentifier = fwflex.StringToFramework(ctx, apiObject.ProjectId) + + if model.UserParameters.IsNull() { // Import + importUserParameters(ctx, &model.UserParameters, apiObject.UserParameters, diags) + } else { + populateUserParameters(ctx, &model.UserParameters, apiObject.UserParameters, diags) + } +} + type resourceLastDeployment struct { DeploymentId types.String `tfsdk:"deployment_id"` DeploymentStatus types.String `tfsdk:"deployment_status"` @@ -521,3 +557,38 @@ type resourceUserParametersData struct { Name types.String `tfsdk:"name"` Value types.String `tfsdk:"value"` } + +func importUserParameters(ctx context.Context, stateUserParams *fwtypes.ListNestedObjectValueOf[resourceUserParametersData], userParameters []awstypes.CustomParameter, diags *diag.Diagnostics) { + params := make([]resourceUserParametersData, 0, len(userParameters)) + for _, param := range userParameters { + // If `DefaultValue` is nil, no value has been set + if param.DefaultValue != nil { + params = append(params, resourceUserParametersData{ + Name: fwflex.StringToFramework(ctx, param.KeyName), + Value: fwflex.StringToFramework(ctx, param.DefaultValue), + }) + } + } + s, d := fwtypes.NewListNestedObjectValueOfValueSlice(ctx, params) + diags.Append(d...) + if d.HasError() { + return + } + *stateUserParams = s +} + +func populateUserParameters(ctx context.Context, stateUserParams *fwtypes.ListNestedObjectValueOf[resourceUserParametersData], userParameters []awstypes.CustomParameter, diags *diag.Diagnostics) { + params, d := stateUserParams.ToSlice(ctx) + diags.Append(d...) + if d.HasError() { + return + } + for _, p := range params { + for _, up := range userParameters { + if p.Name.ValueString() == aws.ToString(up.KeyName) { + p.Value = fwflex.StringToFramework(ctx, up.DefaultValue) + break + } + } + } +} diff --git a/internal/service/datazone/environment_profile_test.go b/internal/service/datazone/environment_profile_test.go index 72747140c19c..9de1ace85c77 100644 --- a/internal/service/datazone/environment_profile_test.go +++ b/internal/service/datazone/environment_profile_test.go @@ -26,9 +26,7 @@ func TestAccDataZoneEnvironmentProfile_basic(t *testing.T) { ctx := acctest.Context(t) var environmentprofile datazone.GetEnvironmentProfileOutput - epName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_environment_profile.test" domainName := "aws_datazone_domain.test" @@ -47,7 +45,7 @@ func TestAccDataZoneEnvironmentProfile_basic(t *testing.T) { CheckDestroy: testAccCheckEnvironmentProfileDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccEnvironmentProfileConfig_basic(epName, dName, pName), + Config: testAccEnvironmentProfileConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckEnvironmentProfileExists(ctx, resourceName, &environmentprofile), resource.TestCheckResourceAttrPair(resourceName, names.AttrAWSAccountID, callName, names.AttrAccountID), @@ -57,7 +55,7 @@ func TestAccDataZoneEnvironmentProfile_basic(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), resource.TestCheckResourceAttrPair(resourceName, "environment_blueprint_identifier", blueName, names.AttrID), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttr(resourceName, names.AttrName, epName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrPair(resourceName, "project_identifier", projectName, names.AttrID), ), }, @@ -76,9 +74,7 @@ func TestAccDataZoneEnvironmentProfile_disappears(t *testing.T) { ctx := acctest.Context(t) var environmentprofile datazone.GetEnvironmentProfileOutput - epName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_environment_profile.test" @@ -92,7 +88,7 @@ func TestAccDataZoneEnvironmentProfile_disappears(t *testing.T) { CheckDestroy: testAccCheckEnvironmentProfileDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccEnvironmentProfileConfig_basic(epName, dName, pName), + Config: testAccEnvironmentProfileConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckEnvironmentProfileExists(ctx, resourceName, &environmentprofile), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceEnvironmentProfile, resourceName), @@ -107,9 +103,7 @@ func TestAccDataZoneEnvironmentProfile_update(t *testing.T) { ctx := acctest.Context(t) var environmentprofile datazone.GetEnvironmentProfileOutput - epName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_environment_profile.test" domainName := "aws_datazone_domain.test" @@ -128,7 +122,7 @@ func TestAccDataZoneEnvironmentProfile_update(t *testing.T) { CheckDestroy: testAccCheckEnvironmentProfileDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccEnvironmentProfileConfig_basic(epName, dName, pName), + Config: testAccEnvironmentProfileConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckEnvironmentProfileExists(ctx, resourceName, &environmentprofile), resource.TestCheckResourceAttrPair(resourceName, names.AttrAWSAccountID, callName, names.AttrAccountID), @@ -141,7 +135,7 @@ func TestAccDataZoneEnvironmentProfile_update(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), resource.TestCheckResourceAttrPair(resourceName, "environment_blueprint_identifier", blueName, names.AttrID), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttr(resourceName, names.AttrName, epName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrPair(resourceName, "project_identifier", projectName, names.AttrID), ), }, @@ -153,7 +147,7 @@ func TestAccDataZoneEnvironmentProfile_update(t *testing.T) { ImportStateVerifyIgnore: []string{"user_parameters"}, }, { - Config: testAccEnvironmentProfileConfig_update(epName, dName, pName), + Config: testAccEnvironmentProfileConfig_update(rName), Check: resource.ComposeTestCheckFunc( testAccCheckEnvironmentProfileExists(ctx, resourceName, &environmentprofile), testAccCheckEnvironmentProfileExists(ctx, resourceName, &environmentprofile), @@ -167,7 +161,7 @@ func TestAccDataZoneEnvironmentProfile_update(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), resource.TestCheckResourceAttrPair(resourceName, "environment_blueprint_identifier", blueName, names.AttrID), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttr(resourceName, names.AttrName, epName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrPair(resourceName, "project_identifier", projectName, names.AttrID), resource.TestCheckResourceAttrSet(resourceName, "updated_at"), ), @@ -243,9 +237,9 @@ func testAccAuthorizerEnvProfImportStateIdFunc(resourceName string) resource.Imp } } -func testAccEnvironmentProfileConfig_base(domainName, projectName string) string { +func testAccEnvironmentProfileConfig_base(rName string) string { return acctest.ConfigCompose( - testAccProjectConfig_basic(projectName, domainName), + testAccProjectConfig_basic(rName), ` data "aws_caller_identity" "test" {} data "aws_region" "test" {} @@ -265,9 +259,9 @@ resource "aws_datazone_environment_blueprint_configuration" "test" { `) } -func testAccEnvironmentProfileConfig_basic(rName, domainName, projectName string) string { +func testAccEnvironmentProfileConfig_basic(rName string) string { return acctest.ConfigCompose( - testAccEnvironmentProfileConfig_base(domainName, projectName), + testAccEnvironmentProfileConfig_base(rName), fmt.Sprintf(` resource "aws_datazone_environment_profile" "test" { aws_account_id = data.aws_caller_identity.test.account_id @@ -285,9 +279,9 @@ resource "aws_datazone_environment_profile" "test" { `, rName)) } -func testAccEnvironmentProfileConfig_update(rName, domainName, projectName string) string { +func testAccEnvironmentProfileConfig_update(rName string) string { return acctest.ConfigCompose( - testAccEnvironmentProfileConfig_base(domainName, projectName), + testAccEnvironmentProfileConfig_base(rName), fmt.Sprintf(` resource "aws_datazone_environment_profile" "test" { aws_account_id = data.aws_caller_identity.test.account_id diff --git a/internal/service/datazone/environment_test.go b/internal/service/datazone/environment_test.go index b3e042e4fd88..52e39d310697 100644 --- a/internal/service/datazone/environment_test.go +++ b/internal/service/datazone/environment_test.go @@ -11,9 +11,14 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/service/datazone" + "github.com/hashicorp/terraform-plugin-testing/compare" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" @@ -22,7 +27,25 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func testAccEnvironment_basic(t *testing.T) { +// Tests need to be serialized due to `aws_lakeformation_data_lake_settings` dependency +func TestAccDataZoneEnvironment_serial(t *testing.T) { + t.Parallel() + + testCases := map[string]func(t *testing.T){ + acctest.CtBasic: testAccDataZoneEnvironment_basic, + acctest.CtDisappears: testAccDataZoneEnvironment_disappears, + "updateNameAndDescription": testAccDataZoneEnvironment_updateNameAndDescription, + "accountIDAndRegion": testAccDataZoneEnvironment_accountIDAndRegion, + "userParameters_Environment": testAccDataZoneEnvironment_userParameters_Environment, + "userParameters_Inherited": testAccDataZoneEnvironment_userParameters_Inherited, + "userParameters_Override": testAccDataZoneEnvironment_userParameters_Override, + "glossaryTerms": testAccDataZoneEnvironment_glossaryTerms, + } + + acctest.RunSerialTests1Level(t, testCases, 0) +} + +func testAccDataZoneEnvironment_basic(t *testing.T) { ctx := acctest.Context(t) var environment datazone.GetEnvironmentOutput @@ -40,35 +63,38 @@ func testAccEnvironment_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccEnvironmentConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckEnvironmentExists(ctx, resourceName, &environment), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, rName), - resource.TestCheckResourceAttrSet(resourceName, "account_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "account_region"), - resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), + acctest.CheckResourceAttrAccountID(ctx, resourceName, "account_identifier"), + resource.TestCheckResourceAttr(resourceName, "account_region", acctest.Region()), + resource.TestCheckResourceAttrPair(resourceName, "blueprint_identifier", "aws_datazone_environment_blueprint_configuration.test", "environment_blueprint_id"), + acctest.CheckResourceAttrRFC3339(resourceName, names.AttrCreatedAt), resource.TestCheckResourceAttrSet(resourceName, "created_by"), - resource.TestCheckResourceAttrSet(resourceName, "domain_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "blueprint_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "profile_identifier"), - resource.TestCheckResourceAttr(resourceName, "user_parameters.#", "3"), + resource.TestCheckNoResourceAttr(resourceName, names.AttrDescription), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", "aws_datazone_domain.test", names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "profile_identifier", "aws_datazone_environment_profile.test", names.AttrID), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, "project_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "provider_environment"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrPair(resourceName, "project_identifier", "aws_datazone_project.test", names.AttrID), + resource.TestCheckResourceAttr(resourceName, "provider_environment", "Amazon DataZone"), ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("glossary_terms"), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("provisioned_resources"), knownvalue.NotNull()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("user_parameters"), knownvalue.ListSizeExact(0)), + }, }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), - ImportStateVerifyIgnore: []string{"user_parameters"}, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), }, }, }) } -func testAccEnvironment_disappears(t *testing.T) { +func testAccDataZoneEnvironment_disappears(t *testing.T) { ctx := acctest.Context(t) var environment datazone.GetEnvironmentOutput @@ -86,7 +112,7 @@ func testAccEnvironment_disappears(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccEnvironmentConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckEnvironmentExists(ctx, resourceName, &environment), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceEnvironment, resourceName), ), @@ -96,7 +122,7 @@ func testAccEnvironment_disappears(t *testing.T) { }) } -func testAccEnvironment_update(t *testing.T) { +func testAccDataZoneEnvironment_updateNameAndDescription(t *testing.T) { ctx := acctest.Context(t) var environment datazone.GetEnvironmentOutput @@ -114,31 +140,300 @@ func testAccEnvironment_update(t *testing.T) { CheckDestroy: testAccCheckEnvironmentDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccEnvironmentConfig_update(rName, rName), - Check: resource.ComposeTestCheckFunc( + Config: testAccEnvironmentConfig_updateNameAndDescription(rName, rName), + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckEnvironmentExists(ctx, resourceName, &environment), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, rName), - resource.TestCheckResourceAttrSet(resourceName, "account_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "account_region"), - resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), - resource.TestCheckResourceAttrSet(resourceName, "created_by"), - resource.TestCheckResourceAttrSet(resourceName, "domain_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "blueprint_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "profile_identifier"), - resource.TestCheckResourceAttr(resourceName, "user_parameters.#", "3"), - resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, "project_identifier"), - resource.TestCheckResourceAttrSet(resourceName, "provider_environment"), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, rName+"-description"), ), }, { - Config: testAccEnvironmentConfig_update(rName, rNameUpdate), - Check: resource.ComposeTestCheckFunc( + Config: testAccEnvironmentConfig_updateNameAndDescription(rName, rNameUpdate), + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckEnvironmentExists(ctx, resourceName, &environment), resource.TestCheckResourceAttr(resourceName, names.AttrName, rNameUpdate), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, rNameUpdate), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, rNameUpdate+"-description"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), + }, + }, + }) +} + +func testAccDataZoneEnvironment_accountIDAndRegion(t *testing.T) { + ctx := acctest.Context(t) + + var environment datazone.GetEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_environment.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_accountIDAndRegion(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &environment), + acctest.CheckResourceAttrAccountID(ctx, resourceName, "account_identifier"), + resource.TestCheckResourceAttr(resourceName, "account_region", acctest.Region()), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), + }, + }, + }) +} + +func testAccDataZoneEnvironment_userParameters_Environment(t *testing.T) { + ctx := acctest.Context(t) + + var environment datazone.GetEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + parameterPrefix := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + parameterPrefixUpdated := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_environment.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_userParameters(rName, parameterPrefix), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &environment), ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("user_parameters"), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("consumerGlueDbName"), + names.AttrValue: knownvalue.StringExact(parameterPrefix + "-consumer"), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("producerGlueDbName"), + names.AttrValue: knownvalue.StringExact(parameterPrefix + "-producer"), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("workgroupName"), + names.AttrValue: knownvalue.StringExact(parameterPrefix + "-workgroup"), + }), + })), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), + }, + { + Config: testAccEnvironmentConfig_userParameters(rName, parameterPrefixUpdated), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &environment), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("user_parameters"), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("consumerGlueDbName"), + names.AttrValue: knownvalue.StringExact(parameterPrefixUpdated + "-consumer"), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("producerGlueDbName"), + names.AttrValue: knownvalue.StringExact(parameterPrefixUpdated + "-producer"), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("workgroupName"), + names.AttrValue: knownvalue.StringExact(parameterPrefixUpdated + "-workgroup"), + }), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionReplace), + }, + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), + }, + }, + }) +} + +func testAccDataZoneEnvironment_userParameters_Inherited(t *testing.T) { + ctx := acctest.Context(t) + + var environment datazone.GetEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_environment.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_userParameters_Inherited(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &environment), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("user_parameters"), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("workgroupName"), + names.AttrValue: knownvalue.StringExact(rName + "-workgroup"), + }), + })), + }, + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "user_parameters", + }, + ImportStateCheck: acctest.ComposeAggregateImportStateCheckFunc( + acctest.ImportCheckResourceAttr("user_parameters.#", "3"), + acctest.ImportCheckResourceAttr("user_parameters.0.name", "consumerGlueDbName"), + acctest.ImportCheckResourceAttr("user_parameters.0.value", rName+"-consumer-inherited"), + acctest.ImportCheckResourceAttr("user_parameters.1.name", "producerGlueDbName"), + acctest.ImportCheckResourceAttr("user_parameters.1.value", rName+"-producer-inherited"), + acctest.ImportCheckResourceAttr("user_parameters.2.name", "workgroupName"), + acctest.ImportCheckResourceAttr("user_parameters.2.value", rName+"-workgroup"), + ), + }, + }, + }) +} + +func testAccDataZoneEnvironment_userParameters_Override(t *testing.T) { + ctx := acctest.Context(t) + + var environment datazone.GetEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_environment.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_userParameters_Override(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &environment), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("user_parameters"), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("consumerGlueDbName"), + names.AttrValue: knownvalue.StringExact(rName + "-consumer"), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("producerGlueDbName"), + names.AttrValue: knownvalue.StringExact(rName + "-producer"), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrName: knownvalue.StringExact("workgroupName"), + names.AttrValue: knownvalue.StringExact(rName + "-workgroup"), + }), + })), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), + }, + }, + }) +} + +func testAccDataZoneEnvironment_glossaryTerms(t *testing.T) { + ctx := acctest.Context(t) + + var environment datazone.GetEnvironmentOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_environment.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.DataZoneEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_glossaryTerms(rName, 3), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &environment), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("glossary_terms"), knownvalue.ListSizeExact(3)), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New("glossary_terms").AtSliceIndex(0), "aws_datazone_glossary_term.test[0]", tfjsonpath.New(names.AttrID), compare.ValuesSame()), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New("glossary_terms").AtSliceIndex(1), "aws_datazone_glossary_term.test[1]", tfjsonpath.New(names.AttrID), compare.ValuesSame()), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New("glossary_terms").AtSliceIndex(2), "aws_datazone_glossary_term.test[2]", tfjsonpath.New(names.AttrID), compare.ValuesSame()), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), + }, + { + Config: testAccEnvironmentConfig_glossaryTerms(rName, 4), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &environment), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("glossary_terms"), knownvalue.ListSizeExact(4)), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New("glossary_terms").AtSliceIndex(0), "aws_datazone_glossary_term.test[0]", tfjsonpath.New(names.AttrID), compare.ValuesSame()), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New("glossary_terms").AtSliceIndex(1), "aws_datazone_glossary_term.test[1]", tfjsonpath.New(names.AttrID), compare.ValuesSame()), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New("glossary_terms").AtSliceIndex(2), "aws_datazone_glossary_term.test[2]", tfjsonpath.New(names.AttrID), compare.ValuesSame()), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New("glossary_terms").AtSliceIndex(3), "aws_datazone_glossary_term.test[3]", tfjsonpath.New(names.AttrID), compare.ValuesSame()), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccEnvironmentImportStateFunc(resourceName), }, }, }) @@ -282,7 +577,6 @@ resource "aws_security_group" "test" { resource "aws_datazone_project" "test" { domain_identifier = aws_datazone_domain.test.id - glossary_terms = ["2N8w6XJCwZf"] name = %[1]q description = %[1]q skip_deletion_check = true @@ -312,30 +606,77 @@ resource "aws_datazone_environment_blueprint_configuration" "test" { } } } - -resource "aws_datazone_environment_profile" "test" { - aws_account_id = data.aws_caller_identity.test.account_id - aws_account_region = data.aws_region.test.region - environment_blueprint_identifier = data.aws_datazone_environment_blueprint.test.id - description = %[1]q - name = %[1]q - project_identifier = aws_datazone_project.test.id - domain_identifier = aws_datazone_domain.test.id - user_parameters { - name = "consumerGlueDbName" - value = "value" - } -} `, rName) } func testAccEnvironmentConfig_basic(rName string) string { - return acctest.ConfigCompose(testAccEnvironmentConfig_base(rName), fmt.Sprintf(` + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + testAccEnvironmentConfig_EnvironmentProfile_userParameters_None(rName), + fmt.Sprintf(` +resource "aws_datazone_environment" "test" { + name = %[1]q + blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id + profile_identifier = aws_datazone_environment_profile.test.id + project_identifier = aws_datazone_project.test.id + domain_identifier = aws_datazone_domain.test.id + + depends_on = [ + aws_lakeformation_data_lake_settings.test, + ] +} +`, rName)) +} + +func testAccEnvironmentConfig_updateNameAndDescription(rName, rNameUpdated string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + testAccEnvironmentConfig_EnvironmentProfile_userParameters_None(rName), + fmt.Sprintf(` +resource "aws_datazone_environment" "test" { + name = %[2]q + description = "%[2]s-description" + blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id + profile_identifier = aws_datazone_environment_profile.test.id + project_identifier = aws_datazone_project.test.id + domain_identifier = aws_datazone_domain.test.id + + depends_on = [ + aws_lakeformation_data_lake_settings.test, + ] +} +`, rName, rNameUpdated)) +} + +func testAccEnvironmentConfig_accountIDAndRegion(rName string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + testAccEnvironmentConfig_EnvironmentProfile_userParameters_None(rName), + fmt.Sprintf(` +resource "aws_datazone_environment" "test" { + name = %[1]q + blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id + profile_identifier = aws_datazone_environment_profile.test.id + project_identifier = aws_datazone_project.test.id + domain_identifier = aws_datazone_domain.test.id + + account_identifier = data.aws_caller_identity.test.account_id + account_region = data.aws_region.test.region + + depends_on = [ + aws_lakeformation_data_lake_settings.test, + ] +} +`, rName)) +} + +func testAccEnvironmentConfig_userParameters(rName, parameterPrefix string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + testAccEnvironmentConfig_EnvironmentProfile_userParameters_None(rName), + fmt.Sprintf(` resource "aws_datazone_environment" "test" { name = %[1]q - description = %[1]q - account_identifier = data.aws_caller_identity.test.account_id - account_region = data.aws_region.test.region blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id profile_identifier = aws_datazone_environment_profile.test.id project_identifier = aws_datazone_project.test.id @@ -343,14 +684,38 @@ resource "aws_datazone_environment" "test" { user_parameters { name = "consumerGlueDbName" - value = "%[1]s-consumer" + value = "%[2]s-consumer" } user_parameters { name = "producerGlueDbName" - value = "%[1]s-producer" + value = "%[2]s-producer" + } + + user_parameters { + name = "workgroupName" + value = "%[2]s-workgroup" } + depends_on = [ + aws_lakeformation_data_lake_settings.test, + ] +} +`, rName, parameterPrefix)) +} + +func testAccEnvironmentConfig_userParameters_Inherited(rName string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + testAccEnvironmentConfig_EnvironmentProfile_userParameters_Inherited(rName), + fmt.Sprintf(` +resource "aws_datazone_environment" "test" { + name = %[1]q + blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id + profile_identifier = aws_datazone_environment_profile.test.id + project_identifier = aws_datazone_project.test.id + domain_identifier = aws_datazone_domain.test.id + user_parameters { name = "workgroupName" value = "%[1]s-workgroup" @@ -363,13 +728,13 @@ resource "aws_datazone_environment" "test" { `, rName)) } -func testAccEnvironmentConfig_update(rName, rNameUpdated string) string { - return acctest.ConfigCompose(testAccEnvironmentConfig_base(rName), fmt.Sprintf(` +func testAccEnvironmentConfig_userParameters_Override(rName string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + testAccEnvironmentConfig_EnvironmentProfile_userParameters_Inherited(rName), + fmt.Sprintf(` resource "aws_datazone_environment" "test" { - name = %[2]q - description = %[2]q - account_identifier = data.aws_caller_identity.test.account_id - account_region = data.aws_region.test.region + name = %[1]q blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id profile_identifier = aws_datazone_environment_profile.test.id project_identifier = aws_datazone_project.test.id @@ -394,5 +759,78 @@ resource "aws_datazone_environment" "test" { aws_lakeformation_data_lake_settings.test, ] } -`, rName, rNameUpdated)) +`, rName)) +} + +func testAccEnvironmentConfig_EnvironmentProfile_userParameters_None(rName string) string { + return fmt.Sprintf(` +resource "aws_datazone_environment_profile" "test" { + name = %[1]q + aws_account_id = data.aws_caller_identity.test.account_id + aws_account_region = data.aws_region.test.region + environment_blueprint_identifier = data.aws_datazone_environment_blueprint.test.id + project_identifier = aws_datazone_project.test.id + domain_identifier = aws_datazone_domain.test.id +} +`, rName) +} + +func testAccEnvironmentConfig_EnvironmentProfile_userParameters_Inherited(rName string) string { + return fmt.Sprintf(` +resource "aws_datazone_environment_profile" "test" { + name = %[1]q + aws_account_id = data.aws_caller_identity.test.account_id + aws_account_region = data.aws_region.test.region + environment_blueprint_identifier = data.aws_datazone_environment_blueprint.test.id + project_identifier = aws_datazone_project.test.id + domain_identifier = aws_datazone_domain.test.id + + user_parameters { + name = "consumerGlueDbName" + value = "%[1]s-consumer-inherited" + } + + user_parameters { + name = "producerGlueDbName" + value = "%[1]s-producer-inherited" + } +} +`, rName) +} + +func testAccEnvironmentConfig_glossaryTerms(rName string, count int) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + testAccEnvironmentConfig_EnvironmentProfile_userParameters_None(rName), + fmt.Sprintf(` +resource "aws_datazone_environment" "test" { + name = %[1]q + blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id + profile_identifier = aws_datazone_environment_profile.test.id + project_identifier = aws_datazone_project.test.id + domain_identifier = aws_datazone_domain.test.id + + glossary_terms = aws_datazone_glossary_term.test[*].id + + depends_on = [ + aws_lakeformation_data_lake_settings.test, + ] +} + +resource "aws_datazone_glossary" "test" { + name = %[1]q + owning_project_identifier = aws_datazone_project.test.id + status = "ENABLED" + domain_identifier = aws_datazone_project.test.domain_identifier +} + +resource "aws_datazone_glossary_term" "test" { + count = %[2]d + + domain_identifier = aws_datazone_glossary.test.domain_identifier + glossary_identifier = aws_datazone_glossary.test.id + name = "%[1]s-${count.index}" + status = "ENABLED" +} +`, rName, count)) } diff --git a/internal/service/datazone/form_type_test.go b/internal/service/datazone/form_type_test.go index 8777b8fb4cdd..20bb3c8ff6c1 100644 --- a/internal/service/datazone/form_type_test.go +++ b/internal/service/datazone/form_type_test.go @@ -165,7 +165,7 @@ func testAccAuthorizerImportStateUserProfileFunc(resourceName string) resource.I } func testAccFormTypeConfig_basic(rName string) string { - return acctest.ConfigCompose(testAccProjectConfig_basic(rName, rName), ` + return acctest.ConfigCompose(testAccProjectConfig_basic(rName), ` resource "aws_datazone_form_type" "test" { description = "desc" name = "SageMakerModelFormType" diff --git a/internal/service/datazone/glossary_term_test.go b/internal/service/datazone/glossary_term_test.go index a114543ea216..6de9105f5994 100644 --- a/internal/service/datazone/glossary_term_test.go +++ b/internal/service/datazone/glossary_term_test.go @@ -32,15 +32,12 @@ func TestAccDataZoneGlossaryTerm_basic(t *testing.T) { var glossaryterm datazone.GetGlossaryTermOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - gName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_glossary_term.test" glossaryName := "aws_datazone_glossary.test" glossarySecond := "aws_datazone_glossary_term.second" - domianName := "aws_datazone_domain.test" + domainName := "aws_datazone_domain.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -53,16 +50,17 @@ func TestAccDataZoneGlossaryTerm_basic(t *testing.T) { CheckDestroy: testAccCheckGlossaryTermDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccGlossaryTermConfig_basic(rName, gName, dName, pName), + Config: testAccGlossaryTermConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domianName, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), resource.TestCheckResourceAttrPair(resourceName, "glossary_identifier", glossaryName, names.AttrID), resource.TestCheckResourceAttr(resourceName, "long_description", "long_description"), resource.TestCheckResourceAttr(resourceName, "short_description", "short_desc"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), + resource.TestCheckResourceAttr(resourceName, "term_relations.#", "1"), resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.classifies.0", glossarySecond, names.AttrID), resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.is_a.0", glossarySecond, names.AttrID), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), @@ -87,13 +85,12 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { var glossaryterm1, glossaryterm2 datazone.GetGlossaryTermOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - gName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_glossary_term.test" domainName := "aws_datazone_domain.test" glossaryName := "aws_datazone_glossary.test" + glossarySecond := "aws_datazone_glossary_term.second" + glossaryThird := "aws_datazone_glossary_term.third" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -106,7 +103,7 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { CheckDestroy: testAccCheckGlossaryTermDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccGlossaryTermConfig_basic(rName, gName, dName, pName), + Config: testAccGlossaryTermConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm1), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), @@ -118,6 +115,9 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), resource.TestCheckResourceAttrSet(resourceName, "created_by"), + resource.TestCheckResourceAttr(resourceName, "term_relations.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.classifies.0", glossarySecond, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.is_a.0", glossarySecond, names.AttrID), ), }, { @@ -128,7 +128,7 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { ImportStateIdFunc: testAccAuthorizerGlossaryTermImportStateIdFunc(resourceName), }, { - Config: testAccGlossaryTermConfig_update(rName, gName, dName, pName), + Config: testAccGlossaryTermConfig_update(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm2), testAccCheckGlossaryTermNotRecreated(&glossaryterm1, &glossaryterm2), @@ -140,6 +140,9 @@ func TestAccDataZoneGlossaryTerm_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "ENABLED"), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), resource.TestCheckResourceAttrSet(resourceName, "created_by"), + resource.TestCheckResourceAttr(resourceName, "term_relations.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.classifies.0", glossaryThird, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "term_relations.0.is_a.0", glossaryThird, names.AttrID), ), }, { @@ -160,9 +163,6 @@ func TestAccDataZoneGlossaryTerm_disappears(t *testing.T) { var glossaryterm datazone.GetGlossaryTermOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - gName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_glossary_term.test" resource.ParallelTest(t, resource.TestCase{ @@ -176,7 +176,7 @@ func TestAccDataZoneGlossaryTerm_disappears(t *testing.T) { CheckDestroy: testAccCheckGlossaryTermDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccGlossaryTermConfig_basic(rName, gName, dName, pName), + Config: testAccGlossaryTermConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryTermExists(ctx, resourceName, &glossaryterm), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceGlossaryTerm, resourceName), @@ -260,17 +260,8 @@ func testAccCheckGlossaryTermNotRecreated(before, after *datazone.GetGlossaryTer } } -func testAccGlossaryTermConfig_basic(rName, gName, dName, pName string) string { - return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` -resource "aws_datazone_glossary_term" "second" { - domain_identifier = aws_datazone_domain.test.id - glossary_identifier = aws_datazone_glossary.test.id - long_description = "long_description" - name = %[2]q - short_description = "short_desc" - status = "ENABLED" -} - +func testAccGlossaryTermConfig_basic(rName string) string { + return acctest.ConfigCompose(testAccGlossaryConfig_basic(rName), fmt.Sprintf(` resource "aws_datazone_glossary_term" "test" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id @@ -283,29 +274,20 @@ resource "aws_datazone_glossary_term" "test" { is_a = [aws_datazone_glossary_term.second.id] } } -`, rName, gName)) -} -func testAccGlossaryTermConfig_update(rName, gName, dName, pName string) string { - return acctest.ConfigCompose(testAccGlossaryConfig_basic(gName, "", dName, pName), fmt.Sprintf(` resource "aws_datazone_glossary_term" "second" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id long_description = "long_description" - name = %[2]q + name = "%[1]s-2" short_description = "short_desc" status = "ENABLED" } - -resource "aws_datazone_glossary_term" "third" { - domain_identifier = aws_datazone_domain.test.id - glossary_identifier = aws_datazone_glossary.test.id - long_description = "long_description" - name = %[3]q - short_description = "short_desc" - status = "ENABLED" +`, rName)) } +func testAccGlossaryTermConfig_update(rName string) string { + return acctest.ConfigCompose(testAccGlossaryConfig_basic(rName), fmt.Sprintf(` resource "aws_datazone_glossary_term" "test" { domain_identifier = aws_datazone_domain.test.id glossary_identifier = aws_datazone_glossary.test.id @@ -318,5 +300,23 @@ resource "aws_datazone_glossary_term" "test" { is_a = [aws_datazone_glossary_term.third.id] } } -`, rName, gName, dName)) + +resource "aws_datazone_glossary_term" "second" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = "%[1]s-2" + short_description = "short_desc" + status = "ENABLED" +} + +resource "aws_datazone_glossary_term" "third" { + domain_identifier = aws_datazone_domain.test.id + glossary_identifier = aws_datazone_glossary.test.id + long_description = "long_description" + name = "%[1]s-3" + short_description = "short_desc" + status = "ENABLED" +} +`, rName)) } diff --git a/internal/service/datazone/glossary_test.go b/internal/service/datazone/glossary_test.go index d17626482853..0ab8fd6252b6 100644 --- a/internal/service/datazone/glossary_test.go +++ b/internal/service/datazone/glossary_test.go @@ -32,9 +32,6 @@ func TestAccDataZoneGlossary_basic(t *testing.T) { var glossary datazone.GetGlossaryOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - token := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_glossary.test" projectName := "aws_datazone_project.test" @@ -49,7 +46,7 @@ func TestAccDataZoneGlossary_basic(t *testing.T) { CheckDestroy: testAccCheckGlossaryDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccGlossaryConfig_basic(rName, token, pName, dName), + Config: testAccGlossaryConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryExists(ctx, resourceName, &glossary), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), @@ -75,9 +72,6 @@ func TestAccDataZoneGlossary_update(t *testing.T) { var glossary, glossary2 datazone.GetGlossaryOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - token := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_glossary.test" projectName := "aws_datazone_project.test" @@ -92,7 +86,7 @@ func TestAccDataZoneGlossary_update(t *testing.T) { CheckDestroy: testAccCheckGlossaryDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccGlossaryConfig_basic(rName, token, pName, dName), + Config: testAccGlossaryConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryExists(ctx, resourceName, &glossary), resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "desc"), @@ -110,7 +104,7 @@ func TestAccDataZoneGlossary_update(t *testing.T) { ImportStateIdFunc: testAccAuthorizerGlossaryImportStateIdFunc(resourceName), }, { - Config: testAccGlossaryConfig_update(rName, token, pName, dName), + Config: testAccGlossaryConfig_update(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryExists(ctx, resourceName, &glossary2), testAccCheckGlossaryNotRecreated(&glossary, &glossary2), @@ -140,9 +134,6 @@ func TestAccDataZoneGlossary_disappears(t *testing.T) { var glossary datazone.GetGlossaryOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - token := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_glossary.test" resource.ParallelTest(t, resource.TestCase{ @@ -155,7 +146,7 @@ func TestAccDataZoneGlossary_disappears(t *testing.T) { CheckDestroy: testAccCheckGlossaryDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccGlossaryConfig_basic(rName, token, pName, dName), + Config: testAccGlossaryConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlossaryExists(ctx, resourceName, &glossary), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceGlossary, resourceName), @@ -235,8 +226,8 @@ func testAccAuthorizerGlossaryImportStateIdFunc(resourceName string) resource.Im } } -func testAccGlossaryConfig_basic(rName, token, dName, pName string) string { - return acctest.ConfigCompose(testAccProjectConfig_basic(pName, dName), fmt.Sprintf(` +func testAccGlossaryConfig_basic(rName string) string { + return acctest.ConfigCompose(testAccProjectConfig_basic(rName), fmt.Sprintf(` resource "aws_datazone_glossary" "test" { description = "desc" name = %[1]q @@ -244,11 +235,11 @@ resource "aws_datazone_glossary" "test" { status = "ENABLED" domain_identifier = aws_datazone_project.test.domain_identifier } -`, rName, token)) +`, rName)) } -func testAccGlossaryConfig_update(rName, token, dName, pName string) string { - return acctest.ConfigCompose(testAccProjectConfig_basic(pName, dName), fmt.Sprintf(` +func testAccGlossaryConfig_update(rName string) string { + return acctest.ConfigCompose(testAccProjectConfig_basic(rName), fmt.Sprintf(` resource "aws_datazone_glossary" "test" { description = "description" name = %[1]q @@ -256,5 +247,5 @@ resource "aws_datazone_glossary" "test" { status = "DISABLED" domain_identifier = aws_datazone_project.test.domain_identifier } -`, rName, token)) +`, rName)) } diff --git a/internal/service/datazone/project.go b/internal/service/datazone/project.go index c992ae692eee..4afe98e18881 100644 --- a/internal/service/datazone/project.go +++ b/internal/service/datazone/project.go @@ -33,6 +33,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/framework" "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -78,7 +79,6 @@ func (r *projectResource) Schema(ctx context.Context, req resource.SchemaRequest "glossary_terms": schema.ListAttribute{ CustomType: fwtypes.ListOfStringType, ElementType: types.StringType, - Validators: []validator.List{ listvalidator.SizeBetween(1, 20), listvalidator.ValueStringsAre(stringvalidator.RegexMatches(regexache.MustCompile(`^[a-zA-Z0-9_-]{1,36}$`), "must conform to: ^[a-zA-Z0-9_-]{1,36}$ ")), @@ -288,10 +288,10 @@ func (r *projectResource) Delete(ctx context.Context, req resource.DeleteRequest } _, err := conn.DeleteProject(ctx, in) - if err != nil { - if errs.IsA[*awstypes.ResourceNotFoundException](err) || errs.IsA[*awstypes.AccessDeniedException](err) { - return - } + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + if err != nil && !errs.IsAErrorMessageContains[*awstypes.ValidationException](err, "is already DELETING") { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.DataZone, create.ErrActionDeleting, ResNameProject, state.ID.String(), err), err.Error(), @@ -302,7 +302,7 @@ func (r *projectResource) Delete(ctx context.Context, req resource.DeleteRequest deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) _, err = waitProjectDeleted(ctx, conn, state.DomainIdentifier.ValueString(), state.ID.ValueString(), deleteTimeout) - if err != nil && !errs.IsA[*awstypes.AccessDeniedException](err) { + if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.DataZone, create.ErrActionWaitingForDeletion, ResNameProject, state.ID.String(), err), err.Error(), @@ -343,10 +343,12 @@ func waitProjectCreated(ctx context.Context, conn *datazone.Client, domain strin func waitProjectDeleted(ctx context.Context, conn *datazone.Client, domain string, identifier string, timeout time.Duration) (*datazone.GetProjectOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: enum.Slice(awstypes.ProjectStatusDeleting, awstypes.ProjectStatusActive), - Target: []string{}, - Refresh: statusProject(ctx, conn, domain, identifier), - Timeout: timeout, + Pending: enum.Slice(awstypes.ProjectStatusDeleting, awstypes.ProjectStatusActive), + Target: []string{}, + Refresh: statusProject(ctx, conn, domain, identifier), + Delay: 5 * time.Second, + PollInterval: 10 * time.Second, + Timeout: timeout, } outputRaw, err := stateConf.WaitForStateContext(ctx) @@ -368,7 +370,15 @@ func statusProject(ctx context.Context, conn *datazone.Client, domain string, id return nil, "", err } - return out, aws.ToString((*string)(&out.ProjectStatus)), nil + if len(out.FailureReasons) > 0 { + if err := errors.Join(tfslices.ApplyToAll(out.FailureReasons, func(e awstypes.ProjectDeletionError) error { + return errors.New(aws.ToString(e.Message)) + })...); err != nil { + return nil, "", err + } + } + + return out, string(out.ProjectStatus), nil } } @@ -388,7 +398,7 @@ func findProjectByID(ctx context.Context, conn *datazone.Client, domain string, return nil, err } - if out == nil || !(out.FailureReasons == nil) { + if out == nil { return nil, tfresource.NewEmptyResultError(in) } diff --git a/internal/service/datazone/project_test.go b/internal/service/datazone/project_test.go index a7b09f3756f1..cc1b13c79360 100644 --- a/internal/service/datazone/project_test.go +++ b/internal/service/datazone/project_test.go @@ -31,7 +31,6 @@ func TestAccDataZoneProject_basic(t *testing.T) { var project datazone.GetProjectOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_project.test" domainName := "aws_datazone_domain.test" @@ -44,17 +43,20 @@ func TestAccDataZoneProject_basic(t *testing.T) { CheckDestroy: testAccCheckProjectDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccProjectConfig_basic(rName, dName), - Check: resource.ComposeTestCheckFunc( + Config: testAccProjectConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckProjectExists(ctx, resourceName, &project), resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, "glossary_terms.#"), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "desc"), + resource.TestCheckResourceAttr(resourceName, "failure_reasons.#", "0"), + resource.TestCheckResourceAttr(resourceName, "glossary_terms.#", "0"), + resource.TestCheckNoResourceAttr(resourceName, names.AttrDescription), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrSet(resourceName, "created_by"), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), - resource.TestCheckResourceAttrSet(resourceName, "last_updated_at"), + acctest.CheckResourceAttrRFC3339(resourceName, names.AttrCreatedAt), + acctest.CheckResourceAttrRFC3339(resourceName, "last_updated_at"), + // resource.TestCheckResourceAttr(resourceName, "project_status", string(types.ProjectStatusActive)), + resource.TestCheckResourceAttr(resourceName, "skip_deletion_check", acctest.CtTrue), ), }, { @@ -62,11 +64,12 @@ func TestAccDataZoneProject_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, ImportStateIdFunc: testAccAuthorizerImportStateIdFunc(resourceName), - ImportStateVerifyIgnore: []string{"skip_deletion_check", "project_status"}, + ImportStateVerifyIgnore: []string{"project_status", "skip_deletion_check"}, }, }, }) } + func TestAccDataZoneProject_disappears(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -75,7 +78,6 @@ func TestAccDataZoneProject_disappears(t *testing.T) { var project datazone.GetProjectOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_datazone_project.test" resource.ParallelTest(t, resource.TestCase{ @@ -85,8 +87,8 @@ func TestAccDataZoneProject_disappears(t *testing.T) { CheckDestroy: testAccCheckProjectDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccProjectConfig_basic(rName, dName), - Check: resource.ComposeTestCheckFunc( + Config: testAccProjectConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckProjectExists(ctx, resourceName, &project), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfdatazone.ResourceProject, resourceName), ), @@ -95,6 +97,73 @@ func TestAccDataZoneProject_disappears(t *testing.T) { }, }) } + +func TestAccDataZoneProject_description(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var v1, v2 datazone.GetProjectOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_datazone_project.test" + domainName := "aws_datazone_domain.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckProjectDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccProjectConfig_description(rName, "desc"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckProjectExists(ctx, resourceName, &v1), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), + resource.TestCheckResourceAttr(resourceName, "glossary_terms.#", "0"), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "desc"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrSet(resourceName, "created_by"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + acctest.CheckResourceAttrRFC3339(resourceName, names.AttrCreatedAt), + acctest.CheckResourceAttrRFC3339(resourceName, "last_updated_at"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerImportStateIdFunc(resourceName), + ImportStateVerifyIgnore: []string{"project_status", "skip_deletion_check"}, + }, + { + Config: testAccProjectConfig_description(rName, "updated"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckProjectExists(ctx, resourceName, &v2), + testAccCheckProjectNotRecreated(&v1, &v2), + resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), + resource.TestCheckResourceAttr(resourceName, "glossary_terms.#", "0"), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "updated"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrSet(resourceName, "created_by"), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + acctest.CheckResourceAttrRFC3339(resourceName, names.AttrCreatedAt), + acctest.CheckResourceAttrRFC3339(resourceName, "last_updated_at"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccAuthorizerImportStateIdFunc(resourceName), + ImportStateVerifyIgnore: []string{"project_status", "skip_deletion_check"}, + }, + }, + }) +} + func testAccCheckProjectDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).DataZoneClient(ctx) @@ -173,72 +242,6 @@ func testAccCheckProjectNotRecreated(before, after *datazone.GetProjectOutput) r return nil } } -func TestAccDataZoneProject_update(t *testing.T) { - ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - - var v1, v2 datazone.GetProjectOutput - pName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - dName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_datazone_project.test" - domainName := "aws_datazone_domain.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, names.DataZoneServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckProjectDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccProjectConfig_basic(pName, dName), - Check: resource.ComposeTestCheckFunc( - testAccCheckProjectExists(ctx, resourceName, &v1), - resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, "glossary_terms.#"), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "desc"), - resource.TestCheckResourceAttr(resourceName, names.AttrName, pName), - resource.TestCheckResourceAttrSet(resourceName, "created_by"), - resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), - resource.TestCheckResourceAttrSet(resourceName, "last_updated_at"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateIdFunc: testAccAuthorizerImportStateIdFunc(resourceName), - ImportStateVerifyIgnore: []string{"skip_deletion_check", "project_status"}, - }, - { - Config: testAccProjectConfigBasicUpdate(pName, dName), - Check: resource.ComposeTestCheckFunc( - testAccCheckProjectExists(ctx, resourceName, &v2), - testAccCheckProjectNotRecreated(&v1, &v2), - resource.TestCheckResourceAttrPair(resourceName, "domain_identifier", domainName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, "glossary_terms.#"), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, names.AttrDescription), - resource.TestCheckResourceAttr(resourceName, names.AttrName, pName), - resource.TestCheckResourceAttrSet(resourceName, "created_by"), - resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), - resource.TestCheckResourceAttrSet(resourceName, "last_updated_at"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateIdFunc: testAccAuthorizerImportStateIdFunc(resourceName), - ImportStateVerifyIgnore: []string{"project_status", "skip_deletion_check"}, - }, - }, - }) -} func testAccAuthorizerImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { @@ -251,33 +254,23 @@ func testAccAuthorizerImportStateIdFunc(resourceName string) resource.ImportStat } } -func testAccProjectConfig_basic(pName, dName string) string { - return acctest.ConfigCompose(testAccDomainConfig_basic(dName), fmt.Sprintf(` -resource "aws_security_group" "test" { - name = %[1]q -} - +func testAccProjectConfig_basic(rName string) string { + return acctest.ConfigCompose(testAccDomainConfig_basic(rName), fmt.Sprintf(` resource "aws_datazone_project" "test" { domain_identifier = aws_datazone_domain.test.id - glossary_terms = ["2N8w6XJCwZf"] name = %[1]q - description = "desc" skip_deletion_check = true } -`, pName)) -} -func testAccProjectConfigBasicUpdate(pName, dName string) string { - return acctest.ConfigCompose(testAccDomainConfig_basic(dName), fmt.Sprintf(` -resource "aws_security_group" "test" { - name = %[1]q +`, rName)) } +func testAccProjectConfig_description(rName, description string) string { + return acctest.ConfigCompose(testAccDomainConfig_basic(rName), fmt.Sprintf(` resource "aws_datazone_project" "test" { domain_identifier = aws_datazone_domain.test.id - glossary_terms = ["2N8w6XJCwZf"] name = %[1]q - description = "description" + description = %[2]q skip_deletion_check = true } -`, pName)) +`, rName, description)) } diff --git a/internal/service/datazone/sweep.go b/internal/service/datazone/sweep.go index 7eea238bc85c..f069e3f3d14a 100644 --- a/internal/service/datazone/sweep.go +++ b/internal/service/datazone/sweep.go @@ -16,15 +16,26 @@ import ( ) func RegisterSweepers() { - awsv2.Register("aws_datazone_domain", sweepDomains) + awsv2.Register("aws_datazone_domain", sweepDomains, + "aws_datazone_project", + "aws_datazone_environment_profile", + ) + + awsv2.Register("aws_datazone_environment", sweepEnvironments) + + awsv2.Register("aws_datazone_environment_profile", sweepEnvironmentProfiles) + + awsv2.Register("aws_datazone_project", sweepProjects, + "aws_datazone_environment", + ) } func sweepDomains(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { conn := client.DataZoneClient(ctx) - input := &datazone.ListDomainsInput{} - sweepResources := make([]sweep.Sweepable, 0) + var sweepResources []sweep.Sweepable - pages := datazone.NewListDomainsPaginator(conn, input) + var input datazone.ListDomainsInput + pages := datazone.NewListDomainsPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if err != nil { @@ -42,3 +53,126 @@ func sweepDomains(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepab return sweepResources, nil } + +func sweepEnvironments(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { + conn := client.DataZoneClient(ctx) + var sweepResources []sweep.Sweepable + + var domainsInput datazone.ListDomainsInput + pages := datazone.NewListDomainsPaginator(conn, &domainsInput) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, domain := range page.Items { + projectsInput := datazone.ListProjectsInput{ + DomainIdentifier: domain.Id, + } + pages := datazone.NewListProjectsPaginator(conn, &projectsInput) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, project := range page.Items { + environmentsInput := datazone.ListEnvironmentsInput{ + DomainIdentifier: domain.Id, + ProjectIdentifier: project.Id, + } + pages := datazone.NewListEnvironmentsPaginator(conn, &environmentsInput) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, environment := range page.Items { + sweepResources = append(sweepResources, framework.NewSweepResource(newEnvironmentResource, client, + framework.NewAttribute(names.AttrID, environment.Id), + framework.NewAttribute("domain_identifier", domain.Id), + )) + } + } + } + } + } + } + + return sweepResources, nil +} + +func sweepEnvironmentProfiles(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { + conn := client.DataZoneClient(ctx) + var sweepResources []sweep.Sweepable + + var domainsInput datazone.ListDomainsInput + pages := datazone.NewListDomainsPaginator(conn, &domainsInput) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, domain := range page.Items { + environmentProfilesInput := datazone.ListEnvironmentProfilesInput{ + DomainIdentifier: domain.Id, + } + pages := datazone.NewListEnvironmentProfilesPaginator(conn, &environmentProfilesInput) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, profile := range page.Items { + sweepResources = append(sweepResources, framework.NewSweepResource(newEnvironmentProfileResource, client, + framework.NewAttribute(names.AttrID, profile.Id), + framework.NewAttribute("domain_identifier", domain.Id), + )) + } + } + } + } + + return sweepResources, nil +} + +func sweepProjects(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { + conn := client.DataZoneClient(ctx) + var sweepResources []sweep.Sweepable + + var domainsInput datazone.ListDomainsInput + pages := datazone.NewListDomainsPaginator(conn, &domainsInput) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, domain := range page.Items { + projectsInput := datazone.ListProjectsInput{ + DomainIdentifier: domain.Id, + } + pages := datazone.NewListProjectsPaginator(conn, &projectsInput) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, project := range page.Items { + sweepResources = append(sweepResources, framework.NewSweepResource(newProjectResource, client, + framework.NewAttribute(names.AttrID, project.Id), + framework.NewAttribute("domain_identifier", domain.Id), + framework.NewAttribute("skip_deletion_check", true), // Automatically delete associated Glossaries + )) + } + } + } + } + + return sweepResources, nil +} diff --git a/internal/service/devopsguru/event_sources_config_identity_gen_test.go b/internal/service/devopsguru/event_sources_config_identity_gen_test.go index a2326f37d435..7893c315d315 100644 --- a/internal/service/devopsguru/event_sources_config_identity_gen_test.go +++ b/internal/service/devopsguru/event_sources_config_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccDevOpsGuruEventSourcesConfig_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccDevOpsGuruEventSourcesConfig_Identity_Basic, - "ExistingResource": testAccDevOpsGuruEventSourcesConfig_Identity_ExistingResource, - "RegionOverride": testAccDevOpsGuruEventSourcesConfig_Identity_RegionOverride, + acctest.CtBasic: testAccDevOpsGuruEventSourcesConfig_Identity_Basic, + "ExistingResource": testAccDevOpsGuruEventSourcesConfig_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccDevOpsGuruEventSourcesConfig_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccDevOpsGuruEventSourcesConfig_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/devopsguru/service_integration_identity_gen_test.go b/internal/service/devopsguru/service_integration_identity_gen_test.go index c1bb885a086b..ee5b9ca3f803 100644 --- a/internal/service/devopsguru/service_integration_identity_gen_test.go +++ b/internal/service/devopsguru/service_integration_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccDevOpsGuruServiceIntegration_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccDevOpsGuruServiceIntegration_Identity_Basic, - "ExistingResource": testAccDevOpsGuruServiceIntegration_Identity_ExistingResource, - "RegionOverride": testAccDevOpsGuruServiceIntegration_Identity_RegionOverride, + acctest.CtBasic: testAccDevOpsGuruServiceIntegration_Identity_Basic, + "ExistingResource": testAccDevOpsGuruServiceIntegration_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccDevOpsGuruServiceIntegration_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccDevOpsGuruServiceIntegration_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/dms/endpoint.go b/internal/service/dms/endpoint.go index e109733122de..0b3d468cbd9f 100644 --- a/internal/service/dms/endpoint.go +++ b/internal/service/dms/endpoint.go @@ -5,6 +5,7 @@ package dms import ( "context" + "errors" "fmt" "log" "strings" @@ -344,6 +345,69 @@ func resourceEndpoint() *schema.Resource { }, }, }, + "mysql_settings": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + DiffSuppressFunc: verify.SuppressMissingOptionalConfigurationBlock, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "after_connect_script": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "authentication_method": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateDiagFunc: enum.Validate[awstypes.MySQLAuthenticationMethod](), + }, + "clean_source_metadata_on_mismatch": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "events_poll_interval": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "execute_timeout": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "max_file_size": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "parallel_load_threads": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "server_timezone": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "service_access_role_arn": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: verify.ValidARN, + }, + "target_db_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateDiagFunc: enum.Validate[awstypes.TargetDbType](), + }, + }, + }, + }, "oracle_settings": { Type: schema.TypeList, Optional: true, @@ -620,39 +684,50 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta an switch d.Get("engine_name").(string) { case engineNameAurora, engineNameMariadb, engineNameMySQL: + settings := &awstypes.MySQLSettings{} + if _, ok := d.GetOk("mysql_settings"); ok { + settings = expandMySQLSettings(d.Get("mysql_settings").([]any)[0].(map[string]any)) + } if _, ok := d.GetOk("secrets_manager_arn"); ok { - input.MySQLSettings = &awstypes.MySQLSettings{ - SecretsManagerAccessRoleArn: aws.String(d.Get("secrets_manager_access_role_arn").(string)), - SecretsManagerSecretId: aws.String(d.Get("secrets_manager_arn").(string)), - } + settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) + settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) } else { - input.MySQLSettings = &awstypes.MySQLSettings{ - Username: aws.String(d.Get(names.AttrUsername).(string)), - Password: aws.String(d.Get(names.AttrPassword).(string)), - ServerName: aws.String(d.Get("server_name").(string)), - Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), + settings.Username = aws.String(d.Get(names.AttrUsername).(string)) + settings.Password = aws.String(d.Get(names.AttrPassword).(string)) + settings.ServerName = aws.String(d.Get("server_name").(string)) + settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) + + // DatabaseName can be empty since it should not be specified + // when mysql_settings.target_db_type is `multiple-databases` + if v, ok := d.GetOk(names.AttrDatabaseName); ok { + settings.DatabaseName = aws.String(v.(string)) } // Set connection info in top-level namespace as well expandTopLevelConnectionInfo(d, &input) } + input.MySQLSettings = settings case engineNameAuroraPostgresql, engineNamePostgres: - settings := &awstypes.PostgreSQLSettings{} - if _, ok := d.GetOk("postgres_settings"); ok { - settings = expandPostgreSQLSettings(d.Get("postgres_settings").([]any)[0].(map[string]any)) + var settings *awstypes.PostgreSQLSettings + + if v, ok := d.GetOk("postgres_settings"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { + settings = expandPostgreSQLSettings(v.([]any)[0].(map[string]any)) + } else { + settings = &awstypes.PostgreSQLSettings{} } + settings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string)) if _, ok := d.GetOk("secrets_manager_arn"); ok { settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) - settings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string)) } else { + if v, ok := d.GetOk(names.AttrPassword); ok { + settings.Password = aws.String(v.(string)) + } + settings.Username = aws.String(d.Get(names.AttrUsername).(string)) - settings.Password = aws.String(d.Get(names.AttrPassword).(string)) settings.ServerName = aws.String(d.Get("server_name").(string)) settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) - settings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string)) // Set connection info in top-level namespace as well expandTopLevelConnectionInfo(d, &input) @@ -705,6 +780,7 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta an var settings = &awstypes.OracleSettings{ DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), } + if v, ok := d.GetOk("oracle_settings"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { settings.AuthenticationMethod = expandOracleSettings(v.([]any)).AuthenticationMethod } @@ -719,11 +795,11 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta an settings.Username = aws.String(d.Get(names.AttrUsername).(string)) settings.ServerName = aws.String(d.Get("server_name").(string)) settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) - settings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string)) // Set connection info in top-level namespace as well expandTopLevelConnectionInfo(d, &input) } + input.OracleSettings = settings case engineNameRedis: input.RedisSettings = expandRedisSettings(d.Get("redis_settings").([]any)[0].(map[string]any)) @@ -736,8 +812,11 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta an settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) } else { + if v, ok := d.GetOk(names.AttrPassword); ok { + settings.Password = aws.String(v.(string)) + } + settings.Username = aws.String(d.Get(names.AttrUsername).(string)) - settings.Password = aws.String(d.Get(names.AttrPassword).(string)) settings.ServerName = aws.String(d.Get("server_name").(string)) settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) @@ -889,6 +968,7 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an if d.HasChangesExcept("pause_replication_tasks") { input := dms.ModifyEndpointInput{ EndpointArn: aws.String(endpointARN), + EngineName: aws.String(d.Get("engine_name").(string)), } if d.HasChange(names.AttrCertificateARN) { @@ -899,10 +979,6 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an input.EndpointType = awstypes.ReplicationEndpointTypeValue(d.Get(names.AttrEndpointType).(string)) } - if d.HasChange("engine_name") { - input.EngineName = aws.String(d.Get("engine_name").(string)) - } - if d.HasChange("extra_connection_attributes") { input.ExtraConnectionAttributes = aws.String(d.Get("extra_connection_attributes").(string)) } @@ -920,50 +996,68 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an switch engineName := d.Get("engine_name").(string); engineName { case engineNameAurora, engineNameMariadb, engineNameMySQL: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "secrets_manager_access_role_arn", - "secrets_manager_arn") { + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, + "secrets_manager_access_role_arn", "secrets_manager_arn", "mysql_settings") { + var settings *awstypes.MySQLSettings + + if v, ok := d.GetOk("mysql_settings"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { + settings = expandMySQLSettings(v.([]any)[0].(map[string]any)) + } else { + settings = &awstypes.MySQLSettings{} + } + if _, ok := d.GetOk("secrets_manager_arn"); ok { - input.MySQLSettings = &awstypes.MySQLSettings{ - SecretsManagerAccessRoleArn: aws.String(d.Get("secrets_manager_access_role_arn").(string)), - SecretsManagerSecretId: aws.String(d.Get("secrets_manager_arn").(string)), - } + settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) + settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) } else { - input.MySQLSettings = &awstypes.MySQLSettings{ - Username: aws.String(d.Get(names.AttrUsername).(string)), - Password: aws.String(d.Get(names.AttrPassword).(string)), - ServerName: aws.String(d.Get("server_name").(string)), - Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), + settings.Username = aws.String(d.Get(names.AttrUsername).(string)) + settings.Password = aws.String(d.Get(names.AttrPassword).(string)) + settings.ServerName = aws.String(d.Get("server_name").(string)) + settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) + + // DatabaseName can be empty since it should not be specified + // when mysql_settings.target_db_type is `multiple-databases` + if v, ok := d.GetOk(names.AttrDatabaseName); ok { + settings.DatabaseName = aws.String(v.(string)) } - input.EngineName = aws.String(engineName) // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) } + + input.MySQLSettings = settings } case engineNameAuroraPostgresql, engineNamePostgres: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "secrets_manager_access_role_arn", - "secrets_manager_arn") { + names.AttrDatabaseName, "postgres_settings", + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, + "secrets_manager_access_role_arn", "secrets_manager_arn") { + var settings *awstypes.PostgreSQLSettings + + if v, ok := d.GetOk("postgres_settings"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { + settings = expandPostgreSQLSettings(v.([]any)[0].(map[string]any)) + } else { + settings = &awstypes.PostgreSQLSettings{} + } + settings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string)) + if _, ok := d.GetOk("secrets_manager_arn"); ok { - input.PostgreSQLSettings = &awstypes.PostgreSQLSettings{ - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), - SecretsManagerAccessRoleArn: aws.String(d.Get("secrets_manager_access_role_arn").(string)), - SecretsManagerSecretId: aws.String(d.Get("secrets_manager_arn").(string)), - } + settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) + settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) } else { - input.PostgreSQLSettings = &awstypes.PostgreSQLSettings{ - Username: aws.String(d.Get(names.AttrUsername).(string)), - Password: aws.String(d.Get(names.AttrPassword).(string)), - ServerName: aws.String(d.Get("server_name").(string)), - Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), + if v, ok := d.GetOk(names.AttrPassword); ok { + settings.Password = aws.String(v.(string)) } - input.EngineName = aws.String(engineName) // Must be included (should be 'postgres') + + settings.Username = aws.String(d.Get(names.AttrUsername).(string)) + settings.ServerName = aws.String(d.Get("server_name").(string)) + settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) } + + input.PostgreSQLSettings = settings } case engineNameDynamoDB: if d.HasChange("service_access_role") { @@ -973,10 +1067,10 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an } case engineNameElasticsearch, engineNameOpenSearch: if d.HasChanges( + "elasticsearch_settings.0.service_access_role_arn", "elasticsearch_settings.0.endpoint_uri", "elasticsearch_settings.0.error_retry_duration", "elasticsearch_settings.0.full_load_error_percentage", - "elasticsearch_settings.0.service_access_role_arn", "elasticsearch_settings.0.use_new_mapping_type") { input.ElasticsearchSettings = &awstypes.ElasticsearchSettings{ ServiceAccessRoleArn: aws.String(d.Get("elasticsearch_settings.0.service_access_role_arn").(string)), @@ -985,67 +1079,55 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an FullLoadErrorPercentage: aws.Int32(int32(d.Get("elasticsearch_settings.0.full_load_error_percentage").(int))), UseNewMappingType: aws.Bool(d.Get("elasticsearch_settings.0.use_new_mapping_type").(bool)), } - input.EngineName = aws.String(engineName) } case engineNameKafka: if d.HasChange("kafka_settings") { input.KafkaSettings = expandKafkaSettings(d.Get("kafka_settings").([]any)[0].(map[string]any)) - input.EngineName = aws.String(engineName) } case engineNameKinesis: if d.HasChanges("kinesis_settings") { input.KinesisSettings = expandKinesisSettings(d.Get("kinesis_settings").([]any)[0].(map[string]any)) - input.EngineName = aws.String(engineName) } case engineNameMongodb: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "mongodb_settings.0.auth_type", - "mongodb_settings.0.auth_mechanism", "mongodb_settings.0.nesting_level", "mongodb_settings.0.extract_doc_id", - "mongodb_settings.0.docs_to_investigate", "mongodb_settings.0.auth_source", "secrets_manager_access_role_arn", - "secrets_manager_arn") { + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, + names.AttrDatabaseName, names.AttrKMSKeyARN, "mongodb_settings.0.auth_type", "mongodb_settings.0.auth_mechanism", "mongodb_settings.0.nesting_level", "mongodb_settings.0.extract_doc_id", "mongodb_settings.0.docs_to_investigate", "mongodb_settings.0.auth_source", + "secrets_manager_access_role_arn", "secrets_manager_arn") { + var settings = &awstypes.MongoDbSettings{} + if _, ok := d.GetOk("secrets_manager_arn"); ok { - input.MongoDbSettings = &awstypes.MongoDbSettings{ - SecretsManagerAccessRoleArn: aws.String(d.Get("secrets_manager_access_role_arn").(string)), - SecretsManagerSecretId: aws.String(d.Get("secrets_manager_arn").(string)), - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), - KmsKeyId: aws.String(d.Get(names.AttrKMSKeyARN).(string)), - - AuthType: awstypes.AuthTypeValue(d.Get("mongodb_settings.0.auth_type").(string)), - AuthMechanism: awstypes.AuthMechanismValue(d.Get("mongodb_settings.0.auth_mechanism").(string)), - NestingLevel: awstypes.NestingLevelValue(d.Get("mongodb_settings.0.nesting_level").(string)), - ExtractDocId: aws.String(d.Get("mongodb_settings.0.extract_doc_id").(string)), - DocsToInvestigate: aws.String(d.Get("mongodb_settings.0.docs_to_investigate").(string)), - AuthSource: aws.String(d.Get("mongodb_settings.0.auth_source").(string)), - } + settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) + settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) } else { - input.MongoDbSettings = &awstypes.MongoDbSettings{ - Username: aws.String(d.Get(names.AttrUsername).(string)), - Password: aws.String(d.Get(names.AttrPassword).(string)), - ServerName: aws.String(d.Get("server_name").(string)), - Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), - KmsKeyId: aws.String(d.Get(names.AttrKMSKeyARN).(string)), - - AuthType: awstypes.AuthTypeValue(d.Get("mongodb_settings.0.auth_type").(string)), - AuthMechanism: awstypes.AuthMechanismValue(d.Get("mongodb_settings.0.auth_mechanism").(string)), - NestingLevel: awstypes.NestingLevelValue(d.Get("mongodb_settings.0.nesting_level").(string)), - ExtractDocId: aws.String(d.Get("mongodb_settings.0.extract_doc_id").(string)), - DocsToInvestigate: aws.String(d.Get("mongodb_settings.0.docs_to_investigate").(string)), - AuthSource: aws.String(d.Get("mongodb_settings.0.auth_source").(string)), - } - input.EngineName = aws.String(engineName) + settings.Username = aws.String(d.Get(names.AttrUsername).(string)) + settings.Password = aws.String(d.Get(names.AttrPassword).(string)) + settings.ServerName = aws.String(d.Get("server_name").(string)) + settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) } + + settings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string)) + settings.KmsKeyId = aws.String(d.Get(names.AttrKMSKeyARN).(string)) + settings.AuthType = awstypes.AuthTypeValue(d.Get("mongodb_settings.0.auth_type").(string)) + settings.AuthMechanism = awstypes.AuthMechanismValue(d.Get("mongodb_settings.0.auth_mechanism").(string)) + settings.NestingLevel = awstypes.NestingLevelValue(d.Get("mongodb_settings.0.nesting_level").(string)) + settings.ExtractDocId = aws.String(d.Get("mongodb_settings.0.extract_doc_id").(string)) + settings.DocsToInvestigate = aws.String(d.Get("mongodb_settings.0.docs_to_investigate").(string)) + settings.AuthSource = aws.String(d.Get("mongodb_settings.0.auth_source").(string)) + + input.MongoDbSettings = settings } case engineNameOracle: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "secrets_manager_access_role_arn", - "secrets_manager_arn", "oracle_settings") { + names.AttrDatabaseName, "oracle_settings", + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, + "secrets_manager_access_role_arn", "secrets_manager_arn") { var settings = &awstypes.OracleSettings{ DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), } + if v, ok := d.GetOk("oracle_settings"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { settings.AuthenticationMethod = expandOracleSettings(v.([]any)).AuthenticationMethod } @@ -1060,73 +1142,72 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an settings.Username = aws.String(d.Get(names.AttrUsername).(string)) settings.ServerName = aws.String(d.Get("server_name").(string)) settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) - settings.DatabaseName = aws.String(d.Get(names.AttrDatabaseName).(string)) - - input.EngineName = aws.String(engineName) // Must be included (should be 'oracle') // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) } + input.OracleSettings = settings } case engineNameRedis: if d.HasChanges("redis_settings") { input.RedisSettings = expandRedisSettings(d.Get("redis_settings").([]any)[0].(map[string]any)) - input.EngineName = aws.String(engineName) } case engineNameRedshift: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, - "redshift_settings", "secrets_manager_access_role_arn", - "secrets_manager_arn") { + names.AttrDatabaseName, "redshift_settings", + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, + "secrets_manager_access_role_arn", "secrets_manager_arn") { + var settings = &awstypes.RedshiftSettings{ + DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), + } + if _, ok := d.GetOk("secrets_manager_arn"); ok { - input.RedshiftSettings = &awstypes.RedshiftSettings{ - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), - SecretsManagerAccessRoleArn: aws.String(d.Get("secrets_manager_access_role_arn").(string)), - SecretsManagerSecretId: aws.String(d.Get("secrets_manager_arn").(string)), - } + settings.SecretsManagerAccessRoleArn = aws.String(d.Get("secrets_manager_access_role_arn").(string)) + settings.SecretsManagerSecretId = aws.String(d.Get("secrets_manager_arn").(string)) } else { - input.RedshiftSettings = &awstypes.RedshiftSettings{ - Username: aws.String(d.Get(names.AttrUsername).(string)), - Password: aws.String(d.Get(names.AttrPassword).(string)), - ServerName: aws.String(d.Get("server_name").(string)), - Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), - DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), + if v, ok := d.GetOk(names.AttrPassword); ok { + settings.Password = aws.String(v.(string)) } - input.EngineName = aws.String(engineName) // Must be included (should be 'redshift') + + settings.Username = aws.String(d.Get(names.AttrUsername).(string)) + settings.ServerName = aws.String(d.Get("server_name").(string)) + settings.Port = aws.Int32(int32(d.Get(names.AttrPort).(int))) // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) + } - if v, ok := d.GetOk("redshift_settings"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { - tfMap := v.([]any)[0].(map[string]any) + if v, ok := d.GetOk("redshift_settings"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { + tfMap := v.([]any)[0].(map[string]any) - if v, ok := tfMap["bucket_folder"].(string); ok && v != "" { - input.RedshiftSettings.BucketFolder = aws.String(v) - } + if v, ok := tfMap["bucket_folder"].(string); ok && v != "" { + settings.BucketFolder = aws.String(v) + } - if v, ok := tfMap[names.AttrBucketName].(string); ok && v != "" { - input.RedshiftSettings.BucketName = aws.String(v) - } + if v, ok := tfMap[names.AttrBucketName].(string); ok && v != "" { + settings.BucketName = aws.String(v) + } - if v, ok := tfMap["encryption_mode"].(string); ok && v != "" { - input.RedshiftSettings.EncryptionMode = awstypes.EncryptionModeValue(v) - } + if v, ok := tfMap["encryption_mode"].(string); ok && v != "" { + settings.EncryptionMode = awstypes.EncryptionModeValue(v) + } - if v, ok := tfMap["server_side_encryption_kms_key_id"].(string); ok && v != "" { - input.RedshiftSettings.ServerSideEncryptionKmsKeyId = aws.String(v) - } + if v, ok := tfMap["server_side_encryption_kms_key_id"].(string); ok && v != "" { + settings.ServerSideEncryptionKmsKeyId = aws.String(v) + } - if v, ok := tfMap["service_access_role_arn"].(string); ok && v != "" { - input.RedshiftSettings.ServiceAccessRoleArn = aws.String(v) - } + if v, ok := tfMap["service_access_role_arn"].(string); ok && v != "" { + settings.ServiceAccessRoleArn = aws.String(v) } + + input.RedshiftSettings = settings } } case engineNameSQLServer, engineNameBabelfish: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "secrets_manager_access_role_arn", - "secrets_manager_arn") { + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, + "secrets_manager_access_role_arn", "secrets_manager_arn") { if _, ok := d.GetOk("secrets_manager_arn"); ok { input.MicrosoftSQLServerSettings = &awstypes.MicrosoftSQLServerSettings{ DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), @@ -1141,7 +1222,6 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), } - input.EngineName = aws.String(engineName) // Must be included (should be 'postgres') // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) @@ -1149,8 +1229,8 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an } case engineNameSybase: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "secrets_manager_access_role_arn", - "secrets_manager_arn") { + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, + "secrets_manager_access_role_arn", "secrets_manager_arn") { if _, ok := d.GetOk("secrets_manager_arn"); ok { input.SybaseSettings = &awstypes.SybaseSettings{ DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), @@ -1165,7 +1245,6 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), } - input.EngineName = aws.String(engineName) // Must be included (should be 'postgres') // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) @@ -1173,8 +1252,8 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an } case engineNameDB2, engineNameDB2zOS: if d.HasChanges( - names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, "secrets_manager_access_role_arn", - "secrets_manager_arn") { + names.AttrUsername, names.AttrPassword, "server_name", names.AttrPort, names.AttrDatabaseName, + "secrets_manager_access_role_arn", "secrets_manager_arn") { if _, ok := d.GetOk("secrets_manager_arn"); ok { input.IBMDb2Settings = &awstypes.IBMDb2Settings{ DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), @@ -1189,7 +1268,6 @@ func resourceEndpointUpdate(ctx context.Context, d *schema.ResourceData, meta an Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), DatabaseName: aws.String(d.Get(names.AttrDatabaseName).(string)), } - input.EngineName = aws.String(engineName) // Must be included (should be 'db2') // Update connection info in top-level namespace as well expandTopLevelConnectionInfoModify(d, &input) @@ -1348,6 +1426,9 @@ func resourceEndpointSetState(d *schema.ResourceData, endpoint *awstypes.Endpoin } else { flattenTopLevelConnectionInfo(d, endpoint) } + if err := d.Set("mysql_settings", flattenMySQLSettings(endpoint.MySQLSettings)); err != nil { + return fmt.Errorf("setting mysql_settings: %w", err) + } case engineNameAuroraPostgresql, engineNamePostgres: if endpoint.PostgreSQLSettings != nil { d.Set(names.AttrUsername, endpoint.PostgreSQLSettings.Username) @@ -1957,6 +2038,47 @@ func flattenRedshiftSettings(settings *awstypes.RedshiftSettings) []map[string]a return []map[string]any{m} } +func expandMySQLSettings(tfMap map[string]any) *awstypes.MySQLSettings { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.MySQLSettings{} + + if v, ok := tfMap["after_connect_script"].(string); ok && v != "" { + apiObject.AfterConnectScript = aws.String(v) + } + if v, ok := tfMap["authentication_method"].(string); ok && v != "" { + apiObject.AuthenticationMethod = awstypes.MySQLAuthenticationMethod(v) + } + if v, ok := tfMap["clean_source_metadata_on_mismatch"].(bool); ok { + apiObject.CleanSourceMetadataOnMismatch = aws.Bool(v) + } + if v, ok := tfMap["events_poll_interval"].(int); ok && v != 0 { + apiObject.EventsPollInterval = aws.Int32(int32(v)) + } + if v, ok := tfMap["execute_timeout"].(int); ok && v != 0 { + apiObject.ExecuteTimeout = aws.Int32(int32(v)) + } + if v, ok := tfMap["max_file_size"].(int); ok && v != 0 { + apiObject.MaxFileSize = aws.Int32(int32(v)) + } + if v, ok := tfMap["parallel_load_threads"].(int); ok && v != 0 { + apiObject.ParallelLoadThreads = aws.Int32(int32(v)) + } + if v, ok := tfMap["server_timezone"].(string); ok && v != "" { + apiObject.ServerTimezone = aws.String(v) + } + if v, ok := tfMap["service_access_role_arn"].(string); ok && v != "" { + apiObject.ServiceAccessRoleArn = aws.String(v) + } + if v, ok := tfMap["target_db_type"].(string); ok && v != "" { + apiObject.TargetDbType = awstypes.TargetDbType(v) + } + + return apiObject +} + func expandPostgreSQLSettings(tfMap map[string]any) *awstypes.PostgreSQLSettings { if tfMap == nil { return nil @@ -2022,6 +2144,47 @@ func expandPostgreSQLSettings(tfMap map[string]any) *awstypes.PostgreSQLSettings return apiObject } +func flattenMySQLSettings(apiObject *awstypes.MySQLSettings) []map[string]any { + if apiObject == nil { + return nil + } + + tfMap := map[string]any{} + + if v := apiObject.AfterConnectScript; v != nil { + tfMap["after_connect_script"] = aws.ToString(v) + } + if v := apiObject.AuthenticationMethod; v != "" { + tfMap["authentication_method"] = string(v) + } + if v := apiObject.CleanSourceMetadataOnMismatch; v != nil { + tfMap["clean_source_metadata_on_mismatch"] = aws.ToBool(v) + } + if v := apiObject.EventsPollInterval; v != nil { + tfMap["events_poll_interval"] = aws.ToInt32(v) + } + if v := apiObject.ExecuteTimeout; v != nil { + tfMap["execute_timeout"] = aws.ToInt32(v) + } + if v := apiObject.MaxFileSize; v != nil { + tfMap["max_file_size"] = aws.ToInt32(v) + } + if v := apiObject.ParallelLoadThreads; v != nil { + tfMap["parallel_load_threads"] = aws.ToInt32(v) + } + if v := apiObject.ServerTimezone; v != nil { + tfMap["server_timezone"] = aws.ToString(v) + } + if v := apiObject.ServiceAccessRoleArn; v != nil { + tfMap["service_access_role_arn"] = aws.ToString(v) + } + if v := apiObject.TargetDbType; v != "" { + tfMap["target_db_type"] = string(v) + } + + return []map[string]any{tfMap} +} + func flattenPostgreSQLSettings(apiObject *awstypes.PostgreSQLSettings) []map[string]any { if apiObject == nil { return nil @@ -2379,6 +2542,7 @@ func waitConnectionSucceeded(ctx context.Context, conn *dms.Client, endpointARN outputRaw, err := stateConf.WaitForStateContext(ctx) if output, ok := outputRaw.(*awstypes.Connection); ok { + tfresource.SetLastError(err, errors.New(aws.ToString(output.LastFailureMessage))) return output, err } diff --git a/internal/service/dms/endpoint_data_source.go b/internal/service/dms/endpoint_data_source.go index b1d363ab9f82..099bb63e8fbe 100644 --- a/internal/service/dms/endpoint_data_source.go +++ b/internal/service/dms/endpoint_data_source.go @@ -245,6 +245,54 @@ func dataSourceEndpoint() *schema.Resource { }, }, }, + "mysql_settings": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "after_connect_script": { + Type: schema.TypeString, + Computed: true, + }, + "authentication_method": { + Type: schema.TypeString, + Computed: true, + }, + "clean_source_metadata_on_mismatch": { + Type: schema.TypeBool, + Computed: true, + }, + "events_poll_interval": { + Type: schema.TypeInt, + Computed: true, + }, + "execute_timeout": { + Type: schema.TypeInt, + Computed: true, + }, + "max_file_size": { + Type: schema.TypeInt, + Computed: true, + }, + "parallel_load_threads": { + Type: schema.TypeInt, + Computed: true, + }, + "server_timezone": { + Type: schema.TypeString, + Computed: true, + }, + "service_access_role_arn": { + Type: schema.TypeString, + Computed: true, + }, + "target_db_type": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, names.AttrPassword: { Type: schema.TypeString, Computed: true, @@ -643,6 +691,9 @@ func resourceEndpointDataSourceSetState(d *schema.ResourceData, endpoint *awstyp } else { flattenTopLevelConnectionInfo(d, endpoint) } + if err := d.Set("mysql_settings", flattenMySQLSettings(endpoint.MySQLSettings)); err != nil { + return fmt.Errorf("setting mysql_settings: %w", err) + } case engineNameAuroraPostgresql, engineNamePostgres: if endpoint.PostgreSQLSettings != nil { d.Set(names.AttrUsername, endpoint.PostgreSQLSettings.Username) diff --git a/internal/service/dms/endpoint_test.go b/internal/service/dms/endpoint_test.go index 23ff94307af3..3a8b580520b6 100644 --- a/internal/service/dms/endpoint_test.go +++ b/internal/service/dms/endpoint_test.go @@ -1144,6 +1144,130 @@ func TestAccDMSEndpoint_PostgreSQL_kmsKey(t *testing.T) { }) } +func TestAccDMSEndpoint_MySQL_settings_source(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_dms_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.DMSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEndpointConfig_mySQLSourceSettings(rName, true, 5), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.after_connect_script", "SELECT NOW();"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.authentication_method", "iam"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.clean_source_metadata_on_mismatch", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.events_poll_interval", "5"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.execute_timeout", "100"), + resource.TestCheckResourceAttrPair(resourceName, "mysql_settings.0.service_access_role_arn", "aws_iam_role.test", names.AttrARN), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrPassword}, + }, + { + // Change events_poll_interval from 5 to 10 + Config: testAccEndpointConfig_mySQLSourceSettings(rName, true, 10), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.after_connect_script", "SELECT NOW();"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.authentication_method", "iam"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.clean_source_metadata_on_mismatch", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.events_poll_interval", "10"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.execute_timeout", "100"), + resource.TestCheckResourceAttrPair(resourceName, "mysql_settings.0.service_access_role_arn", "aws_iam_role.test", names.AttrARN), + ), + }, + { + // Remove mysql_settings block (inherited the previous values) + Config: testAccEndpointConfig_mySQLSourceSettings(rName, false, 10), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.after_connect_script", "SELECT NOW();"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.authentication_method", "iam"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.clean_source_metadata_on_mismatch", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.events_poll_interval", "10"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.execute_timeout", "100"), + resource.TestCheckResourceAttrPair(resourceName, "mysql_settings.0.service_access_role_arn", "aws_iam_role.test", names.AttrARN), + ), + }, + }, + }) +} + +func TestAccDMSEndpoint_MySQL_settings_target(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_dms_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.DMSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEndpointConfig_mySQLTargetSettings(rName, true, 100), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.after_connect_script", "SELECT NOW();"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.authentication_method", string(awstypes.MySQLAuthenticationMethodPassword)), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.execute_timeout", "100"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.max_file_size", "1024"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.parallel_load_threads", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.target_db_type", string(awstypes.TargetDbTypeMultipleDatabases)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrPassword}, + }, + { + // Change execute_timeout from 100 to 60 + Config: testAccEndpointConfig_mySQLTargetSettings(rName, true, 60), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.after_connect_script", "SELECT NOW();"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.authentication_method", string(awstypes.MySQLAuthenticationMethodPassword)), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.execute_timeout", "60"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.max_file_size", "1024"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.parallel_load_threads", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.target_db_type", string(awstypes.TargetDbTypeMultipleDatabases)), + ), + }, + { + // Remove mysql_settings block (inherited the previous values) + Config: testAccEndpointConfig_mySQLTargetSettings(rName, false, 60), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.#", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.after_connect_script", "SELECT NOW();"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.authentication_method", string(awstypes.MySQLAuthenticationMethodPassword)), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.execute_timeout", "60"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.max_file_size", "1024"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.parallel_load_threads", "1"), + resource.TestCheckResourceAttr(resourceName, "mysql_settings.0.target_db_type", string(awstypes.TargetDbTypeMultipleDatabases)), + ), + }, + }, + }) +} + func TestAccDMSEndpoint_PostgreSQL_settings_source(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_dms_endpoint.test" @@ -1210,6 +1334,67 @@ func TestAccDMSEndpoint_PostgreSQL_settings_target(t *testing.T) { }) } +func TestAccDMSEndpoint_PostgreSQL_settings_update(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_dms_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.DMSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + // Create with heartbeat disabled + Config: testAccEndpointConfig_postgreSQLHeartbeat(rName, false, ""), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "engine_name", "postgres"), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_enable", acctest.CtFalse), + ), + }, + { + // Update only nested postgres_settings: enable heartbeat + set schema + Config: testAccEndpointConfig_postgreSQLHeartbeat(rName, true, "dms_heartbeat"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_enable", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "postgres_settings.0.heartbeat_schema", "dms_heartbeat"), + ), + }, + }, + }) +} + +func testAccEndpointConfig_postgreSQLHeartbeat(id string, heartbeat bool, schema string) string { + schemaLine := "" + if schema != "" { + schemaLine = fmt.Sprintf(`heartbeat_schema = %q`, schema) + } + + // DMS ModifyEndpoint accepts metadata changes without validating connectivity, + // so placeholder connection values are sufficient for the test + return fmt.Sprintf(` +resource "aws_dms_endpoint" "test" { + endpoint_id = %q + endpoint_type = "source" + engine_name = "postgres" + + username = "user" + password = "pass" + server_name = "example.com" + database_name = "postgres" + port = 5432 + + postgres_settings { + heartbeat_enable = %t + %s + } +} +`, id, heartbeat, schemaLine) +} + func TestAccDMSEndpoint_SQLServer_basic(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_dms_endpoint.test" @@ -3150,6 +3335,111 @@ resource "aws_dms_endpoint" "test" { `, rName) } +func testAccEndpointConfig_mySQLSourceSettingsBlock(eventsPollInterval int) string { + return fmt.Sprintf(` + mysql_settings { + after_connect_script = "SELECT NOW();" + authentication_method = "iam" + clean_source_metadata_on_mismatch = true + events_poll_interval = %[1]d + execute_timeout = 100 + service_access_role_arn = aws_iam_role.test.arn + server_timezone = "UTC" + } +`, eventsPollInterval) +} + +func testAccEndpointConfig_certificateBase(rName string) string { + return fmt.Sprintf(` +resource "aws_dms_certificate" "dms_certificate" { + certificate_id = %[1]q + certificate_pem = "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIJAJ58TJVjU7G1MA0GCSqGSIb3DQEBBQUAMFExCzAJBgNV\nBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRAwDgYD\nVQQKEwdDaGFydGVyMQwwCgYDVQQLEwNDU0UwHhcNMTcwMTMwMTkyMDA4WhcNMjYx\nMjA5MTkyMDA4WjBRMQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzAN\nBgNVBAcTBkRlbnZlcjEQMA4GA1UEChMHQ2hhcnRlcjEMMAoGA1UECxMDQ1NFMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv6dq6VLIImlAaTrckb5w3X6J\nWP7EGz2ChGAXlkEYto6dPCba0v5+f+8UlMOpeB25XGoai7gdItqNWVFpYsgmndx3\nvTad3ukO1zeElKtw5oHPH2plOaiv/gVJaDa9NTeINj0EtGZs74fCOclAzGFX5vBc\nb08ESWBceRgGjGv3nlij4JzHfqTkCKQz6P6pBivQBfk62rcOkkH5rKoaGltRHROS\nMbkwOhu2hN0KmSYTXRvts0LXnZU4N0l2ms39gmr7UNNNlKYINL2JoTs9dNBc7APD\ndZvlEHd+/FjcLCI8hC3t4g4AbfW0okIBCNG0+oVjqGb2DeONSJKsThahXt89MQID\nAQABo4G0MIGxMB0GA1UdDgQWBBQKq8JxjY1GmeZXJjfOMfW0kBIzPDCBgQYDVR0j\nBHoweIAUCqvCcY2NRpnmVyY3zjH1tJASMzyhVaRTMFExCzAJBgNVBAYTAlVTMREw\nDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRAwDgYDVQQKEwdDaGFy\ndGVyMQwwCgYDVQQLEwNDU0WCCQCefEyVY1OxtTAMBgNVHRMEBTADAQH/MA0GCSqG\nSIb3DQEBBQUAA4IBAQAWifoMk5kbv+yuWXvFwHiB4dWUUmMlUlPU/E300yVTRl58\np6DfOgJs7MMftd1KeWqTO+uW134QlTt7+jwI8Jq0uyKCu/O2kJhVtH/Ryog14tGl\n+wLcuIPLbwJI9CwZX4WMBrq4DnYss+6F47i8NCc+Z3MAiG4vtq9ytBmaod0dj2bI\ng4/Lac0e00dql9RnqENh1+dF0V+QgTJCoPkMqDNAlSB8vOodBW81UAb2z12t+IFi\n3X9J3WtCK2+T5brXL6itzewWJ2ALvX3QpmZx7fMHJ3tE+SjjyivE1BbOlzYHx83t\nTeYnm7pS9un7A/UzTDHbs7hPUezLek+H3xTPAnnq\n-----END CERTIFICATE-----\n" +} +`, rName) +} + +func testAccEndpointConfig_mySQLSourceSettings(rName string, outputMySQLSettings bool, eventsPollInterval int) string { + mysqlSettings := "" + if outputMySQLSettings { + mysqlSettings = testAccEndpointConfig_mySQLSourceSettingsBlock(eventsPollInterval) + } + return acctest.ConfigCompose(testAccEndpointConfig_certificateBase(rName), fmt.Sprintf(` +data "aws_region" "current" {} +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = < 0 { + if v, ok := tfMap["capacity_reservation_target"].([]any); ok && len(v) > 0 && v[0] != nil { apiObject.CapacityReservationTarget = expandCapacityReservationTarget(v[0].(map[string]any)) } @@ -4162,43 +3963,6 @@ func findInstanceLaunchTemplateVersion(ctx context.Context, conn *ec2.Client, id return launchTemplateVersion, nil } -func findLaunchTemplateData(ctx context.Context, conn *ec2.Client, launchTemplateSpecification *awstypes.LaunchTemplateSpecification) (*awstypes.ResponseLaunchTemplateData, error) { - input := ec2.DescribeLaunchTemplateVersionsInput{} - - if v := aws.ToString(launchTemplateSpecification.LaunchTemplateId); v != "" { - input.LaunchTemplateId = aws.String(v) - } else if v := aws.ToString(launchTemplateSpecification.LaunchTemplateName); v != "" { - input.LaunchTemplateName = aws.String(v) - } - - var latestVersion bool - - if v := aws.ToString(launchTemplateSpecification.Version); v != "" { - switch v { - case launchTemplateVersionDefault: - input.Filters = newAttributeFilterList(map[string]string{ - "is-default-version": "true", - }) - case launchTemplateVersionLatest: - latestVersion = true - default: - input.Versions = []string{v} - } - } - - output, err := findLaunchTemplateVersions(ctx, conn, &input) - - if err != nil { - return nil, fmt.Errorf("reading EC2 Launch Template versions: %w", err) - } - - if latestVersion { - return output[len(output)-1].LaunchTemplateData, nil - } - - return output[0].LaunchTemplateData, nil -} - // findLaunchTemplateNameAndVersions returns the specified launch template's name, default version and latest version. func findLaunchTemplateNameAndVersions(ctx context.Context, conn *ec2.Client, id string) (string, string, string, error) { lt, err := findLaunchTemplateByID(ctx, conn, id) @@ -4207,31 +3971,7 @@ func findLaunchTemplateNameAndVersions(ctx context.Context, conn *ec2.Client, id return "", "", "", err } - return aws.ToString(lt.LaunchTemplateName), strconv.FormatInt(aws.ToInt64(lt.DefaultVersionNumber), 10), strconv.FormatInt(aws.ToInt64(lt.LatestVersionNumber), 10), nil -} - -func findInstanceTagValue(ctx context.Context, conn *ec2.Client, instanceID, tagKey string) (string, error) { - input := ec2.DescribeTagsInput{ - Filters: newAttributeFilterList(map[string]string{ - "resource-id": instanceID, - names.AttrKey: tagKey, - }), - } - - output, err := conn.DescribeTags(ctx, &input) - - if err != nil { - return "", err - } - - switch count := len(output.Tags); count { - case 0: - return "", nil - case 1: - return aws.ToString(output.Tags[0].Value), nil - default: - return "", tfresource.NewTooManyResultsError(count, input) - } + return aws.ToString(lt.LaunchTemplateName), flex.Int64ToStringValue(lt.DefaultVersionNumber), flex.Int64ToStringValue(lt.LatestVersionNumber), nil } // isSnowballEdgeInstance returns whether or not the specified instance ID indicates an SBE instance. diff --git a/internal/service/ec2/ec2_instance_metadata_defaults.go b/internal/service/ec2/ec2_instance_metadata_defaults.go index 4a20d23bbd14..92bf42b35bbc 100644 --- a/internal/service/ec2/ec2_instance_metadata_defaults.go +++ b/internal/service/ec2/ec2_instance_metadata_defaults.go @@ -216,21 +216,6 @@ func (r *instanceMetadataDefaultsResource) Delete(ctx context.Context, request r } } -func findInstanceMetadataDefaults(ctx context.Context, conn *ec2.Client) (*awstypes.InstanceMetadataDefaultsResponse, error) { - input := ec2.GetInstanceMetadataDefaultsInput{} - output, err := conn.GetInstanceMetadataDefaults(ctx, &input) - - if err != nil { - return nil, err - } - - if output == nil || output.AccountLevel == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output.AccountLevel, nil -} - type instanceMetadataDefaultsResourceModel struct { framework.WithRegionModel HttpEndpoint fwtypes.StringEnum[awstypes.DefaultInstanceMetadataEndpointState] `tfsdk:"http_endpoint"` diff --git a/internal/service/ec2/ec2_instance_test.go b/internal/service/ec2/ec2_instance_test.go index d6d96de45003..8a352776ea12 100644 --- a/internal/service/ec2/ec2_instance_test.go +++ b/internal/service/ec2/ec2_instance_test.go @@ -10048,7 +10048,7 @@ resource "aws_instance" "test" { resource "aws_ec2_capacity_reservation" "test" { instance_type = data.aws_ec2_instance_type_offering.available.instance_type instance_platform = %[2]q - availability_zone = data.aws_availability_zones.available.names[0] + availability_zone = data.aws_availability_zones.available.names[1] instance_count = 10 tags = { diff --git a/internal/service/ec2/ec2_instance_type_offering_data_source.go b/internal/service/ec2/ec2_instance_type_offering_data_source.go index 9e45c474a778..00aa9f18259e 100644 --- a/internal/service/ec2/ec2_instance_type_offering_data_source.go +++ b/internal/service/ec2/ec2_instance_type_offering_data_source.go @@ -33,6 +33,10 @@ func dataSourceInstanceTypeOffering() *schema.Resource { Type: schema.TypeString, Computed: true, }, + names.AttrLocation: { + Type: schema.TypeString, + Computed: true, + }, "location_type": { Type: schema.TypeString, Optional: true, @@ -71,44 +75,42 @@ func dataSourceInstanceTypeOfferingRead(ctx context.Context, d *schema.ResourceD return sdkdiag.AppendErrorf(diags, "no EC2 Instance Type Offerings found matching criteria; try different search") } - var foundInstanceTypes []string - - for _, instanceTypeOffering := range instanceTypeOfferings { - foundInstanceTypes = append(foundInstanceTypes, string(instanceTypeOffering.InstanceType)) - } - - var resultInstanceType string + var resultInstanceTypeOffering *awstypes.InstanceTypeOffering // Search preferred instance types in their given order and set result // instance type for first match found if v, ok := d.GetOk("preferred_instance_types"); ok { for _, v := range v.([]any) { if v, ok := v.(string); ok { - if slices.Contains(foundInstanceTypes, v) { - resultInstanceType = v + if i := slices.IndexFunc(instanceTypeOfferings, func(e awstypes.InstanceTypeOffering) bool { + return string(e.InstanceType) == v + }); i != -1 { + resultInstanceTypeOffering = &instanceTypeOfferings[i] } - if resultInstanceType != "" { + if resultInstanceTypeOffering != nil { break } } } } - if resultInstanceType == "" && len(foundInstanceTypes) > 1 { + if resultInstanceTypeOffering == nil && len(instanceTypeOfferings) > 1 { return sdkdiag.AppendErrorf(diags, "multiple EC2 Instance Offerings found matching criteria; try different search") } - if resultInstanceType == "" && len(foundInstanceTypes) == 1 { - resultInstanceType = foundInstanceTypes[0] + if resultInstanceTypeOffering == nil && len(instanceTypeOfferings) == 1 { + resultInstanceTypeOffering = &instanceTypeOfferings[0] } - if resultInstanceType == "" { + if resultInstanceTypeOffering == nil { return sdkdiag.AppendErrorf(diags, "no EC2 Instance Type Offerings found matching criteria; try different search") } - d.SetId(resultInstanceType) - d.Set(names.AttrInstanceType, resultInstanceType) + d.SetId(string(resultInstanceTypeOffering.InstanceType)) + d.Set(names.AttrInstanceType, string(resultInstanceTypeOffering.InstanceType)) + d.Set(names.AttrLocation, resultInstanceTypeOffering.Location) + d.Set("location_type", string(resultInstanceTypeOffering.LocationType)) return diags } diff --git a/internal/service/ec2/ec2_instance_type_offering_data_source_test.go b/internal/service/ec2/ec2_instance_type_offering_data_source_test.go index 257f372228a0..622362899f87 100644 --- a/internal/service/ec2/ec2_instance_type_offering_data_source_test.go +++ b/internal/service/ec2/ec2_instance_type_offering_data_source_test.go @@ -14,6 +14,7 @@ import ( func TestAccEC2InstanceTypeOfferingDataSource_filter(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_ec2_instance_type_offering.test" + dataSourceOfferingsName := "data.aws_ec2_instance_type_offerings.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckInstanceTypeOfferings(ctx, t) }, @@ -24,7 +25,9 @@ func TestAccEC2InstanceTypeOfferingDataSource_filter(t *testing.T) { { Config: testAccInstanceTypeOfferingDataSourceConfig_filter(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, names.AttrInstanceType), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrInstanceType, dataSourceOfferingsName, "instance_types.0"), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrLocation, dataSourceOfferingsName, "locations.0"), + resource.TestCheckResourceAttrPair(dataSourceName, "location_type", dataSourceOfferingsName, "location_types.0"), ), }, }, @@ -34,6 +37,7 @@ func TestAccEC2InstanceTypeOfferingDataSource_filter(t *testing.T) { func TestAccEC2InstanceTypeOfferingDataSource_locationType(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_ec2_instance_type_offering.test" + dataSourceOfferingsName := "data.aws_ec2_instance_type_offerings.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckInstanceTypeOfferings(ctx, t) }, @@ -44,7 +48,9 @@ func TestAccEC2InstanceTypeOfferingDataSource_locationType(t *testing.T) { { Config: testAccInstanceTypeOfferingDataSourceConfig_location(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, names.AttrInstanceType), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrInstanceType, dataSourceOfferingsName, "instance_types.0"), + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrLocation, dataSourceOfferingsName, "locations.0"), + resource.TestCheckResourceAttrPair(dataSourceName, "location_type", dataSourceOfferingsName, "location_types.0"), ), }, }, @@ -65,6 +71,8 @@ func TestAccEC2InstanceTypeOfferingDataSource_preferredInstanceTypes(t *testing. Config: testAccInstanceTypeOfferingDataSourceConfig_preferreds(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, names.AttrInstanceType, "t3.micro"), + resource.TestCheckResourceAttrSet(dataSourceName, names.AttrLocation), + resource.TestCheckResourceAttrSet(dataSourceName, "location_type"), ), }, }, diff --git a/internal/service/ec2/ec2_launch_template.go b/internal/service/ec2/ec2_launch_template.go index 78e7861c6bbc..c8a25852dafa 100644 --- a/internal/service/ec2/ec2_launch_template.go +++ b/internal/service/ec2/ec2_launch_template.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -85,7 +84,7 @@ func resourceLaunchTemplate() *schema.Resource { names.AttrKMSKeyID: { Type: schema.TypeString, Optional: true, - ValidateFunc: verify.ValidARN, + ValidateFunc: verify.ValidKMSKeyID, }, names.AttrSnapshotID: { Type: schema.TypeString, @@ -1216,48 +1215,6 @@ func resourceLaunchTemplateDelete(ctx context.Context, d *schema.ResourceData, m return diags } -const ( - LaunchTemplateFound = "Found" -) - -func statusLaunchTemplate(ctx context.Context, conn *ec2.Client, id string, idIsName bool) retry.StateRefreshFunc { - return func() (any, string, error) { - var output *awstypes.LaunchTemplate - var err error - if idIsName { - output, err = findLaunchTemplateByName(ctx, conn, id) - } else { - output, err = findLaunchTemplateByID(ctx, conn, id) - } - - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - return output, LaunchTemplateFound, nil - } -} - -func waitLaunchTemplateReady(ctx context.Context, conn *ec2.Client, id string, idIsName bool, timeout time.Duration) error { - stateConf := &retry.StateChangeConf{ - Pending: []string{""}, - Target: enum.Slice(LaunchTemplateFound), - Refresh: statusLaunchTemplate(ctx, conn, id, idIsName), - Timeout: timeout, - Delay: 5 * time.Second, - NotFoundChecks: 5, - ContinuousTargetOccurence: 3, - } - - _, err := stateConf.WaitForStateContext(ctx) - - return err -} - func expandRequestLaunchTemplateData(ctx context.Context, conn *ec2.Client, d *schema.ResourceData) (*awstypes.RequestLaunchTemplateData, error) { apiObject := &awstypes.RequestLaunchTemplateData{ // Always set at least one field. diff --git a/internal/service/ec2/ec2_serial_console_access_identity_gen_test.go b/internal/service/ec2/ec2_serial_console_access_identity_gen_test.go index 514fe53a7e06..cc61b3041477 100644 --- a/internal/service/ec2/ec2_serial_console_access_identity_gen_test.go +++ b/internal/service/ec2/ec2_serial_console_access_identity_gen_test.go @@ -22,8 +22,9 @@ func testAccEC2SerialConsoleAccess_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccEC2SerialConsoleAccess_Identity_Basic, - "ExistingResource": testAccEC2SerialConsoleAccess_Identity_ExistingResource, + acctest.CtBasic: testAccEC2SerialConsoleAccess_Identity_Basic, + "ExistingResource": testAccEC2SerialConsoleAccess_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccEC2SerialConsoleAccess_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/ec2/ec2_stop_instance_action.go b/internal/service/ec2/ec2_stop_instance_action.go index a9e9a84146a8..ae234daac1ac 100644 --- a/internal/service/ec2/ec2_stop_instance_action.go +++ b/internal/service/ec2/ec2_stop_instance_action.go @@ -5,8 +5,8 @@ package ec2 import ( "context" + "errors" "fmt" - "slices" "time" "github.com/YakDriver/regexache" @@ -21,10 +21,14 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/actionwait" "github.com/hashicorp/terraform-provider-aws/internal/framework" "github.com/hashicorp/terraform-provider-aws/names" ) +// stopInstancePollInterval defines polling cadence for stop instance action. +const stopInstancePollInterval = 10 * time.Second + // @Action(aws_ec2_stop_instance, name="Stop Instance") func newStopInstanceAction(_ context.Context) (action.ActionWithConfigure, error) { return &stopInstanceAction{}, nil @@ -180,13 +184,49 @@ func (a *stopInstanceAction) Invoke(ctx context.Context, req action.InvokeReques }) } - // Wait for instance to stop with periodic progress updates - err = a.waitForInstanceStopped(ctx, conn, instanceID, timeout, resp) + // Wait for instance to stop with periodic progress updates using actionwait + // Use fixed interval since EC2 instance state transitions are predictable and + // relatively quick - consistent polling every 10s is optimal for this operation + _, err = actionwait.WaitForStatus(ctx, func(ctx context.Context) (actionwait.FetchResult[struct{}], error) { + instance, derr := findInstanceByID(ctx, conn, instanceID) + if derr != nil { + return actionwait.FetchResult[struct{}]{}, fmt.Errorf("describing instance: %w", derr) + } + state := string(instance.State.Name) + return actionwait.FetchResult[struct{}]{Status: actionwait.Status(state)}, nil + }, actionwait.Options[struct{}]{ + Timeout: timeout, + Interval: actionwait.FixedInterval(stopInstancePollInterval), + ProgressInterval: 30 * time.Second, + SuccessStates: []actionwait.Status{actionwait.Status(awstypes.InstanceStateNameStopped)}, + TransitionalStates: []actionwait.Status{ + actionwait.Status(awstypes.InstanceStateNameRunning), + actionwait.Status(awstypes.InstanceStateNameStopping), + actionwait.Status(awstypes.InstanceStateNameShuttingDown), + }, + ProgressSink: func(fr actionwait.FetchResult[any], meta actionwait.ProgressMeta) { + resp.SendProgress(action.InvokeProgressEvent{Message: fmt.Sprintf("EC2 instance %s is currently in state '%s', continuing to wait for 'stopped'...", instanceID, fr.Status)}) + }, + }) if err != nil { - resp.Diagnostics.AddError( - "Timeout Waiting for Instance to Stop", - fmt.Sprintf("EC2 instance %s did not stop within %s: %s", instanceID, timeout, err), - ) + var timeoutErr *actionwait.TimeoutError + var unexpectedErr *actionwait.UnexpectedStateError + if errors.As(err, &timeoutErr) { + resp.Diagnostics.AddError( + "Timeout Waiting for Instance to Stop", + fmt.Sprintf("EC2 instance %s did not stop within %s: %s", instanceID, timeout, err), + ) + } else if errors.As(err, &unexpectedErr) { + resp.Diagnostics.AddError( + "Unexpected Instance State", + fmt.Sprintf("EC2 instance %s entered unexpected state while stopping: %s", instanceID, err), + ) + } else { + resp.Diagnostics.AddError( + "Error Waiting for Instance to Stop", + fmt.Sprintf("Error while waiting for EC2 instance %s to stop: %s", instanceID, err), + ) + } return } @@ -209,61 +249,3 @@ func canStopInstance(state awstypes.InstanceStateName) bool { return false } } - -// waitForInstanceStopped waits for an instance to reach the stopped state with progress updates -func (a *stopInstanceAction) waitForInstanceStopped(ctx context.Context, conn *ec2.Client, instanceID string, timeout time.Duration, resp *action.InvokeResponse) error { - const ( - pollInterval = 10 * time.Second - progressInterval = 30 * time.Second - ) - - deadline := time.Now().Add(timeout) - lastProgressUpdate := time.Now() - - for { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - // Check if we've exceeded the timeout - if time.Now().After(deadline) { - return fmt.Errorf("timeout after %s", timeout) - } - - // Get current instance state - instance, err := findInstanceByID(ctx, conn, instanceID) - if err != nil { - return fmt.Errorf("describing instance: %w", err) - } - - currentState := string(instance.State.Name) - - // Send progress update every 30 seconds - if time.Since(lastProgressUpdate) >= progressInterval { - resp.SendProgress(action.InvokeProgressEvent{ - Message: fmt.Sprintf("EC2 instance %s is currently in state '%s', continuing to wait for 'stopped'...", instanceID, currentState), - }) - lastProgressUpdate = time.Now() - } - - // Check if we've reached the target state - if instance.State.Name == awstypes.InstanceStateNameStopped { - return nil - } - - // Check if we're in an unexpected state - validStates := []awstypes.InstanceStateName{ - awstypes.InstanceStateNameRunning, - awstypes.InstanceStateNameStopping, - awstypes.InstanceStateNameShuttingDown, - } - if !slices.Contains(validStates, instance.State.Name) { - return fmt.Errorf("instance entered unexpected state: %s", currentState) - } - - // Wait before next poll - time.Sleep(pollInterval) - } -} diff --git a/internal/service/ec2/exports_test.go b/internal/service/ec2/exports_test.go index dcc6d46ad71b..969489f6f977 100644 --- a/internal/service/ec2/exports_test.go +++ b/internal/service/ec2/exports_test.go @@ -136,6 +136,7 @@ var ( CheckMostRecentAndMissingFilters = checkMostRecentAndMissingFilters CustomFiltersSchema = customFiltersSchema CustomerGatewayConfigurationToTunnelInfo = customerGatewayConfigurationToTunnelInfo + DefaultIPv6CIDRBlockAssociation = defaultIPv6CIDRBlockAssociation ErrCodeDefaultSubnetAlreadyExistsInAvailabilityZone = errCodeDefaultSubnetAlreadyExistsInAvailabilityZone ErrCodeInvalidSpotDatafeedNotFound = errCodeInvalidSpotDatafeedNotFound ExpandIPPerms = expandIPPerms @@ -162,7 +163,7 @@ var ( FindHostByID = findHostByID FindIPAMByID = findIPAMByID FindIPAMPoolAllocationByTwoPartKey = findIPAMPoolAllocationByTwoPartKey - FindIPAMPoolAllocationsForVPC = findIPAMPoolAllocationsForVPC + FindIPAMPoolAllocationForResource = findIPAMPoolAllocationForResource FindIPAMPoolByID = findIPAMPoolByID FindIPAMPoolCIDRByTwoPartKey = findIPAMPoolCIDRByTwoPartKey FindIPAMResourceDiscoveryAssociationByID = findIPAMResourceDiscoveryAssociationByID diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index 5376ddd63e7e..15abb78a0ab9 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -6,6 +6,7 @@ package ec2 import ( "context" "fmt" + "iter" "slices" "strconv" "strings" @@ -379,6 +380,75 @@ func findHost(ctx context.Context, conn *ec2.Client, input *ec2.DescribeHostsInp return tfresource.AssertSingleValueResult(output, func(v *awstypes.Host) bool { return v.HostProperties != nil }) } +func findInstanceByID(ctx context.Context, conn *ec2.Client, id string) (*awstypes.Instance, error) { + input := ec2.DescribeInstancesInput{ + InstanceIds: []string{id}, + } + + output, err := findInstance(ctx, conn, &input) + + if err != nil { + return nil, err + } + + if state := output.State.Name; state == awstypes.InstanceStateNameTerminated { + return nil, &retry.NotFoundError{ + Message: string(state), + LastRequest: &input, + } + } + + // Eventual consistency check. + if aws.ToString(output.InstanceId) != id { + return nil, &retry.NotFoundError{ + LastRequest: &input, + } + } + + return output, nil +} + +func findInstance(ctx context.Context, conn *ec2.Client, input *ec2.DescribeInstancesInput) (*awstypes.Instance, error) { + output, err := tfslices.CollectWithError(listInstances(ctx, conn, input)) + + if err != nil { + return nil, err + } + + return tfresource.AssertSingleValueResult(output, func(v *awstypes.Instance) bool { return v.State != nil }) +} + +// DescribeInstances is an "All-Or-Some" call. +func listInstances(ctx context.Context, conn *ec2.Client, input *ec2.DescribeInstancesInput) iter.Seq2[awstypes.Instance, error] { + return func(yield func(awstypes.Instance, error) bool) { + pages := ec2.NewDescribeInstancesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if tfawserr.ErrCodeEquals(err, errCodeInvalidInstanceIDNotFound) { + yield(awstypes.Instance{}, &retry.NotFoundError{ + LastError: err, + LastRequest: &input, + }) + return + } + + if err != nil { + yield(awstypes.Instance{}, err) + return + } + + for _, v := range page.Reservations { + for _, instance := range v.Instances { + if !yield(instance, nil) { + return + } + } + } + } + } +} + func findInstanceCreditSpecifications(ctx context.Context, conn *ec2.Client, input *ec2.DescribeInstanceCreditSpecificationsInput) ([]awstypes.InstanceCreditSpecification, error) { var output []awstypes.InstanceCreditSpecification @@ -403,6 +473,30 @@ func findInstanceCreditSpecifications(ctx context.Context, conn *ec2.Client, inp return output, nil } +func findInstanceTagValue(ctx context.Context, conn *ec2.Client, instanceID, tagKey string) (string, error) { + input := ec2.DescribeTagsInput{ + Filters: newAttributeFilterList(map[string]string{ + "resource-id": instanceID, + names.AttrKey: tagKey, + }), + } + + output, err := conn.DescribeTags(ctx, &input) + + if err != nil { + return "", err + } + + switch count := len(output.Tags); count { + case 0: + return "", nil + case 1: + return aws.ToString(output.Tags[0].Value), nil + default: + return "", tfresource.NewTooManyResultsError(count, input) + } +} + func findInstanceCreditSpecification(ctx context.Context, conn *ec2.Client, input *ec2.DescribeInstanceCreditSpecificationsInput) (*awstypes.InstanceCreditSpecification, error) { output, err := findInstanceCreditSpecifications(ctx, conn, input) @@ -434,6 +528,21 @@ func findInstanceCreditSpecificationByID(ctx context.Context, conn *ec2.Client, return output, nil } +func findInstanceMetadataDefaults(ctx context.Context, conn *ec2.Client) (*awstypes.InstanceMetadataDefaultsResponse, error) { + input := ec2.GetInstanceMetadataDefaultsInput{} + output, err := conn.GetInstanceMetadataDefaults(ctx, &input) + + if err != nil { + return nil, err + } + + if output == nil || output.AccountLevel == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.AccountLevel, nil +} + func findInstanceStatus(ctx context.Context, conn *ec2.Client, input *ec2.DescribeInstanceStatusInput) (*awstypes.InstanceStatus, error) { output, err := findInstanceStatuses(ctx, conn, input) @@ -770,6 +879,43 @@ func findLaunchTemplateVersionByTwoPartKey(ctx context.Context, conn *ec2.Client return output, nil } +func findLaunchTemplateData(ctx context.Context, conn *ec2.Client, launchTemplateSpecification *awstypes.LaunchTemplateSpecification) (*awstypes.ResponseLaunchTemplateData, error) { + input := ec2.DescribeLaunchTemplateVersionsInput{} + + if v := aws.ToString(launchTemplateSpecification.LaunchTemplateId); v != "" { + input.LaunchTemplateId = aws.String(v) + } else if v := aws.ToString(launchTemplateSpecification.LaunchTemplateName); v != "" { + input.LaunchTemplateName = aws.String(v) + } + + var latestVersion bool + + if v := aws.ToString(launchTemplateSpecification.Version); v != "" { + switch v { + case launchTemplateVersionDefault: + input.Filters = newAttributeFilterList(map[string]string{ + "is-default-version": "true", + }) + case launchTemplateVersionLatest: + latestVersion = true + default: + input.Versions = []string{v} + } + } + + output, err := findLaunchTemplateVersions(ctx, conn, &input) + + if err != nil { + return nil, fmt.Errorf("reading EC2 Launch Template versions: %w", err) + } + + if latestVersion { + return output[len(output)-1].LaunchTemplateData, nil + } + + return output[0].LaunchTemplateData, nil +} + func findLocalGatewayRouteTable(ctx context.Context, conn *ec2.Client, input *ec2.DescribeLocalGatewayRouteTablesInput) (*awstypes.LocalGatewayRouteTable, error) { output, err := findLocalGatewayRouteTables(ctx, conn, input) @@ -1101,6 +1247,48 @@ func findPublicIPv4PoolByID(ctx context.Context, conn *ec2.Client, id string) (* return output, nil } +func findVolumeAttachment(ctx context.Context, conn *ec2.Client, volumeID, instanceID, deviceName string) (*awstypes.VolumeAttachment, error) { + input := ec2.DescribeVolumesInput{ + Filters: newAttributeFilterList(map[string]string{ + "attachment.device": deviceName, + "attachment.instance-id": instanceID, + }), + VolumeIds: []string{volumeID}, + } + + output, err := findEBSVolume(ctx, conn, &input) + + if err != nil { + return nil, err + } + + if state := output.State; state == awstypes.VolumeStateAvailable || state == awstypes.VolumeStateDeleted { + return nil, &retry.NotFoundError{ + Message: string(state), + LastRequest: input, + } + } + + // Eventual consistency check. + if aws.ToString(output.VolumeId) != volumeID { + return nil, &retry.NotFoundError{ + LastRequest: input, + } + } + + for _, v := range output.Attachments { + if v.State == awstypes.VolumeAttachmentStateDetached { + continue + } + + if aws.ToString(v.Device) == deviceName && aws.ToString(v.InstanceId) == instanceID { + return &v, nil + } + } + + return nil, &retry.NotFoundError{} +} + func findVolumeAttachmentInstanceByID(ctx context.Context, conn *ec2.Client, id string) (*awstypes.Instance, error) { input := ec2.DescribeInstancesInput{ InstanceIds: []string{id}, @@ -3998,6 +4186,16 @@ func findIPAMPoolAllocationsByIPAMPoolIDAndResourceID(ctx context.Context, conn }), nil } +func findIPAMPoolAllocationForResource(ctx context.Context, conn *ec2.Client, ipamPoolID, resourceID string) (*awstypes.IpamPoolAllocation, error) { + output, err := findIPAMPoolAllocationsByIPAMPoolIDAndResourceID(ctx, conn, ipamPoolID, resourceID) + + if err != nil { + return nil, err + } + + return tfresource.AssertFirstValueResult(output) +} + func findIPAMPoolCIDR(ctx context.Context, conn *ec2.Client, input *ec2.GetIpamPoolCidrsInput) (*awstypes.IpamPoolCidr, error) { output, err := findIPAMPoolCIDRs(ctx, conn, input) diff --git a/internal/service/ec2/status.go b/internal/service/ec2/status.go index 68360df6177f..04f0f2e509f0 100644 --- a/internal/service/ec2/status.go +++ b/internal/service/ec2/status.go @@ -15,6 +15,10 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) +const ( + launchTemplateFoundStatus = "Found" +) + func statusAvailabilityZoneGroupOptInStatus(ctx context.Context, conn *ec2.Client, name string) retry.StateRefreshFunc { return func() (any, string, error) { output, err := findAvailabilityZoneGroupByName(ctx, conn, name) @@ -221,6 +225,28 @@ func statusInstanceRootBlockDeviceDeleteOnTermination(ctx context.Context, conn } } +func statusLaunchTemplate(ctx context.Context, conn *ec2.Client, id string, idIsName bool) retry.StateRefreshFunc { + return func() (any, string, error) { + var output *awstypes.LaunchTemplate + var err error + if idIsName { + output, err = findLaunchTemplateByName(ctx, conn, id) + } else { + output, err = findLaunchTemplateByID(ctx, conn, id) + } + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, launchTemplateFoundStatus, nil + } +} + func statusLocalGatewayRoute(ctx context.Context, conn *ec2.Client, localGatewayRouteTableID, destinationCIDRBlock string) retry.StateRefreshFunc { return func() (any, string, error) { output, err := findLocalGatewayRouteByTwoPartKey(ctx, conn, localGatewayRouteTableID, destinationCIDRBlock) @@ -564,6 +590,25 @@ func statusVolumeAttachment(ctx context.Context, conn *ec2.Client, volumeID, ins } } +func statusVolumeAttachmentInstanceState(ctx context.Context, conn *ec2.Client, id string) retry.StateRefreshFunc { + return func() (any, string, error) { + // Don't call FindInstanceByID as it maps useful status codes to NotFoundError. + output, err := findInstance(ctx, conn, &ec2.DescribeInstancesInput{ + InstanceIds: []string{id}, + }) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, string(output.State.Name), nil + } +} + func statusVolumeModification(ctx context.Context, conn *ec2.Client, id string) retry.StateRefreshFunc { return func() (any, string, error) { output, err := findVolumeModificationByID(ctx, conn, id) diff --git a/internal/service/ec2/transitgateway_.go b/internal/service/ec2/transitgateway_.go index 5acf92ab34db..0a761d5d81fb 100644 --- a/internal/service/ec2/transitgateway_.go +++ b/internal/service/ec2/transitgateway_.go @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -325,23 +324,3 @@ func resourceTransitGatewayDelete(ctx context.Context, d *schema.ResourceData, m return diags } - -func waitTransitGatewayDeleted(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.TransitGateway, error) { - stateConf := &retry.StateChangeConf{ - Pending: enum.Slice(awstypes.TransitGatewayStateAvailable, awstypes.TransitGatewayStateDeleting), - Target: []string{}, - Refresh: statusTransitGateway(ctx, conn, id), - Timeout: timeout, - Delay: 2 * time.Minute, - MinTimeout: 10 * time.Second, - NotFoundChecks: 1, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*awstypes.TransitGateway); ok { - return output, err - } - - return nil, err -} diff --git a/internal/service/ec2/vpc_.go b/internal/service/ec2/vpc_.go index 71427eb3f8fa..cabb3106f64e 100644 --- a/internal/service/ec2/vpc_.go +++ b/internal/service/ec2/vpc_.go @@ -16,7 +16,6 @@ import ( awstypes "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -484,7 +483,7 @@ func resourceVPCDelete(ctx context.Context, d *schema.ResourceData, meta any) di timeout = 35 * time.Minute // IPAM eventual consistency. It can take ~30 min to release allocations. ) _, err := tfresource.RetryUntilNotFound(ctx, timeout, func(ctx context.Context) (any, error) { - return findIPAMPoolAllocationsForVPC(ctx, conn, ipamPoolID, d.Id()) + return findIPAMPoolAllocationForResource(ctx, conn, ipamPoolID, d.Id()) }) if err != nil { @@ -548,6 +547,7 @@ func defaultIPv6CIDRBlockAssociation(vpc *awstypes.Vpc, associationID string) *a for _, v := range vpc.Ipv6CidrBlockAssociationSet { if v.Ipv6CidrBlockState.State == awstypes.VpcCidrBlockStateCodeAssociated { ipv6CIDRBlockAssociation = v + break } } } @@ -716,28 +716,6 @@ func modifyVPCTenancy(ctx context.Context, conn *ec2.Client, vpcID string, v str return nil } -func findIPAMPoolAllocationsForVPC(ctx context.Context, conn *ec2.Client, poolID, vpcID string) ([]awstypes.IpamPoolAllocation, error) { - input := &ec2.GetIpamPoolAllocationsInput{ - IpamPoolId: aws.String(poolID), - } - - output, err := findIPAMPoolAllocations(ctx, conn, input) - - if err != nil { - return nil, err - } - - output = tfslices.Filter(output, func(v awstypes.IpamPoolAllocation) bool { - return v.ResourceType == awstypes.IpamPoolAllocationResourceTypeVpc && aws.ToString(v.ResourceId) == vpcID - }) - - if len(output) == 0 { - return nil, &retry.NotFoundError{} - } - - return output, nil -} - func vpcARN(ctx context.Context, c *conns.AWSClient, accountID, vpcID string) string { return c.RegionalARNWithAccount(ctx, names.EC2, accountID, "vpc/"+vpcID) } diff --git a/internal/service/ec2/vpc_ipv4_cidr_block_association.go b/internal/service/ec2/vpc_ipv4_cidr_block_association.go index 93d71622a4e7..9d24f7de25a0 100644 --- a/internal/service/ec2/vpc_ipv4_cidr_block_association.go +++ b/internal/service/ec2/vpc_ipv4_cidr_block_association.go @@ -163,7 +163,7 @@ func resourceVPCIPv4CIDRBlockAssociationDelete(ctx context.Context, d *schema.Re } _, err := conn.DisassociateVpcCidrBlock(ctx, &input) - if tfawserr.ErrCodeEquals(err, errCodeInvalidVPCCIDRBlockAssociationIDNotFound) { + if tfawserr.ErrCodeEquals(err, errCodeInvalidVPCCIDRBlockAssociationIDNotFound, errCodeInvalidVPCIDNotFound) { return diags } diff --git a/internal/service/ec2/vpc_ipv4_cidr_block_association_test.go b/internal/service/ec2/vpc_ipv4_cidr_block_association_test.go index 5bcb5e63e8a8..7ce8e52d5350 100644 --- a/internal/service/ec2/vpc_ipv4_cidr_block_association_test.go +++ b/internal/service/ec2/vpc_ipv4_cidr_block_association_test.go @@ -277,7 +277,7 @@ func testAccCheckVPCIPv4CIDRBlockAssociationWaitVPCIPAMPoolAllocationDeleted(ctx timeout = 35 * time.Minute // IPAM eventual consistency. It can take ~30 min to release allocations. ) _, err := tfresource.RetryUntilNotFound(ctx, timeout, func(ctx context.Context) (any, error) { - return tfec2.FindIPAMPoolAllocationsForVPC(ctx, conn, rsIPAMPool.Primary.ID, rsVPC.Primary.ID) + return tfec2.FindIPAMPoolAllocationForResource(ctx, conn, rsIPAMPool.Primary.ID, rsVPC.Primary.ID) }) return err diff --git a/internal/service/ec2/vpc_test.go b/internal/service/ec2/vpc_test.go index 056accddcd37..1c3acc12a6e2 100644 --- a/internal/service/ec2/vpc_test.go +++ b/internal/service/ec2/vpc_test.go @@ -29,6 +29,22 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) +func TestDefaultIPv6CIDRBlockAssociation(t *testing.T) { + t.Parallel() + + vpc := awstypes.Vpc{ + Ipv6CidrBlockAssociationSet: []awstypes.VpcIpv6CidrBlockAssociation{ + {AssociationId: aws.String("default_cidr"), Ipv6CidrBlock: aws.String("fd00:1::/64"), Ipv6CidrBlockState: &awstypes.VpcCidrBlockState{State: awstypes.VpcCidrBlockStateCodeAssociated}}, + {AssociationId: aws.String("some_other_cidr"), Ipv6CidrBlock: aws.String("fd00:2::/64"), Ipv6CidrBlockState: &awstypes.VpcCidrBlockState{State: awstypes.VpcCidrBlockStateCodeAssociated}}, + }, + } + if v := tfec2.DefaultIPv6CIDRBlockAssociation(&vpc, ""); v == nil { + t.Errorf("defaultIPv6CIDRBlockAssociation() got nil") + } else if got, want := aws.ToString(v.AssociationId), "default_cidr"; got != want { + t.Errorf("defaultIPv6CIDRBlockAssociation() = %v, want = %v", got, want) + } +} + func TestAccVPC_basic(t *testing.T) { ctx := acctest.Context(t) var vpc awstypes.Vpc diff --git a/internal/service/ec2/wait.go b/internal/service/ec2/wait.go index 1c8a24f8075e..3a2ba186485d 100644 --- a/internal/service/ec2/wait.go +++ b/internal/service/ec2/wait.go @@ -652,6 +652,132 @@ func waitImageDeleted(ctx context.Context, conn *ec2.Client, id string, timeout return nil, err } +func waitInstanceCreated(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Instance, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.InstanceStateNamePending), + Target: enum.Slice(awstypes.InstanceStateNameRunning), + Refresh: statusInstance(ctx, conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.ToString(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + +func waitInstanceDeleted(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Instance, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice( + awstypes.InstanceStateNamePending, + awstypes.InstanceStateNameRunning, + awstypes.InstanceStateNameShuttingDown, + awstypes.InstanceStateNameStopping, + awstypes.InstanceStateNameStopped, + ), + Target: enum.Slice(awstypes.InstanceStateNameTerminated), + Refresh: statusInstance(ctx, conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.ToString(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + +func waitInstanceReady(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Instance, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.InstanceStateNamePending, awstypes.InstanceStateNameStopping), + Target: enum.Slice(awstypes.InstanceStateNameRunning, awstypes.InstanceStateNameStopped), + Refresh: statusInstance(ctx, conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.ToString(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + +func waitInstanceStarted(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Instance, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.InstanceStateNamePending, awstypes.InstanceStateNameStopped), + Target: enum.Slice(awstypes.InstanceStateNameRunning), + Refresh: statusInstance(ctx, conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.ToString(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + +func waitInstanceStopped(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Instance, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice( + awstypes.InstanceStateNamePending, + awstypes.InstanceStateNameRunning, + awstypes.InstanceStateNameShuttingDown, + awstypes.InstanceStateNameStopping, + ), + Target: enum.Slice(awstypes.InstanceStateNameStopped), + Refresh: statusInstance(ctx, conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.ToString(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + func waitInstanceCapacityReservationSpecificationUpdated(ctx context.Context, conn *ec2.Client, instanceID string, expectedValue *awstypes.CapacityReservationSpecification) (*awstypes.Instance, error) { stateConf := &retry.StateChangeConf{ Target: enum.Slice(strconv.FormatBool(true)), @@ -1125,6 +1251,22 @@ func waitIPAMUpdated(ctx context.Context, conn *ec2.Client, id string, timeout t return nil, err } +func waitLaunchTemplateReady(ctx context.Context, conn *ec2.Client, id string, idIsName bool, timeout time.Duration) error { + stateConf := &retry.StateChangeConf{ + Pending: []string{""}, + Target: enum.Slice(launchTemplateFoundStatus), + Refresh: statusLaunchTemplate(ctx, conn, id, idIsName), + Timeout: timeout, + Delay: 5 * time.Second, + NotFoundChecks: 5, + ContinuousTargetOccurence: 3, + } + + _, err := stateConf.WaitForStateContext(ctx) + + return err +} + func waitLocalGatewayRouteDeleted(ctx context.Context, conn *ec2.Client, localGatewayRouteTableID, destinationCIDRBlock string) (*awstypes.LocalGatewayRoute, error) { const ( timeout = 5 * time.Minute @@ -2174,6 +2316,26 @@ func waitTransitGatewayCreated(ctx context.Context, conn *ec2.Client, id string, return nil, err } +func waitTransitGatewayDeleted(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.TransitGateway, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.TransitGatewayStateAvailable, awstypes.TransitGatewayStateDeleting), + Target: []string{}, + Refresh: statusTransitGateway(ctx, conn, id), + Timeout: timeout, + Delay: 2 * time.Minute, + MinTimeout: 10 * time.Second, + NotFoundChecks: 1, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.TransitGateway); ok { + return output, err + } + + return nil, err +} + func waitTransitGatewayMulticastDomainCreated(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.TransitGatewayMulticastDomain, error) { stateConf := &retry.StateChangeConf{ Pending: enum.Slice(awstypes.TransitGatewayMulticastDomainStatePending), @@ -2718,6 +2880,76 @@ func waitVolumeAttachmentCreated(ctx context.Context, conn *ec2.Client, volumeID return nil, err } +func waitVolumeAttachmentDeleted(ctx context.Context, conn *ec2.Client, volumeID, instanceID, deviceName string, timeout time.Duration) (*awstypes.VolumeAttachment, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.VolumeAttachmentStateDetaching), + Target: []string{}, + Refresh: statusVolumeAttachment(ctx, conn, volumeID, instanceID, deviceName), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.VolumeAttachment); ok { + return output, err + } + + return nil, err +} + +func waitVolumeAttachmentInstanceReady(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Instance, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.InstanceStateNamePending, awstypes.InstanceStateNameStopping), + Target: enum.Slice(awstypes.InstanceStateNameRunning, awstypes.InstanceStateNameStopped), + Refresh: statusVolumeAttachmentInstanceState(ctx, conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.ToString(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + +func waitVolumeAttachmentInstanceStopped(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Instance, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice( + awstypes.InstanceStateNamePending, + awstypes.InstanceStateNameRunning, + awstypes.InstanceStateNameShuttingDown, + awstypes.InstanceStateNameStopping, + ), + Target: enum.Slice(awstypes.InstanceStateNameStopped), + Refresh: statusVolumeAttachmentInstanceState(ctx, conn, id), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Instance); ok { + if stateReason := output.StateReason; stateReason != nil { + tfresource.SetLastError(err, errors.New(aws.ToString(stateReason.Message))) + } + + return output, err + } + + return nil, err +} + func waitVolumeCreated(ctx context.Context, conn *ec2.Client, id string, timeout time.Duration) (*awstypes.Volume, error) { stateConf := &retry.StateChangeConf{ Pending: enum.Slice(awstypes.VolumeStateCreating), diff --git a/internal/service/ecs/capacity_provider.go b/internal/service/ecs/capacity_provider.go index dbb9fcd05eb8..8545dbaa7da0 100644 --- a/internal/service/ecs/capacity_provider.go +++ b/internal/service/ecs/capacity_provider.go @@ -9,6 +9,7 @@ import ( "log" "time" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/ecs" awstypes "github.com/aws/aws-sdk-go-v2/service/ecs/types" @@ -20,6 +21,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -39,15 +41,49 @@ func resourceCapacityProvider() *schema.Resource { UpdateWithoutTimeout: resourceCapacityProviderUpdate, DeleteWithoutTimeout: resourceCapacityProviderDelete, + CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, meta any) error { + // Ensure exactly one of auto_scaling_group_provider or managed_instances_provider is specified + asgProvider := diff.Get("auto_scaling_group_provider").([]any) + managedProvider := diff.Get("managed_instances_provider").([]any) + clusterName := diff.Get("cluster").(string) + + if len(asgProvider) == 0 && len(managedProvider) == 0 { + return errors.New("exactly one of auto_scaling_group_provider or managed_instances_provider must be specified") + } else if len(asgProvider) > 0 && len(managedProvider) > 0 { + return errors.New("only one of auto_scaling_group_provider or managed_instances_provider must be specified") + } + + // Validate cluster field requirements + if len(managedProvider) > 0 { + // cluster is required for Managed Instances CP + if clusterName == "" { + return errors.New("cluster is required when using managed_instances_provider") + } + } else if len(asgProvider) > 0 { + // cluster must not be set for ASG CP + if clusterName != "" { + return errors.New("cluster must not be set when using auto_scaling_group_provider") + } + } + + return nil + }, + Schema: map[string]*schema.Schema{ names.AttrARN: { Type: schema.TypeString, Computed: true, }, + "cluster": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validateClusterName, + }, "auto_scaling_group_provider": { Type: schema.TypeList, MaxItems: 1, - Required: true, + Optional: true, ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -111,6 +147,368 @@ func resourceCapacityProvider() *schema.Resource { }, }, }, + "managed_instances_provider": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "infrastructure_role_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, + "instance_launch_template": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ec2_instance_profile_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, + "instance_requirements": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "accelerator_count": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + names.AttrMin: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + }, + }, + }, + "accelerator_manufacturers": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.AcceleratorManufacturer](), + }, + }, + "accelerator_names": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.AcceleratorName](), + }, + }, + "accelerator_total_memory_mib": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + names.AttrMin: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + }, + }, + }, + "accelerator_types": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.AcceleratorType](), + }, + }, + "allowed_instance_types": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 400, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 30), + validation.StringMatch(regexache.MustCompile(`^[a-zA-Z0-9\.\*\-]+$`), "must contain only alphanumeric characters, dots, asterisks, and hyphens"), + ), + }, + }, + "bare_metal": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.BareMetal](), + }, + "baseline_ebs_bandwidth_mbps": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + names.AttrMin: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + }, + }, + }, + "burstable_performance": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.BurstablePerformance](), + }, + "cpu_manufacturers": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.CpuManufacturer](), + }, + }, + "excluded_instance_types": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 400, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 30), + validation.StringMatch(regexache.MustCompile(`^[a-zA-Z0-9\.\*\-]+$`), "must contain only alphanumeric characters, dots, asterisks, and hyphens"), + ), + }, + }, + "instance_generations": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.InstanceGeneration](), + }, + }, + "local_storage": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.LocalStorage](), + }, + "local_storage_types": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.LocalStorageType](), + }, + }, + "max_spot_price_as_percentage_of_optimal_on_demand_price": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + "memory_gib_per_vcpu": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeFloat, + Optional: true, + ValidateFunc: validation.FloatAtLeast(0), + }, + names.AttrMin: { + Type: schema.TypeFloat, + Optional: true, + ValidateFunc: validation.FloatAtLeast(0), + }, + }, + }, + }, + "memory_mib": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(1), + }, + names.AttrMin: { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntAtLeast(1), + }, + }, + }, + }, + "network_bandwidth_gbps": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeFloat, + Optional: true, + ValidateFunc: validation.FloatAtLeast(0), + }, + names.AttrMin: { + Type: schema.TypeFloat, + Optional: true, + ValidateFunc: validation.FloatAtLeast(0), + }, + }, + }, + }, + "network_interface_count": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(1), + }, + names.AttrMin: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(1), + }, + }, + }, + }, + "on_demand_max_price_percentage_over_lowest_price": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + "require_hibernate_support": { + Type: schema.TypeBool, + Optional: true, + }, + "spot_max_price_percentage_over_lowest_price": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + "total_local_storage_gb": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeFloat, + Optional: true, + ValidateFunc: validation.FloatAtLeast(0), + }, + names.AttrMin: { + Type: schema.TypeFloat, + Optional: true, + ValidateFunc: validation.FloatAtLeast(0), + }, + }, + }, + }, + "vcpu_count": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrMax: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(1), + }, + names.AttrMin: { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntAtLeast(1), + }, + }, + }, + }, + }, + }, + }, + "monitoring": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.ManagedInstancesMonitoringOptions](), + }, + names.AttrNetworkConfiguration: { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrSecurityGroups: { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + names.AttrSubnets: { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "storage_configuration": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "storage_size_gib": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntAtLeast(1), + }, + }, + }, + }, + }, + }, + }, + names.AttrPropagateTags: { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.PropagateMITags](), + }, + }, + }, + }, names.AttrName: { Type: schema.TypeString, Required: true, @@ -130,10 +528,15 @@ func resourceCapacityProviderCreate(ctx context.Context, d *schema.ResourceData, name := d.Get(names.AttrName).(string) input := ecs.CreateCapacityProviderInput{ AutoScalingGroupProvider: expandAutoScalingGroupProviderCreate(d.Get("auto_scaling_group_provider")), + ManagedInstancesProvider: expandManagedInstancesProviderCreate(d.Get("managed_instances_provider")), Name: aws.String(name), Tags: getTagsIn(ctx), } + if v, ok := d.GetOk("cluster"); ok { + input.Cluster = aws.String(v.(string)) + } + output, err := conn.CreateCapacityProvider(ctx, &input) // Some partitions (e.g. ISO) may not support tag-on-create. @@ -186,6 +589,10 @@ func resourceCapacityProviderRead(ctx context.Context, d *schema.ResourceData, m if err := d.Set("auto_scaling_group_provider", flattenAutoScalingGroupProvider(output.AutoScalingGroupProvider)); err != nil { return sdkdiag.AppendErrorf(diags, "setting auto_scaling_group_provider: %s", err) } + d.Set("cluster", output.Cluster) + if err := d.Set("managed_instances_provider", flattenManagedInstancesProvider(output.ManagedInstancesProvider)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting managed_instances_provider: %s", err) + } d.Set(names.AttrName, output.Name) setTagsOut(ctx, output.Tags) @@ -198,16 +605,21 @@ func resourceCapacityProviderUpdate(ctx context.Context, d *schema.ResourceData, conn := meta.(*conns.AWSClient).ECSClient(ctx) if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) { - input := &ecs.UpdateCapacityProviderInput{ + input := ecs.UpdateCapacityProviderInput{ AutoScalingGroupProvider: expandAutoScalingGroupProviderUpdate(d.Get("auto_scaling_group_provider")), + ManagedInstancesProvider: expandManagedInstancesProviderUpdate(d.Get("managed_instances_provider")), Name: aws.String(d.Get(names.AttrName).(string)), } + if v, ok := d.GetOk("cluster"); ok { + input.Cluster = aws.String(v.(string)) + } + const ( timeout = 10 * time.Minute ) _, err := tfresource.RetryWhenIsA[any, *awstypes.UpdateInProgressException](ctx, timeout, func(ctx context.Context) (any, error) { - return conn.UpdateCapacityProvider(ctx, input) + return conn.UpdateCapacityProvider(ctx, &input) }) if err != nil { @@ -227,9 +639,10 @@ func resourceCapacityProviderDelete(ctx context.Context, d *schema.ResourceData, conn := meta.(*conns.AWSClient).ECSClient(ctx) log.Printf("[DEBUG] Deleting ECS Capacity Provider: %s", d.Id()) - _, err := conn.DeleteCapacityProvider(ctx, &ecs.DeleteCapacityProviderInput{ + input := ecs.DeleteCapacityProviderInput{ CapacityProvider: aws.String(d.Id()), - }) + } + _, err := conn.DeleteCapacityProvider(ctx, &input) // "An error occurred (ClientException) when calling the DeleteCapacityProvider operation: The specified capacity provider does not exist. Specify a valid name or ARN and try again." if errs.IsAErrorMessageContains[*awstypes.ClientException](err, "capacity provider does not exist") { @@ -285,18 +698,18 @@ func findCapacityProviders(ctx context.Context, conn *ecs.Client, input *ecs.Des } func findCapacityProviderByARN(ctx context.Context, conn *ecs.Client, arn string) (*awstypes.CapacityProvider, error) { - input := &ecs.DescribeCapacityProvidersInput{ + input := ecs.DescribeCapacityProvidersInput{ CapacityProviders: []string{arn}, Include: []awstypes.CapacityProviderField{awstypes.CapacityProviderFieldTags}, } - output, err := findCapacityProvider(ctx, conn, input) + output, err := findCapacityProvider(ctx, conn, &input) // Some partitions (i.e., ISO) may not support tagging, giving error. if errs.IsUnsupportedOperationInPartitionError(partitionFromConn(conn), err) { input.Include = nil - output, err = findCapacityProvider(ctx, conn, input) + output, err = findCapacityProvider(ctx, conn, &input) } if err != nil { @@ -366,7 +779,7 @@ func waitCapacityProviderUpdated(ctx context.Context, conn *ecs.Client, arn stri func waitCapacityProviderDeleted(ctx context.Context, conn *ecs.Client, arn string, timeout time.Duration) (*awstypes.CapacityProvider, error) { stateConf := &retry.StateChangeConf{ - Pending: enum.Slice(awstypes.CapacityProviderStatusActive), + Pending: enum.Slice(awstypes.CapacityProviderStatusActive, awstypes.CapacityProviderStatusDeprovisioning), Target: []string{}, Refresh: statusCapacityProvider(ctx, conn, arn), Timeout: timeout, @@ -492,3 +905,594 @@ func flattenAutoScalingGroupProvider(provider *awstypes.AutoScalingGroupProvider result := []map[string]any{p} return result } + +func expandManagedInstancesProviderCreate(configured any) *awstypes.CreateManagedInstancesProviderConfiguration { + if configured == nil { + return nil + } + + if len(configured.([]any)) == 0 { + return nil + } + + tfMap := configured.([]any)[0].(map[string]any) + apiObject := &awstypes.CreateManagedInstancesProviderConfiguration{} + + if v, ok := tfMap["infrastructure_role_arn"].(string); ok && v != "" { + apiObject.InfrastructureRoleArn = aws.String(v) + } + + if v, ok := tfMap["instance_launch_template"].([]any); ok && len(v) > 0 { + apiObject.InstanceLaunchTemplate = expandInstanceLaunchTemplateCreate(v) + } + + if v, ok := tfMap[names.AttrPropagateTags].(string); ok && v != "" { + apiObject.PropagateTags = awstypes.PropagateMITags(v) + } + + return apiObject +} + +func expandManagedInstancesProviderUpdate(configured any) *awstypes.UpdateManagedInstancesProviderConfiguration { + if configured == nil { + return nil + } + + if len(configured.([]any)) == 0 { + return nil + } + + tfMap := configured.([]any)[0].(map[string]any) + apiObject := &awstypes.UpdateManagedInstancesProviderConfiguration{} + + if v, ok := tfMap["infrastructure_role_arn"].(string); ok && v != "" { + apiObject.InfrastructureRoleArn = aws.String(v) + } + + if v, ok := tfMap["instance_launch_template"].([]any); ok && len(v) > 0 { + apiObject.InstanceLaunchTemplate = expandInstanceLaunchTemplateUpdate(v) + } + + if v, ok := tfMap[names.AttrPropagateTags].(string); ok && v != "" { + apiObject.PropagateTags = awstypes.PropagateMITags(v) + } + + return apiObject +} + +func expandInstanceLaunchTemplateCreate(tfList []any) *awstypes.InstanceLaunchTemplate { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.InstanceLaunchTemplate{} + + if v, ok := tfMap["ec2_instance_profile_arn"].(string); ok && v != "" { + apiObject.Ec2InstanceProfileArn = aws.String(v) + } + + if v, ok := tfMap["instance_requirements"].([]any); ok && len(v) > 0 { + apiObject.InstanceRequirements = expandInstanceRequirementsRequest(v) + } + + if v, ok := tfMap["monitoring"].(string); ok && v != "" { + apiObject.Monitoring = awstypes.ManagedInstancesMonitoringOptions(v) + } + + if v, ok := tfMap[names.AttrNetworkConfiguration].([]any); ok && len(v) > 0 { + apiObject.NetworkConfiguration = expandManagedInstancesNetworkConfiguration(v) + } + + if v, ok := tfMap["storage_configuration"].([]any); ok && len(v) > 0 { + apiObject.StorageConfiguration = expandManagedInstancesStorageConfiguration(v) + } + + return apiObject +} + +func expandInstanceLaunchTemplateUpdate(tfList []any) *awstypes.InstanceLaunchTemplateUpdate { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.InstanceLaunchTemplateUpdate{} + + if v, ok := tfMap["ec2_instance_profile_arn"].(string); ok && v != "" { + apiObject.Ec2InstanceProfileArn = aws.String(v) + } + + if v, ok := tfMap["instance_requirements"].([]any); ok && len(v) > 0 { + apiObject.InstanceRequirements = expandInstanceRequirementsRequest(v) + } + + if v, ok := tfMap["monitoring"].(string); ok && v != "" { + apiObject.Monitoring = awstypes.ManagedInstancesMonitoringOptions(v) + } + + if v, ok := tfMap[names.AttrNetworkConfiguration].([]any); ok && len(v) > 0 { + apiObject.NetworkConfiguration = expandManagedInstancesNetworkConfiguration(v) + } + + if v, ok := tfMap["storage_configuration"].([]any); ok && len(v) > 0 { + apiObject.StorageConfiguration = expandManagedInstancesStorageConfiguration(v) + } + + return apiObject +} + +func expandManagedInstancesNetworkConfiguration(tfList []any) *awstypes.ManagedInstancesNetworkConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.ManagedInstancesNetworkConfiguration{} + + if v, ok := tfMap[names.AttrSecurityGroups].(*schema.Set); ok && v.Len() > 0 { + apiObject.SecurityGroups = flex.ExpandStringValueSet(v) + } + + if v, ok := tfMap[names.AttrSubnets].(*schema.Set); ok && v.Len() > 0 { + apiObject.Subnets = flex.ExpandStringValueSet(v) + } + + return apiObject +} + +func expandManagedInstancesStorageConfiguration(tfList []any) *awstypes.ManagedInstancesStorageConfiguration { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.ManagedInstancesStorageConfiguration{} + + if v, ok := tfMap["storage_size_gib"].(int); ok && v > 0 { + apiObject.StorageSizeGiB = aws.Int32(int32(v)) + } + + return apiObject +} + +func expandInstanceRequirementsRequest(tfList []any) *awstypes.InstanceRequirementsRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.InstanceRequirementsRequest{} + + if v, ok := tfMap["accelerator_count"].([]any); ok && len(v) > 0 { + apiObject.AcceleratorCount = expandAcceleratorCountRequest(v) + } + + if v, ok := tfMap["accelerator_manufacturers"].(*schema.Set); ok && v.Len() > 0 { + apiObject.AcceleratorManufacturers = flex.ExpandStringyValueSet[awstypes.AcceleratorManufacturer](v) + } + + if v, ok := tfMap["accelerator_names"].(*schema.Set); ok && v.Len() > 0 { + apiObject.AcceleratorNames = flex.ExpandStringyValueSet[awstypes.AcceleratorName](v) + } + + if v, ok := tfMap["accelerator_total_memory_mib"].([]any); ok && len(v) > 0 { + apiObject.AcceleratorTotalMemoryMiB = expandAcceleratorTotalMemoryMiBRequest(v) + } + + if v, ok := tfMap["accelerator_types"].(*schema.Set); ok && v.Len() > 0 { + apiObject.AcceleratorTypes = flex.ExpandStringyValueSet[awstypes.AcceleratorType](v) + } + + if v, ok := tfMap["allowed_instance_types"].(*schema.Set); ok && v.Len() > 0 { + apiObject.AllowedInstanceTypes = flex.ExpandStringValueSet(v) + } + + if v, ok := tfMap["bare_metal"].(string); ok && v != "" { + apiObject.BareMetal = awstypes.BareMetal(v) + } + + if v, ok := tfMap["baseline_ebs_bandwidth_mbps"].([]any); ok && len(v) > 0 { + apiObject.BaselineEbsBandwidthMbps = expandBaselineEBSBandwidthMbpsRequest(v) + } + + if v, ok := tfMap["burstable_performance"].(string); ok && v != "" { + apiObject.BurstablePerformance = awstypes.BurstablePerformance(v) + } + + if v, ok := tfMap["cpu_manufacturers"].(*schema.Set); ok && v.Len() > 0 { + apiObject.CpuManufacturers = flex.ExpandStringyValueSet[awstypes.CpuManufacturer](v) + } + + if v, ok := tfMap["excluded_instance_types"].(*schema.Set); ok && v.Len() > 0 { + apiObject.ExcludedInstanceTypes = flex.ExpandStringValueSet(v) + } + + if v, ok := tfMap["instance_generations"].(*schema.Set); ok && v.Len() > 0 { + apiObject.InstanceGenerations = flex.ExpandStringyValueSet[awstypes.InstanceGeneration](v) + } + + if v, ok := tfMap["local_storage"].(string); ok && v != "" { + apiObject.LocalStorage = awstypes.LocalStorage(v) + } + + if v, ok := tfMap["local_storage_types"].(*schema.Set); ok && v.Len() > 0 { + apiObject.LocalStorageTypes = flex.ExpandStringyValueSet[awstypes.LocalStorageType](v) + } + + if v, ok := tfMap["max_spot_price_as_percentage_of_optimal_on_demand_price"].(int); ok && v > 0 { + apiObject.MaxSpotPriceAsPercentageOfOptimalOnDemandPrice = aws.Int32(int32(v)) + } + + if v, ok := tfMap["memory_gib_per_vcpu"].([]any); ok && len(v) > 0 { + apiObject.MemoryGiBPerVCpu = expandMemoryGiBPerVCPURequest(v) + } + + if v, ok := tfMap["memory_mib"].([]any); ok && len(v) > 0 { + apiObject.MemoryMiB = expandMemoryMiBRequest(v) + } + + if v, ok := tfMap["network_bandwidth_gbps"].([]any); ok && len(v) > 0 { + apiObject.NetworkBandwidthGbps = expandNetworkBandwidthGbpsRequest(v) + } + + if v, ok := tfMap["network_interface_count"].([]any); ok && len(v) > 0 { + apiObject.NetworkInterfaceCount = expandNetworkInterfaceCountRequest(v) + } + + if v, ok := tfMap["on_demand_max_price_percentage_over_lowest_price"].(int); ok && v > 0 { + apiObject.OnDemandMaxPricePercentageOverLowestPrice = aws.Int32(int32(v)) + } + + if v, ok := tfMap["require_hibernate_support"].(bool); ok { + apiObject.RequireHibernateSupport = aws.Bool(v) + } + + if v, ok := tfMap["spot_max_price_percentage_over_lowest_price"].(int); ok && v > 0 { + apiObject.SpotMaxPricePercentageOverLowestPrice = aws.Int32(int32(v)) + } + + if v, ok := tfMap["total_local_storage_gb"].([]any); ok && len(v) > 0 { + apiObject.TotalLocalStorageGB = expandTotalLocalStorageGBRequest(v) + } + + if v, ok := tfMap["vcpu_count"].([]any); ok && len(v) > 0 { + apiObject.VCpuCount = expandVCPUCountRangeRequest(v) + } + + return apiObject +} + +func expandVCPUCountRangeRequest(tfList []any) *awstypes.VCpuCountRangeRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.VCpuCountRangeRequest{} + + if v, ok := tfMap[names.AttrMin].(int); ok && v > 0 { + apiObject.Min = aws.Int32(int32(v)) + } + + if v, ok := tfMap[names.AttrMax].(int); ok && v > 0 { + apiObject.Max = aws.Int32(int32(v)) + } + + return apiObject +} + +func expandMemoryMiBRequest(tfList []any) *awstypes.MemoryMiBRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.MemoryMiBRequest{} + + if v, ok := tfMap[names.AttrMin].(int); ok && v > 0 { + apiObject.Min = aws.Int32(int32(v)) + } + + if v, ok := tfMap[names.AttrMax].(int); ok && v > 0 { + apiObject.Max = aws.Int32(int32(v)) + } + + return apiObject +} + +func expandMemoryGiBPerVCPURequest(tfList []any) *awstypes.MemoryGiBPerVCpuRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.MemoryGiBPerVCpuRequest{} + + if v, ok := tfMap[names.AttrMin].(float64); ok && v > 0 { + apiObject.Min = aws.Float64(v) + } + + if v, ok := tfMap[names.AttrMax].(float64); ok && v > 0 { + apiObject.Max = aws.Float64(v) + } + + return apiObject +} + +func expandNetworkBandwidthGbpsRequest(tfList []any) *awstypes.NetworkBandwidthGbpsRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.NetworkBandwidthGbpsRequest{} + + if v, ok := tfMap[names.AttrMin].(float64); ok && v > 0 { + apiObject.Min = aws.Float64(v) + } + + if v, ok := tfMap[names.AttrMax].(float64); ok && v > 0 { + apiObject.Max = aws.Float64(v) + } + + return apiObject +} + +func expandNetworkInterfaceCountRequest(tfList []any) *awstypes.NetworkInterfaceCountRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.NetworkInterfaceCountRequest{} + + if v, ok := tfMap[names.AttrMin].(int); ok && v > 0 { + apiObject.Min = aws.Int32(int32(v)) + } + + if v, ok := tfMap[names.AttrMax].(int); ok && v > 0 { + apiObject.Max = aws.Int32(int32(v)) + } + + return apiObject +} + +func expandTotalLocalStorageGBRequest(tfList []any) *awstypes.TotalLocalStorageGBRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.TotalLocalStorageGBRequest{} + + if v, ok := tfMap[names.AttrMin].(float64); ok && v > 0 { + apiObject.Min = aws.Float64(v) + } + + if v, ok := tfMap[names.AttrMax].(float64); ok && v > 0 { + apiObject.Max = aws.Float64(v) + } + + return apiObject +} + +func expandBaselineEBSBandwidthMbpsRequest(tfList []any) *awstypes.BaselineEbsBandwidthMbpsRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.BaselineEbsBandwidthMbpsRequest{} + + if v, ok := tfMap[names.AttrMin].(int); ok && v > 0 { + apiObject.Min = aws.Int32(int32(v)) + } + + if v, ok := tfMap[names.AttrMax].(int); ok && v > 0 { + apiObject.Max = aws.Int32(int32(v)) + } + + return apiObject +} + +func expandAcceleratorCountRequest(tfList []any) *awstypes.AcceleratorCountRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.AcceleratorCountRequest{} + + if v, ok := tfMap[names.AttrMin].(int); ok && v >= 0 { + apiObject.Min = aws.Int32(int32(v)) + } + + if v, ok := tfMap[names.AttrMax].(int); ok && v >= 0 { + apiObject.Max = aws.Int32(int32(v)) + } + + return apiObject +} + +func expandAcceleratorTotalMemoryMiBRequest(tfList []any) *awstypes.AcceleratorTotalMemoryMiBRequest { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]any) + apiObject := &awstypes.AcceleratorTotalMemoryMiBRequest{} + + if v, ok := tfMap[names.AttrMin].(int); ok && v >= 0 { + apiObject.Min = aws.Int32(int32(v)) + } + + if v, ok := tfMap[names.AttrMax].(int); ok && v >= 0 { + apiObject.Max = aws.Int32(int32(v)) + } + + return apiObject +} + +func flattenManagedInstancesProvider(provider *awstypes.ManagedInstancesProvider) []map[string]any { + if provider == nil { + return nil + } + + tfMap := map[string]any{ + "infrastructure_role_arn": aws.ToString(provider.InfrastructureRoleArn), + names.AttrPropagateTags: string(provider.PropagateTags), + } + + if provider.InstanceLaunchTemplate != nil { + tfMap["instance_launch_template"] = flattenInstanceLaunchTemplate(provider.InstanceLaunchTemplate) + } + + return []map[string]any{tfMap} +} + +func flattenInstanceLaunchTemplate(template *awstypes.InstanceLaunchTemplate) []map[string]any { + if template == nil { + return nil + } + + tfMap := map[string]any{ + "ec2_instance_profile_arn": aws.ToString(template.Ec2InstanceProfileArn), + "monitoring": string(template.Monitoring), + } + + if template.InstanceRequirements != nil { + tfMap["instance_requirements"] = flattenInstanceRequirementsRequest(template.InstanceRequirements) + } + + if template.NetworkConfiguration != nil { + networkConfig := map[string]any{ + names.AttrSubnets: template.NetworkConfiguration.Subnets, + } + if template.NetworkConfiguration.SecurityGroups != nil { + networkConfig[names.AttrSecurityGroups] = template.NetworkConfiguration.SecurityGroups + } + tfMap[names.AttrNetworkConfiguration] = []map[string]any{networkConfig} + } + + if template.StorageConfiguration != nil { + tfMap["storage_configuration"] = []map[string]any{{ + "storage_size_gib": aws.ToInt32(template.StorageConfiguration.StorageSizeGiB), + }} + } + + return []map[string]any{tfMap} +} + +func flattenInstanceRequirementsRequest(req *awstypes.InstanceRequirementsRequest) []map[string]any { + if req == nil { + return nil + } + + tfMap := map[string]any{ + "bare_metal": string(req.BareMetal), + "burstable_performance": string(req.BurstablePerformance), + "local_storage": string(req.LocalStorage), + "max_spot_price_as_percentage_of_optimal_on_demand_price": aws.ToInt32(req.MaxSpotPriceAsPercentageOfOptimalOnDemandPrice), + "on_demand_max_price_percentage_over_lowest_price": aws.ToInt32(req.OnDemandMaxPricePercentageOverLowestPrice), + "require_hibernate_support": aws.ToBool(req.RequireHibernateSupport), + "spot_max_price_percentage_over_lowest_price": aws.ToInt32(req.SpotMaxPricePercentageOverLowestPrice), + } + + if req.AcceleratorCount != nil { + tfMap["accelerator_count"] = []map[string]any{{ + names.AttrMin: aws.ToInt32(req.AcceleratorCount.Min), + names.AttrMax: aws.ToInt32(req.AcceleratorCount.Max), + }} + } + + if req.AcceleratorManufacturers != nil { + tfMap["accelerator_manufacturers"] = req.AcceleratorManufacturers + } + + if req.AcceleratorNames != nil { + tfMap["accelerator_names"] = req.AcceleratorNames + } + + if req.AcceleratorTotalMemoryMiB != nil { + tfMap["accelerator_total_memory_mib"] = []map[string]any{{ + names.AttrMin: aws.ToInt32(req.AcceleratorTotalMemoryMiB.Min), + names.AttrMax: aws.ToInt32(req.AcceleratorTotalMemoryMiB.Max), + }} + } + + if req.AcceleratorTypes != nil { + tfMap["accelerator_types"] = req.AcceleratorTypes + } + + if req.AllowedInstanceTypes != nil { + tfMap["allowed_instance_types"] = req.AllowedInstanceTypes + } + + if req.BaselineEbsBandwidthMbps != nil { + tfMap["baseline_ebs_bandwidth_mbps"] = []map[string]any{{ + names.AttrMin: aws.ToInt32(req.BaselineEbsBandwidthMbps.Min), + names.AttrMax: aws.ToInt32(req.BaselineEbsBandwidthMbps.Max), + }} + } + + if req.CpuManufacturers != nil { + tfMap["cpu_manufacturers"] = req.CpuManufacturers + } + + if req.ExcludedInstanceTypes != nil { + tfMap["excluded_instance_types"] = req.ExcludedInstanceTypes + } + + if req.InstanceGenerations != nil { + tfMap["instance_generations"] = req.InstanceGenerations + } + + if req.LocalStorageTypes != nil { + tfMap["local_storage_types"] = req.LocalStorageTypes + } + + if req.MemoryGiBPerVCpu != nil { + tfMap["memory_gib_per_vcpu"] = []map[string]any{{ + names.AttrMin: aws.ToFloat64(req.MemoryGiBPerVCpu.Min), + names.AttrMax: aws.ToFloat64(req.MemoryGiBPerVCpu.Max), + }} + } + + if req.MemoryMiB != nil { + tfMap["memory_mib"] = []map[string]any{{ + names.AttrMin: aws.ToInt32(req.MemoryMiB.Min), + names.AttrMax: aws.ToInt32(req.MemoryMiB.Max), + }} + } + + if req.NetworkBandwidthGbps != nil { + tfMap["network_bandwidth_gbps"] = []map[string]any{{ + names.AttrMin: aws.ToFloat64(req.NetworkBandwidthGbps.Min), + names.AttrMax: aws.ToFloat64(req.NetworkBandwidthGbps.Max), + }} + } + + if req.NetworkInterfaceCount != nil { + tfMap["network_interface_count"] = []map[string]any{{ + names.AttrMin: aws.ToInt32(req.NetworkInterfaceCount.Min), + names.AttrMax: aws.ToInt32(req.NetworkInterfaceCount.Max), + }} + } + + if req.TotalLocalStorageGB != nil { + tfMap["total_local_storage_gb"] = []map[string]any{{ + names.AttrMin: aws.ToFloat64(req.TotalLocalStorageGB.Min), + names.AttrMax: aws.ToFloat64(req.TotalLocalStorageGB.Max), + }} + } + + if req.VCpuCount != nil { + tfMap["vcpu_count"] = []map[string]any{{ + names.AttrMin: aws.ToInt32(req.VCpuCount.Min), + names.AttrMax: aws.ToInt32(req.VCpuCount.Max), + }} + } + + return []map[string]any{tfMap} +} diff --git a/internal/service/ecs/capacity_provider_test.go b/internal/service/ecs/capacity_provider_test.go index f84c2c2a2edd..254f5919f907 100644 --- a/internal/service/ecs/capacity_provider_test.go +++ b/internal/service/ecs/capacity_provider_test.go @@ -8,6 +8,7 @@ import ( "fmt" "testing" + "github.com/YakDriver/regexache" awstypes "github.com/aws/aws-sdk-go-v2/service/ecs/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -229,6 +230,192 @@ func TestAccECSCapacityProvider_tags(t *testing.T) { }) } +func TestAccECSCapacityProvider_clusterFieldValidations(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCapacityProviderDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCapacityProviderConfig_autoScalingGroups_withCluster(rName), + ExpectError: regexache.MustCompile(`cluster must not be set when using auto_scaling_group_provider`), + }, + { + Config: testAccCapacityProviderConfig_managedInstances_withoutCluster(rName), + ExpectError: regexache.MustCompile(`cluster is required when using managed_instances_provider`), + }, + }, + }) +} + +func TestAccECSCapacityProvider_mutualExclusivity(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCapacityProviderDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCapacityProviderConfig_bothProviders(rName), + ExpectError: regexache.MustCompile(`only one of auto_scaling_group_provider or managed_instances_provider must be specified`), + }, + { + Config: testAccCapacityProviderConfig_noProviders(rName), + ExpectError: regexache.MustCompile(`exactly one of auto_scaling_group_provider or managed_instances_provider must be specified`), + }, + }, + }) +} + +func TestAccECSCapacityProvider_createManagedInstancesProvider_basic(t *testing.T) { + ctx := acctest.Context(t) + var provider awstypes.CapacityProvider + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecs_capacity_provider.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCapacityProviderDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCapacityProviderConfig_managedInstancesProvider_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckCapacityProviderExists(ctx, resourceName, &provider), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "managed_instances_provider.0.infrastructure_role_arn", "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "managed_instances_provider.0.instance_launch_template.0.ec2_instance_profile_arn", "aws_iam_instance_profile.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.network_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.network_configuration.0.subnets.#", "2"), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrID, "ecs", fmt.Sprintf("capacity-provider/%s", rName)), + resource.TestCheckResourceAttrPair(resourceName, names.AttrID, resourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, "cluster", rName), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccECSCapacityProvider_createManagedInstancesProvider_withInstanceRequirements(t *testing.T) { + ctx := acctest.Context(t) + var provider awstypes.CapacityProvider + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecs_capacity_provider.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCapacityProviderDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCapacityProviderConfig_managedInstancesProvider_withInstanceRequirements(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckCapacityProviderExists(ctx, resourceName, &provider), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.vcpu_count.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.vcpu_count.0.min", "2"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.vcpu_count.0.max", "8"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.memory_mib.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.memory_mib.0.min", "2048"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.memory_mib.0.max", "16384"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.cpu_manufacturers.#", "2"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.instance_generations.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.burstable_performance", "excluded"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.propagate_tags", "NONE"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccECSCapacityProvider_createManagedInstancesProvider_withStorageConfiguration(t *testing.T) { + ctx := acctest.Context(t) + var provider awstypes.CapacityProvider + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecs_capacity_provider.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCapacityProviderDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCapacityProviderConfig_managedInstancesProvider_withStorageConfiguration(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckCapacityProviderExists(ctx, resourceName, &provider), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.storage_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.storage_configuration.0.storage_size_gib", "50"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccECSCapacityProvider_updateManagedInstancesProvider(t *testing.T) { + ctx := acctest.Context(t) + var provider awstypes.CapacityProvider + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecs_capacity_provider.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCapacityProviderDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCapacityProviderConfig_managedInstancesProvider_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckCapacityProviderExists(ctx, resourceName, &provider), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.propagate_tags", ""), + ), + }, + { + Config: testAccCapacityProviderConfig_updateManagedInstancesProvider(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckCapacityProviderExists(ctx, resourceName, &provider), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.propagate_tags", "NONE"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckCapacityProviderDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).ECSClient(ctx) @@ -395,3 +582,305 @@ resource "aws_ecs_capacity_provider" "test" { } `, rName, tag1Key, tag1Value, tag2Key, tag2Value)) } + +func testAccCapacityProviderConfig_bothProviders(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} +data "aws_region" "current" {} + +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q + cluster = "dummy" + + auto_scaling_group_provider { + auto_scaling_group_arn = "arn:${data.aws_partition.current.partition}:autoscaling:${data.aws_region.current.region}:000000000000:autoScalingGroup:a4536b1a-b122-49ef-918f-bfaed967ccfa:autoScalingGroupName/dummy" + } + + managed_instances_provider { + infrastructure_role_arn = "arn:${data.aws_partition.current.partition}:iam::000000000000:role/dummy" + + instance_launch_template { + ec2_instance_profile_arn = "arn:${data.aws_partition.current.partition}:iam::000000000000:instance-profile/dummy" + + network_configuration { + subnets = ["subnet-0b48066557a0e97ac"] + } + + instance_requirements { + vcpu_count { + min = 1 + } + + memory_mib { + min = 1024 + } + } + } + } +} +`, rName) +} + +func testAccCapacityProviderConfig_autoScalingGroups_withCluster(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} +data "aws_region" "current" {} + +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q + cluster = "dummy" + + auto_scaling_group_provider { + auto_scaling_group_arn = "arn:${data.aws_partition.current.partition}:autoscaling:${data.aws_region.current.region}:000000000000:autoScalingGroup:a4536b1a-b122-49ef-918f-bfaed967ccfa:autoScalingGroupName/dummy" + } +} +`, rName) +} + +func testAccCapacityProviderConfig_managedInstances_withoutCluster(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q + + managed_instances_provider { + infrastructure_role_arn = "arn:${data.aws_partition.current.partition}:iam::000000000000:role/dummy" + + instance_launch_template { + ec2_instance_profile_arn = "arn:${data.aws_partition.current.partition}:iam::000000000000:instance-profile/dummy" + + network_configuration { + subnets = ["subnet-0b48066557a0e97ac"] + } + + instance_requirements { + vcpu_count { + min = 1 + } + + memory_mib { + min = 1024 + } + } + } + } +} +`, rName) +} + +func testAccCapacityProviderConfig_noProviders(rName string) string { + return fmt.Sprintf(` +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q +} +`, rName) +} + +func testAccCapacityProviderConfig_managedInstancesProvider_base(rName string) string { + return acctest.ConfigCompose( + acctest.ConfigAvailableAZsNoOptInDefaultExclude(), + fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + enable_dns_hostnames = false + enable_dns_support = false + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + count = 2 + + availability_zone = data.aws_availability_zones.available.names[count.index] + cidr_block = "10.0.${count.index}.0/24" + vpc_id = aws_vpc.test.id + + tags = { + Name = "%[1]s-${count.index}" + } +} + +resource "aws_ecs_cluster" "test" { + name = %[1]q +} + +data "aws_iam_policy_document" "test_assume_role_policy" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ecs.${data.aws_partition.current.dns_suffix}"] + } + } +} + +resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = data.aws_iam_policy_document.test_assume_role_policy.json +} + +resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/AdministratorAccess" +} + +data "aws_iam_policy_document" "test_instance_assume_role_policy" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ec2.${data.aws_partition.current.dns_suffix}"] + } + } +} + +resource "aws_iam_role" "test_instance" { + name = "%[1]s-instance" + assume_role_policy = data.aws_iam_policy_document.test_instance_assume_role_policy.json +} + +resource "aws_iam_role_policy_attachment" "test_instance" { + role = aws_iam_role.test_instance.name + policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" +} + +resource "aws_iam_instance_profile" "test" { + name = %[1]q + role = aws_iam_role.test_instance.name +} +`, rName)) +} + +func testAccCapacityProviderConfig_managedInstancesProvider_basic(rName string) string { + return acctest.ConfigCompose(testAccCapacityProviderConfig_managedInstancesProvider_base(rName), fmt.Sprintf(` +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q + cluster = aws_ecs_cluster.test.name + + managed_instances_provider { + infrastructure_role_arn = aws_iam_role.test.arn + + instance_launch_template { + ec2_instance_profile_arn = aws_iam_instance_profile.test.arn + + network_configuration { + subnets = aws_subnet.test[*].id + } + } + } +} +`, rName)) +} + +func testAccCapacityProviderConfig_managedInstancesProvider_withInstanceRequirements(rName string) string { + return acctest.ConfigCompose(testAccCapacityProviderConfig_managedInstancesProvider_base(rName), fmt.Sprintf(` +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q + cluster = aws_ecs_cluster.test.name + + managed_instances_provider { + infrastructure_role_arn = aws_iam_role.test.arn + propagate_tags = "NONE" + + instance_launch_template { + ec2_instance_profile_arn = aws_iam_instance_profile.test.arn + + network_configuration { + subnets = aws_subnet.test[*].id + } + + instance_requirements { + vcpu_count { + min = 2 + max = 8 + } + + memory_mib { + min = 2048 + max = 16384 + } + + cpu_manufacturers = ["intel", "amd"] + instance_generations = ["current"] + burstable_performance = "excluded" + } + } + } +} +`, rName)) +} + +func testAccCapacityProviderConfig_managedInstancesProvider_withStorageConfiguration(rName string) string { + return acctest.ConfigCompose(testAccCapacityProviderConfig_managedInstancesProvider_base(rName), fmt.Sprintf(` +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q + cluster = aws_ecs_cluster.test.name + + managed_instances_provider { + infrastructure_role_arn = aws_iam_role.test.arn + propagate_tags = "CAPACITY_PROVIDER" + + instance_launch_template { + ec2_instance_profile_arn = aws_iam_instance_profile.test.arn + + network_configuration { + subnets = aws_subnet.test[*].id + } + + storage_configuration { + storage_size_gib = 50 + } + + instance_requirements { + vcpu_count { + min = 1 + } + + memory_mib { + min = 1024 + } + } + } + } +} +`, rName)) +} + +func testAccCapacityProviderConfig_updateManagedInstancesProvider(rName string) string { + return acctest.ConfigCompose(testAccCapacityProviderConfig_managedInstancesProvider_base(rName), fmt.Sprintf(` +resource "aws_ecs_capacity_provider" "test" { + name = %[1]q + cluster = aws_ecs_cluster.test.name + + managed_instances_provider { + infrastructure_role_arn = aws_iam_role.test.arn + propagate_tags = "NONE" + + instance_launch_template { + ec2_instance_profile_arn = aws_iam_instance_profile.test.arn + + network_configuration { + subnets = aws_subnet.test[*].id + } + + instance_requirements { + vcpu_count { + min = 1 + } + + memory_mib { + min = 1024 + } + } + } + } +} +`, rName)) +} diff --git a/internal/service/ecs/task_definition.go b/internal/service/ecs/task_definition.go index 03914eaa5fca..9e664301e006 100644 --- a/internal/service/ecs/task_definition.go +++ b/internal/service/ecs/task_definition.go @@ -233,6 +233,7 @@ func resourceTaskDefinition() *schema.Resource { "EC2", "FARGATE", "EXTERNAL", + "MANAGED_INSTANCES", }, false), }, }, diff --git a/internal/service/elasticbeanstalk/configuration_template_test.go b/internal/service/elasticbeanstalk/configuration_template_test.go index 156a9ede902d..c5147fe795f8 100644 --- a/internal/service/elasticbeanstalk/configuration_template_test.go +++ b/internal/service/elasticbeanstalk/configuration_template_test.go @@ -11,6 +11,7 @@ import ( awstypes "github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -137,6 +138,51 @@ func TestAccElasticBeanstalkConfigurationTemplate_settings(t *testing.T) { }) } +func TestAccElasticBeanstalkConfigurationTemplate_migrate_settingsResourceDefault(t *testing.T) { + ctx := acctest.Context(t) + var config awstypes.ConfigurationSettingsDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elastic_beanstalk_configuration_template.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ElasticBeanstalkServiceID), + CheckDestroy: testAccCheckConfigurationTemplateDestroy(ctx), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "6.14.1", + }, + }, + Config: testAccConfigurationTemplateConfig_setting(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckConfigurationTemplateExists(ctx, resourceName, &config), + ), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Config: testAccConfigurationTemplateConfig_setting(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckConfigurationTemplateExists(ctx, resourceName, &config), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPreRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + }, + }, + }) +} + func testAccCheckConfigurationTemplateDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).ElasticBeanstalkClient(ctx) diff --git a/internal/service/elasticbeanstalk/environment.go b/internal/service/elasticbeanstalk/environment.go index d3a799eeb882..713c2f0c61a6 100644 --- a/internal/service/elasticbeanstalk/environment.go +++ b/internal/service/elasticbeanstalk/environment.go @@ -50,6 +50,7 @@ func settingSchema() *schema.Resource { "resource": { Type: schema.TypeString, Optional: true, + Default: "", // This default is required to work around an error seen is some situations with Unknown values }, names.AttrValue: { Type: schema.TypeString, @@ -95,7 +96,7 @@ func resourceEnvironment() *schema.Resource { }, SchemaVersion: 1, - MigrateState: EnvironmentMigrateState, + MigrateState: environmentMigrateState, SchemaFunc: func() map[string]*schema.Schema { return map[string]*schema.Schema{ @@ -334,19 +335,17 @@ func resourceEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta a return sdkdiag.AppendErrorf(diags, "reading Elastic Beanstalk Environment (%s) resources: %s", d.Id(), err) } - applicationName := aws.ToString(env.ApplicationName) - environmentName := aws.ToString(env.EnvironmentName) - input := &elasticbeanstalk.DescribeConfigurationSettingsInput{ - ApplicationName: aws.String(applicationName), - EnvironmentName: aws.String(environmentName), + input := elasticbeanstalk.DescribeConfigurationSettingsInput{ + ApplicationName: env.ApplicationName, + EnvironmentName: env.EnvironmentName, } - configurationSettings, err := findConfigurationSettings(ctx, conn, input) + configurationSettings, err := findConfigurationSettings(ctx, conn, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Elastic Beanstalk Environment (%s) configuration settings: %s", d.Id(), err) } - d.Set("application", applicationName) + d.Set("application", env.ApplicationName) d.Set(names.AttrARN, env.EnvironmentArn) if err := d.Set("autoscaling_groups", flattenAutoScalingGroups(resources.EnvironmentResources.AutoScalingGroups)); err != nil { return sdkdiag.AppendErrorf(diags, "setting autoscaling_groups: %s", err) @@ -375,7 +374,7 @@ func resourceEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta a if err := d.Set("load_balancers", flattenLoadBalancers(resources.EnvironmentResources.LoadBalancers)); err != nil { return sdkdiag.AppendErrorf(diags, "setting load_balancers: %s", err) } - d.Set(names.AttrName, environmentName) + d.Set(names.AttrName, env.EnvironmentName) d.Set("platform_arn", env.PlatformArn) if err := d.Set("queues", flattenQueues(resources.EnvironmentResources.Queues)); err != nil { return sdkdiag.AppendErrorf(diags, "setting queues: %s", err) diff --git a/internal/service/elasticbeanstalk/environment_migrate.go b/internal/service/elasticbeanstalk/environment_migrate.go index 4caf838542a9..b08592449fec 100644 --- a/internal/service/elasticbeanstalk/environment_migrate.go +++ b/internal/service/elasticbeanstalk/environment_migrate.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) -func EnvironmentMigrateState(v int, is *terraform.InstanceState, meta any) (*terraform.InstanceState, error) { +func environmentMigrateState(v int, is *terraform.InstanceState, meta any) (*terraform.InstanceState, error) { switch v { case 0: log.Println("[INFO] Found AWS Elastic Beanstalk Environment State v0; migrating to v1") diff --git a/internal/service/elasticbeanstalk/environment_test.go b/internal/service/elasticbeanstalk/environment_test.go index d822e050f92b..200a3cce8a90 100644 --- a/internal/service/elasticbeanstalk/environment_test.go +++ b/internal/service/elasticbeanstalk/environment_test.go @@ -18,7 +18,11 @@ import ( awstypes "github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfelasticbeanstalk "github.com/hashicorp/terraform-provider-aws/internal/service/elasticbeanstalk" @@ -47,13 +51,17 @@ func TestAccElasticBeanstalkEnvironment_basic(t *testing.T) { Config: testAccEnvironmentConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckEnvironmentExists(ctx, resourceName, &app), - acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "elasticbeanstalk", fmt.Sprintf("environment/%s/%s", rName, rName)), + acctest.CheckResourceAttrRegionalARNFormat(ctx, resourceName, names.AttrARN, "elasticbeanstalk", "environment/{application}/{name}"), resource.TestMatchResourceAttr(resourceName, "autoscaling_groups.0", beanstalkAsgNameRegexp), resource.TestMatchResourceAttr(resourceName, "endpoint_url", beanstalkEndpointURL), resource.TestMatchResourceAttr(resourceName, "instances.0", beanstalkInstancesNameRegexp), resource.TestMatchResourceAttr(resourceName, "launch_configurations.0", beanstalkLcNameRegexp), resource.TestMatchResourceAttr(resourceName, "load_balancers.0", beanstalkElbNameRegexp), ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_basic())), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("all_settings"), knownvalue.SetPartial(settingsChecks_basic())), + }, }, { ResourceName: resourceName, @@ -64,6 +72,17 @@ func TestAccElasticBeanstalkEnvironment_basic(t *testing.T) { "wait_for_ready_timeout", }, }, + { + Config: testAccEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + }, }, }) } @@ -445,10 +464,10 @@ func TestAccElasticBeanstalkEnvironment_platformARN(t *testing.T) { var app awstypes.EnvironmentDescription rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_elastic_beanstalk_environment.test" - platformNameWithVersion1 := "Python 3.9 running on 64bit Amazon Linux 2023/4.0.9" + platformNameWithVersion1 := "Python 3.12 running on 64bit Amazon Linux 2023/4.7.2" rValue1 := sdkacctest.RandIntRange(1000, 2000) rValue1Str := strconv.Itoa(rValue1) - platformNameWithVersion2 := "Python 3.11 running on 64bit Amazon Linux 2023/4.1.3" + platformNameWithVersion2 := "Python 3.13 running on 64bit Amazon Linux 2023/4.7.2" rValue2 := sdkacctest.RandIntRange(3000, 4000) rValue2Str := strconv.Itoa(rValue2) @@ -497,6 +516,274 @@ func TestAccElasticBeanstalkEnvironment_platformARN(t *testing.T) { }) } +func TestAccElasticBeanstalkEnvironment_migrate_settingsResourceDefault(t *testing.T) { + ctx := acctest.Context(t) + var app awstypes.EnvironmentDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elastic_beanstalk_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ElasticBeanstalkServiceID), + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "6.14.1", + }, + }, + Config: testAccEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_basic())), + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Config: testAccEnvironmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPreRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + }, + }, + }) +} + +func TestAccElasticBeanstalkEnvironment_taint(t *testing.T) { + ctx := acctest.Context(t) + var app awstypes.EnvironmentDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + value1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + value2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elastic_beanstalk_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ElasticBeanstalkServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_setting_ComputedValue(rName, value1), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_ValueChanged(value1))), + }, + }, + { + Taint: []string{"terraform_data.test"}, + Config: testAccEnvironmentConfig_setting_ComputedValue(rName, value2), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectResourceAction("terraform_data.test", plancheck.ResourceActionReplace), + + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("Subnets"), + "resource": knownvalue.StringExact(""), + // "value": Unknown value, + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("AssociatePublicIpAddress"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.StringExact(acctest.CtTrue), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:autoscaling:launchconfiguration"), + names.AttrName: knownvalue.StringExact("IamInstanceProfile"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_iam_instance_profile.test.name + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:elasticbeanstalk:application:environment"), + names.AttrName: knownvalue.StringExact("ENV_TEST"), + "resource": knownvalue.StringExact(""), + // "value": Unknown value, + }), + })), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_ValueChanged(value2))), + }, + }, + }, + }) +} + +func TestAccElasticBeanstalkEnvironment_setting_ComputedValue(t *testing.T) { + ctx := acctest.Context(t) + var app awstypes.EnvironmentDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + value1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + value2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elastic_beanstalk_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ElasticBeanstalkServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_setting_ComputedValue(rName, value1), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_ValueChanged(value1))), + }, + }, + { + Config: testAccEnvironmentConfig_setting_ComputedValue(rName, value2), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectResourceAction("terraform_data.test", plancheck.ResourceActionUpdate), + + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("Subnets"), + "resource": knownvalue.StringExact(""), + // "value": Unknown value, + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("AssociatePublicIpAddress"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.StringExact(acctest.CtTrue), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:autoscaling:launchconfiguration"), + names.AttrName: knownvalue.StringExact("IamInstanceProfile"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_iam_instance_profile.test.name + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:elasticbeanstalk:application:environment"), + names.AttrName: knownvalue.StringExact("ENV_TEST"), + "resource": knownvalue.StringExact(""), + // "value": Unknown value, + }), + })), + }, + PostApplyPreRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_ValueChanged(value2))), + }, + }, + }, + }) +} + +func TestAccElasticBeanstalkEnvironment_setting_ForceNew(t *testing.T) { + ctx := acctest.Context(t) + var app awstypes.EnvironmentDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + value1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + value2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elastic_beanstalk_environment.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ElasticBeanstalkServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEnvironmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEnvironmentConfig_setting_ForceNew(rName, value1), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_ValueChanged(value1))), + }, + }, + { + Config: testAccEnvironmentConfig_setting_ForceNew(rName, value2), + Check: resource.ComposeTestCheckFunc( + testAccCheckEnvironmentExists(ctx, resourceName, &app), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectResourceAction("terraform_data.test", plancheck.ResourceActionReplace), + + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("Subnets"), + "resource": knownvalue.StringExact(""), + // "value": Unknown value, + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("AssociatePublicIpAddress"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.StringExact(acctest.CtTrue), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:autoscaling:launchconfiguration"), + names.AttrName: knownvalue.StringExact("IamInstanceProfile"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_iam_instance_profile.test.name + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:elasticbeanstalk:application:environment"), + names.AttrName: knownvalue.StringExact("ENV_TEST"), + "resource": knownvalue.StringExact(""), + // "value": Unknown value, + }), + })), + }, + PostApplyPreRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("setting"), knownvalue.SetExact(settingsChecks_ValueChanged(value2))), + }, + }, + }, + }) +} + func testAccCheckEnvironmentDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).ElasticBeanstalkClient(ctx) @@ -800,6 +1087,52 @@ resource "aws_elastic_beanstalk_environment" "test" { `, rName)) } +func settingsChecks_basic() []knownvalue.Check { + return []knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("VPCId"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_vpc.test.id + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("Subnets"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_subnet.test[0].id + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("AssociatePublicIpAddress"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.StringExact(acctest.CtTrue), + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:autoscaling:launchconfiguration"), + names.AttrName: knownvalue.StringExact("SecurityGroups"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_security_group.test.id + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:autoscaling:launchconfiguration"), + names.AttrName: knownvalue.StringExact("IamInstanceProfile"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_iam_instance_profile.test.name + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:elasticbeanstalk:environment"), + names.AttrName: knownvalue.StringExact("ServiceRole"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_iam_role.service_role.name + }), + } +} + func testAccEnvironmentConfig_platformARN(rName, platformNameWithVersion string, rValue int) string { return acctest.ConfigCompose(testAccEnvironmentConfig_base(rName), fmt.Sprintf(` resource "aws_elastic_beanstalk_environment" "test" { @@ -1675,3 +2008,94 @@ EOF } `, rName, publicKey, email)) } + +func testAccEnvironmentConfig_setting_ComputedValue(rName, value string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_setting_ValueChange(rName), + fmt.Sprintf(` +resource "terraform_data" "test" { + input = %[1]q +} +`, value)) +} + +func testAccEnvironmentConfig_setting_ForceNew(rName, value string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_setting_ValueChange(rName), + fmt.Sprintf(` +resource "terraform_data" "test" { + input = %[2]q + triggers_replace = [%[2]q] +} +`, rName, value)) +} + +func testAccEnvironmentConfig_setting_ValueChange(rName string) string { + return acctest.ConfigCompose( + testAccEnvironmentConfig_base(rName), + fmt.Sprintf(` +resource "aws_elastic_beanstalk_environment" "test" { + application = aws_elastic_beanstalk_application.test.name + name = %[1]q + solution_stack_name = data.aws_elastic_beanstalk_solution_stack.test.name + + setting { + namespace = "aws:ec2:vpc" + name = "Subnets" + # This contrived example is a simple way to trigger the error with computed values. + # It should not be used in production configurations. + value = replace("${aws_subnet.test[0].id}${terraform_data.test.output}", terraform_data.test.output, "") + } + + setting { + namespace = "aws:ec2:vpc" + name = "AssociatePublicIpAddress" + value = "true" + } + + setting { + namespace = "aws:autoscaling:launchconfiguration" + name = "IamInstanceProfile" + value = aws_iam_instance_profile.test.name + } + + setting { + namespace = "aws:elasticbeanstalk:application:environment" + name = "ENV_TEST" + value = terraform_data.test.output + } +} +`, rName)) +} + +func settingsChecks_ValueChanged(envVal string) []knownvalue.Check { + return []knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("Subnets"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_subnet.test[0].id + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:ec2:vpc"), + names.AttrName: knownvalue.StringExact("AssociatePublicIpAddress"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.StringExact(acctest.CtTrue), + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:autoscaling:launchconfiguration"), + names.AttrName: knownvalue.StringExact("IamInstanceProfile"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.NotNull(), // Pair: aws_iam_instance_profile.test.name + }), + + knownvalue.ObjectExact(map[string]knownvalue.Check{ + names.AttrNamespace: knownvalue.StringExact("aws:elasticbeanstalk:application:environment"), + names.AttrName: knownvalue.StringExact("ENV_TEST"), + "resource": knownvalue.StringExact(""), + names.AttrValue: knownvalue.StringExact(envVal), + }), + } +} diff --git a/internal/service/elasticbeanstalk/exports_test.go b/internal/service/elasticbeanstalk/exports_test.go index 07aef7be767f..c72489ced556 100644 --- a/internal/service/elasticbeanstalk/exports_test.go +++ b/internal/service/elasticbeanstalk/exports_test.go @@ -15,4 +15,6 @@ var ( FindConfigurationSettingsByTwoPartKey = findConfigurationSettingsByTwoPartKey FindEnvironmentByID = findEnvironmentByID HostedZoneIDs = hostedZoneIDs + + EnvironmentMigrateState = environmentMigrateState ) diff --git a/internal/service/elbv2/load_balancer_data_source.go b/internal/service/elbv2/load_balancer_data_source.go index b1c5b642f6ec..fda02152ec33 100644 --- a/internal/service/elbv2/load_balancer_data_source.go +++ b/internal/service/elbv2/load_balancer_data_source.go @@ -175,6 +175,10 @@ func dataSourceLoadBalancer() *schema.Resource { Type: schema.TypeBool, Computed: true, }, + "secondary_ips_auto_assigned_per_subnet": { + Type: schema.TypeInt, + Computed: true, + }, names.AttrSecurityGroups: { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, diff --git a/internal/service/elbv2/load_balancer_data_source_test.go b/internal/service/elbv2/load_balancer_data_source_test.go index 497ec8c99bc1..dc2763ae59ce 100644 --- a/internal/service/elbv2/load_balancer_data_source_test.go +++ b/internal/service/elbv2/load_balancer_data_source_test.go @@ -216,6 +216,28 @@ func TestAccELBV2LoadBalancerDataSource_backwardsCompatibility(t *testing.T) { }) } +func TestAccELBV2LoadBalancerDataSource_nlbSecondaryIPAddresses(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_lb.nlb_test_with_arn" + resourceName := "aws_lb.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ELBV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccLoadBalancerDataSourceConfig_nlbSecondaryIPAddresses(rName, 3, 3), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrName, resourceName, names.AttrName), + resource.TestCheckResourceAttrPair(dataSourceName, "secondary_ips_auto_assigned_per_subnet", resourceName, "secondary_ips_auto_assigned_per_subnet"), + ), + }, + }, + }) +} + func testAccLoadBalancerDataSourceConfig_basic(rName string) string { return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 2), fmt.Sprintf(` resource "aws_lb" "test" { @@ -397,3 +419,11 @@ data "aws_alb" "alb_test_with_tags" { } `, rName)) } + +func testAccLoadBalancerDataSourceConfig_nlbSecondaryIPAddresses(rName string, subnetCount, addressCount int) string { + return acctest.ConfigCompose(testAccLoadBalancerConfig_nlbSecondaryIPAddresses(rName, subnetCount, addressCount), ` +data "aws_lb" "nlb_test_with_arn" { + arn = aws_lb.test.arn +} +`) +} diff --git a/internal/service/emr/validate.go b/internal/service/emr/validate.go index 86d0920fd423..cc9a2a94e6de 100644 --- a/internal/service/emr/validate.go +++ b/internal/service/emr/validate.go @@ -19,7 +19,7 @@ func validCustomAMIID(v any, k string) (ws []string, errors []error) { if !regexache.MustCompile(`^ami\-[0-9a-z]+$`).MatchString(value) { errors = append(errors, fmt.Errorf( - "%q must begin with 'ami-' and be comprised of only [0-9a-z]: %v", k, value)) + "%q must begin with 'ami-' and only contain [0-9a-z]: %v", k, value)) } return diff --git a/internal/service/events/put_events_action.go b/internal/service/events/put_events_action.go new file mode 100644 index 000000000000..aefc90cfc5dc --- /dev/null +++ b/internal/service/events/put_events_action.go @@ -0,0 +1,140 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package events + +import ( + "context" + "strconv" + + "github.com/aws/aws-sdk-go-v2/service/eventbridge" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework/action" + "github.com/hashicorp/terraform-plugin-framework/action/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @Action(aws_events_put_events, name="Put Events") +// nosemgrep: ci.events-in-func-name -- "PutEvents" matches AWS API operation name (PutEvents). Required for consistent generated/action naming; safe to ignore. +func newPutEventsAction(_ context.Context) (action.ActionWithConfigure, error) { + return &putEventsAction{}, nil +} + +var ( + _ action.Action = (*putEventsAction)(nil) +) + +type putEventsAction struct { + framework.ActionWithModel[putEventsActionModel] +} + +type putEventsActionModel struct { + framework.WithRegionModel + Entry fwtypes.ListNestedObjectValueOf[putEventEntryModel] `tfsdk:"entry"` +} + +type putEventEntryModel struct { + Detail types.String `tfsdk:"detail"` + DetailType types.String `tfsdk:"detail_type"` + EventBusName types.String `tfsdk:"event_bus_name"` + Resources fwtypes.ListValueOf[types.String] `tfsdk:"resources"` + Source types.String `tfsdk:"source"` + Time timetypes.RFC3339 `tfsdk:"time"` +} + +func (a *putEventsAction) Schema(ctx context.Context, req action.SchemaRequest, resp *action.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Sends custom events to Amazon EventBridge so that they can be matched to rules.", + Blocks: map[string]schema.Block{ + "entry": schema.ListNestedBlock{ + Description: "The entry that defines an event in your system.", + CustomType: fwtypes.NewListNestedObjectTypeOf[putEventEntryModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "detail": schema.StringAttribute{ + Description: "A valid JSON string. There is no other schema imposed.", + Optional: true, + }, + "detail_type": schema.StringAttribute{ + Description: "Free-form string used to decide what fields to expect in the event detail.", + Optional: true, + }, + "event_bus_name": schema.StringAttribute{ + Description: "The name or ARN of the event bus to receive the event.", + Optional: true, + }, + names.AttrResources: schema.ListAttribute{ + Description: "AWS resources, identified by Amazon Resource Name (ARN), which the event primarily concerns.", + CustomType: fwtypes.ListOfStringType, + Optional: true, + }, + names.AttrSource: schema.StringAttribute{ + Description: "The source of the event.", + Required: true, + }, + "time": schema.StringAttribute{ + Description: "The time stamp of the event, per RFC3339.", + Optional: true, + CustomType: timetypes.RFC3339Type{}, + }, + }, + }, + }, + }, + } +} + +func (a *putEventsAction) Invoke(ctx context.Context, req action.InvokeRequest, resp *action.InvokeResponse) { + var model putEventsActionModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &model)...) + if resp.Diagnostics.HasError() { + return + } + + conn := a.Meta().EventsClient(ctx) + + tflog.Info(ctx, "Putting events", map[string]any{ + "entry_count": len(model.Entry.Elements()), + }) + + resp.SendProgress(action.InvokeProgressEvent{ + Message: "Putting events to EventBridge...", + }) + + var input eventbridge.PutEventsInput + resp.Diagnostics.Append(fwflex.Expand(ctx, model, &input)...) + if resp.Diagnostics.HasError() { + return + } + + output, err := conn.PutEvents(ctx, &input) + if err != nil { + resp.Diagnostics.AddError( + "Putting Events", + "Could not put events: "+err.Error(), + ) + return + } + + if output.FailedEntryCount > 0 { + resp.Diagnostics.AddError( + "Putting Events", + strconv.Itoa(int(output.FailedEntryCount))+" entries failed to be processed", + ) + return + } + + resp.SendProgress(action.InvokeProgressEvent{ + Message: "Events put successfully", + }) + + tflog.Info(ctx, "Put events completed", map[string]any{ + "successful_entries": len(output.Entries), + }) +} diff --git a/internal/service/events/put_events_action_test.go b/internal/service/events/put_events_action_test.go new file mode 100644 index 000000000000..3c51187378d2 --- /dev/null +++ b/internal/service/events/put_events_action_test.go @@ -0,0 +1,386 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package events_test + +import ( + "context" + "encoding/json" + "fmt" + "strings" + "testing" + "time" + + "github.com/aws/aws-sdk-go-v2/service/eventbridge" + "github.com/aws/aws-sdk-go-v2/service/sqs" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccEventsPutEventsAction_basic(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EventsServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: testAccCheckBusDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPutEventsActionConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckPutEventsDelivered(ctx, rName, 1), + ), + }, + }, + }) +} + +func TestAccEventsPutEventsAction_multipleEntries(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EventsServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: testAccCheckBusDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPutEventsActionConfig_multipleEntries(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckPutEventsDelivered(ctx, rName, 2), + ), + }, + }, + }) +} + +func TestAccEventsPutEventsAction_customBus(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EventsServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: testAccCheckBusDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPutEventsActionConfig_customBus(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckPutEventsDelivered(ctx, rName, 1), + ), + }, + }, + }) +} + +// nosemgrep: ci.events-in-func-name -- Verification helper for PutEvents delivery +func testAccCheckPutEventsDelivered(ctx context.Context, rName string, expected int) resource.TestCheckFunc { + return func(s *terraform.State) error { + meta := acctest.Provider.Meta().(*conns.AWSClient) + evConn := meta.EventsClient(ctx) + sqsConn := meta.SQSClient(ctx) + + // Ensure bus exists (sanity) + if _, err := evConn.DescribeEventBus(ctx, &eventbridge.DescribeEventBusInput{Name: &rName}); err != nil { + return fmt.Errorf("event bus %s not found: %w", rName, err) + } + + // Discover queue URL via name convention + queueName := rName + "-events-test" + getOut, err := sqsConn.GetQueueUrl(ctx, &sqs.GetQueueUrlInput{QueueName: &queueName}) + if err != nil { + return fmt.Errorf("getting queue url: %w", err) + } + + deadline := time.Now().Add(2 * time.Minute) + received := 0 + marker := rName + for time.Now().Before(deadline) && received < expected { + // Long poll + msgOut, err := sqsConn.ReceiveMessage(ctx, &sqs.ReceiveMessageInput{ + QueueUrl: getOut.QueueUrl, + MaxNumberOfMessages: 10, + WaitTimeSeconds: 10, + }) + if err != nil { + // transient network errors: retry + continue + } + for _, m := range msgOut.Messages { + if m.Body == nil { + continue + } + // EventBridge SQS target wraps the event as JSON; look for marker inside detail + if strings.Contains(*m.Body, marker) { + // Optionally parse to verify structure + var parsed map[string]any + _ = json.Unmarshal([]byte(*m.Body), &parsed) + received++ + } + } + } + + if received < expected { + return fmt.Errorf("expected %d events delivered to SQS, received %d", expected, received) + } + return nil + } +} + +// nosemgrep: ci.events-in-func-name -- Function reflects PutEvents operation naming for consistency. +func testAccPutEventsActionConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_cloudwatch_event_bus" "test" { + name = %[1]q +} + +resource "aws_cloudwatch_event_rule" "test" { + name = %[1]q + event_bus_name = aws_cloudwatch_event_bus.test.name + event_pattern = jsonencode({ + source = ["test.application"] + }) +} + +resource "aws_sqs_queue" "events_target" { + name = "%[1]s-events-test" +} + +resource "aws_sqs_queue_policy" "events_target" { + queue_url = aws_sqs_queue.events_target.id + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "AllowEventBridgeSendMessage" + Effect = "Allow" + Principal = { Service = "events.amazonaws.com" } + Action = "sqs:SendMessage" + Resource = aws_sqs_queue.events_target.arn + Condition = { + ArnEquals = { "aws:SourceArn" = aws_cloudwatch_event_rule.test.arn } + } + } + ] + }) +} + +resource "aws_cloudwatch_event_target" "test" { + rule = aws_cloudwatch_event_rule.test.name + event_bus_name = aws_cloudwatch_event_bus.test.name + target_id = "sqs" + arn = aws_sqs_queue.events_target.arn +} + +action "aws_events_put_events" "test" { + config { + entry { + source = "test.application" + detail_type = "Test Event" + event_bus_name = aws_cloudwatch_event_bus.test.name + detail = jsonencode({ + marker = %[1]q + action = "test" + }) + } + } +} + +resource "terraform_data" "trigger" { + input = "trigger" + lifecycle { + action_trigger { + events = [after_create, before_update] + actions = [action.aws_events_put_events.test] + } + } + depends_on = [ + aws_cloudwatch_event_target.test, + aws_sqs_queue_policy.events_target + ] +} +`, rName) +} + +// nosemgrep: ci.events-in-func-name -- Function reflects PutEvents operation naming for consistency. +func testAccPutEventsActionConfig_multipleEntries(rName string) string { + return fmt.Sprintf(` +resource "aws_cloudwatch_event_bus" "test" { + name = %[1]q +} + +resource "aws_cloudwatch_event_rule" "test" { + name = %[1]q + event_bus_name = aws_cloudwatch_event_bus.test.name + event_pattern = jsonencode({ + source = ["test.application", "test.orders"] + }) +} + +resource "aws_sqs_queue" "events_target" { + name = "%[1]s-events-test" +} + +resource "aws_sqs_queue_policy" "events_target" { + queue_url = aws_sqs_queue.events_target.id + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "AllowEventBridgeSendMessage" + Effect = "Allow" + Principal = { Service = "events.amazonaws.com" } + Action = "sqs:SendMessage" + Resource = aws_sqs_queue.events_target.arn + Condition = { + ArnEquals = { "aws:SourceArn" = aws_cloudwatch_event_rule.test.arn } + } + } + ] + }) +} + +resource "aws_cloudwatch_event_target" "test" { + rule = aws_cloudwatch_event_rule.test.name + event_bus_name = aws_cloudwatch_event_bus.test.name + target_id = "sqs" + arn = aws_sqs_queue.events_target.arn +} + +action "aws_events_put_events" "test" { + config { + entry { + source = "test.application" + detail_type = "User Action" + event_bus_name = aws_cloudwatch_event_bus.test.name + detail = jsonencode({ + marker = %[1]q + action = "login" + }) + } + + entry { + source = "test.orders" + detail_type = "Order Created" + event_bus_name = aws_cloudwatch_event_bus.test.name + detail = jsonencode({ + marker = %[1]q + amount = 99.99 + }) + } + } +} + +resource "terraform_data" "trigger" { + input = "trigger" + lifecycle { + action_trigger { + events = [after_create, before_update] + actions = [action.aws_events_put_events.test] + } + } + depends_on = [ + aws_cloudwatch_event_target.test, + aws_sqs_queue_policy.events_target + ] +} +`, rName) +} + +// nosemgrep: ci.events-in-func-name -- Function reflects PutEvents operation naming for consistency. +func testAccPutEventsActionConfig_customBus(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_cloudwatch_event_bus" "test" { + name = %[1]q +} + +resource "aws_cloudwatch_event_rule" "test" { + name = %[1]q + event_bus_name = aws_cloudwatch_event_bus.test.name + event_pattern = jsonencode({ + source = ["custom.source"] + detail-type = ["Custom Event"] + }) +} + +resource "aws_sqs_queue" "events_target" { + name = "%[1]s-events-test" +} + +resource "aws_sqs_queue_policy" "events_target" { + queue_url = aws_sqs_queue.events_target.id + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "AllowEventBridgeSendMessage" + Effect = "Allow" + Principal = { Service = "events.amazonaws.com" } + Action = "sqs:SendMessage" + Resource = aws_sqs_queue.events_target.arn + Condition = { + ArnEquals = { "aws:SourceArn" = aws_cloudwatch_event_rule.test.arn } + } + } + ] + }) +} + +resource "aws_cloudwatch_event_target" "test" { + rule = aws_cloudwatch_event_rule.test.name + event_bus_name = aws_cloudwatch_event_bus.test.name + target_id = "sqs" + arn = aws_sqs_queue.events_target.arn +} + +action "aws_events_put_events" "test" { + config { + entry { + source = "custom.source" + detail_type = "Custom Event" + event_bus_name = aws_cloudwatch_event_bus.test.name + time = "2023-01-01T12:00:00Z" + resources = ["arn:${data.aws_partition.current.partition}:s3:::example-bucket"] + detail = jsonencode({ + custom_field = "custom_value" + marker = %[1]q + timestamp = "2023-01-01T12:00:00Z" + }) + } + } +} + +resource "terraform_data" "trigger" { + input = "trigger" + lifecycle { + action_trigger { + events = [after_create, before_update] + actions = [action.aws_events_put_events.test] + } + } + depends_on = [ + aws_cloudwatch_event_target.test, + aws_sqs_queue_policy.events_target + ] +} +`, rName) +} diff --git a/internal/service/events/service_package.go b/internal/service/events/service_package.go new file mode 100644 index 000000000000..637e9cdc2b0d --- /dev/null +++ b/internal/service/events/service_package.go @@ -0,0 +1,41 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package events + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/retry" + "github.com/aws/aws-sdk-go-v2/service/eventbridge" + awstypes "github.com/aws/aws-sdk-go-v2/service/eventbridge/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/internal/vcr" +) + +func (p *servicePackage) withExtraOptions(ctx context.Context, config map[string]any) []func(*eventbridge.Options) { + cfg := *(config["aws_sdkv2_config"].(*aws.Config)) + + return []func(*eventbridge.Options){ + func(o *eventbridge.Options) { + retryables := []retry.IsErrorRetryable{ + retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*awstypes.LimitExceededException](err, "The requested resource exceeds the maximum number allowed") { + return aws.FalseTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + }), + } + // Include go-vcr retryable to prevent generated client retryer from being overridden + if inContext, ok := conns.FromContext(ctx); ok && inContext.VCREnabled() { + tflog.Info(ctx, "overriding retry behavior to immediately return VCR errors") + retryables = append(retryables, vcr.InteractionNotFoundRetryableFunc) + } + + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retryables...) + }, + } +} diff --git a/internal/service/events/service_package_gen.go b/internal/service/events/service_package_gen.go index 926a7e2ffea2..082a8622fb80 100644 --- a/internal/service/events/service_package_gen.go +++ b/internal/service/events/service_package_gen.go @@ -17,6 +17,17 @@ import ( type servicePackage struct{} +func (p *servicePackage) Actions(ctx context.Context) []*inttypes.ServicePackageAction { + return []*inttypes.ServicePackageAction{ + { + Factory: newPutEventsAction, + TypeName: "aws_events_put_events", + Name: "Put Events", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, + } +} + func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*inttypes.ServicePackageFrameworkDataSource { return []*inttypes.ServicePackageFrameworkDataSource{ { diff --git a/internal/service/fsx/lustre_file_system.go b/internal/service/fsx/lustre_file_system.go index fb23b3514ce3..f094ea32642d 100644 --- a/internal/service/fsx/lustre_file_system.go +++ b/internal/service/fsx/lustre_file_system.go @@ -660,9 +660,35 @@ func resourceLustreFileSystemUpdate(ctx context.Context, d *schema.ResourceData, var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxClient(ctx) + updated := false + // First, update the metadata configuration if it has changed. + // Sometimes it is necessary to increase IOPS before increasing storage_capacity. + if d.HasChange("metadata_configuration") { + input := &fsx.UpdateFileSystemInput{ + ClientRequestToken: aws.String(id.UniqueId()), + FileSystemId: aws.String(d.Id()), + LustreConfiguration: &awstypes.UpdateFileSystemLustreConfiguration{ + MetadataConfiguration: expandLustreMetadataUpdateConfiguration(d.Get("metadata_configuration").([]any)), + }, + } + + startTime := time.Now() + _, err := conn.UpdateFileSystem(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating FSX for Lustre File System (%s) metadata_configuration: %s", d.Id(), err) + } + + if _, err := waitFileSystemUpdated(ctx, conn, d.Id(), startTime, d.Timeout(schema.TimeoutUpdate)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for FSx for Lustre File System (%s) metadata_configuration update: %s", d.Id(), err) + } + updated = true + } + if d.HasChangesExcept( "final_backup_tags", "skip_final_backup", + "metadata_configuration", names.AttrTags, names.AttrTagsAll, ) { @@ -696,10 +722,6 @@ func resourceLustreFileSystemUpdate(ctx context.Context, d *schema.ResourceData, input.LustreConfiguration.LogConfiguration = expandLustreLogCreateConfiguration(d.Get("log_configuration").([]any)) } - if d.HasChange("metadata_configuration") { - input.LustreConfiguration.MetadataConfiguration = expandLustreMetadataUpdateConfiguration(d.Get("metadata_configuration").([]any)) - } - if d.HasChange("per_unit_storage_throughput") { input.LustreConfiguration.PerUnitStorageThroughput = aws.Int32(int32(d.Get("per_unit_storage_throughput").(int))) } @@ -730,7 +752,10 @@ func resourceLustreFileSystemUpdate(ctx context.Context, d *schema.ResourceData, if _, err := waitFileSystemUpdated(ctx, conn, d.Id(), startTime, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for FSx for Lustre File System (%s) update: %s", d.Id(), err) } + updated = true + } + if updated { if _, err := waitFileSystemAdministrativeActionCompleted(ctx, conn, d.Id(), awstypes.AdministrativeActionTypeFileSystemUpdate, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for FSx for Lustre File System (%s) administrative action (%s) complete: %s", d.Id(), awstypes.AdministrativeActionTypeFileSystemUpdate, err) } diff --git a/internal/service/fsx/lustre_file_system_test.go b/internal/service/fsx/lustre_file_system_test.go index 4a40c8ad07c7..b12f869ee025 100644 --- a/internal/service/fsx/lustre_file_system_test.go +++ b/internal/service/fsx/lustre_file_system_test.go @@ -1010,7 +1010,7 @@ func TestAccFSxLustreFileSystem_metadataConfig(t *testing.T) { ImportStateVerifyIgnore: []string{names.AttrSecurityGroupIDs}, }, { - Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500), + Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500, 1200), Check: resource.ComposeTestCheckFunc( testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2), testAccCheckLustreFileSystemNotRecreated(&filesystem1, &filesystem2), @@ -1036,7 +1036,7 @@ func TestAccFSxLustreFileSystem_metadataConfig_increase(t *testing.T) { CheckDestroy: testAccCheckLustreFileSystemDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500), + Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500, 1200), Check: resource.ComposeTestCheckFunc( testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", "1"), @@ -1051,7 +1051,7 @@ func TestAccFSxLustreFileSystem_metadataConfig_increase(t *testing.T) { ImportStateVerifyIgnore: []string{names.AttrSecurityGroupIDs}, }, { - Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 3000), + Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 3000, 1200), Check: resource.ComposeTestCheckFunc( testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2), testAccCheckLustreFileSystemNotRecreated(&filesystem1, &filesystem2), @@ -1077,7 +1077,7 @@ func TestAccFSxLustreFileSystem_metadataConfig_decrease(t *testing.T) { CheckDestroy: testAccCheckLustreFileSystemDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 3000), + Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 3000, 1200), Check: resource.ComposeTestCheckFunc( testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", "1"), @@ -1092,7 +1092,7 @@ func TestAccFSxLustreFileSystem_metadataConfig_decrease(t *testing.T) { ImportStateVerifyIgnore: []string{names.AttrSecurityGroupIDs}, }, { - Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500), + Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500, 1200), Check: resource.ComposeTestCheckFunc( testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2), testAccCheckLustreFileSystemRecreated(&filesystem1, &filesystem2), @@ -1105,6 +1105,44 @@ func TestAccFSxLustreFileSystem_metadataConfig_decrease(t *testing.T) { }) } +func TestAccFSxLustreFileSystem_metadataConfig_increaseWithStorageCapacity(t *testing.T) { + ctx := acctest.Context(t) + var filesystem1, filesystem2 awstypes.FileSystem + resourceName := "aws_fsx_lustre_file_system.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.FSxEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.FSxServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLustreFileSystemDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 1500, 1200), + Check: resource.ComposeTestCheckFunc( + testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem1), + resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "USER_PROVISIONED"), + resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.iops", "1500"), + resource.TestCheckResourceAttr(resourceName, "storage_capacity", "1200"), + ), + }, + { + // When storage_capacity is increased to 2400, IOPS must be increased to at least 3000. + Config: testAccLustreFileSystemConfig_metadata_iops(rName, "USER_PROVISIONED", 3000, 2400), + Check: resource.ComposeTestCheckFunc( + testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckLustreFileSystemNotRecreated(&filesystem1, &filesystem2), + resource.TestCheckResourceAttr(resourceName, "metadata_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.mode", "USER_PROVISIONED"), + resource.TestCheckResourceAttr(resourceName, "metadata_configuration.0.iops", "3000"), + resource.TestCheckResourceAttr(resourceName, "storage_capacity", "2400"), + ), + }, + }, + }) +} + func TestAccFSxLustreFileSystem_rootSquashConfig(t *testing.T) { ctx := acctest.Context(t) var filesystem awstypes.FileSystem @@ -2015,10 +2053,10 @@ resource "aws_fsx_lustre_file_system" "test" { `, rName, mode)) } -func testAccLustreFileSystemConfig_metadata_iops(rName, mode string, iops int) string { +func testAccLustreFileSystemConfig_metadata_iops(rName, mode string, iops, storageCapacity int) string { return acctest.ConfigCompose(testAccLustreFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_lustre_file_system" "test" { - storage_capacity = 1200 + storage_capacity = %[4]d subnet_ids = aws_subnet.test[*].id deployment_type = "PERSISTENT_2" per_unit_storage_throughput = 125 @@ -2032,7 +2070,7 @@ resource "aws_fsx_lustre_file_system" "test" { Name = %[1]q } } -`, rName, mode, iops)) +`, rName, mode, iops, storageCapacity)) } func testAccLustreFileSystemConfig_rootSquash(rName, uid string) string { diff --git a/internal/service/glue/resource_policy_identity_gen_test.go b/internal/service/glue/resource_policy_identity_gen_test.go index 0e1f8b0c11b3..e40bb2b0b7da 100644 --- a/internal/service/glue/resource_policy_identity_gen_test.go +++ b/internal/service/glue/resource_policy_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccGlueResourcePolicy_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccGlueResourcePolicy_Identity_Basic, - "ExistingResource": testAccGlueResourcePolicy_Identity_ExistingResource, - "RegionOverride": testAccGlueResourcePolicy_Identity_RegionOverride, + acctest.CtBasic: testAccGlueResourcePolicy_Identity_Basic, + "ExistingResource": testAccGlueResourcePolicy_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccGlueResourcePolicy_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccGlueResourcePolicy_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/glue/sweep.go b/internal/service/glue/sweep.go index 5ed7574ebd61..7b6f5d1e7d66 100644 --- a/internal/service/glue/sweep.go +++ b/internal/service/glue/sweep.go @@ -18,7 +18,10 @@ import ( ) func RegisterSweepers() { - awsv2.Register("aws_glue_catalog_database", sweepCatalogDatabases) + awsv2.Register("aws_glue_catalog_database", sweepCatalogDatabases, + "aws_datazone_environment", + ) + awsv2.Register("aws_glue_classifier", sweepClassifiers) awsv2.Register("aws_glue_connection", sweepConnections) awsv2.Register("aws_glue_crawler", sweepCrawlers) diff --git a/internal/service/iam/access_key.go b/internal/service/iam/access_key.go index c194aab5f545..2a5b6e086ef4 100644 --- a/internal/service/iam/access_key.go +++ b/internal/service/iam/access_key.go @@ -9,7 +9,6 @@ import ( "crypto/sha256" "fmt" "log" - "reflect" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -24,7 +23,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - itypes "github.com/hashicorp/terraform-provider-aws/internal/types" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -249,10 +248,11 @@ func resourceAccessKeyDelete(ctx context.Context, d *schema.ResourceData, meta a conn := meta.(*conns.AWSClient).IAMClient(ctx) log.Printf("[DEBUG] Deleting IAM Access Key: %s", d.Id()) - _, err := conn.DeleteAccessKey(ctx, &iam.DeleteAccessKeyInput{ + input := iam.DeleteAccessKeyInput{ AccessKeyId: aws.String(d.Id()), UserName: aws.String(d.Get("user").(string)), - }) + } + _, err := conn.DeleteAccessKey(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { return diags @@ -281,7 +281,7 @@ func findAccessKeyByTwoPartKey(ctx context.Context, conn *iam.Client, username, UserName: aws.String(username), } - return findAccessKey(ctx, conn, input, func(v awstypes.AccessKeyMetadata) bool { + return findAccessKey(ctx, conn, input, func(v *awstypes.AccessKeyMetadata) bool { return aws.ToString(v.AccessKeyId) == id }) } @@ -291,10 +291,10 @@ func findAccessKeysByUser(ctx context.Context, conn *iam.Client, username string UserName: aws.String(username), } - return findAccessKeys(ctx, conn, input, tfslices.PredicateTrue[awstypes.AccessKeyMetadata]()) + return findAccessKeys(ctx, conn, input, tfslices.PredicateTrue[*awstypes.AccessKeyMetadata]()) } -func findAccessKey(ctx context.Context, conn *iam.Client, input *iam.ListAccessKeysInput, filter tfslices.Predicate[awstypes.AccessKeyMetadata]) (*awstypes.AccessKeyMetadata, error) { +func findAccessKey(ctx context.Context, conn *iam.Client, input *iam.ListAccessKeysInput, filter tfslices.Predicate[*awstypes.AccessKeyMetadata]) (*awstypes.AccessKeyMetadata, error) { output, err := findAccessKeys(ctx, conn, input, filter) if err != nil { @@ -304,7 +304,7 @@ func findAccessKey(ctx context.Context, conn *iam.Client, input *iam.ListAccessK return tfresource.AssertSingleValueResult(output) } -func findAccessKeys(ctx context.Context, conn *iam.Client, input *iam.ListAccessKeysInput, filter tfslices.Predicate[awstypes.AccessKeyMetadata]) ([]awstypes.AccessKeyMetadata, error) { +func findAccessKeys(ctx context.Context, conn *iam.Client, input *iam.ListAccessKeysInput, filter tfslices.Predicate[*awstypes.AccessKeyMetadata]) ([]awstypes.AccessKeyMetadata, error) { var output []awstypes.AccessKeyMetadata pages := iam.NewListAccessKeysPaginator(conn, input) @@ -323,7 +323,7 @@ func findAccessKeys(ctx context.Context, conn *iam.Client, input *iam.ListAccess } for _, v := range page.AccessKeyMetadata { - if !reflect.ValueOf(v).IsZero() && filter(v) { + if p := &v; !inttypes.IsZero(p) && filter(p) { output = append(output, v) } } @@ -371,5 +371,5 @@ func sesSMTPPasswordFromSecretKeySigV4(key *string, region string) (string, erro versionedSig := make([]byte, 0, len(rawSig)+1) versionedSig = append(versionedSig, version) versionedSig = append(versionedSig, rawSig...) - return itypes.Base64Encode(versionedSig), nil + return inttypes.Base64Encode(versionedSig), nil } diff --git a/internal/service/iam/account_alias.go b/internal/service/iam/account_alias.go index fb2f42218218..1b0402259a20 100644 --- a/internal/service/iam/account_alias.go +++ b/internal/service/iam/account_alias.go @@ -5,13 +5,17 @@ package iam import ( "context" + "log" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" + awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) // @SDKResource("aws_iam_account_alias", name="Account Alias") @@ -41,15 +45,14 @@ func resourceAccountAliasCreate(ctx context.Context, d *schema.ResourceData, met conn := meta.(*conns.AWSClient).IAMClient(ctx) accountAlias := d.Get("account_alias").(string) - - params := &iam.CreateAccountAliasInput{ + input := iam.CreateAccountAliasInput{ AccountAlias: aws.String(accountAlias), } - _, err := conn.CreateAccountAlias(ctx, params) + _, err := conn.CreateAccountAlias(ctx, &input) if err != nil { - return sdkdiag.AppendErrorf(diags, "creating account alias with name '%s': %s", accountAlias, err) + return sdkdiag.AppendErrorf(diags, "creating IAM Account Alias (%s): %s", accountAlias, err) } d.SetId(accountAlias) @@ -61,23 +64,20 @@ func resourceAccountAliasRead(ctx context.Context, d *schema.ResourceData, meta var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - params := &iam.ListAccountAliasesInput{} - - resp, err := conn.ListAccountAliases(ctx, params) + var input iam.ListAccountAliasesInput + output, err := findAccountAlias(ctx, conn, &input) - if err != nil { - return sdkdiag.AppendErrorf(diags, "listing account aliases: %s", err) - } - - if !d.IsNewResource() && (resp == nil || len(resp.AccountAliases) == 0) { + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] IAM Account Alias (%s) not found, removing from state", d.Id()) d.SetId("") return diags } - accountAlias := resp.AccountAliases[0] + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading IAM Account Alias (%s): %s", d.Id(), err) + } - d.SetId(accountAlias) - d.Set("account_alias", accountAlias) + d.Set("account_alias", output) return diags } @@ -86,17 +86,47 @@ func resourceAccountAliasDelete(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - accountAlias := d.Get("account_alias").(string) - - params := &iam.DeleteAccountAliasInput{ - AccountAlias: aws.String(accountAlias), + log.Printf("[DEBUG] Deleting IAM Account Alias: %s", d.Id()) + input := iam.DeleteAccountAliasInput{ + AccountAlias: aws.String(d.Id()), } - _, err := conn.DeleteAccountAlias(ctx, params) + _, err := conn.DeleteAccountAlias(ctx, &input) + + if errs.IsA[*awstypes.NoSuchEntityException](err) { + return diags + } if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting account alias with name '%s': %s", accountAlias, err) + return sdkdiag.AppendErrorf(diags, "deleting IAM Account Alias (%s): %s", d.Id(), err) } return diags } + +func findAccountAlias(ctx context.Context, conn *iam.Client, input *iam.ListAccountAliasesInput) (*string, error) { + output, err := findAccountAliases(ctx, conn, input) + + if err != nil { + return nil, err + } + + return tfresource.AssertSingleValueResult(output) +} + +func findAccountAliases(ctx context.Context, conn *iam.Client, input *iam.ListAccountAliasesInput) ([]string, error) { + var output []string + + pages := iam.NewListAccountAliasesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + return nil, err + } + + output = append(output, page.AccountAliases...) + } + + return output, nil +} diff --git a/internal/service/iam/account_alias_data_source.go b/internal/service/iam/account_alias_data_source.go index a894f797789a..06f342467641 100644 --- a/internal/service/iam/account_alias_data_source.go +++ b/internal/service/iam/account_alias_data_source.go @@ -5,8 +5,8 @@ package iam import ( "context" - "log" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -32,22 +32,15 @@ func dataSourceAccountAliasRead(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - log.Printf("[DEBUG] Reading IAM Account Aliases.") + var input iam.ListAccountAliasesInput + output, err := findAccountAlias(ctx, conn, &input) - req := &iam.ListAccountAliasesInput{} - resp, err := conn.ListAccountAliases(ctx, req) if err != nil { return sdkdiag.AppendErrorf(diags, "reading IAM Account Alias: %s", err) } - // 'AccountAliases': [] if there is no alias. - if resp == nil || len(resp.AccountAliases) == 0 { - return sdkdiag.AppendErrorf(diags, "reading IAM Account Alias: empty result") - } - - alias := resp.AccountAliases[0] - d.SetId(alias) - d.Set("account_alias", alias) + d.SetId(aws.ToString(output)) + d.Set("account_alias", output) return diags } diff --git a/internal/service/iam/account_alias_test.go b/internal/service/iam/account_alias_test.go index d83da881ff0a..62a081bb8720 100644 --- a/internal/service/iam/account_alias_test.go +++ b/internal/service/iam/account_alias_test.go @@ -16,6 +16,8 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfiam "github.com/hashicorp/terraform-provider-aws/internal/service/iam" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -27,7 +29,8 @@ func TestAccIAMAccountAlias_serial(t *testing.T) { acctest.CtBasic: testAccAccountAliasDataSource_basic, }, "Resource": { - acctest.CtBasic: testAccAccountAlias_basic, + acctest.CtBasic: testAccAccountAlias_basic, + acctest.CtDisappears: testAccAccountAlias_disappears, }, } @@ -37,7 +40,6 @@ func TestAccIAMAccountAlias_serial(t *testing.T) { func testAccAccountAlias_basic(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_iam_account_alias.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.Test(t, resource.TestCase{ @@ -64,6 +66,32 @@ func testAccAccountAlias_basic(t *testing.T) { }) } +func testAccAccountAlias_disappears(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_iam_account_alias.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckAccountAlias(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.IAMServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckAccountAliasDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccAccountAliasConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAccountAliasExists(ctx, resourceName), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfiam.ResourceAccountAlias(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckAccountAliasDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).IAMClient(ctx) @@ -73,21 +101,18 @@ func testAccCheckAccountAliasDestroy(ctx context.Context) resource.TestCheckFunc continue } - params := &iam.ListAccountAliasesInput{} - - resp, err := conn.ListAccountAliases(ctx, params) + var input iam.ListAccountAliasesInput + _, err := tfiam.FindAccountAlias(ctx, conn, &input) - if err != nil { - return fmt.Errorf("error reading IAM Account Alias (%s): %w", rs.Primary.ID, err) + if tfresource.NotFound(err) { + continue } - if resp == nil { - return fmt.Errorf("error reading IAM Account Alias (%s): empty response", rs.Primary.ID) + if err != nil { + return err } - if len(resp.AccountAliases) > 0 { - return fmt.Errorf("Bad: Account alias still exists: %q", rs.Primary.ID) - } + return fmt.Errorf("IAM Server Certificate %s still exists", rs.Primary.ID) } return nil @@ -96,29 +121,17 @@ func testAccCheckAccountAliasDestroy(ctx context.Context) resource.TestCheckFunc func testAccCheckAccountAliasExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] + _, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).IAMClient(ctx) - params := &iam.ListAccountAliasesInput{} - resp, err := conn.ListAccountAliases(ctx, params) + var input iam.ListAccountAliasesInput + _, err := tfiam.FindAccountAlias(ctx, conn, &input) - if err != nil { - return fmt.Errorf("error reading IAM Account Alias (%s): %w", rs.Primary.ID, err) - } - - if resp == nil { - return fmt.Errorf("error reading IAM Account Alias (%s): empty response", rs.Primary.ID) - } - - if len(resp.AccountAliases) == 0 { - return fmt.Errorf("Bad: Account alias %q does not exist", rs.Primary.ID) - } - - return nil + return err } } diff --git a/internal/service/iam/consts.go b/internal/service/iam/consts.go new file mode 100644 index 000000000000..6ff9286f67cc --- /dev/null +++ b/internal/service/iam/consts.go @@ -0,0 +1,17 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package iam + +import ( + "time" +) + +const ( + // Maximum amount of time to wait for IAM changes to propagate + // This timeout should not be increased without strong consideration + // as this will negatively impact user experience when configurations + // have incorrect references or permissions. + // Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency + propagationTimeout = 2 * time.Minute +) diff --git a/internal/service/iam/exports.go b/internal/service/iam/exports.go index e4939cba4da9..ac083eb3151f 100644 --- a/internal/service/iam/exports.go +++ b/internal/service/iam/exports.go @@ -7,8 +7,12 @@ package iam var ( ResourceRole = resourceRole - DeleteServiceLinkedRole = deleteServiceLinkedRole - FindRoleByName = findRoleByName - ListGroupsForUserPages = listGroupsForUserPages - AttachPolicyToUser = attachPolicyToUser + DeleteServiceLinkedRole = deleteServiceLinkedRole + FindRoleByName = findRoleByName + PolicyHasValidAWSPrincipals = policyHasValidAWSPrincipals // nosemgrep:ci.aws-in-var-name +) + +type ( + IAMPolicyDoc = iamPolicyDoc + IAMPolicyStatement = iamPolicyStatement ) diff --git a/internal/service/iam/exports_test.go b/internal/service/iam/exports_test.go index 9a8ae3366a4a..142d1ebd5bd0 100644 --- a/internal/service/iam/exports_test.go +++ b/internal/service/iam/exports_test.go @@ -5,8 +5,8 @@ package iam // Exports for use in tests only. var ( - ResourceAccessKey = resourceAccessKey - // ResourceAccountAlias = resourceAccountAlias + ResourceAccessKey = resourceAccessKey + ResourceAccountAlias = resourceAccountAlias ResourceAccountPasswordPolicy = resourceAccountPasswordPolicy ResourceGroup = resourceGroup // ResourceGroupMembership = resourceGroupMembership @@ -32,33 +32,49 @@ var ( ResourceUserSSHKey = resourceUserSSHKey ResourceVirtualMFADevice = resourceVirtualMFADevice - FindAccessKeyByTwoPartKey = findAccessKeyByTwoPartKey - FindAccountPasswordPolicy = findAccountPasswordPolicy - FindAttachedGroupPolicies = findAttachedGroupPolicies - FindAttachedGroupPolicyByTwoPartKey = findAttachedGroupPolicyByTwoPartKey - FindAttachedRolePolicies = findAttachedRolePolicies - FindAttachedRolePolicyByTwoPartKey = findAttachedRolePolicyByTwoPartKey - FindAttachedUserPolicies = findAttachedUserPolicies - FindAttachedUserPolicyByTwoPartKey = findAttachedUserPolicyByTwoPartKey - FindEntitiesForPolicyByARN = findEntitiesForPolicyByARN - FindGroupByName = findGroupByName - FindGroupPoliciesByName = findGroupPoliciesByName - FindGroupPolicyAttachmentsByName = findGroupPolicyAttachmentsByName - FindInstanceProfileByName = findInstanceProfileByName - FindOpenIDConnectProviderByARN = findOpenIDConnectProviderByARN - FindOrganizationsFeatures = findOrganizationsFeatures - FindPolicyByARN = findPolicyByARN - FindRolePolicyByTwoPartKey = findRolePolicyByTwoPartKey - FindRolePoliciesByName = findRolePoliciesByName - FindRolePolicyAttachmentsByName = findRolePolicyAttachmentsByName - FindSAMLProviderByARN = findSAMLProviderByARN - FindServerCertificateByName = findServerCertificateByName - FindSSHPublicKeyByThreePartKey = findSSHPublicKeyByThreePartKey - FindUserByName = findUserByName - FindUserPoliciesByName = findUserPoliciesByName - FindUserPolicyAttachmentsByName = findUserPolicyAttachmentsByName - FindVirtualMFADeviceBySerialNumber = findVirtualMFADeviceBySerialNumber - SESSMTPPasswordFromSecretKeySigV4 = sesSMTPPasswordFromSecretKeySigV4 + FindAccessKeyByTwoPartKey = findAccessKeyByTwoPartKey + FindAccountAlias = findAccountAlias + FindAccountPasswordPolicy = findAccountPasswordPolicy + FindAttachedGroupPolicies = findAttachedGroupPolicies + FindAttachedGroupPolicyByTwoPartKey = findAttachedGroupPolicyByTwoPartKey + FindAttachedRolePolicies = findAttachedRolePolicies + FindAttachedRolePolicyByTwoPartKey = findAttachedRolePolicyByTwoPartKey + FindAttachedUserPolicies = findAttachedUserPolicies + FindAttachedUserPolicyByTwoPartKey = findAttachedUserPolicyByTwoPartKey + FindEntitiesForPolicyByARN = findEntitiesForPolicyByARN + FindGroupByName = findGroupByName + FindGroupPoliciesByName = findGroupPoliciesByName + FindGroupPolicyAttachmentsByName = findGroupPolicyAttachmentsByName + FindGroupPolicyByTwoPartKey = findGroupPolicyByTwoPartKey + FindInstanceProfileByName = findInstanceProfileByName + FindOpenIDConnectProviderByARN = findOpenIDConnectProviderByARN + FindOrganizationsFeatures = findOrganizationsFeatures + FindPolicyByARN = findPolicyByARN + FindRolePolicyByTwoPartKey = findRolePolicyByTwoPartKey + FindRolePoliciesByName = findRolePoliciesByName + FindRolePolicyAttachmentsByName = findRolePolicyAttachmentsByName + FindSAMLProviderByARN = findSAMLProviderByARN + FindServerCertificateByName = findServerCertificateByName + FindServiceSpecificCredentialByThreePartKey = findServiceSpecificCredentialByThreePartKey + FindSigningCertificateByTwoPartKey = findSigningCertificateByTwoPartKey + FindSSHPublicKeyByThreePartKey = findSSHPublicKeyByThreePartKey + FindUserByName = findUserByName + FindUserPoliciesByName = findUserPoliciesByName + FindUserPolicyAttachmentsByName = findUserPolicyAttachmentsByName + FindUserPolicyByTwoPartKey = findUserPolicyByTwoPartKey + FindVirtualMFADeviceBySerialNumber = findVirtualMFADeviceBySerialNumber - RolePolicyParseID = rolePolicyParseID + AttachPolicyToUser = attachPolicyToUser + CheckPwdPolicy = checkPwdPolicy + GeneratePassword = generatePassword + IsValidPolicyAWSPrincipal = isValidPolicyAWSPrincipal // nosemgrep:ci.aws-in-var-name + ListGroupsForUserPages = listGroupsForUserPages + RoleNameSessionFromARN = roleNameSessionFromARN + RolePolicyParseID = rolePolicyParseID + ServiceLinkedRoleParseResourceID = serviceLinkedRoleParseResourceID + SESSMTPPasswordFromSecretKeySigV4 = sesSMTPPasswordFromSecretKeySigV4 +) + +type ( + IAMPolicyStatementConditionSet = iamPolicyStatementConditionSet ) diff --git a/internal/service/iam/find.go b/internal/service/iam/find.go deleted file mode 100644 index 88478b22c305..000000000000 --- a/internal/service/iam/find.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package iam - -import ( - "context" - "reflect" - - "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/iam" - awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/errs" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -) - -func FindUsers(ctx context.Context, conn *iam.Client, nameRegex, pathPrefix string) ([]awstypes.User, error) { - input := &iam.ListUsersInput{} - - if pathPrefix != "" { - input.PathPrefix = aws.String(pathPrefix) - } - - var results []awstypes.User - - pages := iam.NewListUsersPaginator(conn, input) - for pages.HasMorePages() { - page, err := pages.NextPage(ctx) - if err != nil { - return nil, err - } - - for _, user := range page.Users { - if nameRegex != "" && !regexache.MustCompile(nameRegex).MatchString(aws.ToString(user.UserName)) { - continue - } - - results = append(results, user) - } - } - - return results, nil -} - -func FindServiceSpecificCredential(ctx context.Context, conn *iam.Client, serviceName, userName, credID string) (*awstypes.ServiceSpecificCredentialMetadata, error) { - input := &iam.ListServiceSpecificCredentialsInput{ - ServiceName: aws.String(serviceName), - UserName: aws.String(userName), - } - - output, err := conn.ListServiceSpecificCredentials(ctx, input) - - if errs.IsA[*awstypes.NoSuchEntityException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if len(output.ServiceSpecificCredentials) == 0 { - return nil, tfresource.NewEmptyResultError(output) - } - - var cred awstypes.ServiceSpecificCredentialMetadata - - for _, crd := range output.ServiceSpecificCredentials { - if aws.ToString(crd.ServiceName) == serviceName && - aws.ToString(crd.UserName) == userName && - aws.ToString(crd.ServiceSpecificCredentialId) == credID { - cred = crd - break - } - } - - if reflect.ValueOf(cred).IsZero() { - return nil, tfresource.NewEmptyResultError(cred) - } - - return &cred, nil -} - -func FindSigningCertificate(ctx context.Context, conn *iam.Client, userName, certId string) (*awstypes.SigningCertificate, error) { - input := &iam.ListSigningCertificatesInput{ - UserName: aws.String(userName), - } - - output, err := conn.ListSigningCertificates(ctx, input) - - if errs.IsA[*awstypes.NoSuchEntityException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if len(output.Certificates) == 0 { - return nil, tfresource.NewEmptyResultError(output) - } - - var cert awstypes.SigningCertificate - - for _, crt := range output.Certificates { - if aws.ToString(crt.UserName) == userName && - aws.ToString(crt.CertificateId) == certId { - cert = crt - break - } - } - - if reflect.ValueOf(cert).IsZero() { - return nil, tfresource.NewEmptyResultError(cert) - } - - return &cert, nil -} diff --git a/internal/service/iam/generate.go b/internal/service/iam/generate.go index b6d07a91ffb9..7c4709a6f705 100644 --- a/internal/service/iam/generate.go +++ b/internal/service/iam/generate.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/listpages/main.go -Paginator=Marker -ListOps=ListGroupsForUser +//go:generate go run ../../generate/listpages/main.go -Paginator=Marker -ListOps=ListGroupsForUser,ListServiceSpecificCredentials //go:generate go run ../../generate/tags/main.go -ServiceTagsSlice //go:generate go run ../../generate/servicepackage/main.go //go:generate go run ../../generate/tagstests/main.go diff --git a/internal/service/iam/group_policy.go b/internal/service/iam/group_policy.go index 35a31dcdac55..60b8b656ed30 100644 --- a/internal/service/iam/group_policy.go +++ b/internal/service/iam/group_policy.go @@ -81,25 +81,24 @@ func resourceGroupPolicyPut(ctx context.Context, d *schema.ResourceData, meta an return sdkdiag.AppendFromErr(diags, err) } - groupName := d.Get("group").(string) - policyName := create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string)) - request := &iam.PutGroupPolicyInput{ + groupName, policyName := d.Get("group").(string), create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string)) + input := iam.PutGroupPolicyInput{ GroupName: aws.String(groupName), PolicyDocument: aws.String(policyDoc), PolicyName: aws.String(policyName), } - _, err = conn.PutGroupPolicy(ctx, request) + _, err = conn.PutGroupPolicy(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "putting IAM Group (%s) Policy (%s): %s", groupName, policyName, err) } if d.IsNewResource() { - d.SetId(fmt.Sprintf("%s:%s", groupName, policyName)) + d.SetId(groupPolicyCreateResourceID(groupName, policyName)) _, err := tfresource.RetryWhenNotFound(ctx, propagationTimeout, func(ctx context.Context) (any, error) { - return FindGroupPolicyByTwoPartKey(ctx, conn, groupName, policyName) + return findGroupPolicyByTwoPartKey(ctx, conn, groupName, policyName) }) if err != nil { @@ -114,12 +113,12 @@ func resourceGroupPolicyRead(ctx context.Context, d *schema.ResourceData, meta a var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - groupName, policyName, err := GroupPolicyParseID(d.Id()) + groupName, policyName, err := groupPolicyParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } - policyDocument, err := FindGroupPolicyByTwoPartKey(ctx, conn, groupName, policyName) + policyDocument, err := findGroupPolicyByTwoPartKey(ctx, conn, groupName, policyName) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] IAM Group Policy %s not found, removing from state", d.Id()) @@ -153,16 +152,17 @@ func resourceGroupPolicyDelete(ctx context.Context, d *schema.ResourceData, meta var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - groupName, policyName, err := GroupPolicyParseID(d.Id()) + groupName, policyName, err := groupPolicyParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } log.Printf("[INFO] Deleting IAM Group Policy: %s", d.Id()) - _, err = conn.DeleteGroupPolicy(ctx, &iam.DeleteGroupPolicyInput{ + input := iam.DeleteGroupPolicyInput{ GroupName: aws.String(groupName), PolicyName: aws.String(policyName), - }) + } + _, err = conn.DeleteGroupPolicy(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { return diags @@ -175,12 +175,16 @@ func resourceGroupPolicyDelete(ctx context.Context, d *schema.ResourceData, meta return diags } -func FindGroupPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, groupName, policyName string) (string, error) { - input := &iam.GetGroupPolicyInput{ +func findGroupPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, groupName, policyName string) (string, error) { + input := iam.GetGroupPolicyInput{ GroupName: aws.String(groupName), PolicyName: aws.String(policyName), } + return findGroupPolicy(ctx, conn, &input) +} + +func findGroupPolicy(ctx context.Context, conn *iam.Client, input *iam.GetGroupPolicyInput) (string, error) { output, err := conn.GetGroupPolicy(ctx, input) if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -201,14 +205,21 @@ func FindGroupPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, groupNam return aws.ToString(output.PolicyDocument), nil } -func GroupPolicyParseID(id string) (groupName, policyName string, err error) { - parts := strings.SplitN(id, ":", 2) +const groupPolicyResourceIDSeparator = ":" + +func groupPolicyCreateResourceID(groupName, policyName string) string { + parts := []string{groupName, policyName} + id := strings.Join(parts, groupPolicyResourceIDSeparator) + + return id +} + +func groupPolicyParseResourceID(id string) (string, string, error) { + parts := strings.SplitN(id, groupPolicyResourceIDSeparator, 2) + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { - err = fmt.Errorf("group_policy id must be of the form :") - return + return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected GROUP-NAME%[2]sPOLICY-NAME", id, groupPolicyResourceIDSeparator) } - groupName = parts[0] - policyName = parts[1] - return + return parts[0], parts[1], nil } diff --git a/internal/service/iam/group_policy_attachment.go b/internal/service/iam/group_policy_attachment.go index cf6a25bb7eb9..73e94e9bfb8d 100644 --- a/internal/service/iam/group_policy_attachment.go +++ b/internal/service/iam/group_policy_attachment.go @@ -7,7 +7,6 @@ import ( "context" "fmt" "log" - "reflect" "strings" "github.com/aws/aws-sdk-go-v2/aws" @@ -22,6 +21,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) @@ -159,16 +159,16 @@ func detachPolicyFromGroup(ctx context.Context, conn *iam.Client, group, policyA } func findAttachedGroupPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, groupName, policyARN string) (*awstypes.AttachedPolicy, error) { - input := &iam.ListAttachedGroupPoliciesInput{ + input := iam.ListAttachedGroupPoliciesInput{ GroupName: aws.String(groupName), } - return findAttachedGroupPolicy(ctx, conn, input, func(v awstypes.AttachedPolicy) bool { + return findAttachedGroupPolicy(ctx, conn, &input, func(v *awstypes.AttachedPolicy) bool { return aws.ToString(v.PolicyArn) == policyARN }) } -func findAttachedGroupPolicy(ctx context.Context, conn *iam.Client, input *iam.ListAttachedGroupPoliciesInput, filter tfslices.Predicate[awstypes.AttachedPolicy]) (*awstypes.AttachedPolicy, error) { +func findAttachedGroupPolicy(ctx context.Context, conn *iam.Client, input *iam.ListAttachedGroupPoliciesInput, filter tfslices.Predicate[*awstypes.AttachedPolicy]) (*awstypes.AttachedPolicy, error) { output, err := findAttachedGroupPolicies(ctx, conn, input, filter) if err != nil { @@ -178,7 +178,7 @@ func findAttachedGroupPolicy(ctx context.Context, conn *iam.Client, input *iam.L return tfresource.AssertSingleValueResult(output) } -func findAttachedGroupPolicies(ctx context.Context, conn *iam.Client, input *iam.ListAttachedGroupPoliciesInput, filter tfslices.Predicate[awstypes.AttachedPolicy]) ([]awstypes.AttachedPolicy, error) { +func findAttachedGroupPolicies(ctx context.Context, conn *iam.Client, input *iam.ListAttachedGroupPoliciesInput, filter tfslices.Predicate[*awstypes.AttachedPolicy]) ([]awstypes.AttachedPolicy, error) { var output []awstypes.AttachedPolicy pages := iam.NewListAttachedGroupPoliciesPaginator(conn, input) @@ -197,7 +197,7 @@ func findAttachedGroupPolicies(ctx context.Context, conn *iam.Client, input *iam } for _, v := range page.AttachedPolicies { - if !reflect.ValueOf(v).IsZero() && filter(v) { + if p := &v; !inttypes.IsZero(p) && filter(p) { output = append(output, v) } } diff --git a/internal/service/iam/group_policy_attachment_test.go b/internal/service/iam/group_policy_attachment_test.go index c942a5d684bb..85e37175b420 100644 --- a/internal/service/iam/group_policy_attachment_test.go +++ b/internal/service/iam/group_policy_attachment_test.go @@ -145,7 +145,7 @@ func testAccCheckGroupPolicyAttachmentCount(ctx context.Context, groupName strin input := &iam.ListAttachedGroupPoliciesInput{ GroupName: aws.String(groupName), } - output, err := tfiam.FindAttachedGroupPolicies(ctx, conn, input, tfslices.PredicateTrue[awstypes.AttachedPolicy]()) + output, err := tfiam.FindAttachedGroupPolicies(ctx, conn, input, tfslices.PredicateTrue[*awstypes.AttachedPolicy]()) if err != nil { return err diff --git a/internal/service/iam/group_policy_test.go b/internal/service/iam/group_policy_test.go index 1472f593f24a..8f62d53f7a7b 100644 --- a/internal/service/iam/group_policy_test.go +++ b/internal/service/iam/group_policy_test.go @@ -199,12 +199,7 @@ func testAccCheckGroupPolicyDestroy(ctx context.Context) resource.TestCheckFunc continue } - groupName, policyName, err := tfiam.GroupPolicyParseID(rs.Primary.ID) - if err != nil { - return err - } - - _, err = tfiam.FindGroupPolicyByTwoPartKey(ctx, conn, groupName, policyName) + _, err := tfiam.FindGroupPolicyByTwoPartKey(ctx, conn, rs.Primary.Attributes["group"], rs.Primary.Attributes[names.AttrName]) if tfresource.NotFound(err) { continue @@ -228,14 +223,9 @@ func testAccCheckGroupPolicyExists(ctx context.Context, n string, v *string) res return fmt.Errorf("Not Found: %s", n) } - groupName, policyName, err := tfiam.GroupPolicyParseID(rs.Primary.ID) - if err != nil { - return err - } - conn := acctest.Provider.Meta().(*conns.AWSClient).IAMClient(ctx) - output, err := tfiam.FindGroupPolicyByTwoPartKey(ctx, conn, groupName, policyName) + output, err := tfiam.FindGroupPolicyByTwoPartKey(ctx, conn, rs.Primary.Attributes["group"], rs.Primary.Attributes[names.AttrName]) if err != nil { return err diff --git a/internal/service/iam/instance_profile.go b/internal/service/iam/instance_profile.go index 9f62591e4a6a..9eca00f359c5 100644 --- a/internal/service/iam/instance_profile.go +++ b/internal/service/iam/instance_profile.go @@ -342,8 +342,8 @@ func findInstanceProfileByName(ctx context.Context, conn *iam.Client, name strin } const ( - InstanceProfileFound = "Found" - InstanceProfileInvalidARN = "InvalidARN" + instanceProfileFoundState = "Found" + instanceProfileInvalidARNState = "InvalidARN" ) func statusInstanceProfile(ctx context.Context, conn *iam.Client, name string) retry.StateRefreshFunc { @@ -359,17 +359,17 @@ func statusInstanceProfile(ctx context.Context, conn *iam.Client, name string) r _, err = arn.Parse(aws.ToString(output.Arn)) if err != nil { - return nil, InstanceProfileInvalidARN, nil // lint:ignore nilerr // this is usually a temporary state + return nil, instanceProfileInvalidARNState, nil // lint:ignore nilerr // this is usually a temporary state } - return output, InstanceProfileFound, nil + return output, instanceProfileFoundState, nil } } func waitInstanceProfileReady(ctx context.Context, conn *iam.Client, id string, timeout time.Duration) error { stateConf := &retry.StateChangeConf{ - Pending: []string{"", InstanceProfileInvalidARN}, - Target: enum.Slice(InstanceProfileFound), + Pending: []string{"", instanceProfileInvalidARNState}, + Target: enum.Slice(instanceProfileFoundState), Refresh: statusInstanceProfile(ctx, conn, id), Timeout: timeout, Delay: 5 * time.Second, diff --git a/internal/service/iam/instance_profiles_data_source.go b/internal/service/iam/instance_profiles_data_source.go index 8813ece81557..a9f50beb2864 100644 --- a/internal/service/iam/instance_profiles_data_source.go +++ b/internal/service/iam/instance_profiles_data_source.go @@ -5,7 +5,6 @@ package iam import ( "context" - "reflect" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" @@ -16,6 +15,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -51,7 +51,6 @@ func dataSourceInstanceProfiles() *schema.Resource { func dataSourceInstanceProfilesRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).IAMClient(ctx) roleName := d.Get("role_name").(string) @@ -78,12 +77,12 @@ func dataSourceInstanceProfilesRead(ctx context.Context, d *schema.ResourceData, } func findInstanceProfilesForRole(ctx context.Context, conn *iam.Client, roleName string) ([]awstypes.InstanceProfile, error) { - input := &iam.ListInstanceProfilesForRoleInput{ + input := iam.ListInstanceProfilesForRoleInput{ RoleName: aws.String(roleName), } var output []awstypes.InstanceProfile - pages := iam.NewListInstanceProfilesForRolePaginator(conn, input) + pages := iam.NewListInstanceProfilesForRolePaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) @@ -99,7 +98,7 @@ func findInstanceProfilesForRole(ctx context.Context, conn *iam.Client, roleName } for _, v := range page.InstanceProfiles { - if !reflect.ValueOf(v).IsZero() { + if p := &v; !inttypes.IsZero(p) { output = append(output, v) } } diff --git a/internal/service/iam/list_pages_gen.go b/internal/service/iam/list_pages_gen.go index f6a1a78e5c71..75ef4505e304 100644 --- a/internal/service/iam/list_pages_gen.go +++ b/internal/service/iam/list_pages_gen.go @@ -1,4 +1,4 @@ -// Code generated by "internal/generate/listpages/main.go -Paginator=Marker -ListOps=ListGroupsForUser"; DO NOT EDIT. +// Code generated by "internal/generate/listpages/main.go -Paginator=Marker -ListOps=ListGroupsForUser,ListServiceSpecificCredentials"; DO NOT EDIT. package iam @@ -25,3 +25,19 @@ func listGroupsForUserPages(ctx context.Context, conn *iam.Client, input *iam.Li } return nil } +func listServiceSpecificCredentialsPages(ctx context.Context, conn *iam.Client, input *iam.ListServiceSpecificCredentialsInput, fn func(*iam.ListServiceSpecificCredentialsOutput, bool) bool, optFns ...func(*iam.Options)) error { + for { + output, err := conn.ListServiceSpecificCredentials(ctx, input, optFns...) + if err != nil { + return err + } + + lastPage := aws.ToString(output.Marker) == "" + if !fn(output, lastPage) || lastPage { + break + } + + input.Marker = output.Marker + } + return nil +} diff --git a/internal/service/iam/openid_connect_provider.go b/internal/service/iam/openid_connect_provider.go index 382a20acebc2..4da9feb23163 100644 --- a/internal/service/iam/openid_connect_provider.go +++ b/internal/service/iam/openid_connect_provider.go @@ -224,10 +224,14 @@ func resourceOpenIDConnectProviderDelete(ctx context.Context, d *schema.Resource } func findOpenIDConnectProviderByARN(ctx context.Context, conn *iam.Client, arn string) (*iam.GetOpenIDConnectProviderOutput, error) { - input := &iam.GetOpenIDConnectProviderInput{ + input := iam.GetOpenIDConnectProviderInput{ OpenIDConnectProviderArn: aws.String(arn), } + return findOpenIDConnectProvider(ctx, conn, &input) +} + +func findOpenIDConnectProvider(ctx context.Context, conn *iam.Client, input *iam.GetOpenIDConnectProviderInput) (*iam.GetOpenIDConnectProviderOutput, error) { output, err := conn.GetOpenIDConnectProvider(ctx, input) if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -236,6 +240,7 @@ func findOpenIDConnectProviderByARN(ctx context.Context, conn *iam.Client, arn s LastRequest: input, } } + if err != nil { return nil, err } diff --git a/internal/service/iam/openid_connect_provider_data_source.go b/internal/service/iam/openid_connect_provider_data_source.go index 2646d1adbd74..4ff2e35175ee 100644 --- a/internal/service/iam/openid_connect_provider_data_source.go +++ b/internal/service/iam/openid_connect_provider_data_source.go @@ -6,18 +6,18 @@ package iam import ( "context" "fmt" - "reflect" "strings" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" - "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -42,12 +42,12 @@ func dataSourceOpenIDConnectProvider() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + names.AttrTags: tftags.TagsSchemaComputed(), "thumbprint_list": { Type: schema.TypeList, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - names.AttrTags: tftags.TagsSchemaComputed(), names.AttrURL: { Type: schema.TypeString, Optional: true, @@ -62,71 +62,67 @@ func dataSourceOpenIDConnectProvider() *schema.Resource { func dataSourceOpenIDConnectProviderRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).IAMClient(ctx) - input := &iam.GetOpenIDConnectProviderInput{} + var input iam.GetOpenIDConnectProviderInput if v, ok := d.GetOk(names.AttrARN); ok { input.OpenIDConnectProviderArn = aws.String(v.(string)) } else if v, ok := d.GetOk(names.AttrURL); ok { url := v.(string) - oidcpEntry, err := dataSourceGetOpenIDConnectProviderByURL(ctx, conn, url) + oidcpEntry, err := findOpenIDConnectProviderByURL(ctx, conn, url) + if err != nil { - return sdkdiag.AppendErrorf(diags, "finding IAM OIDC Provider by url (%s): %s", url, err) + return sdkdiag.AppendErrorf(diags, "reading IAM OIDC Provider (%s): %s", url, err) } - if oidcpEntry == nil { - return sdkdiag.AppendErrorf(diags, "finding IAM OIDC Provider by url (%s): not found", url) - } input.OpenIDConnectProviderArn = oidcpEntry.Arn } - resp, err := conn.GetOpenIDConnectProvider(ctx, input) + output, err := findOpenIDConnectProvider(ctx, conn, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "reading IAM OIDC Provider: %s", err) } - d.SetId(aws.ToString(input.OpenIDConnectProviderArn)) - d.Set(names.AttrARN, input.OpenIDConnectProviderArn) - d.Set(names.AttrURL, resp.Url) - d.Set("client_id_list", flex.FlattenStringValueList(resp.ClientIDList)) - d.Set("thumbprint_list", flex.FlattenStringValueList(resp.ThumbprintList)) + arn := aws.ToString(input.OpenIDConnectProviderArn) + d.SetId(arn) + d.Set(names.AttrARN, arn) + d.Set("client_id_list", output.ClientIDList) + d.Set("thumbprint_list", output.ThumbprintList) + d.Set(names.AttrURL, output.Url) - setTagsOut(ctx, resp.Tags) + setTagsOut(ctx, output.Tags) return diags } -func dataSourceGetOpenIDConnectProviderByURL(ctx context.Context, conn *iam.Client, url string) (*awstypes.OpenIDConnectProviderListEntry, error) { - var result *awstypes.OpenIDConnectProviderListEntry - - input := &iam.ListOpenIDConnectProvidersInput{} +func findOpenIDConnectProviderByURL(ctx context.Context, conn *iam.Client, url string) (*awstypes.OpenIDConnectProviderListEntry, error) { + var input iam.ListOpenIDConnectProvidersInput - output, err := conn.ListOpenIDConnectProviders(ctx, input) + output, err := conn.ListOpenIDConnectProviders(ctx, &input) if err != nil { return nil, err } - for _, oidcp := range output.OpenIDConnectProviderList { - if reflect.ValueOf(oidcp).IsZero() { + for _, v := range output.OpenIDConnectProviderList { + if p := &v; inttypes.IsZero(p) { continue } - arnUrl, err := urlFromOpenIDConnectProviderARN(aws.ToString(oidcp.Arn)) + arnUrl, err := urlFromOpenIDConnectProviderARN(aws.ToString(v.Arn)) if err != nil { return nil, err } if arnUrl == strings.TrimPrefix(url, "https://") { - return &oidcp, nil + return &v, nil } } - return result, nil + return nil, &retry.NotFoundError{} } func urlFromOpenIDConnectProviderARN(arn string) (string, error) { diff --git a/internal/service/iam/policy.go b/internal/service/iam/policy.go index 80fce89dab07..03fc3f78af6a 100644 --- a/internal/service/iam/policy.go +++ b/internal/service/iam/policy.go @@ -8,7 +8,6 @@ import ( "fmt" "log" "net/url" - "reflect" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" @@ -25,6 +24,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -113,7 +113,7 @@ func resourcePolicyCreate(ctx context.Context, d *schema.ResourceData, meta any) } name := create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string)) - input := &iam.CreatePolicyInput{ + input := iam.CreatePolicyInput{ Description: aws.String(d.Get(names.AttrDescription).(string)), Path: aws.String(d.Get(names.AttrPath).(string)), PolicyDocument: aws.String(policy), @@ -121,14 +121,14 @@ func resourcePolicyCreate(ctx context.Context, d *schema.ResourceData, meta any) Tags: getTagsIn(ctx), } - output, err := conn.CreatePolicy(ctx, input) + output, err := conn.CreatePolicy(ctx, &input) // Some partitions (e.g. ISO) may not support tag-on-create. partition := meta.(*conns.AWSClient).Partition(ctx) if input.Tags != nil && errs.IsUnsupportedOperationInPartitionError(partition, err) { input.Tags = nil - output, err = conn.CreatePolicy(ctx, input) + output, err = conn.CreatePolicy(ctx, &input) } if err != nil { @@ -171,7 +171,7 @@ func resourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta any) d return nil, err } - if v, err := findPolicyVersion(ctx, conn, d.Id(), aws.ToString(iamPolicy.policy.DefaultVersionId)); err == nil { + if v, err := findPolicyVersionByTwoPartKey(ctx, conn, d.Id(), aws.ToString(iamPolicy.policy.DefaultVersionId)); err == nil { iamPolicy.policyVersion = v } else { return nil, err @@ -202,7 +202,6 @@ func resourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta any) d setTagsOut(ctx, policy.Tags) policyDocument, err := url.QueryUnescape(aws.ToString(output.policyVersion.Document)) - if err != nil { return sdkdiag.AppendErrorf(diags, "parsing IAM Policy (%s) document: %s", d.Id(), err) } @@ -231,13 +230,13 @@ func resourcePolicyUpdate(ctx context.Context, d *schema.ResourceData, meta any) return sdkdiag.AppendErrorf(diags, "policy (%s) is invalid JSON: %s", policy, err) } - input := &iam.CreatePolicyVersionInput{ + input := iam.CreatePolicyVersionInput{ PolicyArn: aws.String(d.Id()), PolicyDocument: aws.String(policy), SetAsDefault: true, } - _, err = conn.CreatePolicyVersion(ctx, input) + _, err = conn.CreatePolicyVersion(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM Policy (%s): %s", d.Id(), err) @@ -273,9 +272,10 @@ func resourcePolicyDelete(ctx context.Context, d *schema.ResourceData, meta any) } log.Printf("[INFO] Deleting IAM Policy: %s", d.Id()) - _, err = conn.DeletePolicy(ctx, &iam.DeletePolicyInput{ + input := iam.DeletePolicyInput{ PolicyArn: aws.String(d.Id()), - }) + } + _, err = conn.DeletePolicy(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { return diags @@ -325,12 +325,12 @@ func policyPruneVersions(ctx context.Context, conn *iam.Client, arn string) erro } func policyDeleteVersion(ctx context.Context, conn *iam.Client, arn, versionID string) error { - input := &iam.DeletePolicyVersionInput{ + input := iam.DeletePolicyVersionInput{ PolicyArn: aws.String(arn), VersionId: aws.String(versionID), } - _, err := conn.DeletePolicyVersion(ctx, input) + _, err := conn.DeletePolicyVersion(ctx, &input) if err != nil { return fmt.Errorf("deleting IAM Policy (%s) version (%s): %w", arn, versionID, err) @@ -340,10 +340,14 @@ func policyDeleteVersion(ctx context.Context, conn *iam.Client, arn, versionID s } func findPolicyByARN(ctx context.Context, conn *iam.Client, arn string) (*awstypes.Policy, error) { - input := &iam.GetPolicyInput{ + input := iam.GetPolicyInput{ PolicyArn: aws.String(arn), } + return findPolicy(ctx, conn, &input) +} + +func findPolicy(ctx context.Context, conn *iam.Client, input *iam.GetPolicyInput) (*awstypes.Policy, error) { output, err := conn.GetPolicy(ctx, input) if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -365,12 +369,12 @@ func findPolicyByARN(ctx context.Context, conn *iam.Client, arn string) (*awstyp } func findPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, name, pathPrefix string) (*awstypes.Policy, error) { - input := &iam.ListPoliciesInput{} + var input iam.ListPoliciesInput if pathPrefix != "" { input.PathPrefix = aws.String(pathPrefix) } - output, err := findPolicies(ctx, conn, input) + output, err := findPolicies(ctx, conn, &input) if err != nil { return nil, err @@ -397,7 +401,7 @@ func findPolicies(ctx context.Context, conn *iam.Client, input *iam.ListPolicies } for _, v := range page.Policies { - if !reflect.ValueOf(v).IsZero() { + if p := &v; !inttypes.IsZero(p) { output = append(output, v) } } @@ -406,12 +410,16 @@ func findPolicies(ctx context.Context, conn *iam.Client, input *iam.ListPolicies return output, nil } -func findPolicyVersion(ctx context.Context, conn *iam.Client, arn, versionID string) (*awstypes.PolicyVersion, error) { - input := &iam.GetPolicyVersionInput{ +func findPolicyVersionByTwoPartKey(ctx context.Context, conn *iam.Client, arn, versionID string) (*awstypes.PolicyVersion, error) { + input := iam.GetPolicyVersionInput{ PolicyArn: aws.String(arn), VersionId: aws.String(versionID), } + return findPolicyVersion(ctx, conn, &input) +} + +func findPolicyVersion(ctx context.Context, conn *iam.Client, input *iam.GetPolicyVersionInput) (*awstypes.PolicyVersion, error) { output, err := conn.GetPolicyVersion(ctx, input) if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -433,9 +441,14 @@ func findPolicyVersion(ctx context.Context, conn *iam.Client, arn, versionID str } func findPolicyVersionsByARN(ctx context.Context, conn *iam.Client, arn string) ([]awstypes.PolicyVersion, error) { - input := &iam.ListPolicyVersionsInput{ + input := iam.ListPolicyVersionsInput{ PolicyArn: aws.String(arn), } + + return findPolicyVersions(ctx, conn, &input) +} + +func findPolicyVersions(ctx context.Context, conn *iam.Client, input *iam.ListPolicyVersionsInput) ([]awstypes.PolicyVersion, error) { var output []awstypes.PolicyVersion pages := iam.NewListPolicyVersionsPaginator(conn, input) @@ -454,7 +467,7 @@ func findPolicyVersionsByARN(ctx context.Context, conn *iam.Client, arn string) } for _, v := range page.Versions { - if !reflect.ValueOf(v).IsZero() { + if p := &v; !inttypes.IsZero(p) { output = append(output, v) } } diff --git a/internal/service/iam/policy_attachment.go b/internal/service/iam/policy_attachment.go index 4f74c8e4e326..10dc4ad2ba19 100644 --- a/internal/service/iam/policy_attachment.go +++ b/internal/service/iam/policy_attachment.go @@ -7,7 +7,6 @@ import ( "context" "errors" "log" - "reflect" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" @@ -22,6 +21,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/flex" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -275,10 +275,10 @@ func detachPolicyFromUsers(ctx context.Context, conn *iam.Client, users []string } func findEntitiesForPolicyByARN(ctx context.Context, conn *iam.Client, arn string) ([]string, []string, []string, error) { - input := &iam.ListEntitiesForPolicyInput{ + input := iam.ListEntitiesForPolicyInput{ PolicyArn: aws.String(arn), } - groups, roles, users, err := findEntitiesForPolicy(ctx, conn, input) + groups, roles, users, err := findEntitiesForPolicy(ctx, conn, &input) if err != nil { return nil, nil, nil, err @@ -316,17 +316,17 @@ func findEntitiesForPolicy(ctx context.Context, conn *iam.Client, input *iam.Lis } for _, v := range page.PolicyGroups { - if !reflect.ValueOf(v).IsZero() { + if p := &v; !inttypes.IsZero(p) { groups = append(groups, v) } } for _, v := range page.PolicyRoles { - if !reflect.ValueOf(v).IsZero() { + if p := &v; !inttypes.IsZero(p) { roles = append(roles, v) } } for _, v := range page.PolicyUsers { - if !reflect.ValueOf(v).IsZero() { + if p := &v; !inttypes.IsZero(p) { users = append(users, v) } } diff --git a/internal/service/iam/policy_data_source.go b/internal/service/iam/policy_data_source.go index ff5ca6ec76a5..19d2dad0ccc5 100644 --- a/internal/service/iam/policy_data_source.go +++ b/internal/service/iam/policy_data_source.go @@ -113,7 +113,7 @@ func dataSourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta any) output, err := tfresource.RetryWhenNotFound(ctx, propagationTimeout, func(ctx context.Context) (*awstypes.PolicyVersion, error) { - return findPolicyVersion(ctx, conn, arn, aws.ToString(policy.DefaultVersionId)) + return findPolicyVersionByTwoPartKey(ctx, conn, arn, aws.ToString(policy.DefaultVersionId)) }, ) diff --git a/internal/service/iam/policy_document_data_source.go b/internal/service/iam/policy_document_data_source.go index f3bd573d16ce..ca66419f0790 100644 --- a/internal/service/iam/policy_document_data_source.go +++ b/internal/service/iam/policy_document_data_source.go @@ -169,7 +169,7 @@ func dataSourcePolicyDocument() *schema.Resource { func dataSourcePolicyDocumentRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { var diags diag.Diagnostics - mergedDoc := &IAMPolicyDoc{} + mergedDoc := &iamPolicyDoc{} if v, ok := d.GetOk("source_policy_documents"); ok && len(v.([]any)) > 0 { // generate sid map to assure there are no duplicates in source jsons @@ -186,7 +186,7 @@ func dataSourcePolicyDocumentRead(ctx context.Context, d *schema.ResourceData, m continue } - sourceDoc := &IAMPolicyDoc{} + sourceDoc := &iamPolicyDoc{} if err := json.Unmarshal([]byte(sourceJSON.(string)), sourceDoc); err != nil { return sdkdiag.AppendErrorf(diags, "writing IAM Policy Document: merging source document %d: %s", sourceJSONIndex, err) } @@ -206,7 +206,7 @@ func dataSourcePolicyDocumentRead(ctx context.Context, d *schema.ResourceData, m } // process the current document - doc := &IAMPolicyDoc{ + doc := &iamPolicyDoc{ Version: d.Get(names.AttrVersion).(string), } @@ -216,12 +216,12 @@ func dataSourcePolicyDocumentRead(ctx context.Context, d *schema.ResourceData, m if cfgStmts, hasCfgStmts := d.GetOk("statement"); hasCfgStmts { var cfgStmtIntf = cfgStmts.([]any) - stmts := make([]*IAMPolicyStatement, len(cfgStmtIntf)) + stmts := make([]*iamPolicyStatement, len(cfgStmtIntf)) sidMap := make(map[string]struct{}) for i, stmtI := range cfgStmtIntf { cfgStmt := stmtI.(map[string]any) - stmt := &IAMPolicyStatement{ + stmt := &iamPolicyStatement{ Effect: cfgStmt["effect"].(string), } @@ -300,7 +300,7 @@ func dataSourcePolicyDocumentRead(ctx context.Context, d *schema.ResourceData, m if overrideJSON == nil { continue } - overrideDoc := &IAMPolicyDoc{} + overrideDoc := &iamPolicyDoc{} if err := json.Unmarshal([]byte(overrideJSON.(string)), overrideDoc); err != nil { return sdkdiag.AppendErrorf(diags, "writing IAM Policy Document: merging override document %d: %s", overrideJSONIndex, err) } @@ -353,12 +353,12 @@ func dataSourcePolicyDocumentReplaceVarsInList(in any, version string) (any, err } } -func dataSourcePolicyDocumentMakeConditions(in []any, version string) (IAMPolicyStatementConditionSet, error) { - out := make([]IAMPolicyStatementCondition, len(in)) +func dataSourcePolicyDocumentMakeConditions(in []any, version string) (iamPolicyStatementConditionSet, error) { + out := make([]iamPolicyStatementCondition, len(in)) for i, itemI := range in { var err error item := itemI.(map[string]any) - out[i] = IAMPolicyStatementCondition{ + out[i] = iamPolicyStatementCondition{ Test: item["test"].(string), Variable: item["variable"].(string), } @@ -374,15 +374,15 @@ func dataSourcePolicyDocumentMakeConditions(in []any, version string) (IAMPolicy out[i].Values = itemValues[0] } } - return IAMPolicyStatementConditionSet(out), nil + return iamPolicyStatementConditionSet(out), nil } -func dataSourcePolicyDocumentMakePrincipals(in []any, version string) (IAMPolicyStatementPrincipalSet, error) { - out := make([]IAMPolicyStatementPrincipal, len(in)) +func dataSourcePolicyDocumentMakePrincipals(in []any, version string) (iamPolicyStatementPrincipalSet, error) { + out := make([]iamPolicyStatementPrincipal, len(in)) for i, itemI := range in { var err error item := itemI.(map[string]any) - out[i] = IAMPolicyStatementPrincipal{ + out[i] = iamPolicyStatementPrincipal{ Type: item[names.AttrType].(string), } out[i].Identifiers, err = dataSourcePolicyDocumentReplaceVarsInList( @@ -394,5 +394,5 @@ func dataSourcePolicyDocumentMakePrincipals(in []any, version string) (IAMPolicy return nil, fmt.Errorf("reading identifiers: %w", err) } } - return IAMPolicyStatementPrincipalSet(out), nil + return iamPolicyStatementPrincipalSet(out), nil } diff --git a/internal/service/iam/policy_model.go b/internal/service/iam/policy_model.go index bb65ae7244a2..4a9803cfc7a5 100644 --- a/internal/service/iam/policy_model.go +++ b/internal/service/iam/policy_model.go @@ -18,39 +18,40 @@ const ( policyModelMarshallJSONStartSliceSize = 2 ) -type IAMPolicyDoc struct { +type iamPolicyDoc struct { Version string `json:",omitempty"` Id string `json:",omitempty"` - Statements []*IAMPolicyStatement `json:"Statement,omitempty"` + Statements []*iamPolicyStatement `json:"Statement,omitempty"` } -type IAMPolicyStatement struct { +type iamPolicyStatement struct { Sid string `json:",omitempty"` Effect string `json:",omitempty"` Actions any `json:"Action,omitempty"` NotActions any `json:"NotAction,omitempty"` Resources any `json:"Resource,omitempty"` NotResources any `json:"NotResource,omitempty"` - Principals IAMPolicyStatementPrincipalSet `json:"Principal,omitempty"` - NotPrincipals IAMPolicyStatementPrincipalSet `json:"NotPrincipal,omitempty"` - Conditions IAMPolicyStatementConditionSet `json:"Condition,omitempty"` + Principals iamPolicyStatementPrincipalSet `json:"Principal,omitempty"` + NotPrincipals iamPolicyStatementPrincipalSet `json:"NotPrincipal,omitempty"` + Conditions iamPolicyStatementConditionSet `json:"Condition,omitempty"` } -type IAMPolicyStatementPrincipal struct { +type iamPolicyStatementPrincipal struct { Type string Identifiers any } -type IAMPolicyStatementCondition struct { +type iamPolicyStatementPrincipalSet []iamPolicyStatementPrincipal + +type iamPolicyStatementCondition struct { Test string Variable string Values any } -type IAMPolicyStatementPrincipalSet []IAMPolicyStatementPrincipal -type IAMPolicyStatementConditionSet []IAMPolicyStatementCondition +type iamPolicyStatementConditionSet []iamPolicyStatementCondition -func (s *IAMPolicyDoc) Merge(newDoc *IAMPolicyDoc) { +func (s *iamPolicyDoc) Merge(newDoc *iamPolicyDoc) { // adopt newDoc's Id if len(newDoc.Id) > 0 { s.Id = newDoc.Id @@ -82,7 +83,7 @@ func (s *IAMPolicyDoc) Merge(newDoc *IAMPolicyDoc) { } } -func (ps IAMPolicyStatementPrincipalSet) MarshalJSON() ([]byte, error) { +func (ps iamPolicyStatementPrincipalSet) MarshalJSON() ([]byte, error) { raw := map[string]any{} // Although IAM documentation says that "*" and {"AWS": "*"} are equivalent @@ -137,8 +138,8 @@ func (ps IAMPolicyStatementPrincipalSet) MarshalJSON() ([]byte, error) { return json.Marshal(&raw) } -func (ps *IAMPolicyStatementPrincipalSet) UnmarshalJSON(b []byte) error { - var out IAMPolicyStatementPrincipalSet +func (ps *iamPolicyStatementPrincipalSet) UnmarshalJSON(b []byte) error { + var out iamPolicyStatementPrincipalSet var data any if err := json.Unmarshal(b, &data); err != nil { @@ -147,19 +148,19 @@ func (ps *IAMPolicyStatementPrincipalSet) UnmarshalJSON(b []byte) error { switch t := data.(type) { case string: - out = append(out, IAMPolicyStatementPrincipal{Type: "*", Identifiers: []string{"*"}}) + out = append(out, iamPolicyStatementPrincipal{Type: "*", Identifiers: []string{"*"}}) case map[string]any: for key, value := range data.(map[string]any) { switch vt := value.(type) { case string: - out = append(out, IAMPolicyStatementPrincipal{Type: key, Identifiers: value.(string)}) + out = append(out, iamPolicyStatementPrincipal{Type: key, Identifiers: value.(string)}) case []any: values := []string{} for _, v := range value.([]any) { values = append(values, v.(string)) } slices.Sort(values) - out = append(out, IAMPolicyStatementPrincipal{Type: key, Identifiers: values}) + out = append(out, iamPolicyStatementPrincipal{Type: key, Identifiers: values}) default: return fmt.Errorf("Unsupported data type %T for IAMPolicyStatementPrincipalSet.Identifiers", vt) } @@ -172,7 +173,7 @@ func (ps *IAMPolicyStatementPrincipalSet) UnmarshalJSON(b []byte) error { return nil } -func (cs IAMPolicyStatementConditionSet) MarshalJSON() ([]byte, error) { +func (cs iamPolicyStatementConditionSet) MarshalJSON() ([]byte, error) { raw := map[string]map[string]any{} for _, c := range cs { @@ -206,8 +207,8 @@ func (cs IAMPolicyStatementConditionSet) MarshalJSON() ([]byte, error) { return json.Marshal(&raw) } -func (cs *IAMPolicyStatementConditionSet) UnmarshalJSON(b []byte) error { - var out IAMPolicyStatementConditionSet +func (cs *iamPolicyStatementConditionSet) UnmarshalJSON(b []byte) error { + var out iamPolicyStatementConditionSet var data map[string]map[string]any if err := json.Unmarshal(b, &data); err != nil { @@ -218,15 +219,15 @@ func (cs *IAMPolicyStatementConditionSet) UnmarshalJSON(b []byte) error { for var_key, var_values := range test_value { switch var_values := var_values.(type) { case string: - out = append(out, IAMPolicyStatementCondition{Test: test_key, Variable: var_key, Values: []string{var_values}}) + out = append(out, iamPolicyStatementCondition{Test: test_key, Variable: var_key, Values: []string{var_values}}) case bool: - out = append(out, IAMPolicyStatementCondition{Test: test_key, Variable: var_key, Values: strconv.FormatBool(var_values)}) + out = append(out, iamPolicyStatementCondition{Test: test_key, Variable: var_key, Values: strconv.FormatBool(var_values)}) case []any: values := []string{} for _, v := range var_values { values = append(values, v.(string)) } - out = append(out, IAMPolicyStatementCondition{Test: test_key, Variable: var_key, Values: values}) + out = append(out, iamPolicyStatementCondition{Test: test_key, Variable: var_key, Values: values}) } } } @@ -248,11 +249,11 @@ func policyDecodeConfigStringList(lI []any) any { return ret } -// PolicyHasValidAWSPrincipals validates that the Principals in an IAM Policy are valid +// policyHasValidAWSPrincipals validates that the Principals in an IAM Policy are valid // Assumes that non-"AWS" Principals are valid // The value can be a single string or a slice of strings // Valid strings are either an ARN or an AWS account ID -func PolicyHasValidAWSPrincipals(policy string) (bool, error) { // nosemgrep:ci.aws-in-func-name +func policyHasValidAWSPrincipals(policy string) (bool, error) { // nosemgrep:ci.aws-in-func-name var policyData any err := json.Unmarshal([]byte(policy), &policyData) if err != nil { @@ -272,12 +273,12 @@ func PolicyHasValidAWSPrincipals(policy string) (bool, error) { // nosemgrep:ci. for _, principal := range principals { switch x := principal.(type) { case string: - if !IsValidPolicyAWSPrincipal(x) { + if !isValidPolicyAWSPrincipal(x) { return false, nil } case []string: for _, s := range x { - if !IsValidPolicyAWSPrincipal(s) { + if !isValidPolicyAWSPrincipal(s) { return false, nil } } @@ -287,9 +288,9 @@ func PolicyHasValidAWSPrincipals(policy string) (bool, error) { // nosemgrep:ci. return true, nil } -// IsValidPolicyAWSPrincipal returns true if a string is a valid AWS Princial for an IAM Policy document +// isValidPolicyAWSPrincipal returns true if a string is a valid AWS Princial for an IAM Policy document // That is: either an ARN, an AWS account ID, or `*` -func IsValidPolicyAWSPrincipal(principal string) bool { // nosemgrep:ci.aws-in-func-name +func isValidPolicyAWSPrincipal(principal string) bool { // nosemgrep:ci.aws-in-func-name if principal == "*" { return true } diff --git a/internal/service/iam/role.go b/internal/service/iam/role.go index 3da98908bc5c..dce4dbd39e38 100644 --- a/internal/service/iam/role.go +++ b/internal/service/iam/role.go @@ -10,12 +10,12 @@ import ( "iter" "log" "net/url" - "reflect" "strings" "time" "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go-v2/service/iam" awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" awspolicy "github.com/hashicorp/awspolicyequivalence" @@ -27,7 +27,6 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -40,9 +39,10 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/framework" fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" "github.com/hashicorp/terraform-provider-aws/internal/provider/sdkv2/importer" + "github.com/hashicorp/terraform-provider-aws/internal/retry" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - itypes "github.com/hashicorp/terraform-provider-aws/internal/types" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -213,7 +213,7 @@ func resourceRole() *schema.Resource { } // @SDKListResource("aws_iam_role") -func instanceResourceAsListResource() itypes.ListResourceForSDK { +func instanceResourceAsListResource() inttypes.ListResourceForSDK { l := roleListResource{} l.SetResourceSchema(resourceRole()) @@ -230,7 +230,7 @@ func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, meta any) d } name := create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string)) - input := &iam.CreateRoleInput{ + input := iam.CreateRoleInput{ AssumeRolePolicyDocument: aws.String(assumeRolePolicy), Path: aws.String(d.Get(names.AttrPath).(string)), RoleName: aws.String(name), @@ -249,14 +249,14 @@ func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, meta any) d input.PermissionsBoundary = aws.String(v.(string)) } - output, err := retryCreateRole(ctx, conn, input) + output, err := retryCreateRole(ctx, conn, &input) // Some partitions (e.g. ISO) may not support tag-on-create. partition := meta.(*conns.AWSClient).Partition(ctx) if input.Tags != nil && errs.IsUnsupportedOperationInPartitionError(partition, err) { input.Tags = nil - output, err = retryCreateRole(ctx, conn, input) + output, err = retryCreateRole(ctx, conn, &input) } if err != nil { @@ -368,14 +368,14 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, meta any) d return sdkdiag.AppendErrorf(diags, "assume_role_policy (%s) is invalid JSON: %s", assumeRolePolicy, err) } - input := &iam.UpdateAssumeRolePolicyInput{ + input := iam.UpdateAssumeRolePolicyInput{ RoleName: aws.String(d.Id()), PolicyDocument: aws.String(assumeRolePolicy), } _, err = tfresource.RetryWhen(ctx, propagationTimeout, func(ctx context.Context) (any, error) { - return conn.UpdateAssumeRolePolicy(ctx, input) + return conn.UpdateAssumeRolePolicy(ctx, &input) }, func(err error) (bool, error) { if errs.IsAErrorMessageContains[*awstypes.MalformedPolicyDocumentException](err, "Invalid principal in policy") { @@ -392,12 +392,12 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, meta any) d } if d.HasChange(names.AttrDescription) { - input := &iam.UpdateRoleDescriptionInput{ - RoleName: aws.String(d.Id()), + input := iam.UpdateRoleDescriptionInput{ Description: aws.String(d.Get(names.AttrDescription).(string)), + RoleName: aws.String(d.Id()), } - _, err := conn.UpdateRoleDescription(ctx, input) + _, err := conn.UpdateRoleDescription(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM Role (%s) description: %s", d.Id(), err) @@ -405,12 +405,12 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, meta any) d } if d.HasChange("max_session_duration") { - input := &iam.UpdateRoleInput{ - RoleName: aws.String(d.Id()), + input := iam.UpdateRoleInput{ MaxSessionDuration: aws.Int32(int32(d.Get("max_session_duration").(int))), + RoleName: aws.String(d.Id()), } - _, err := conn.UpdateRole(ctx, input) + _, err := conn.UpdateRole(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM Role (%s) MaxSessionDuration: %s", d.Id(), err) @@ -420,22 +420,22 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, meta any) d if d.HasChange("permissions_boundary") { permissionsBoundary := d.Get("permissions_boundary").(string) if permissionsBoundary != "" { - input := &iam.PutRolePermissionsBoundaryInput{ + input := iam.PutRolePermissionsBoundaryInput{ PermissionsBoundary: aws.String(permissionsBoundary), RoleName: aws.String(d.Id()), } - _, err := conn.PutRolePermissionsBoundary(ctx, input) + _, err := conn.PutRolePermissionsBoundary(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM Role (%s) permissions boundary: %s", d.Id(), err) } } else { - input := &iam.DeleteRolePermissionsBoundaryInput{ + input := iam.DeleteRolePermissionsBoundaryInput{ RoleName: aws.String(d.Id()), } - _, err := conn.DeleteRolePermissionsBoundary(ctx, input) + _, err := conn.DeleteRolePermissionsBoundary(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "deleting IAM Role (%s) permissions boundary: %s", d.Id(), err) @@ -557,12 +557,12 @@ func deleteRole(ctx context.Context, conn *iam.Client, roleName string, forceDet } } - input := &iam.DeleteRoleInput{ + input := iam.DeleteRoleInput{ RoleName: aws.String(roleName), } _, err := tfresource.RetryWhenIsA[any, *awstypes.DeleteConflictException](ctx, propagationTimeout, func(ctx context.Context) (any, error) { - return conn.DeleteRole(ctx, input) + return conn.DeleteRole(ctx, &input) }) if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -587,12 +587,12 @@ func deleteRoleInstanceProfiles(ctx context.Context, conn *iam.Client, roleName for _, instanceProfile := range instanceProfiles { instanceProfileName := aws.ToString(instanceProfile.InstanceProfileName) - input := &iam.RemoveRoleFromInstanceProfileInput{ + input := iam.RemoveRoleFromInstanceProfileInput{ InstanceProfileName: aws.String(instanceProfileName), RoleName: aws.String(roleName), } - _, err := conn.RemoveRoleFromInstanceProfile(ctx, input) + _, err := conn.RemoveRoleFromInstanceProfile(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { continue @@ -636,11 +636,11 @@ func retryCreateRole(ctx context.Context, conn *iam.Client, input *iam.CreateRol } func findRoleByName(ctx context.Context, conn *iam.Client, name string) (*awstypes.Role, error) { - input := &iam.GetRoleInput{ + input := iam.GetRoleInput{ RoleName: aws.String(name), } - return findRole(ctx, conn, input) + return findRole(ctx, conn, &input) } func findRole(ctx context.Context, conn *iam.Client, input *iam.GetRoleInput) (*awstypes.Role, error) { @@ -648,8 +648,7 @@ func findRole(ctx context.Context, conn *iam.Client, input *iam.GetRoleInput) (* if errs.IsA[*awstypes.NoSuchEntityException](err) { return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, + LastError: err, } } @@ -664,6 +663,55 @@ func findRole(ctx context.Context, conn *iam.Client, input *iam.GetRoleInput) (* return output.Role, nil } +const ( + roleARNIsUniqueIDState = "uniqueid" + roleNotFoundState = "notfound" +) + +func statusRoleCreate(conn *iam.Client, id string) retry.StateRefreshFunc { + return func(ctx context.Context) (any, string, error) { + role, err := findRoleByName(ctx, conn, id) + + if tfresource.NotFound(err) { + return nil, roleNotFoundState, nil + } + + if err != nil { + return nil, "", err + } + + if arn.IsARN(aws.ToString(role.Arn)) { + return role, names.AttrARN, nil + } + + return role, roleARNIsUniqueIDState, nil + } +} + +func waitRoleARNIsNotUniqueID(ctx context.Context, conn *iam.Client, id string, role *awstypes.Role) (*awstypes.Role, error) { + if arn.IsARN(aws.ToString(role.Arn)) { + return role, nil + } + + stateConf := &retry.StateChangeConf{ + Pending: []string{roleARNIsUniqueIDState, roleNotFoundState}, + Target: []string{names.AttrARN}, + Refresh: statusRoleCreate(conn, id), + Timeout: propagationTimeout, + NotFoundChecks: 10, + ContinuousTargetOccurence: 5, + Delay: 10 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Role); ok { + return output, err + } + + return nil, err +} + func listRoles(ctx context.Context, conn *iam.Client, input *iam.ListRolesInput) iter.Seq2[awstypes.Role, error] { return func(yield func(awstypes.Role, error) bool) { pages := iam.NewListRolesPaginator(conn, input) @@ -718,19 +766,18 @@ func resourceRoleFlatten(ctx context.Context, role *awstypes.Role, d *schema.Res } func findRoleAttachedPolicies(ctx context.Context, conn *iam.Client, roleName string) ([]string, error) { - input := &iam.ListAttachedRolePoliciesInput{ + input := iam.ListAttachedRolePoliciesInput{ RoleName: aws.String(roleName), } var output []string - pages := iam.NewListAttachedRolePoliciesPaginator(conn, input) + pages := iam.NewListAttachedRolePoliciesPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if errs.IsA[*awstypes.NoSuchEntityException](err) { return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, + LastError: err, } } @@ -739,7 +786,7 @@ func findRoleAttachedPolicies(ctx context.Context, conn *iam.Client, roleName st } for _, v := range page.AttachedPolicies { - if !reflect.ValueOf(v).IsZero() { + if p := &v; !inttypes.IsZero(p) { output = append(output, aws.ToString(v.PolicyArn)) } } @@ -749,19 +796,18 @@ func findRoleAttachedPolicies(ctx context.Context, conn *iam.Client, roleName st } func findRolePolicyNames(ctx context.Context, conn *iam.Client, roleName string) ([]string, error) { - input := &iam.ListRolePoliciesInput{ + input := iam.ListRolePoliciesInput{ RoleName: aws.String(roleName), } var output []string - pages := iam.NewListRolePoliciesPaginator(conn, input) + pages := iam.NewListRolePoliciesPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if errs.IsA[*awstypes.NoSuchEntityException](err) { return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, + LastError: err, } } @@ -783,12 +829,12 @@ func deleteRolePolicyAttachments(ctx context.Context, conn *iam.Client, roleName var errsList []error for _, policyARN := range policyARNs { - input := &iam.DetachRolePolicyInput{ + input := iam.DetachRolePolicyInput{ PolicyArn: aws.String(policyARN), RoleName: aws.String(roleName), } - _, err := conn.DetachRolePolicy(ctx, input) + _, err := conn.DetachRolePolicy(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { continue @@ -810,12 +856,12 @@ func deleteRoleInlinePolicies(ctx context.Context, conn *iam.Client, roleName st continue } - input := &iam.DeleteRolePolicyInput{ + input := iam.DeleteRolePolicyInput{ PolicyName: aws.String(policyName), RoleName: aws.String(roleName), } - _, err := conn.DeleteRolePolicy(ctx, input) + _, err := conn.DeleteRolePolicy(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { continue @@ -950,10 +996,11 @@ func readRoleInlinePolicies(ctx context.Context, conn *iam.Client, roleName stri var apiObjects []*iam.PutRolePolicyInput for _, policyName := range policyNames { - output, err := conn.GetRolePolicy(ctx, &iam.GetRolePolicyInput{ - RoleName: aws.String(roleName), + input := iam.GetRolePolicyInput{ PolicyName: aws.String(policyName), - }) + RoleName: aws.String(roleName), + } + output, err := conn.GetRolePolicy(ctx, &input) if err != nil { return nil, err @@ -970,9 +1017,9 @@ func readRoleInlinePolicies(ctx context.Context, conn *iam.Client, roleName stri } apiObject := &iam.PutRolePolicyInput{ - RoleName: aws.String(roleName), PolicyDocument: aws.String(p), PolicyName: aws.String(policyName), + RoleName: aws.String(roleName), } apiObjects = append(apiObjects, apiObject) diff --git a/internal/service/iam/roles_data_source.go b/internal/service/iam/roles_data_source.go index b2f85ab7fc7c..318dfaf7c337 100644 --- a/internal/service/iam/roles_data_source.go +++ b/internal/service/iam/roles_data_source.go @@ -5,7 +5,6 @@ package iam import ( "context" - "reflect" "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" @@ -16,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -68,7 +68,7 @@ func dataSourceRolesRead(ctx context.Context, d *schema.ResourceData, meta any) } for _, role := range page.Roles { - if reflect.ValueOf(role).IsZero() { + if p := &role; inttypes.IsZero(p) { continue } @@ -89,13 +89,8 @@ func dataSourceRolesRead(ctx context.Context, d *schema.ResourceData, meta any) nms = append(nms, aws.ToString(r.RoleName)) } - if err := d.Set(names.AttrARNs, arns); err != nil { - return sdkdiag.AppendErrorf(diags, "setting arns: %s", err) - } - - if err := d.Set(names.AttrNames, nms); err != nil { - return sdkdiag.AppendErrorf(diags, "setting names: %s", err) - } + d.Set(names.AttrARNs, arns) + d.Set(names.AttrNames, nms) return diags } diff --git a/internal/service/iam/roles_data_source_test.go b/internal/service/iam/roles_data_source_test.go index 7ebcea71b1ac..fac9055d0602 100644 --- a/internal/service/iam/roles_data_source_test.go +++ b/internal/service/iam/roles_data_source_test.go @@ -143,7 +143,7 @@ resource "aws_iam_role" "test" { { "Action": "sts:AssumeRole", "Principal": { - "Service": data.aws_service_principal.ec2.name + "Service": "${data.aws_service_principal.ec2.name}" }, "Effect": "Allow", "Sid": "" @@ -179,7 +179,7 @@ resource "aws_iam_role" "test" { { "Action": "sts:AssumeRole", "Principal": { - "Service": data.aws_service_principal.ec2.name + "Service": "${data.aws_service_principal.ec2.name}" }, "Effect": "Allow", "Sid": "" @@ -220,7 +220,7 @@ resource "aws_iam_role" "test" { { "Action": "sts:AssumeRole", "Principal": { - "Service": data.aws_service_principal.ec2.name + "Service": "${data.aws_service_principal.ec2.name}" }, "Effect": "Allow", "Sid": "" diff --git a/internal/service/iam/server_certificate.go b/internal/service/iam/server_certificate.go index 25c8bd3ad040..614ee3ca19e6 100644 --- a/internal/service/iam/server_certificate.go +++ b/internal/service/iam/server_certificate.go @@ -23,6 +23,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/sdkv2" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" @@ -56,14 +57,14 @@ func resourceServerCertificate() *schema.Resource { Required: true, ForceNew: true, DiffSuppressFunc: suppressNormalizeCertRemoval, - StateFunc: StateTrimSpace, + StateFunc: sdkv2.TrimSpaceSchemaStateFunc, }, names.AttrCertificateChain: { Type: schema.TypeString, Optional: true, ForceNew: true, DiffSuppressFunc: suppressNormalizeCertRemoval, - StateFunc: StateTrimSpace, + StateFunc: sdkv2.TrimSpaceSchemaStateFunc, }, "expiration": { Type: schema.TypeString, @@ -94,7 +95,7 @@ func resourceServerCertificate() *schema.Resource { ForceNew: true, Sensitive: true, DiffSuppressFunc: suppressNormalizeCertRemoval, - StateFunc: StateTrimSpace, + StateFunc: sdkv2.TrimSpaceSchemaStateFunc, }, names.AttrTags: tftags.TagsSchema(), names.AttrTagsAll: tftags.TagsSchemaComputed(), @@ -111,7 +112,7 @@ func resourceServerCertificateCreate(ctx context.Context, d *schema.ResourceData conn := meta.(*conns.AWSClient).IAMClient(ctx) sslCertName := create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string)) - input := &iam.UploadServerCertificateInput{ + input := iam.UploadServerCertificateInput{ CertificateBody: aws.String(d.Get("certificate_body").(string)), PrivateKey: aws.String(d.Get(names.AttrPrivateKey).(string)), ServerCertificateName: aws.String(sslCertName), @@ -126,14 +127,14 @@ func resourceServerCertificateCreate(ctx context.Context, d *schema.ResourceData input.Path = aws.String(v.(string)) } - output, err := conn.UploadServerCertificate(ctx, input) + output, err := conn.UploadServerCertificate(ctx, &input) // Some partitions (e.g. ISO) may not support tag-on-create. partition := meta.(*conns.AWSClient).Partition(ctx) if input.Tags != nil && errs.IsUnsupportedOperationInPartitionError(partition, err) { input.Tags = nil - output, err = conn.UploadServerCertificate(ctx, input) + output, err = conn.UploadServerCertificate(ctx, &input) } if err != nil { @@ -206,7 +207,7 @@ func resourceServerCertificateUpdate(ctx context.Context, d *schema.ResourceData conn := meta.(*conns.AWSClient).IAMClient(ctx) if d.HasChanges(names.AttrName, names.AttrNamePrefix, names.AttrPath) { - input := &iam.UpdateServerCertificateInput{} + var input iam.UpdateServerCertificateInput if d.HasChange(names.AttrName) { oldName, newName := d.GetChange(names.AttrName) @@ -235,7 +236,7 @@ func resourceServerCertificateUpdate(ctx context.Context, d *schema.ResourceData input.NewPath = aws.String(d.Get(names.AttrPath).(string)) } - _, err := conn.UpdateServerCertificate(ctx, input) + _, err := conn.UpdateServerCertificate(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM Server Certificate (%s): %s", d.Id(), err) @@ -255,10 +256,11 @@ func resourceServerCertificateDelete(ctx context.Context, d *schema.ResourceData conn := meta.(*conns.AWSClient).IAMClient(ctx) log.Printf("[DEBUG] Deleting IAM Server Certificate: %s", d.Id()) + input := iam.DeleteServerCertificateInput{ + ServerCertificateName: aws.String(d.Get(names.AttrName).(string)), + } _, err := tfresource.RetryWhenIsAErrorMessageContains[any, *awstypes.DeleteConflictException](ctx, d.Timeout(schema.TimeoutDelete), func(ctx context.Context) (any, error) { - return conn.DeleteServerCertificate(ctx, &iam.DeleteServerCertificateInput{ - ServerCertificateName: aws.String(d.Get(names.AttrName).(string)), - }) + return conn.DeleteServerCertificate(ctx, &input) }, "currently in use by arn") if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -279,10 +281,14 @@ func resourceServerCertificateImport(ctx context.Context, d *schema.ResourceData } func findServerCertificateByName(ctx context.Context, conn *iam.Client, name string) (*awstypes.ServerCertificate, error) { - input := &iam.GetServerCertificateInput{ + input := iam.GetServerCertificateInput{ ServerCertificateName: aws.String(name), } + return findServerCertificate(ctx, conn, &input) +} + +func findServerCertificate(ctx context.Context, conn *iam.Client, input *iam.GetServerCertificateInput) (*awstypes.ServerCertificate, error) { output, err := conn.GetServerCertificate(ctx, input) if errs.IsA[*awstypes.NoSuchEntityException](err) { diff --git a/internal/service/iam/service_linked_role.go b/internal/service/iam/service_linked_role.go index b25a94ea2a22..072196056e96 100644 --- a/internal/service/iam/service_linked_role.go +++ b/internal/service/iam/service_linked_role.go @@ -93,7 +93,7 @@ func resourceServiceLinkedRoleCreate(ctx context.Context, d *schema.ResourceData conn := meta.(*conns.AWSClient).IAMClient(ctx) serviceName := d.Get("aws_service_name").(string) - input := &iam.CreateServiceLinkedRoleInput{ + input := iam.CreateServiceLinkedRoleInput{ AWSServiceName: aws.String(serviceName), } @@ -106,7 +106,7 @@ func resourceServiceLinkedRoleCreate(ctx context.Context, d *schema.ResourceData } output, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, propagationTimeout, func(ctx context.Context) (*iam.CreateServiceLinkedRoleOutput, error) { - return conn.CreateServiceLinkedRole(ctx, input) + return conn.CreateServiceLinkedRole(ctx, &input) }, "AccessDenied") if err != nil { return sdkdiag.AppendErrorf(diags, "creating IAM Service Linked Role (%s): %s", serviceName, err) @@ -115,8 +115,7 @@ func resourceServiceLinkedRoleCreate(ctx context.Context, d *schema.ResourceData d.SetId(aws.ToString(output.Role.Arn)) if tags := getTagsIn(ctx); len(tags) > 0 { - _, roleName, _, err := DecodeServiceLinkedRoleID(d.Id()) - + _, roleName, _, err := serviceLinkedRoleParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -141,8 +140,7 @@ func resourceServiceLinkedRoleRead(ctx context.Context, d *schema.ResourceData, var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - serviceName, roleName, customSuffix, err := DecodeServiceLinkedRoleID(d.Id()) - + serviceName, roleName, customSuffix, err := serviceLinkedRoleParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -180,17 +178,16 @@ func resourceServiceLinkedRoleUpdate(ctx context.Context, d *schema.ResourceData conn := meta.(*conns.AWSClient).IAMClient(ctx) if d.HasChangesExcept(names.AttrTagsAll, names.AttrTags) { - _, roleName, _, err := DecodeServiceLinkedRoleID(d.Id()) + _, roleName, _, err := serviceLinkedRoleParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } - input := &iam.UpdateRoleInput{ + input := iam.UpdateRoleInput{ Description: aws.String(d.Get(names.AttrDescription).(string)), RoleName: aws.String(roleName), } - - _, err = conn.UpdateRole(ctx, input) + _, err = conn.UpdateRole(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM Service Linked Role (%s): %s", d.Id(), err) @@ -204,8 +201,7 @@ func resourceServiceLinkedRoleDelete(ctx context.Context, d *schema.ResourceData var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - _, roleName, _, err := DecodeServiceLinkedRoleID(d.Id()) - + _, roleName, _, err := serviceLinkedRoleParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -219,11 +215,10 @@ func resourceServiceLinkedRoleDelete(ctx context.Context, d *schema.ResourceData } func deleteServiceLinkedRole(ctx context.Context, conn *iam.Client, roleName string) error { - input := &iam.DeleteServiceLinkedRoleInput{ + input := iam.DeleteServiceLinkedRoleInput{ RoleName: aws.String(roleName), } - - output, err := conn.DeleteServiceLinkedRole(ctx, input) + output, err := conn.DeleteServiceLinkedRole(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { return nil @@ -234,7 +229,6 @@ func deleteServiceLinkedRole(ctx context.Context, conn *iam.Client, roleName str } deletionTaskID := aws.ToString(output.DeletionTaskId) - if deletionTaskID == "" { return nil } @@ -315,26 +309,25 @@ func findServiceLinkedRoleDeletionStatusByID(ctx context.Context, conn *iam.Clie return output, nil } -func DecodeServiceLinkedRoleID(id string) (serviceName, roleName, customSuffix string, err error) { - idArn, err := arn.Parse(id) - +func serviceLinkedRoleParseResourceID(id string) (string, string, string, error) { + arn, err := arn.Parse(id) if err != nil { return "", "", "", err } - resourceParts := strings.Split(idArn.Resource, "/") - + resourceParts := strings.Split(arn.Resource, "/") if len(resourceParts) != 4 { - return "", "", "", fmt.Errorf("expected IAM Service Role ARN (arn:PARTITION:iam::ACCOUNTID:role/aws-service-role/SERVICENAME/ROLENAME), received: %s", id) + return "", "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected IAM Service Role ARN (arn:PARTITION:iam::ACCOUNTID:role/aws-service-role/SERVICENAME/ROLENAME)", id) } - serviceName = resourceParts[2] - roleName = resourceParts[3] + serviceName := resourceParts[2] + roleName := resourceParts[3] + var customSuffix string roleNameParts := strings.Split(roleName, "_") if len(roleNameParts) == 2 { customSuffix = roleNameParts[1] } - return + return serviceName, roleName, customSuffix, nil } diff --git a/internal/service/iam/service_linked_role_test.go b/internal/service/iam/service_linked_role_test.go index fc491c7436d3..76ba8e86e908 100644 --- a/internal/service/iam/service_linked_role_test.go +++ b/internal/service/iam/service_linked_role_test.go @@ -18,7 +18,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func TestDecodeServiceLinkedRoleID(t *testing.T) { +func TestServiceLinkedRoleParseResourceID(t *testing.T) { t.Parallel() var testCases = []struct { @@ -60,7 +60,7 @@ func TestDecodeServiceLinkedRoleID(t *testing.T) { } for _, tc := range testCases { - serviceName, roleName, customSuffix, err := tfiam.DecodeServiceLinkedRoleID(tc.Input) + serviceName, roleName, customSuffix, err := tfiam.ServiceLinkedRoleParseResourceID(tc.Input) if tc.ErrCount == 0 && err != nil { t.Fatalf("expected %q not to trigger an error, received: %s", tc.Input, err) } @@ -259,8 +259,7 @@ func testAccCheckServiceLinkedRoleDestroy(ctx context.Context) resource.TestChec continue } - _, roleName, _, err := tfiam.DecodeServiceLinkedRoleID(rs.Primary.ID) - + _, roleName, _, err := tfiam.ServiceLinkedRoleParseResourceID(rs.Primary.ID) if err != nil { return err } @@ -291,8 +290,7 @@ func testAccCheckServiceLinkedRoleExists(ctx context.Context, n string) resource conn := acctest.Provider.Meta().(*conns.AWSClient).IAMClient(ctx) - _, roleName, _, err := tfiam.DecodeServiceLinkedRoleID(rs.Primary.ID) - + _, roleName, _, err := tfiam.ServiceLinkedRoleParseResourceID(rs.Primary.ID) if err != nil { return err } diff --git a/internal/service/iam/service_specific_credential.go b/internal/service/iam/service_specific_credential.go index 18af7ca3832b..5d84b23c4b3b 100644 --- a/internal/service/iam/service_specific_credential.go +++ b/internal/service/iam/service_specific_credential.go @@ -8,18 +8,22 @@ import ( "fmt" "log" "strings" + "time" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -30,41 +34,65 @@ func resourceServiceSpecificCredential() *schema.Resource { ReadWithoutTimeout: resourceServiceSpecificCredentialRead, UpdateWithoutTimeout: resourceServiceSpecificCredentialUpdate, DeleteWithoutTimeout: resourceServiceSpecificCredentialDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, Schema: map[string]*schema.Schema{ - names.AttrServiceName: { + "create_date": { Type: schema.TypeString, - Required: true, - ForceNew: true, + Computed: true, }, - names.AttrUserName: { - Type: schema.TypeString, - Required: true, + "credential_age_days": { + Type: schema.TypeInt, + Optional: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 64), + ValidateFunc: validation.IntBetween(1, 36600), }, - names.AttrStatus: { - Type: schema.TypeString, - Optional: true, - Default: awstypes.StatusTypeActive, - ValidateDiagFunc: enum.Validate[awstypes.StatusType](), + "expiration_date": { + Type: schema.TypeString, + Computed: true, + }, + "service_credential_alias": { + Type: schema.TypeString, + Computed: true, + }, + "service_credential_secret": { + Type: schema.TypeString, + Sensitive: true, + Computed: true, + }, + names.AttrServiceName: { + Type: schema.TypeString, + Required: true, + ForceNew: true, }, "service_password": { Type: schema.TypeString, Sensitive: true, Computed: true, }, - "service_user_name": { + "service_specific_credential_id": { Type: schema.TypeString, Computed: true, }, - "service_specific_credential_id": { + "service_user_name": { Type: schema.TypeString, Computed: true, }, + names.AttrStatus: { + Type: schema.TypeString, + Optional: true, + Default: awstypes.StatusTypeActive, + ValidateDiagFunc: enum.Validate[awstypes.StatusType](), + }, + names.AttrUserName: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 64), + }, }, } } @@ -73,31 +101,39 @@ func resourceServiceSpecificCredentialCreate(ctx context.Context, d *schema.Reso var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - input := &iam.CreateServiceSpecificCredentialInput{ - ServiceName: aws.String(d.Get(names.AttrServiceName).(string)), - UserName: aws.String(d.Get(names.AttrUserName).(string)), + serviceName, userName := d.Get(names.AttrServiceName).(string), d.Get(names.AttrUserName).(string) + input := iam.CreateServiceSpecificCredentialInput{ + ServiceName: aws.String(serviceName), + UserName: aws.String(userName), } - out, err := conn.CreateServiceSpecificCredential(ctx, input) - if err != nil { - return sdkdiag.AppendErrorf(diags, "creating IAM Service Specific Credential: %s", err) + if v, ok := d.GetOk("credential_age_days"); ok { + input.CredentialAgeDays = aws.Int32(int32(v.(int))) } - cred := out.ServiceSpecificCredential + output, err := conn.CreateServiceSpecificCredential(ctx, &input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "creating IAM Service-Specific Credential: %s", err) + } - d.SetId(fmt.Sprintf("%s:%s:%s", aws.ToString(cred.ServiceName), aws.ToString(cred.UserName), aws.ToString(cred.ServiceSpecificCredentialId))) + cred := output.ServiceSpecificCredential + credID := aws.ToString(cred.ServiceSpecificCredentialId) + d.SetId(serviceSpecificCredentialCreateResourceID(serviceName, userName, credID)) + d.Set("service_credential_secret", cred.ServiceCredentialSecret) d.Set("service_password", cred.ServicePassword) - if v, ok := d.GetOk(names.AttrStatus); ok && v.(string) != string(awstypes.StatusTypeActive) { - updateInput := &iam.UpdateServiceSpecificCredentialInput{ - ServiceSpecificCredentialId: cred.ServiceSpecificCredentialId, - UserName: cred.UserName, + if v, ok := d.GetOk(names.AttrStatus); ok && awstypes.StatusType(v.(string)) != awstypes.StatusTypeActive { + input := iam.UpdateServiceSpecificCredentialInput{ + ServiceSpecificCredentialId: aws.String(credID), Status: awstypes.StatusType(v.(string)), + UserName: aws.String(userName), } - _, err := conn.UpdateServiceSpecificCredential(ctx, updateInput) + _, err := conn.UpdateServiceSpecificCredential(ctx, &input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "settings IAM Service Specific Credential status: %s", err) + return sdkdiag.AppendErrorf(diags, "setting IAM Service-Specific Credential (%s) status: %s", d.Id(), err) } } @@ -108,13 +144,13 @@ func resourceServiceSpecificCredentialRead(ctx context.Context, d *schema.Resour var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - serviceName, userName, credID, err := DecodeServiceSpecificCredentialId(d.Id()) + serviceName, userName, credID, err := serviceSpecificCredentialParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading IAM Service Specific Credential (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } cred, err := tfresource.RetryWhenNewResourceNotFound(ctx, propagationTimeout, func(ctx context.Context) (*awstypes.ServiceSpecificCredentialMetadata, error) { - return FindServiceSpecificCredential(ctx, conn, serviceName, userName, credID) + return findServiceSpecificCredentialByThreePartKey(ctx, conn, serviceName, userName, credID) }, d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { @@ -127,11 +163,16 @@ func resourceServiceSpecificCredentialRead(ctx context.Context, d *schema.Resour return sdkdiag.AppendErrorf(diags, "reading IAM Service Specific Credential (%s): %s", d.Id(), err) } + d.Set("create_date", cred.CreateDate.Format(time.RFC3339)) + if cred.ExpirationDate != nil { + d.Set("expiration_date", cred.ExpirationDate.Format(time.RFC3339)) + } + d.Set("service_credential_alias", cred.ServiceCredentialAlias) + d.Set(names.AttrServiceName, cred.ServiceName) d.Set("service_specific_credential_id", cred.ServiceSpecificCredentialId) d.Set("service_user_name", cred.ServiceUserName) - d.Set(names.AttrServiceName, cred.ServiceName) - d.Set(names.AttrUserName, cred.UserName) d.Set(names.AttrStatus, cred.Status) + d.Set(names.AttrUserName, cred.UserName) return diags } @@ -140,14 +181,20 @@ func resourceServiceSpecificCredentialUpdate(ctx context.Context, d *schema.Reso var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - request := &iam.UpdateServiceSpecificCredentialInput{ - ServiceSpecificCredentialId: aws.String(d.Get("service_specific_credential_id").(string)), - UserName: aws.String(d.Get(names.AttrUserName).(string)), + _, userName, credID, err := serviceSpecificCredentialParseResourceID(d.Id()) + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + + input := iam.UpdateServiceSpecificCredentialInput{ + ServiceSpecificCredentialId: aws.String(credID), Status: awstypes.StatusType(d.Get(names.AttrStatus).(string)), + UserName: aws.String(userName), } - _, err := conn.UpdateServiceSpecificCredential(ctx, request) + _, err = conn.UpdateServiceSpecificCredential(ctx, &input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "updating IAM Service Specific Credential %s: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "updating IAM Service-Specific Credential (%s): %s", d.Id(), err) } return append(diags, resourceServiceSpecificCredentialRead(ctx, d, meta)...) @@ -157,28 +204,96 @@ func resourceServiceSpecificCredentialDelete(ctx context.Context, d *schema.Reso var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - request := &iam.DeleteServiceSpecificCredentialInput{ - ServiceSpecificCredentialId: aws.String(d.Get("service_specific_credential_id").(string)), - UserName: aws.String(d.Get(names.AttrUserName).(string)), + _, userName, credID, err := serviceSpecificCredentialParseResourceID(d.Id()) + if err != nil { + return sdkdiag.AppendFromErr(diags, err) } - if _, err := conn.DeleteServiceSpecificCredential(ctx, request); err != nil { - if errs.IsA[*awstypes.NoSuchEntityException](err) { - return diags - } - return sdkdiag.AppendErrorf(diags, "deleting IAM Service Specific Credential %s: %s", d.Id(), err) + log.Printf("[DEBUG] Deleting IAM Service-Specific Credential: %s", d.Id()) + input := iam.DeleteServiceSpecificCredentialInput{ + ServiceSpecificCredentialId: aws.String(credID), + UserName: aws.String(userName), } + _, err = conn.DeleteServiceSpecificCredential(ctx, &input) + + if errs.IsA[*awstypes.NoSuchEntityException](err) { + return diags + } + + if err != nil { + return sdkdiag.AppendErrorf(diags, "deleting IAM Service-Specific Credential (%s): %s", d.Id(), err) + } + return diags } -func DecodeServiceSpecificCredentialId(id string) (string, string, string, error) { - creds := strings.Split(id, ":") - if len(creds) != 3 { - return "", "", "", fmt.Errorf("unknown IAM Service Specific Credential ID format") +const serviceSpecificCredentialResourceIDSeparator = ":" + +func serviceSpecificCredentialCreateResourceID(serviceName, userName, serviceSpecificCredentialID string) string { + parts := []string{serviceName, userName, serviceSpecificCredentialID} + id := strings.Join(parts, serviceSpecificCredentialResourceIDSeparator) + + return id +} + +func serviceSpecificCredentialParseResourceID(id string) (string, string, string, error) { + parts := strings.SplitN(id, serviceSpecificCredentialResourceIDSeparator, 3) + + if len(parts) != 3 || parts[0] == "" || parts[1] == "" || parts[2] == "" { + return "", "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected SERVICE-NAME%[2]sUSER-NAME%[2]sSERVICE-SPECIFIC-CREDENTIAL-ID", id, serviceSpecificCredentialResourceIDSeparator) + } + + return parts[0], parts[1], parts[2], nil +} + +func findServiceSpecificCredentialByThreePartKey(ctx context.Context, conn *iam.Client, serviceName, userName, serviceSpecificCredentialID string) (*awstypes.ServiceSpecificCredentialMetadata, error) { + input := iam.ListServiceSpecificCredentialsInput{ + ServiceName: aws.String(serviceName), + UserName: aws.String(userName), + } + + return findServiceSpecificCredential(ctx, conn, &input, func(v *awstypes.ServiceSpecificCredentialMetadata) bool { + return aws.ToString(v.ServiceSpecificCredentialId) == serviceSpecificCredentialID + }) +} + +func findServiceSpecificCredential(ctx context.Context, conn *iam.Client, input *iam.ListServiceSpecificCredentialsInput, filter tfslices.Predicate[*awstypes.ServiceSpecificCredentialMetadata]) (*awstypes.ServiceSpecificCredentialMetadata, error) { + output, err := findServiceSpecificCredentials(ctx, conn, input, filter) + + if err != nil { + return nil, err + } + + return tfresource.AssertSingleValueResult(output) +} + +func findServiceSpecificCredentials(ctx context.Context, conn *iam.Client, input *iam.ListServiceSpecificCredentialsInput, filter tfslices.Predicate[*awstypes.ServiceSpecificCredentialMetadata]) ([]awstypes.ServiceSpecificCredentialMetadata, error) { + var output []awstypes.ServiceSpecificCredentialMetadata + + err := listServiceSpecificCredentialsPages(ctx, conn, input, func(page *iam.ListServiceSpecificCredentialsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.ServiceSpecificCredentials { + if p := &v; !inttypes.IsZero(p) && filter(p) { + output = append(output, v) + } + } + + return !lastPage + }) + + if errs.IsA[*awstypes.NoSuchEntityException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err } - serviceName := creds[0] - userName := creds[1] - credId := creds[2] - return serviceName, userName, credId, nil + return output, nil } diff --git a/internal/service/iam/service_specific_credential_test.go b/internal/service/iam/service_specific_credential_test.go index bdc45e3948ce..42c476db1d6f 100644 --- a/internal/service/iam/service_specific_credential_test.go +++ b/internal/service/iam/service_specific_credential_test.go @@ -47,7 +47,7 @@ func TestAccIAMServiceSpecificCredential_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_password"}, + ImportStateVerifyIgnore: []string{"service_password", "service_credential_secret"}, }, }, }) @@ -87,7 +87,7 @@ func TestAccIAMServiceSpecificCredential_multi(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_password"}, + ImportStateVerifyIgnore: []string{"service_password", "service_credential_secret"}, }, }, }) @@ -117,7 +117,7 @@ func TestAccIAMServiceSpecificCredential_status(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_password"}, + ImportStateVerifyIgnore: []string{"service_password", "service_credential_secret"}, }, { Config: testAccServiceSpecificCredentialConfig_status(rName, "Active"), @@ -163,29 +163,22 @@ func TestAccIAMServiceSpecificCredential_disappears(t *testing.T) { }) } -func testAccCheckServiceSpecificCredentialExists(ctx context.Context, n string, cred *awstypes.ServiceSpecificCredentialMetadata) resource.TestCheckFunc { +func testAccCheckServiceSpecificCredentialExists(ctx context.Context, n string, v *awstypes.ServiceSpecificCredentialMetadata) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Server Cert ID is set") - } conn := acctest.Provider.Meta().(*conns.AWSClient).IAMClient(ctx) - serviceName, userName, credId, err := tfiam.DecodeServiceSpecificCredentialId(rs.Primary.ID) - if err != nil { - return err - } + output, err := tfiam.FindServiceSpecificCredentialByThreePartKey(ctx, conn, rs.Primary.Attributes[names.AttrServiceName], rs.Primary.Attributes[names.AttrUserName], rs.Primary.Attributes["service_specific_credential_id"]) - output, err := tfiam.FindServiceSpecificCredential(ctx, conn, serviceName, userName, credId) if err != nil { return err } - *cred = *output + *v = *output return nil } @@ -200,19 +193,14 @@ func testAccCheckServiceSpecificCredentialDestroy(ctx context.Context) resource. continue } - serviceName, userName, credId, err := tfiam.DecodeServiceSpecificCredentialId(rs.Primary.ID) - if err != nil { - return err - } - - output, err := tfiam.FindServiceSpecificCredential(ctx, conn, serviceName, userName, credId) + output, err := tfiam.FindServiceSpecificCredentialByThreePartKey(ctx, conn, rs.Primary.Attributes[names.AttrServiceName], rs.Primary.Attributes[names.AttrUserName], rs.Primary.Attributes["service_specific_credential_id"]) if tfresource.NotFound(err) { continue } if output != nil { - return fmt.Errorf("IAM Service Specific Credential (%s) still exists", rs.Primary.ID) + return fmt.Errorf("IAM Service-Specific Credential (%s) still exists", rs.Primary.ID) } } @@ -264,3 +252,54 @@ resource "aws_iam_service_specific_credential" "test" { } `, rName, status) } + +func TestAccIAMServiceSpecificCredential_bedrockWithExpiration(t *testing.T) { + ctx := acctest.Context(t) + var cred awstypes.ServiceSpecificCredentialMetadata + + resourceName := "aws_iam_service_specific_credential.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.IAMServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckServiceSpecificCredentialDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccServiceSpecificCredentialConfig_bedrockWithExpiration(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckServiceSpecificCredentialExists(ctx, resourceName, &cred), + resource.TestCheckResourceAttrPair(resourceName, names.AttrUserName, "aws_iam_user.test", names.AttrName), + resource.TestCheckResourceAttr(resourceName, names.AttrServiceName, "bedrock.amazonaws.com"), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "Active"), + resource.TestCheckResourceAttr(resourceName, "credential_age_days", "30"), + resource.TestCheckResourceAttrSet(resourceName, "service_credential_alias"), + resource.TestCheckResourceAttrSet(resourceName, "service_specific_credential_id"), + resource.TestCheckResourceAttrSet(resourceName, "create_date"), + resource.TestCheckResourceAttrSet(resourceName, "expiration_date"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_password", "service_credential_secret", "credential_age_days"}, + }, + }, + }) +} + +func testAccServiceSpecificCredentialConfig_bedrockWithExpiration(rName string) string { + return fmt.Sprintf(` +resource "aws_iam_user" "test" { + name = %[1]q +} + +resource "aws_iam_service_specific_credential" "test" { + service_name = "bedrock.amazonaws.com" + user_name = aws_iam_user.test.name + credential_age_days = 30 +} +`, rName) +} diff --git a/internal/service/iam/session_context_data_source.go b/internal/service/iam/session_context_data_source.go index ad34b716e37e..e343c8b06e05 100644 --- a/internal/service/iam/session_context_data_source.go +++ b/internal/service/iam/session_context_data_source.go @@ -61,7 +61,7 @@ func dataSourceSessionContextRead(ctx context.Context, d *schema.ResourceData, m var roleName, sessionName string var err error - if roleName, sessionName = RoleNameSessionFromARN(arn); roleName == "" { + if roleName, sessionName = roleNameSessionFromARN(arn); roleName == "" { d.Set("issuer_arn", arn) d.Set("issuer_id", "") d.Set("issuer_name", "") @@ -104,9 +104,9 @@ func dataSourceSessionContextRead(ctx context.Context, d *schema.ResourceData, m return diags } -// RoleNameSessionFromARN returns the role and session names in an ARN if any. +// roleNameSessionFromARN returns the role and session names in an ARN if any. // Otherwise, it returns empty strings. -func RoleNameSessionFromARN(rawARN string) (string, string) { +func roleNameSessionFromARN(rawARN string) (string, string) { parsedARN, err := arn.Parse(rawARN) if err != nil { diff --git a/internal/service/iam/signing_certificate.go b/internal/service/iam/signing_certificate.go index afb6ad2eff60..30bb094e32b1 100644 --- a/internal/service/iam/signing_certificate.go +++ b/internal/service/iam/signing_certificate.go @@ -3,8 +3,7 @@ package iam -import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports - +import ( "context" "fmt" "log" @@ -14,12 +13,15 @@ import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports "github.com/aws/aws-sdk-go-v2/service/iam" awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -30,6 +32,7 @@ func resourceSigningCertificate() *schema.Resource { ReadWithoutTimeout: resourceSigningCertificateRead, UpdateWithoutTimeout: resourceSigningCertificateUpdate, DeleteWithoutTimeout: resourceSigningCertificateDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -64,30 +67,33 @@ func resourceSigningCertificateCreate(ctx context.Context, d *schema.ResourceDat var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - createOpts := &iam.UploadSigningCertificateInput{ + userName := d.Get(names.AttrUserName).(string) + input := iam.UploadSigningCertificateInput{ CertificateBody: aws.String(d.Get("certificate_body").(string)), - UserName: aws.String(d.Get(names.AttrUserName).(string)), + UserName: aws.String(userName), } - resp, err := conn.UploadSigningCertificate(ctx, createOpts) + output, err := conn.UploadSigningCertificate(ctx, &input) + if err != nil { return sdkdiag.AppendErrorf(diags, "uploading IAM Signing Certificate: %s", err) } - cert := resp.Certificate - certId := cert.CertificateId - d.SetId(fmt.Sprintf("%s:%s", aws.ToString(certId), aws.ToString(cert.UserName))) + cert := output.Certificate + certID := aws.ToString(cert.CertificateId) + d.SetId(signingCertificateCreateResourceID(certID, userName)) if v, ok := d.GetOk(names.AttrStatus); ok && v.(string) != string(awstypes.StatusTypeActive) { - updateInput := &iam.UpdateSigningCertificateInput{ - CertificateId: certId, - UserName: aws.String(d.Get(names.AttrUserName).(string)), + input := iam.UpdateSigningCertificateInput{ + CertificateId: aws.String(certID), Status: awstypes.StatusType(v.(string)), + UserName: aws.String(userName), } - _, err := conn.UpdateSigningCertificate(ctx, updateInput) + _, err := conn.UpdateSigningCertificate(ctx, &input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "settings IAM Signing Certificate status: %s", err) + return sdkdiag.AppendErrorf(diags, "settings IAM Signing Certificate (%s) status: %s", d.Id(), err) } } @@ -98,13 +104,13 @@ func resourceSigningCertificateRead(ctx context.Context, d *schema.ResourceData, var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - certId, userName, err := DecodeSigningCertificateId(d.Id()) + certID, userName, err := signingCertificateParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading IAM Signing Certificate (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } output, err := tfresource.RetryWhenNewResourceNotFound(ctx, propagationTimeout, func(ctx context.Context) (*awstypes.SigningCertificate, error) { - return FindSigningCertificate(ctx, conn, userName, certId) + return findSigningCertificateByTwoPartKey(ctx, conn, userName, certID) }, d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { @@ -119,8 +125,8 @@ func resourceSigningCertificateRead(ctx context.Context, d *schema.ResourceData, d.Set("certificate_body", output.CertificateBody) d.Set("certificate_id", output.CertificateId) - d.Set(names.AttrUserName, output.UserName) d.Set(names.AttrStatus, output.Status) + d.Set(names.AttrUserName, output.UserName) return diags } @@ -129,18 +135,18 @@ func resourceSigningCertificateUpdate(ctx context.Context, d *schema.ResourceDat var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - certId, userName, err := DecodeSigningCertificateId(d.Id()) + certID, userName, err := signingCertificateParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "updating IAM Signing Certificate (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } - updateInput := &iam.UpdateSigningCertificateInput{ - CertificateId: aws.String(certId), - UserName: aws.String(userName), + input := iam.UpdateSigningCertificateInput{ + CertificateId: aws.String(certID), Status: awstypes.StatusType(d.Get(names.AttrStatus).(string)), + UserName: aws.String(userName), } + _, err = conn.UpdateSigningCertificate(ctx, &input) - _, err = conn.UpdateSigningCertificate(ctx, updateInput) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM Signing Certificate (%s): %s", d.Id(), err) } @@ -151,36 +157,93 @@ func resourceSigningCertificateUpdate(ctx context.Context, d *schema.ResourceDat func resourceSigningCertificateDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - log.Printf("[INFO] Deleting IAM Signing Certificate: %s", d.Id()) - certId, userName, err := DecodeSigningCertificateId(d.Id()) + certID, userName, err := signingCertificateParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting IAM Signing Certificate (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } - input := &iam.DeleteSigningCertificateInput{ - CertificateId: aws.String(certId), + log.Printf("[INFO] Deleting IAM Signing Certificate: %s", d.Id()) + input := iam.DeleteSigningCertificateInput{ + CertificateId: aws.String(certID), UserName: aws.String(userName), } + _, err = conn.DeleteSigningCertificate(ctx, &input) - if _, err := conn.DeleteSigningCertificate(ctx, input); err != nil { - if errs.IsA[*awstypes.NoSuchEntityException](err) { - return diags - } + if errs.IsA[*awstypes.NoSuchEntityException](err) { + return diags + } + + if err != nil { return sdkdiag.AppendErrorf(diags, "deleting IAM Signing Certificate (%s): %s", d.Id(), err) } return diags } -func DecodeSigningCertificateId(id string) (string, string, error) { - creds := strings.Split(id, ":") - if len(creds) != 2 { - return "", "", fmt.Errorf("unknown IAM Signing Certificate ID format") +const signingCertificateResourceIDSeparator = ":" + +func signingCertificateCreateResourceID(certificateID, userName string) string { + parts := []string{certificateID, userName} + id := strings.Join(parts, signingCertificateResourceIDSeparator) + + return id +} + +func signingCertificateParseResourceID(id string) (string, string, error) { + parts := strings.SplitN(id, signingCertificateResourceIDSeparator, 2) + + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected CERTIFICATE-ID%[2]sUSER-NAME", id, signingCertificateResourceIDSeparator) + } + + return parts[0], parts[1], nil +} + +func findSigningCertificateByTwoPartKey(ctx context.Context, conn *iam.Client, userName, certID string) (*awstypes.SigningCertificate, error) { + input := &iam.ListSigningCertificatesInput{ + UserName: aws.String(userName), + } + + return findSigningCertificate(ctx, conn, input, func(v *awstypes.SigningCertificate) bool { + return aws.ToString(v.CertificateId) == certID + }) +} + +func findSigningCertificate(ctx context.Context, conn *iam.Client, input *iam.ListSigningCertificatesInput, filter tfslices.Predicate[*awstypes.SigningCertificate]) (*awstypes.SigningCertificate, error) { + output, err := findSigningCertificates(ctx, conn, input, filter) + + if err != nil { + return nil, err } - certId := creds[0] - userName := creds[1] + return tfresource.AssertSingleValueResult(output) +} + +func findSigningCertificates(ctx context.Context, conn *iam.Client, input *iam.ListSigningCertificatesInput, filter tfslices.Predicate[*awstypes.SigningCertificate]) ([]awstypes.SigningCertificate, error) { + var output []awstypes.SigningCertificate + + pages := iam.NewListSigningCertificatesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if errs.IsA[*awstypes.NoSuchEntityException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + for _, v := range page.Certificates { + if p := &v; !inttypes.IsZero(p) && filter(p) { + output = append(output, v) + } + } + } - return certId, userName, nil + return output, nil } diff --git a/internal/service/iam/signing_certificate_test.go b/internal/service/iam/signing_certificate_test.go index 07933e4d6069..a1b0d6fd3e6b 100644 --- a/internal/service/iam/signing_certificate_test.go +++ b/internal/service/iam/signing_certificate_test.go @@ -126,29 +126,22 @@ func TestAccIAMSigningCertificate_disappears(t *testing.T) { }) } -func testAccCheckSigningCertificateExists(ctx context.Context, n string, cred *awstypes.SigningCertificate) resource.TestCheckFunc { +func testAccCheckSigningCertificateExists(ctx context.Context, n string, v *awstypes.SigningCertificate) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Server Cert ID is set") - } conn := acctest.Provider.Meta().(*conns.AWSClient).IAMClient(ctx) - certId, userName, err := tfiam.DecodeSigningCertificateId(rs.Primary.ID) - if err != nil { - return err - } + output, err := tfiam.FindSigningCertificateByTwoPartKey(ctx, conn, rs.Primary.Attributes[names.AttrUserName], rs.Primary.Attributes["certificate_id"]) - output, err := tfiam.FindSigningCertificate(ctx, conn, userName, certId) if err != nil { return err } - *cred = *output + *v = *output return nil } @@ -163,19 +156,14 @@ func testAccCheckSigningCertificateDestroy(ctx context.Context) resource.TestChe continue } - certId, userName, err := tfiam.DecodeSigningCertificateId(rs.Primary.ID) - if err != nil { - return err - } - - output, err := tfiam.FindSigningCertificate(ctx, conn, userName, certId) + output, err := tfiam.FindSigningCertificateByTwoPartKey(ctx, conn, rs.Primary.Attributes[names.AttrUserName], rs.Primary.Attributes["certificate_id"]) if tfresource.NotFound(err) { continue } if output != nil { - return fmt.Errorf("IAM Service Specific Credential (%s) still exists", rs.Primary.ID) + return fmt.Errorf("IAM Signing Certificate (%s) still exists", rs.Primary.ID) } } diff --git a/internal/service/iam/state_funcs.go b/internal/service/iam/state_funcs.go deleted file mode 100644 index 568eaef0b4e2..000000000000 --- a/internal/service/iam/state_funcs.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package iam - -import ( - "strings" -) // StateTrimSpace is a StateFunc that trims extraneous whitespace from strings. -// This prevents differences caused by an API canonicalizing a string with a -// trailing newline character removed. -func StateTrimSpace(v any) string { - s, ok := v.(string) - - if !ok { - return "" - } - - return strings.TrimSpace(s) -} diff --git a/internal/service/iam/sweep.go b/internal/service/iam/sweep.go index 16622a6c92cd..fbbb1edc57d3 100644 --- a/internal/service/iam/sweep.go +++ b/internal/service/iam/sweep.go @@ -65,6 +65,7 @@ func RegisterSweepers() { "aws_config_configuration_aggregator", "aws_config_configuration_recorder", "aws_datasync_location", + "aws_datazone_domain", "aws_dax_cluster", "aws_db_instance", "aws_db_option_group", @@ -87,10 +88,8 @@ func RegisterSweepers() { F: sweepRoles, }) - awsv2.Register("aws_iam_saml_provider", sweepSAMLProvider) - + awsv2.Register("aws_iam_saml_provider", sweepSAMLProviders) awsv2.Register("aws_iam_service_specific_credential", sweepServiceSpecificCredentials) - awsv2.Register("aws_iam_signing_certificate", sweepSigningCertificates) resource.AddTestSweepers("aws_iam_server_certificate", &resource.Sweeper{ @@ -292,7 +291,8 @@ func sweepOpenIDConnectProvider(ctx context.Context, client *conns.AWSClient) ([ func sweepServiceSpecificCredentials(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { conn := client.IAMClient(ctx) - + var input iam.ListUsersInput + var users []awstypes.User prefixes := []string{ "test-user", "test_user", @@ -300,48 +300,55 @@ func sweepServiceSpecificCredentials(ctx context.Context, client *conns.AWSClien "tf_acc", } - var users []awstypes.User - - pages := iam.NewListUsersPaginator(conn, &iam.ListUsersInput{}) + pages := iam.NewListUsersPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) + if err != nil { return nil, err } - for _, user := range page.Users { + for _, v := range page.Users { for _, prefix := range prefixes { - if strings.HasPrefix(aws.ToString(user.UserName), prefix) { - users = append(users, user) + if strings.HasPrefix(aws.ToString(v.UserName), prefix) { + users = append(users, v) break } } } } - var sweepResources []sweep.Sweepable + sweepResources := make([]sweep.Sweepable, 0) for _, user := range users { - out, err := conn.ListServiceSpecificCredentials(ctx, &iam.ListServiceSpecificCredentialsInput{ - UserName: user.UserName, + userName := aws.ToString(user.UserName) + input := iam.ListServiceSpecificCredentialsInput{ + UserName: aws.String(userName), + } + + err := listServiceSpecificCredentialsPages(ctx, conn, &input, func(page *iam.ListServiceSpecificCredentialsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.ServiceSpecificCredentials { + r := resourceServiceSpecificCredential() + d := r.Data(nil) + d.SetId(serviceSpecificCredentialCreateResourceID(aws.ToString(v.ServiceName), aws.ToString(v.UserName), aws.ToString(v.ServiceSpecificCredentialId))) + + sweepResources = append(sweepResources, sdk.NewSweepResource(r, d, client)) + } + + return !lastPage }) + if err != nil { tflog.Warn(ctx, "Skipping resource", map[string]any{ "error": err.Error(), - names.AttrUserName: user.UserName, + names.AttrUserName: userName, }) continue } - - for _, cred := range out.ServiceSpecificCredentials { - id := fmt.Sprintf("%s:%s:%s", aws.ToString(cred.ServiceName), aws.ToString(cred.UserName), aws.ToString(cred.ServiceSpecificCredentialId)) - - r := resourceServiceSpecificCredential() - d := r.Data(nil) - d.SetId(id) - - sweepResources = append(sweepResources, sdk.NewSweepResource(r, d, client)) - } } return sweepResources, nil @@ -479,7 +486,7 @@ func sweepRoles(region string) error { return sweeperErrs.ErrorOrNil() } -func sweepSAMLProvider(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { +func sweepSAMLProviders(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { conn := client.IAMClient(ctx) var sweepResources []sweep.Sweepable @@ -746,7 +753,8 @@ func sweepVirtualMFADevice(ctx context.Context, client *conns.AWSClient) ([]swee func sweepSigningCertificates(ctx context.Context, client *conns.AWSClient) ([]sweep.Sweepable, error) { conn := client.IAMClient(ctx) - + var input iam.ListUsersInput + var users []awstypes.User prefixes := []string{ "test-user", "test_user", @@ -754,47 +762,51 @@ func sweepSigningCertificates(ctx context.Context, client *conns.AWSClient) ([]s "tf_acc", } - var users []awstypes.User - - pages := iam.NewListUsersPaginator(conn, &iam.ListUsersInput{}) + pages := iam.NewListUsersPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) + if err != nil { return nil, err } - for _, user := range page.Users { + for _, v := range page.Users { for _, prefix := range prefixes { - if strings.HasPrefix(aws.ToString(user.UserName), prefix) { - users = append(users, user) + if strings.HasPrefix(aws.ToString(v.UserName), prefix) { + users = append(users, v) break } } } } - var sweepResources []sweep.Sweepable + sweepResources := make([]sweep.Sweepable, 0) for _, user := range users { - out, err := conn.ListSigningCertificates(ctx, &iam.ListSigningCertificatesInput{ - UserName: user.UserName, - }) - if err != nil { - tflog.Warn(ctx, "Skipping resource", map[string]any{ - "error": err.Error(), - names.AttrUserName: user.UserName, - }) - continue + userName := aws.ToString(user.UserName) + input := iam.ListSigningCertificatesInput{ + UserName: aws.String(userName), } - for _, cert := range out.Certificates { - id := fmt.Sprintf("%s:%s", aws.ToString(cert.CertificateId), aws.ToString(cert.UserName)) + pages := iam.NewListSigningCertificatesPaginator(conn, &input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) - r := resourceSigningCertificate() - d := r.Data(nil) - d.SetId(id) + if err != nil { + tflog.Warn(ctx, "Skipping resource", map[string]any{ + "error": err.Error(), + names.AttrUserName: userName, + }) + continue + } - sweepResources = append(sweepResources, sdk.NewSweepResource(r, d, client)) + for _, v := range page.Certificates { + r := resourceSigningCertificate() + d := r.Data(nil) + d.SetId(signingCertificateCreateResourceID(aws.ToString(v.CertificateId), aws.ToString(v.UserName))) + + sweepResources = append(sweepResources, sdk.NewSweepResource(r, d, client)) + } } } diff --git a/internal/service/iam/tags.go b/internal/service/iam/tags.go index 3b92c631f278..52f7c45837c2 100644 --- a/internal/service/iam/tags.go +++ b/internal/service/iam/tags.go @@ -451,7 +451,7 @@ func updateTags(ctx context.Context, conn *iam.Client, identifier, resourceType case "Role": return roleUpdateTags(ctx, conn, identifier, oldTagsMap, newTagsMap) case "ServiceLinkedRole": - _, roleName, _, err := DecodeServiceLinkedRoleID(identifier) + _, roleName, _, err := serviceLinkedRoleParseResourceID(identifier) if err != nil { return err } @@ -494,7 +494,7 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier, res case "ServiceLinkedRole": var roleName string - _, roleName, _, err = DecodeServiceLinkedRoleID(identifier) + _, roleName, _, err = serviceLinkedRoleParseResourceID(identifier) if err != nil { return err } diff --git a/internal/service/iam/user.go b/internal/service/iam/user.go index d8c42a5c55f7..b2a83114f40a 100644 --- a/internal/service/iam/user.go +++ b/internal/service/iam/user.go @@ -93,7 +93,7 @@ func resourceUserCreate(ctx context.Context, d *schema.ResourceData, meta any) d name := d.Get(names.AttrName).(string) path := d.Get(names.AttrPath).(string) - input := &iam.CreateUserInput{ + input := iam.CreateUserInput{ Path: aws.String(path), Tags: getTagsIn(ctx), UserName: aws.String(name), @@ -103,14 +103,14 @@ func resourceUserCreate(ctx context.Context, d *schema.ResourceData, meta any) d input.PermissionsBoundary = aws.String(v.(string)) } - output, err := retryCreateUser(ctx, conn, input) + output, err := retryCreateUser(ctx, conn, &input) // Some partitions (e.g. ISO) may not support tag-on-create. partition := meta.(*conns.AWSClient).Partition(ctx) if input.Tags != nil && errs.IsUnsupportedOperationInPartitionError(partition, err) { input.Tags = nil - output, err = retryCreateUser(ctx, conn, input) + output, err = retryCreateUser(ctx, conn, &input) } if err != nil { @@ -175,13 +175,13 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta any) d if d.HasChanges(names.AttrName, names.AttrPath) { o, n := d.GetChange(names.AttrName) - input := &iam.UpdateUserInput{ - UserName: aws.String(o.(string)), + input := iam.UpdateUserInput{ NewUserName: aws.String(n.(string)), NewPath: aws.String(d.Get(names.AttrPath).(string)), + UserName: aws.String(o.(string)), } - _, err := conn.UpdateUser(ctx, input) + _, err := conn.UpdateUser(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating IAM User (%s): %s", d.Id(), err) @@ -192,21 +192,21 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta any) d if d.HasChange("permissions_boundary") { if v, ok := d.GetOk("permissions_boundary"); ok { - input := &iam.PutUserPermissionsBoundaryInput{ + input := iam.PutUserPermissionsBoundaryInput{ PermissionsBoundary: aws.String(v.(string)), UserName: aws.String(d.Id()), } - _, err := conn.PutUserPermissionsBoundary(ctx, input) + _, err := conn.PutUserPermissionsBoundary(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "setting IAM User (%s) permissions boundary: %s", d.Id(), err) } } else { - input := &iam.DeleteUserPermissionsBoundaryInput{ + input := iam.DeleteUserPermissionsBoundaryInput{ UserName: aws.String(d.Id()), } - _, err := conn.DeleteUserPermissionsBoundary(ctx, input) + _, err := conn.DeleteUserPermissionsBoundary(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "deleting IAM User (%s) permissions boundary: %s", d.Id(), err) @@ -253,9 +253,10 @@ func resourceUserDelete(ctx context.Context, d *schema.ResourceData, meta any) d } log.Println("[DEBUG] Deleting IAM User:", d.Id()) - _, err := conn.DeleteUser(ctx, &iam.DeleteUserInput{ + input := iam.DeleteUserInput{ UserName: aws.String(d.Id()), - }) + } + _, err := conn.DeleteUser(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { return diags @@ -269,10 +270,14 @@ func resourceUserDelete(ctx context.Context, d *schema.ResourceData, meta any) d } func findUserByName(ctx context.Context, conn *iam.Client, name string) (*awstypes.User, error) { - input := &iam.GetUserInput{ + input := iam.GetUserInput{ UserName: aws.String(name), } + return findUser(ctx, conn, &input) +} + +func findUser(ctx context.Context, conn *iam.Client, input *iam.GetUserInput) (*awstypes.User, error) { output, err := conn.GetUser(ctx, input) if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -281,6 +286,7 @@ func findUserByName(ctx context.Context, conn *iam.Client, name string) (*awstyp LastRequest: input, } } + if err != nil { return nil, err } @@ -293,12 +299,12 @@ func findUserByName(ctx context.Context, conn *iam.Client, name string) (*awstyp } func deleteUserGroupMemberships(ctx context.Context, conn *iam.Client, user string) error { - input := &iam.ListGroupsForUserInput{ + input := iam.ListGroupsForUserInput{ UserName: aws.String(user), } var groupNames []string - pages := iam.NewListGroupsForUserPaginator(conn, input) + pages := iam.NewListGroupsForUserPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if err != nil { @@ -321,118 +327,124 @@ func deleteUserGroupMemberships(ctx context.Context, conn *iam.Client, user stri return nil } -func deleteUserSSHKeys(ctx context.Context, conn *iam.Client, username string) error { - var publicKeys []string - - listSSHPublicKeys := &iam.ListSSHPublicKeysInput{ - UserName: aws.String(username), +func deleteUserSSHKeys(ctx context.Context, conn *iam.Client, user string) error { + input := iam.ListSSHPublicKeysInput{ + UserName: aws.String(user), } + var ids []string - pages := iam.NewListSSHPublicKeysPaginator(conn, listSSHPublicKeys) + pages := iam.NewListSSHPublicKeysPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if err != nil { - return fmt.Errorf("removing public SSH keys of user %s: %w", username, err) + return fmt.Errorf("listing IAM User (%s) SSH public keys: %w", user, err) } - for _, k := range page.SSHPublicKeys { - publicKeys = append(publicKeys, *k.SSHPublicKeyId) + for _, v := range page.SSHPublicKeys { + ids = append(ids, aws.ToString(v.SSHPublicKeyId)) } } - for _, k := range publicKeys { - _, err := conn.DeleteSSHPublicKey(ctx, &iam.DeleteSSHPublicKeyInput{ - UserName: aws.String(username), - SSHPublicKeyId: aws.String(k), - }) + for _, v := range ids { + input := iam.DeleteSSHPublicKeyInput{ + SSHPublicKeyId: aws.String(v), + UserName: aws.String(user), + } + _, err := conn.DeleteSSHPublicKey(ctx, &input) + if err != nil { - return fmt.Errorf("deleting public SSH key %s: %w", k, err) + return fmt.Errorf("deleting IAM User (%s) SSH public key (%s): %w", user, v, err) } } return nil } -func deleteUserVirtualMFADevices(ctx context.Context, conn *iam.Client, username string) error { - var VirtualMFADevices []string - - listVirtualMFADevices := &iam.ListVirtualMFADevicesInput{ - AssignmentStatus: awstypes.AssignmentStatusType("Assigned"), +func deleteUserVirtualMFADevices(ctx context.Context, conn *iam.Client, user string) error { + input := iam.ListVirtualMFADevicesInput{ + AssignmentStatus: awstypes.AssignmentStatusTypeAssigned, } + var virtualMFADevices []string - pages := iam.NewListVirtualMFADevicesPaginator(conn, listVirtualMFADevices) + pages := iam.NewListVirtualMFADevicesPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if err != nil { - return fmt.Errorf("removing Virtual MFA devices of user %s: %w", username, err) + return fmt.Errorf("listing IAM Virtual MFA Devices: %w", err) } - for _, m := range page.VirtualMFADevices { + for _, v := range page.VirtualMFADevices { // UserName is `nil` for the root user - if aws.ToString(m.User.UserName) == username { - VirtualMFADevices = append(VirtualMFADevices, *m.SerialNumber) + if aws.ToString(v.User.UserName) == user { + virtualMFADevices = append(virtualMFADevices, aws.ToString(v.SerialNumber)) } } } - for _, m := range VirtualMFADevices { - _, err := conn.DeactivateMFADevice(ctx, &iam.DeactivateMFADeviceInput{ - UserName: aws.String(username), - SerialNumber: aws.String(m), - }) + for _, v := range virtualMFADevices { + inputDeactivate := iam.DeactivateMFADeviceInput{ + SerialNumber: aws.String(v), + UserName: aws.String(user), + } + _, err := conn.DeactivateMFADevice(ctx, &inputDeactivate) + if err != nil { - return fmt.Errorf("deactivating Virtual MFA device %s: %w", m, err) + return fmt.Errorf("deactivating IAM User (%s) virtual MFA device (%s): %w", user, v, err) + } + + inputDelete := iam.DeleteVirtualMFADeviceInput{ + SerialNumber: aws.String(v), } - _, err = conn.DeleteVirtualMFADevice(ctx, &iam.DeleteVirtualMFADeviceInput{ - SerialNumber: aws.String(m), - }) + _, err = conn.DeleteVirtualMFADevice(ctx, &inputDelete) + if err != nil { - return fmt.Errorf("deleting Virtual MFA device %s: %w", m, err) + return fmt.Errorf("deleting IAM Virtual MFA Device (%s): %w", v, err) } } return nil } -func deactivateUserMFADevices(ctx context.Context, conn *iam.Client, username string) error { - var MFADevices []string - - listMFADevices := &iam.ListMFADevicesInput{ - UserName: aws.String(username), +func deactivateUserMFADevices(ctx context.Context, conn *iam.Client, user string) error { + input := iam.ListMFADevicesInput{ + UserName: aws.String(user), } + var mfaDevices []string - pages := iam.NewListMFADevicesPaginator(conn, listMFADevices) + pages := iam.NewListMFADevicesPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if err != nil { - return fmt.Errorf("removing MFA devices of user %s: %w", username, err) + return fmt.Errorf("listing IAM User (%s) MFA devices: %w", user, err) } for _, v := range page.MFADevices { - MFADevices = append(MFADevices, *v.SerialNumber) + mfaDevices = append(mfaDevices, aws.ToString(v.SerialNumber)) } } - for _, m := range MFADevices { - _, err := conn.DeactivateMFADevice(ctx, &iam.DeactivateMFADeviceInput{ - UserName: aws.String(username), - SerialNumber: aws.String(m), - }) + for _, v := range mfaDevices { + input := iam.DeactivateMFADeviceInput{ + SerialNumber: aws.String(v), + UserName: aws.String(user), + } + _, err := conn.DeactivateMFADevice(ctx, &input) + if err != nil { - return fmt.Errorf("deactivating MFA device %s: %w", m, err) + return fmt.Errorf("deactivating IAM User (%s) MFA device (%s): %w", user, v, err) } } return nil } -func deleteUserLoginProfile(ctx context.Context, conn *iam.Client, username string) error { - var err error - input := &iam.DeleteLoginProfileInput{ - UserName: aws.String(username), +func deleteUserLoginProfile(ctx context.Context, conn *iam.Client, user string) error { + input := iam.DeleteLoginProfileInput{ + UserName: aws.String(user), } - err = tfresource.Retry(ctx, propagationTimeout, func(ctx context.Context) *tfresource.RetryError { - _, err = conn.DeleteLoginProfile(ctx, input) + + err := tfresource.Retry(ctx, propagationTimeout, func(ctx context.Context) *tfresource.RetryError { + _, err := conn.DeleteLoginProfile(ctx, &input) if err != nil { var errNoSuchEntityException *awstypes.NoSuchEntityException if tfawserr.ErrCodeEquals(err, errNoSuchEntityException.ErrorCode()) { @@ -449,144 +461,159 @@ func deleteUserLoginProfile(ctx context.Context, conn *iam.Client, username stri }) if err != nil { - return fmt.Errorf("deleting Account Login Profile: %w", err) + return fmt.Errorf("deleting IAM User (%s) login profile: %w", user, err) } return nil } -func deleteUserAccessKeys(ctx context.Context, conn *iam.Client, username string) error { - accessKeys, err := findAccessKeysByUser(ctx, conn, username) +func deleteUserAccessKeys(ctx context.Context, conn *iam.Client, user string) error { + accessKeys, err := findAccessKeysByUser(ctx, conn, user) if err != nil && !tfresource.NotFound(err) { - return fmt.Errorf("listing access keys for IAM User (%s): %w", username, err) + return fmt.Errorf("listing IAM User (%s) access keys: %w", user, err) } var errs []error + for _, v := range accessKeys { + accessKeyID := aws.ToString(v.AccessKeyId) + input := iam.DeleteAccessKeyInput{ + AccessKeyId: aws.String(accessKeyID), + UserName: aws.String(user), + } + _, err := conn.DeleteAccessKey(ctx, &input) - for _, k := range accessKeys { - _, err := conn.DeleteAccessKey(ctx, &iam.DeleteAccessKeyInput{ - UserName: aws.String(username), - AccessKeyId: k.AccessKeyId, - }) if err != nil { - errs = append(errs, fmt.Errorf("deleting Access Key (%s) from User (%s): %w", aws.ToString(k.AccessKeyId), username, err)) + return fmt.Errorf("deleting IAM User (%s) access key (%s): %w", user, accessKeyID, err) } } return errors.Join(errs...) } -func deleteUserSigningCertificates(ctx context.Context, conn *iam.Client, userName string) error { - var certificateIDList []string - - listInput := &iam.ListSigningCertificatesInput{ - UserName: aws.String(userName), +func deleteUserSigningCertificates(ctx context.Context, conn *iam.Client, user string) error { + input := iam.ListSigningCertificatesInput{ + UserName: aws.String(user), } + var ids []string - pages := iam.NewListSigningCertificatesPaginator(conn, listInput) + pages := iam.NewListSigningCertificatesPaginator(conn, &input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) if err != nil { - return fmt.Errorf("removing signing certificates of user %s: %w", userName, err) + return fmt.Errorf("listing IAM User (%s) signing certificates: %w", user, err) } - for _, c := range page.Certificates { - certificateIDList = append(certificateIDList, aws.ToString(c.CertificateId)) + for _, v := range page.Certificates { + ids = append(ids, aws.ToString(v.CertificateId)) } } - for _, c := range certificateIDList { - _, err := conn.DeleteSigningCertificate(ctx, &iam.DeleteSigningCertificateInput{ - CertificateId: aws.String(c), - UserName: aws.String(userName), - }) + for _, v := range ids { + input := iam.DeleteSigningCertificateInput{ + CertificateId: aws.String(v), + UserName: aws.String(user), + } + _, err := conn.DeleteSigningCertificate(ctx, &input) + if err != nil { - return fmt.Errorf("deleting signing certificate %s: %w", c, err) + return fmt.Errorf("deleting IAM User (%s) signing certificate (%s): %w", user, v, err) } } return nil } -func deleteServiceSpecificCredentials(ctx context.Context, conn *iam.Client, username string) error { - input := &iam.ListServiceSpecificCredentialsInput{ - UserName: aws.String(username), +func deleteServiceSpecificCredentials(ctx context.Context, conn *iam.Client, user string) error { + input := iam.ListServiceSpecificCredentialsInput{ + UserName: aws.String(user), } + var ids []string + + err := listServiceSpecificCredentialsPages(ctx, conn, &input, func(page *iam.ListServiceSpecificCredentialsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.ServiceSpecificCredentials { + ids = append(ids, aws.ToString(v.ServiceSpecificCredentialId)) + } + + return !lastPage + }) - output, err := conn.ListServiceSpecificCredentials(ctx, input) if err != nil { - return fmt.Errorf("listing Service Specific Credentials of user %s: %w", username, err) + return fmt.Errorf("listing IAM User (%s) service-specific credentials: %w", user, err) } - for _, m := range output.ServiceSpecificCredentials { - _, err := conn.DeleteServiceSpecificCredential(ctx, &iam.DeleteServiceSpecificCredentialInput{ - UserName: aws.String(username), - ServiceSpecificCredentialId: m.ServiceSpecificCredentialId, - }) + + for _, v := range ids { + input := iam.DeleteServiceSpecificCredentialInput{ + ServiceSpecificCredentialId: aws.String(v), + UserName: aws.String(user), + } + _, err := conn.DeleteServiceSpecificCredential(ctx, &input) + if err != nil { - return fmt.Errorf("deleting Service Specific Credentials %v: %w", m, err) + return fmt.Errorf("deleting IAM User (%s) service-specific credential (%s): %w", user, v, err) } } return nil } -func deleteUserPolicies(ctx context.Context, conn *iam.Client, username string) error { - input := &iam.ListUserPoliciesInput{ - UserName: aws.String(username), +func deleteUserPolicies(ctx context.Context, conn *iam.Client, user string) error { + input := iam.ListUserPoliciesInput{ + UserName: aws.String(user), } + var policies []string - output, err := conn.ListUserPolicies(ctx, input) - if errs.IsA[*awstypes.NoSuchEntityException](err) { - // user not found - return nil - } + pages := iam.NewListUserPoliciesPaginator(conn, &input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return fmt.Errorf("listing IAM User (%s) policies: %w", user, err) + } - if err != nil { - return fmt.Errorf("listing/deleting IAM User (%s) inline policies: %w", username, err) + policies = append(policies, page.PolicyNames...) } - for _, name := range output.PolicyNames { - log.Printf("[DEBUG] Deleting IAM User (%s) inline policy %q", username, name) - - input := &iam.DeleteUserPolicyInput{ - PolicyName: aws.String(name), - UserName: aws.String(username), + for _, v := range policies { + input := iam.DeleteUserPolicyInput{ + PolicyName: aws.String(v), + UserName: aws.String(user), } - if _, err := conn.DeleteUserPolicy(ctx, input); err != nil { - if errs.IsA[*awstypes.NoSuchEntityException](err) { - continue - } - return fmt.Errorf("deleting IAM User (%s) inline policies: %w", username, err) + _, err := conn.DeleteUserPolicy(ctx, &input) + + if err != nil { + return fmt.Errorf("deleting IAM User (%s) policy (%s): %w", user, v, err) } } return nil } -func detachUserPolicies(ctx context.Context, conn *iam.Client, username string) error { - input := &iam.ListAttachedUserPoliciesInput{ - UserName: aws.String(username), +func detachUserPolicies(ctx context.Context, conn *iam.Client, user string) error { + input := iam.ListAttachedUserPoliciesInput{ + UserName: aws.String(user), } + var policies []string - output, err := conn.ListAttachedUserPolicies(ctx, input) - if errs.IsA[*awstypes.NoSuchEntityException](err) { - // user was an entity 2 nanoseconds ago, but now it's not - return nil - } + pages := iam.NewListAttachedUserPoliciesPaginator(conn, &input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return fmt.Errorf("listing IAM User (%s) attached policies: %w", user, err) + } - if err != nil { - return fmt.Errorf("listing/detaching IAM User (%s) attached policy: %w", username, err) + for _, v := range page.AttachedPolicies { + policies = append(policies, aws.ToString(v.PolicyArn)) + } } - for _, policy := range output.AttachedPolicies { - policyARN := aws.ToString(policy.PolicyArn) - - log.Printf("[DEBUG] Detaching IAM User (%s) attached policy: %s", username, policyARN) - - if err := detachPolicyFromUser(ctx, conn, username, policyARN); err != nil { - return fmt.Errorf("detaching IAM User (%s) attached policy: %w", username, err) + for _, v := range policies { + if err := detachPolicyFromUser(ctx, conn, user, v); err != nil { + return err } } diff --git a/internal/service/iam/user_data_source.go b/internal/service/iam/user_data_source.go index 11c4f6ae0e07..315df56f6116 100644 --- a/internal/service/iam/user_data_source.go +++ b/internal/service/iam/user_data_source.go @@ -5,10 +5,8 @@ package iam import ( "context" - "log" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -55,17 +53,12 @@ func dataSourceUserRead(ctx context.Context, d *schema.ResourceData, meta any) d conn := meta.(*conns.AWSClient).IAMClient(ctx) userName := d.Get(names.AttrUserName).(string) - req := &iam.GetUserInput{ - UserName: aws.String(userName), - } + user, err := findUserByName(ctx, conn, userName) - log.Printf("[DEBUG] Reading IAM User: %v", req) - resp, err := conn.GetUser(ctx, req) if err != nil { - return sdkdiag.AppendErrorf(diags, "getting user: %s", err) + return sdkdiag.AppendErrorf(diags, "reading IAM User (%s): %s", userName, err) } - user := resp.User d.SetId(aws.ToString(user.UserId)) d.Set(names.AttrARN, user.Arn) d.Set(names.AttrPath, user.Path) diff --git a/internal/service/iam/user_login_profile.go b/internal/service/iam/user_login_profile.go index f22ed9950f54..644c8bc2783d 100644 --- a/internal/service/iam/user_login_profile.go +++ b/internal/service/iam/user_login_profile.go @@ -89,9 +89,9 @@ const ( charSymbols = "!@#$%^&*()_+-=[]{}|'" ) -// GeneratePassword generates a random password of a given length, matching the +// generatePassword generates a random password of a given length, matching the // most restrictive iam password policy. -func GeneratePassword(length int) (string, error) { +func generatePassword(length int) (string, error) { const charset = charLower + charUpper + charNumbers + charSymbols result := make([]byte, length) @@ -117,7 +117,7 @@ func GeneratePassword(length int) (string, error) { result[i] = charset[r.Int64()] } - if !CheckPwdPolicy(result) { + if !checkPwdPolicy(result) { continue } @@ -129,7 +129,7 @@ func GeneratePassword(length int) (string, error) { // Check the generated password contains all character classes listed in the // IAM password policy. -func CheckPwdPolicy(pass []byte) bool { +func checkPwdPolicy(pass []byte) bool { return (bytes.ContainsAny(pass, charLower) && bytes.ContainsAny(pass, charNumbers) && bytes.ContainsAny(pass, charSymbols) && @@ -142,7 +142,7 @@ func resourceUserLoginProfileCreate(ctx context.Context, d *schema.ResourceData, username := d.Get("user").(string) passwordLength := d.Get("password_length").(int) - initialPassword, err := GeneratePassword(passwordLength) + initialPassword, err := generatePassword(passwordLength) if err != nil { return sdkdiag.AppendErrorf(diags, "creating IAM User Login Profile for %q: %s", username, err) } diff --git a/internal/service/iam/user_policy.go b/internal/service/iam/user_policy.go index ee39ae67acc3..81ef42a67e53 100644 --- a/internal/service/iam/user_policy.go +++ b/internal/service/iam/user_policy.go @@ -81,25 +81,24 @@ func resourceUserPolicyPut(ctx context.Context, d *schema.ResourceData, meta any return sdkdiag.AppendFromErr(diags, err) } - userName := d.Get("user").(string) - policyName := create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string)) - input := &iam.PutUserPolicyInput{ + userName, policyName := d.Get("user").(string), create.Name(d.Get(names.AttrName).(string), d.Get(names.AttrNamePrefix).(string)) + input := iam.PutUserPolicyInput{ PolicyDocument: aws.String(policyDoc), PolicyName: aws.String(policyName), UserName: aws.String(userName), } - _, err = conn.PutUserPolicy(ctx, input) + _, err = conn.PutUserPolicy(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "putting IAM User (%s) Policy (%s): %s", userName, policyName, err) } if d.IsNewResource() { - d.SetId(fmt.Sprintf("%s:%s", userName, policyName)) + d.SetId(userPolicyCreateResourceID(userName, policyName)) _, err := tfresource.RetryWhenNotFound(ctx, propagationTimeout, func(ctx context.Context) (any, error) { - return FindUserPolicyByTwoPartKey(ctx, conn, userName, policyName) + return findUserPolicyByTwoPartKey(ctx, conn, userName, policyName) }) if err != nil { @@ -114,12 +113,12 @@ func resourceUserPolicyRead(ctx context.Context, d *schema.ResourceData, meta an var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - userName, policyName, err := UserPolicyParseID(d.Id()) + userName, policyName, err := userPolicyParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } - policyDocument, err := FindUserPolicyByTwoPartKey(ctx, conn, userName, policyName) + policyDocument, err := findUserPolicyByTwoPartKey(ctx, conn, userName, policyName) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] IAM User Policy %s not found, removing from state", d.Id()) @@ -153,16 +152,17 @@ func resourceUserPolicyDelete(ctx context.Context, d *schema.ResourceData, meta var diags diag.Diagnostics conn := meta.(*conns.AWSClient).IAMClient(ctx) - userName, policyName, err := UserPolicyParseID(d.Id()) + userName, policyName, err := userPolicyParseResourceID(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) } log.Printf("[INFO] Deleting IAM User Policy: %s", d.Id()) - _, err = conn.DeleteUserPolicy(ctx, &iam.DeleteUserPolicyInput{ + input := iam.DeleteUserPolicyInput{ PolicyName: aws.String(policyName), UserName: aws.String(userName), - }) + } + _, err = conn.DeleteUserPolicy(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { return diags @@ -175,12 +175,16 @@ func resourceUserPolicyDelete(ctx context.Context, d *schema.ResourceData, meta return diags } -func FindUserPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, userName, policyName string) (string, error) { - input := &iam.GetUserPolicyInput{ +func findUserPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, userName, policyName string) (string, error) { + input := iam.GetUserPolicyInput{ PolicyName: aws.String(policyName), UserName: aws.String(userName), } + return findUserPolicy(ctx, conn, &input) +} + +func findUserPolicy(ctx context.Context, conn *iam.Client, input *iam.GetUserPolicyInput) (string, error) { output, err := conn.GetUserPolicy(ctx, input) if errs.IsA[*awstypes.NoSuchEntityException](err) { @@ -201,14 +205,21 @@ func FindUserPolicyByTwoPartKey(ctx context.Context, conn *iam.Client, userName, return aws.ToString(output.PolicyDocument), nil } -func UserPolicyParseID(id string) (userName, policyName string, err error) { - parts := strings.SplitN(id, ":", 2) - if len(parts) != 2 { - err = fmt.Errorf("user_policy id must be of the form :") - return +const userPolicyResourceIDSeparator = ":" + +func userPolicyCreateResourceID(userName, policyName string) string { + parts := []string{userName, policyName} + id := strings.Join(parts, userPolicyResourceIDSeparator) + + return id +} + +func userPolicyParseResourceID(id string) (string, string, error) { + parts := strings.SplitN(id, userPolicyResourceIDSeparator, 2) + + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected USER-NAME%[2]sPOLICY-NAME", id, userPolicyResourceIDSeparator) } - userName = parts[0] - policyName = parts[1] - return + return parts[0], parts[1], nil } diff --git a/internal/service/iam/user_policy_test.go b/internal/service/iam/user_policy_test.go index d6eb06bc42c3..26ef64f77126 100644 --- a/internal/service/iam/user_policy_test.go +++ b/internal/service/iam/user_policy_test.go @@ -247,14 +247,9 @@ func testAccCheckUserPolicyExists(ctx context.Context, n string, v *string) reso return fmt.Errorf("Not found: %s", n) } - userName, policyName, err := tfiam.UserPolicyParseID(rs.Primary.ID) - if err != nil { - return err - } - conn := acctest.Provider.Meta().(*conns.AWSClient).IAMClient(ctx) - output, err := tfiam.FindUserPolicyByTwoPartKey(ctx, conn, userName, policyName) + output, err := tfiam.FindUserPolicyByTwoPartKey(ctx, conn, rs.Primary.Attributes["user"], rs.Primary.Attributes[names.AttrName]) if err != nil { return err @@ -275,12 +270,7 @@ func testAccCheckUserPolicyDestroy(ctx context.Context) resource.TestCheckFunc { continue } - userName, policyName, err := tfiam.UserPolicyParseID(rs.Primary.ID) - if err != nil { - return err - } - - _, err = tfiam.FindUserPolicyByTwoPartKey(ctx, conn, userName, policyName) + _, err := tfiam.FindUserPolicyByTwoPartKey(ctx, conn, rs.Primary.Attributes["user"], rs.Primary.Attributes[names.AttrName]) if tfresource.NotFound(err) { continue diff --git a/internal/service/iam/users_data_source.go b/internal/service/iam/users_data_source.go index 137dde04d0d7..fcd4075246e1 100644 --- a/internal/service/iam/users_data_source.go +++ b/internal/service/iam/users_data_source.go @@ -6,12 +6,16 @@ package iam import ( "context" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -19,6 +23,7 @@ import ( func dataSourceUsers() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceUsersRead, + Schema: map[string]*schema.Schema{ names.AttrARNs: { Type: schema.TypeSet, @@ -48,12 +53,21 @@ func dataSourceUsersRead(ctx context.Context, d *schema.ResourceData, meta any) conn := meta.(*conns.AWSClient).IAMClient(ctx) nameRegex := d.Get("name_regex").(string) - pathPrefix := d.Get("path_prefix").(string) + var input iam.ListUsersInput + if v, ok := d.GetOk("path_prefix"); ok { + input.PathPrefix = aws.String(v.(string)) + } + + results, err := findUsers(ctx, conn, &input, func(v *awstypes.User) bool { + if nameRegex != "" { + return regexache.MustCompile(nameRegex).MatchString(aws.ToString(v.UserName)) + } - results, err := FindUsers(ctx, conn, nameRegex, pathPrefix) + return true + }) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading IAM users: %s", err) + return sdkdiag.AppendErrorf(diags, "reading IAM Users: %s", err) } d.SetId(meta.(*conns.AWSClient).Region(ctx)) @@ -65,13 +79,29 @@ func dataSourceUsersRead(ctx context.Context, d *schema.ResourceData, meta any) arns = append(arns, aws.ToString(r.Arn)) } - if err := d.Set(names.AttrNames, nms); err != nil { - return sdkdiag.AppendErrorf(diags, "setting names: %s", err) - } + d.Set(names.AttrARNs, arns) + d.Set(names.AttrNames, nms) - if err := d.Set(names.AttrARNs, arns); err != nil { - return sdkdiag.AppendErrorf(diags, "setting arns: %s", err) + return diags +} + +func findUsers(ctx context.Context, conn *iam.Client, input *iam.ListUsersInput, filter tfslices.Predicate[*awstypes.User]) ([]awstypes.User, error) { + var output []awstypes.User + + pages := iam.NewListUsersPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + return nil, err + } + + for _, v := range page.Users { + if filter(&v) { + output = append(output, v) + } + } } - return diags + return output, nil } diff --git a/internal/service/iam/virtual_mfa_device.go b/internal/service/iam/virtual_mfa_device.go index ef280b512ea4..9b83c0fec23d 100644 --- a/internal/service/iam/virtual_mfa_device.go +++ b/internal/service/iam/virtual_mfa_device.go @@ -7,7 +7,6 @@ import ( "context" "fmt" "log" - "reflect" "time" "github.com/YakDriver/regexache" @@ -16,14 +15,15 @@ import ( "github.com/aws/aws-sdk-go-v2/service/iam" awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + inttypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -89,20 +89,20 @@ func resourceVirtualMFADeviceCreate(ctx context.Context, d *schema.ResourceData, conn := meta.(*conns.AWSClient).IAMClient(ctx) name := d.Get("virtual_mfa_device_name").(string) - input := &iam.CreateVirtualMFADeviceInput{ + input := iam.CreateVirtualMFADeviceInput{ Path: aws.String(d.Get(names.AttrPath).(string)), Tags: getTagsIn(ctx), VirtualMFADeviceName: aws.String(name), } - output, err := conn.CreateVirtualMFADevice(ctx, input) + output, err := conn.CreateVirtualMFADevice(ctx, &input) // Some partitions (e.g. ISO) may not support tag-on-create. partition := meta.(*conns.AWSClient).Partition(ctx) if input.Tags != nil && errs.IsUnsupportedOperationInPartitionError(partition, err) { input.Tags = nil - output, err = conn.CreateVirtualMFADevice(ctx, input) + output, err = conn.CreateVirtualMFADevice(ctx, &input) } if err != nil { @@ -191,22 +191,26 @@ func resourceVirtualMFADeviceDelete(ctx context.Context, d *schema.ResourceData, conn := meta.(*conns.AWSClient).IAMClient(ctx) if v := d.Get(names.AttrUserName); v != "" { - _, err := conn.DeactivateMFADevice(ctx, &iam.DeactivateMFADeviceInput{ - UserName: aws.String(v.(string)), + input := iam.DeactivateMFADeviceInput{ SerialNumber: aws.String(d.Id()), - }) + UserName: aws.String(v.(string)), + } + _, err := conn.DeactivateMFADevice(ctx, &input) + if errs.IsA[*awstypes.NoSuchEntityException](err) { return diags } + if err != nil { return sdkdiag.AppendErrorf(diags, "deactivating IAM Virtual MFA Device (%s): %s", d.Id(), err) } } log.Printf("[INFO] Deleting IAM Virtual MFA Device: %s", d.Id()) - _, err := conn.DeleteVirtualMFADevice(ctx, &iam.DeleteVirtualMFADeviceInput{ + input := iam.DeleteVirtualMFADeviceInput{ SerialNumber: aws.String(d.Id()), - }) + } + _, err := conn.DeleteVirtualMFADevice(ctx, &input) if errs.IsA[*awstypes.NoSuchEntityException](err) { return diags @@ -220,29 +224,42 @@ func resourceVirtualMFADeviceDelete(ctx context.Context, d *schema.ResourceData, } func findVirtualMFADeviceBySerialNumber(ctx context.Context, conn *iam.Client, serialNumber string) (*awstypes.VirtualMFADevice, error) { - input := &iam.ListVirtualMFADevicesInput{} - var output awstypes.VirtualMFADevice + var input iam.ListVirtualMFADevicesInput + + return findVirtualMFADevice(ctx, conn, &input, func(v *awstypes.VirtualMFADevice) bool { + return aws.ToString(v.SerialNumber) == serialNumber + }) +} + +func findVirtualMFADevice(ctx context.Context, conn *iam.Client, input *iam.ListVirtualMFADevicesInput, filter tfslices.Predicate[*awstypes.VirtualMFADevice]) (*awstypes.VirtualMFADevice, error) { + output, err := findVirtualMFADevices(ctx, conn, input, filter) + + if err != nil { + return nil, err + } + + return tfresource.AssertSingleValueResult(output) +} + +func findVirtualMFADevices(ctx context.Context, conn *iam.Client, input *iam.ListVirtualMFADevicesInput, filter tfslices.Predicate[*awstypes.VirtualMFADevice]) ([]awstypes.VirtualMFADevice, error) { + var output []awstypes.VirtualMFADevice pages := iam.NewListVirtualMFADevicesPaginator(conn, input) for pages.HasMorePages() { page, err := pages.NextPage(ctx) + if err != nil { return nil, err } for _, v := range page.VirtualMFADevices { - if !reflect.ValueOf(v).IsZero() && aws.ToString(v.SerialNumber) == serialNumber { - output = v - break + if p := &v; !inttypes.IsZero(p) && filter(p) { + output = append(output, v) } } } - if reflect.ValueOf(output).IsZero() { - return nil, &retry.NotFoundError{} - } - - return &output, nil + return output, nil } func parseVirtualMFADeviceARN(s string) (path, name string, err error) { diff --git a/internal/service/iam/wait.go b/internal/service/iam/wait.go deleted file mode 100644 index eeb1733b9036..000000000000 --- a/internal/service/iam/wait.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package iam - -import ( - "context" - "time" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/aws/arn" - "github.com/aws/aws-sdk-go-v2/service/iam" - awstypes "github.com/aws/aws-sdk-go-v2/service/iam/types" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - "github.com/hashicorp/terraform-provider-aws/names" -) - -const ( - // Maximum amount of time to wait for IAM changes to propagate - // This timeout should not be increased without strong consideration - // as this will negatively impact user experience when configurations - // have incorrect references or permissions. - // Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency - propagationTimeout = 2 * time.Minute - - RoleStatusARNIsUniqueID = "uniqueid" - RoleStatusARNIsARN = names.AttrARN - RoleStatusNotFound = "notfound" -) - -func waitRoleARNIsNotUniqueID(ctx context.Context, conn *iam.Client, id string, role *awstypes.Role) (*awstypes.Role, error) { - if arn.IsARN(aws.ToString(role.Arn)) { - return role, nil - } - - stateConf := &retry.StateChangeConf{ - Pending: []string{RoleStatusARNIsUniqueID, RoleStatusNotFound}, - Target: []string{names.AttrARN}, - Refresh: statusRoleCreate(ctx, conn, id), - Timeout: propagationTimeout, - NotFoundChecks: 10, - ContinuousTargetOccurence: 5, - Delay: 10 * time.Second, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*awstypes.Role); ok { - return output, err - } - - return nil, err -} - -func statusRoleCreate(ctx context.Context, conn *iam.Client, id string) retry.StateRefreshFunc { - return func() (any, string, error) { - role, err := findRoleByName(ctx, conn, id) - - if tfresource.NotFound(err) { - return nil, RoleStatusNotFound, nil - } - - if err != nil { - return nil, "", err - } - - if arn.IsARN(aws.ToString(role.Arn)) { - return role, names.AttrARN, nil - } - - return role, RoleStatusARNIsUniqueID, nil - } -} diff --git a/internal/service/iot/event_configurations_identity_gen_test.go b/internal/service/iot/event_configurations_identity_gen_test.go index 26315c1a9c29..a9931e847e6a 100644 --- a/internal/service/iot/event_configurations_identity_gen_test.go +++ b/internal/service/iot/event_configurations_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccIoTEventConfigurations_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccIoTEventConfigurations_Identity_Basic, - "ExistingResource": testAccIoTEventConfigurations_Identity_ExistingResource, - "RegionOverride": testAccIoTEventConfigurations_Identity_RegionOverride, + acctest.CtBasic: testAccIoTEventConfigurations_Identity_Basic, + "ExistingResource": testAccIoTEventConfigurations_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccIoTEventConfigurations_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccIoTEventConfigurations_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/iot/indexing_configuration_identity_gen_test.go b/internal/service/iot/indexing_configuration_identity_gen_test.go index 3237a6f467c6..2122ac981ed6 100644 --- a/internal/service/iot/indexing_configuration_identity_gen_test.go +++ b/internal/service/iot/indexing_configuration_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccIoTIndexingConfiguration_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccIoTIndexingConfiguration_Identity_Basic, - "ExistingResource": testAccIoTIndexingConfiguration_Identity_ExistingResource, - "RegionOverride": testAccIoTIndexingConfiguration_Identity_RegionOverride, + acctest.CtBasic: testAccIoTIndexingConfiguration_Identity_Basic, + "ExistingResource": testAccIoTIndexingConfiguration_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccIoTIndexingConfiguration_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccIoTIndexingConfiguration_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/iot/logging_options_identity_gen_test.go b/internal/service/iot/logging_options_identity_gen_test.go index 002462a57bb7..dc4385a99c5b 100644 --- a/internal/service/iot/logging_options_identity_gen_test.go +++ b/internal/service/iot/logging_options_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccIoTLoggingOptions_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccIoTLoggingOptions_Identity_Basic, - "ExistingResource": testAccIoTLoggingOptions_Identity_ExistingResource, - "RegionOverride": testAccIoTLoggingOptions_Identity_RegionOverride, + acctest.CtBasic: testAccIoTLoggingOptions_Identity_Basic, + "ExistingResource": testAccIoTLoggingOptions_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccIoTLoggingOptions_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccIoTLoggingOptions_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/ivs/playback_key_pair_identity_gen_test.go b/internal/service/ivs/playback_key_pair_identity_gen_test.go index 933fcc5daa26..2584ee5f21a1 100644 --- a/internal/service/ivs/playback_key_pair_identity_gen_test.go +++ b/internal/service/ivs/playback_key_pair_identity_gen_test.go @@ -23,9 +23,10 @@ func testAccIVSPlaybackKeyPair_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccIVSPlaybackKeyPair_Identity_Basic, - "ExistingResource": testAccIVSPlaybackKeyPair_Identity_ExistingResource, - "RegionOverride": testAccIVSPlaybackKeyPair_Identity_RegionOverride, + acctest.CtBasic: testAccIVSPlaybackKeyPair_Identity_Basic, + "ExistingResource": testAccIVSPlaybackKeyPair_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccIVSPlaybackKeyPair_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccIVSPlaybackKeyPair_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/kinesisanalyticsv2/application.go b/internal/service/kinesisanalyticsv2/application.go index bcb729276be4..aab5bec4ce14 100644 --- a/internal/service/kinesisanalyticsv2/application.go +++ b/internal/service/kinesisanalyticsv2/application.go @@ -1283,20 +1283,6 @@ func resourceApplicationUpdate(ctx context.Context, d *schema.ResourceData, meta } } - if d.HasChange("application_configuration.0.run_configuration") { - application, err := findApplicationDetailByName(ctx, conn, applicationName) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Kinesis Analytics v2 Application (%s): %s", applicationName, err) - } - - if actual, expected := application.ApplicationStatus, awstypes.ApplicationStatusRunning; actual == expected { - input.RunConfigurationUpdate = expandRunConfigurationUpdate(d.Get("application_configuration.0.run_configuration").([]any)) - - updateApplication = true - } - } - input.ApplicationConfigurationUpdate = applicationConfigurationUpdate } @@ -1392,6 +1378,17 @@ func resourceApplicationUpdate(ctx context.Context, d *schema.ResourceData, meta } if updateApplication { + // Always send 'run_configuration', else defaults are applied. + application, err := findApplicationDetailByName(ctx, conn, applicationName) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading Kinesis Analytics v2 Application (%s): %s", applicationName, err) + } + + if actual, expected := application.ApplicationStatus, awstypes.ApplicationStatusRunning; actual == expected { + input.RunConfigurationUpdate = expandRunConfigurationUpdate(d.Get("application_configuration.0.run_configuration").([]any)) + } + input.CurrentApplicationVersionId = aws.Int64(currentApplicationVersionID) output, err := waitIAMPropagation(ctx, func() (*kinesisanalyticsv2.UpdateApplicationOutput, error) { diff --git a/internal/service/kinesisanalyticsv2/application_test.go b/internal/service/kinesisanalyticsv2/application_test.go index c108e3e7c7e7..75891927b731 100644 --- a/internal/service/kinesisanalyticsv2/application_test.go +++ b/internal/service/kinesisanalyticsv2/application_test.go @@ -1272,6 +1272,171 @@ func TestAccKinesisAnalyticsV2Application_FlinkApplication_restoreFromSnapshot(t }) } +func TestAccKinesisAnalyticsV2Application_FlinkApplication_snapshotToggleWhenSkipRestoreFromSnapshot(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.ApplicationDetail + resourceName := "aws_kinesisanalyticsv2_application.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.KinesisAnalyticsV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckApplicationDestroy(ctx), + Steps: []resource.TestStep{ + // Step 1: Create application with snapshots enabled and SKIP_RESTORE_FROM_SNAPSHOT + { + Config: testAccApplicationConfig_snapshotToggleBug(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_snapshot_configuration.0.snapshots_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.application_restore_configuration.0.application_restore_type", "SKIP_RESTORE_FROM_SNAPSHOT"), + ), + }, + // Step 2: Disable snapshots but maintain SKIP_RESTORE_FROM_SNAPSHOT + { + Config: testAccApplicationConfig_snapshotToggleBug(rName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_snapshot_configuration.0.snapshots_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.application_restore_configuration.0.application_restore_type", "SKIP_RESTORE_FROM_SNAPSHOT"), + ), + }, + // Step 3: Re-enable snapshots - application_restore_type should remain SKIP_RESTORE_FROM_SNAPSHOT + { + Config: testAccApplicationConfig_snapshotToggleBug(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_snapshot_configuration.0.snapshots_enabled", acctest.CtTrue), + // This is the critical check - the restore type should remain SKIP_RESTORE_FROM_SNAPSHOT + // but the bug causes it to default to restore from latest snapshot + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.application_restore_configuration.0.application_restore_type", "SKIP_RESTORE_FROM_SNAPSHOT"), + ), + }, + }, + }) +} + +func TestAccKinesisAnalyticsV2Application_FlinkApplication_updateRestorable(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.ApplicationDetail + resourceName := "aws_kinesisanalyticsv2_application.test" + iamRoleResourceName := "aws_iam_role.test.0" + s3BucketResourceName := "aws_s3_bucket.test" + s3Object1ResourceName := "aws_s3_object.test.0" + s3Object2ResourceName := "aws_s3_object.test.1" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.KinesisAnalyticsV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckApplicationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccApplicationConfig_startRestorableSnapshotFlink(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "application_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.0.code_content.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.0.bucket_arn", s3BucketResourceName, names.AttrARN), + resource.TestCheckResourceAttrPair(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.0.file_key", s3Object1ResourceName, names.AttrKey), + resource.TestCheckResourceAttrPair(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.0.object_version", s3Object1ResourceName, "version_id"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.0.code_content_type", "ZIPFILE"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_snapshot_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_snapshot_configuration.0.snapshots_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.environment_properties.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.checkpointing_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.checkpoint_interval", "60000"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.configuration_type", "DEFAULT"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.min_pause_between_checkpoints", "5000"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.0.configuration_type", "CUSTOM"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.0.log_level", "DEBUG"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.0.metrics_level", "TASK"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.auto_scaling_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.configuration_type", "CUSTOM"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.parallelism", "10"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.parallelism_per_kpu", "4"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.application_restore_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.application_restore_configuration.0.application_restore_type", "RESTORE_FROM_LATEST_SNAPSHOT"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.flink_run_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.flink_run_configuration.0.allow_non_restored_state", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.sql_application_configuration.#", "0"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.vpc_configuration.#", "0"), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "kinesisanalytics", fmt.Sprintf("application/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "cloudwatch_logging_options.#", "0"), + resource.TestCheckResourceAttrSet(resourceName, "create_timestamp"), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, ""), + resource.TestCheckNoResourceAttr(resourceName, "force_stop"), + resource.TestCheckResourceAttrSet(resourceName, "last_update_timestamp"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, "runtime_environment", "FLINK-1_20"), + resource.TestCheckResourceAttrPair(resourceName, "service_execution_role", iamRoleResourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "RUNNING"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, "version_id", "1"), + ), + }, + { + Config: testAccApplicationConfig_startUpdatedRestorableSnapshotFlink(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckApplicationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "application_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.0.code_content.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.0.bucket_arn", s3BucketResourceName, names.AttrARN), + resource.TestCheckResourceAttrPair(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.0.file_key", s3Object2ResourceName, names.AttrKey), + resource.TestCheckResourceAttrPair(resourceName, "application_configuration.0.application_code_configuration.0.code_content.0.s3_content_location.0.object_version", s3Object2ResourceName, "version_id"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_code_configuration.0.code_content_type", "ZIPFILE"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_snapshot_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.application_snapshot_configuration.0.snapshots_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.environment_properties.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.checkpointing_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.checkpoint_interval", "60000"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.configuration_type", "DEFAULT"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.checkpoint_configuration.0.min_pause_between_checkpoints", "5000"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.0.configuration_type", "CUSTOM"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.0.log_level", "DEBUG"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.monitoring_configuration.0.metrics_level", "TASK"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.auto_scaling_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.configuration_type", "CUSTOM"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.parallelism", "10"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.flink_application_configuration.0.parallelism_configuration.0.parallelism_per_kpu", "4"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.application_restore_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.application_restore_configuration.0.application_restore_type", "RESTORE_FROM_LATEST_SNAPSHOT"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.flink_run_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.run_configuration.0.flink_run_configuration.0.allow_non_restored_state", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.sql_application_configuration.#", "0"), + resource.TestCheckResourceAttr(resourceName, "application_configuration.0.vpc_configuration.#", "0"), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "kinesisanalytics", fmt.Sprintf("application/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "cloudwatch_logging_options.#", "0"), + resource.TestCheckResourceAttrSet(resourceName, "create_timestamp"), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, ""), + resource.TestCheckNoResourceAttr(resourceName, "force_stop"), + resource.TestCheckResourceAttrSet(resourceName, "last_update_timestamp"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, "runtime_environment", "FLINK-1_20"), + resource.TestCheckResourceAttrPair(resourceName, "service_execution_role", iamRoleResourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "RUNNING"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, "version_id", "2"), + ), + }, + }, + }) +} + func TestAccKinesisAnalyticsV2Application_FlinkApplicationStartApplication_onCreate(t *testing.T) { ctx := acctest.Context(t) var v awstypes.ApplicationDetail @@ -5750,3 +5915,245 @@ resource "aws_kinesisanalyticsv2_application" "test" { } `, rName)) } + +func testAccApplicationConfig_snapshotToggleBug(rName string, snapshotsEnabled bool) string { + return acctest.ConfigCompose( + testAccApplicationConfig_baseServiceExecutionIAMRole(rName), + testAccApplicationConfig_baseFlinkApplication(rName), + fmt.Sprintf(` +resource "aws_kinesisanalyticsv2_application" "test" { + name = %[1]q + runtime_environment = "FLINK-1_20" + service_execution_role = aws_iam_role.test[0].arn + start_application = true + + application_configuration { + application_code_configuration { + code_content { + s3_content_location { + bucket_arn = aws_s3_bucket.test.arn + file_key = aws_s3_object.test[0].key + object_version = aws_s3_object.test[0].version_id + } + } + + code_content_type = "ZIPFILE" + } + + application_snapshot_configuration { + snapshots_enabled = %[2]t + } + + environment_properties { + property_group { + property_group_id = "InputStream0" + + property_map = { + "aws.region" = data.aws_region.current.region + "stream.name" = aws_kinesis_stream.input.name + } + } + + property_group { + property_group_id = "OutputStream0" + + property_map = { + "aws.region" = data.aws_region.current.region + "stream.name" = aws_kinesis_stream.output.name + } + } + } + + flink_application_configuration { + checkpoint_configuration { + configuration_type = "DEFAULT" + } + + monitoring_configuration { + configuration_type = "CUSTOM" + log_level = "DEBUG" + metrics_level = "TASK" + } + + parallelism_configuration { + auto_scaling_enabled = true + configuration_type = "CUSTOM" + parallelism = 1 + parallelism_per_kpu = 1 + } + } + + run_configuration { + application_restore_configuration { + application_restore_type = "SKIP_RESTORE_FROM_SNAPSHOT" + } + flink_run_configuration { + allow_non_restored_state = false + } + } + } +} +`, rName, snapshotsEnabled)) +} + +func testAccApplicationConfig_startRestorableSnapshotFlink(rName string) string { + return acctest.ConfigCompose( + testAccApplicationConfig_baseServiceExecutionIAMRole(rName), + testAccApplicationConfig_baseFlinkApplication(rName), + fmt.Sprintf(` +resource "aws_kinesisanalyticsv2_application" "test" { + name = %[1]q + runtime_environment = "FLINK-1_20" + service_execution_role = aws_iam_role.test[0].arn + + application_configuration { + application_code_configuration { + code_content { + s3_content_location { + bucket_arn = aws_s3_bucket.test.arn + file_key = aws_s3_object.test[0].key + object_version = aws_s3_object.test[0].version_id + } + } + + code_content_type = "ZIPFILE" + } + + application_snapshot_configuration { + snapshots_enabled = true + } + + environment_properties { + property_group { + property_group_id = "InputStream0" + + property_map = { + "aws.region" = data.aws_region.current.name + "stream.name" = aws_kinesis_stream.input.name + } + } + + property_group { + property_group_id = "OutputStream0" + + property_map = { + "aws.region" = data.aws_region.current.name + "stream.name" = aws_kinesis_stream.output.name + } + } + } + + flink_application_configuration { + checkpoint_configuration { + configuration_type = "DEFAULT" + } + + monitoring_configuration { + configuration_type = "CUSTOM" + log_level = "DEBUG" + metrics_level = "TASK" + } + + parallelism_configuration { + auto_scaling_enabled = true + configuration_type = "CUSTOM" + parallelism = 10 + parallelism_per_kpu = 4 + } + } + + run_configuration { + application_restore_configuration { + application_restore_type = "RESTORE_FROM_LATEST_SNAPSHOT" + } + flink_run_configuration { + allow_non_restored_state = true + } + } + } + + start_application = true +} +`, rName)) +} + +func testAccApplicationConfig_startUpdatedRestorableSnapshotFlink(rName string) string { + return acctest.ConfigCompose( + testAccApplicationConfig_baseServiceExecutionIAMRole(rName), + testAccApplicationConfig_baseFlinkApplication(rName), + fmt.Sprintf(` +resource "aws_kinesisanalyticsv2_application" "test" { + name = %[1]q + runtime_environment = "FLINK-1_20" + service_execution_role = aws_iam_role.test[0].arn + + application_configuration { + application_code_configuration { + code_content { + s3_content_location { + bucket_arn = aws_s3_bucket.test.arn + file_key = aws_s3_object.test[1].key + object_version = aws_s3_object.test[1].version_id + } + } + + code_content_type = "ZIPFILE" + } + + application_snapshot_configuration { + snapshots_enabled = true + } + + environment_properties { + property_group { + property_group_id = "InputStream0" + + property_map = { + "aws.region" = data.aws_region.current.name + "stream.name" = aws_kinesis_stream.input.name + } + } + + property_group { + property_group_id = "OutputStream0" + + property_map = { + "aws.region" = data.aws_region.current.name + "stream.name" = aws_kinesis_stream.output.name + } + } + } + + flink_application_configuration { + checkpoint_configuration { + configuration_type = "DEFAULT" + } + + monitoring_configuration { + configuration_type = "CUSTOM" + log_level = "DEBUG" + metrics_level = "TASK" + } + + parallelism_configuration { + auto_scaling_enabled = true + configuration_type = "CUSTOM" + parallelism = 10 + parallelism_per_kpu = 4 + } + } + + run_configuration { + application_restore_configuration { + application_restore_type = "RESTORE_FROM_LATEST_SNAPSHOT" + } + flink_run_configuration { + allow_non_restored_state = true + } + } + } + + start_application = true +} +`, rName)) +} diff --git a/internal/service/kms/validate.go b/internal/service/kms/validate.go index d909185dd515..a02ed4935af5 100644 --- a/internal/service/kms/validate.go +++ b/internal/service/kms/validate.go @@ -42,7 +42,7 @@ func validNameForDataSource(v any, k string) (ws []string, es []error) { if !aliasNameRegex.MatchString(value) { es = append(es, fmt.Errorf( - "%q must begin with 'alias/' and be comprised of only [0-9A-Za-z_/-]", k)) + "%q must begin with 'alias/' and only contain [0-9A-Za-z_/-]", k)) } return } @@ -56,7 +56,7 @@ func validNameForResource(v any, k string) (ws []string, es []error) { if !aliasNameRegex.MatchString(value) { es = append(es, fmt.Errorf( - "%q must begin with 'alias/' and be comprised of only [0-9A-Za-z_/-]", k)) + "%q must begin with 'alias/' and only contain [0-9A-Za-z_/-]", k)) } return } diff --git a/internal/service/lakeformation/sweep.go b/internal/service/lakeformation/sweep.go index 22f0078d7326..ead5ab9c907b 100644 --- a/internal/service/lakeformation/sweep.go +++ b/internal/service/lakeformation/sweep.go @@ -16,7 +16,9 @@ import ( ) func RegisterSweepers() { - awsv2.Register("aws_lakeformation_permissions", sweepPermissions) + awsv2.Register("aws_lakeformation_permissions", sweepPermissions, + "aws_datazone_environment", + ) awsv2.Register("aws_lakeformation_resource", sweepResource) } diff --git a/internal/service/lambda/event_source_mapping.go b/internal/service/lambda/event_source_mapping.go index 47abd4561fb5..e52aef66ecd0 100644 --- a/internal/service/lambda/event_source_mapping.go +++ b/internal/service/lambda/event_source_mapping.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go-v2/service/lambda" @@ -61,6 +62,7 @@ func resourceEventSourceMapping() *schema.Resource { ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 200), }, + "schema_registry_config": kafkaSchemaRegistryConfigSchema(), }, }, }, @@ -352,6 +354,7 @@ func resourceEventSourceMapping() *schema.Resource { ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 200), }, + "schema_registry_config": kafkaSchemaRegistryConfigSchema(), }, }, }, @@ -417,6 +420,70 @@ func resourceEventSourceMapping() *schema.Resource { } } +func kafkaSchemaRegistryConfigSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_config": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrType: { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[awstypes.KafkaSchemaRegistryAuthType](), + }, + names.AttrURI: { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, + }, + }, + }, + }, + "event_record_format": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[awstypes.SchemaRegistryEventRecordFormat](), + }, + "schema_registry_uri": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 10000), + validation.StringMatch(regexache.MustCompile(`[a-zA-Z0-9-/*:_+=.@-]*`), "must be ARN or URL of the registry"), + ), + }, + "schema_validation_config": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "attribute": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[awstypes.KafkaSchemaValidationAttribute](), + }, + }, + }, + }, + }, + }, + } +} + func resourceEventSourceMappingCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).LambdaClient(ctx) @@ -1134,6 +1201,9 @@ func expandAmazonManagedKafkaEventSourceConfig(tfMap map[string]any) *awstypes.A if v, ok := tfMap["consumer_group_id"].(string); ok && v != "" { apiObject.ConsumerGroupId = aws.String(v) } + if v, ok := tfMap["schema_registry_config"].([]any); ok && len(v) > 0 && v[0] != nil { + apiObject.SchemaRegistryConfig = expandKafkaSchemaRegistryConfig(v[0].(map[string]any)) + } return apiObject } @@ -1149,6 +1219,10 @@ func flattenAmazonManagedKafkaEventSourceConfig(apiObject *awstypes.AmazonManage tfMap["consumer_group_id"] = aws.ToString(v) } + if v := apiObject.SchemaRegistryConfig; v != nil { + tfMap["schema_registry_config"] = []any{flattenKafkaSchemaRegistryConfig(v)} + } + return tfMap } @@ -1163,6 +1237,10 @@ func expandSelfManagedKafkaEventSourceConfig(tfMap map[string]any) *awstypes.Sel apiObject.ConsumerGroupId = aws.String(v) } + if v, ok := tfMap["schema_registry_config"].([]any); ok && len(v) > 0 && v[0] != nil { + apiObject.SchemaRegistryConfig = expandKafkaSchemaRegistryConfig(v[0].(map[string]any)) + } + return apiObject } @@ -1177,6 +1255,10 @@ func flattenSelfManagedKafkaEventSourceConfig(apiObject *awstypes.SelfManagedKaf tfMap["consumer_group_id"] = aws.ToString(v) } + if v := apiObject.SchemaRegistryConfig; v != nil { + tfMap["schema_registry_config"] = []any{flattenKafkaSchemaRegistryConfig(v)} + } + return tfMap } @@ -1442,3 +1524,137 @@ func flattenEventSourceMappingMetricsConfig(apiObject *awstypes.EventSourceMappi return tfMap } + +func expandKafkaSchemaRegistryConfig(tfMap map[string]any) *awstypes.KafkaSchemaRegistryConfig { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.KafkaSchemaRegistryConfig{} + + if v, ok := tfMap["access_config"].(*schema.Set); ok && v != nil && v.Len() > 0 { + apiObject.AccessConfigs = expandKafkaSchemaRegistryAccessConfig(v.List()) + } + + if v, ok := tfMap["event_record_format"].(string); ok && v != "" { + apiObject.EventRecordFormat = awstypes.SchemaRegistryEventRecordFormat(v) + } + + if v, ok := tfMap["schema_registry_uri"].(string); ok && v != "" { + apiObject.SchemaRegistryURI = aws.String(v) + } + + if v, ok := tfMap["schema_validation_config"].(*schema.Set); ok && v != nil && v.Len() > 0 { + apiObject.SchemaValidationConfigs = expandKafkaSchemaValidationConfig(v.List()) + } + + return apiObject +} + +func expandKafkaSchemaRegistryAccessConfig(tfList []any) []awstypes.KafkaSchemaRegistryAccessConfig { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + var apiObjects []awstypes.KafkaSchemaRegistryAccessConfig + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]any) + + if !ok { + continue + } + + apiObject := awstypes.KafkaSchemaRegistryAccessConfig{} + if v, ok := tfMap[names.AttrType].(string); ok && v != "" { + apiObject.Type = awstypes.KafkaSchemaRegistryAuthType(v) + } + if v, ok := tfMap[names.AttrURI].(string); ok && v != "" { + apiObject.URI = aws.String(v) + } + + apiObjects = append(apiObjects, apiObject) + } + return apiObjects +} + +func expandKafkaSchemaValidationConfig(tfList []any) []awstypes.KafkaSchemaValidationConfig { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + var apiObjects []awstypes.KafkaSchemaValidationConfig + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]any) + + if !ok { + continue + } + + apiObject := awstypes.KafkaSchemaValidationConfig{} + if v, ok := tfMap["attribute"].(string); ok && v != "" { + apiObject.Attribute = awstypes.KafkaSchemaValidationAttribute(v) + } + + apiObjects = append(apiObjects, apiObject) + } + return apiObjects +} + +func flattenKafkaSchemaRegistryConfig(apiObject *awstypes.KafkaSchemaRegistryConfig) map[string]any { + if apiObject == nil { + return nil + } + + tfMap := map[string]any{} + if v := apiObject.AccessConfigs; len(v) > 0 { + tfMap["access_config"] = flattenKafkaSchemaRegistryAccessConfig(v) + } + if v := apiObject.EventRecordFormat; v != "" { + tfMap["event_record_format"] = v + } + if v := apiObject.SchemaRegistryURI; v != nil { + tfMap["schema_registry_uri"] = aws.ToString(v) + } + if v := apiObject.SchemaValidationConfigs; len(v) > 0 { + tfMap["schema_validation_config"] = flattenSchemaValidationConfig(v) + } + + return tfMap +} + +func flattenKafkaSchemaRegistryAccessConfig(apiObjects []awstypes.KafkaSchemaRegistryAccessConfig) []any { + if len(apiObjects) == 0 { + return nil + } + + var tfList []any + for _, apiObject := range apiObjects { + tfMap := map[string]any{} + if v := apiObject.Type; v != "" { + tfMap[names.AttrType] = v + } + if v := apiObject.URI; v != nil { + tfMap[names.AttrURI] = aws.ToString(v) + } + tfList = append(tfList, tfMap) + } + return tfList +} + +func flattenSchemaValidationConfig(apiObjects []awstypes.KafkaSchemaValidationConfig) []any { + if len(apiObjects) == 0 { + return nil + } + + var tfList []any + for _, apiObject := range apiObjects { + tfMap := map[string]any{} + if v := apiObject.Attribute; v != "" { + tfMap["attribute"] = v + } + tfList = append(tfList, tfMap) + } + return tfList +} diff --git a/internal/service/lambda/event_source_mapping_test.go b/internal/service/lambda/event_source_mapping_test.go index b4db01ec6765..508f64373c1f 100644 --- a/internal/service/lambda/event_source_mapping_test.go +++ b/internal/service/lambda/event_source_mapping_test.go @@ -1028,6 +1028,78 @@ func TestAccLambdaEventSourceMapping_mskWithEventSourceConfig(t *testing.T) { }) } +func TestAccLambdaEventSourceMapping_mskWithEventSourceConfigSchemaRegistry(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var v lambda.GetEventSourceMappingOutput + resourceName := "aws_lambda_event_source_mapping.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckMSK(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.LambdaEndpointID, "kafka"), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEventSourceMappingDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEventSourceMappingConfig_mskWithEventSourceConfigSchemaRegistryByConfluent(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEventSourceMappingExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.consumer_group_id", "amazon-managed-test-group-id"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.0.type", string(awstypes.KafkaSchemaRegistryAuthTypeBasicAuth)), + resource.TestCheckResourceAttrPair(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.0.uri", "aws_secretsmanager_secret.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.event_record_format", string(awstypes.SchemaRegistryEventRecordFormatJson)), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_registry_uri", "https://test-schema-registry.com"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeKey), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeValue), + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"last_modified"}, + }, + { + Config: testAccEventSourceMappingConfig_mskWithEventSourceConfigSchemaRegistryByGlue(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEventSourceMappingExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.consumer_group_id", "amazon-managed-test-group-id"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.event_record_format", string(awstypes.SchemaRegistryEventRecordFormatJson)), + resource.TestCheckResourceAttrPair(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_registry_uri", "aws_glue_registry.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeKey), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "amazon_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeValue), + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"last_modified"}, + }, + }, + }) +} + func TestAccLambdaEventSourceMapping_selfManagedKafka(t *testing.T) { ctx := acctest.Context(t) var v lambda.GetEventSourceMappingOutput @@ -1125,6 +1197,79 @@ func TestAccLambdaEventSourceMapping_selfManagedKafkaWithEventSourceConfig(t *te }) } +func TestAccLambdaEventSourceMapping_selfManagedKafkaWithEventSourceConfigSchemaRegistry(t *testing.T) { + ctx := acctest.Context(t) + var v lambda.GetEventSourceMappingOutput + resourceName := "aws_lambda_event_source_mapping.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.LambdaServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEventSourceMappingDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEventSourceMappingConfig_selfManagedKafkaWithEventSourceConfigSchemaRegistryByConfluent(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEventSourceMappingExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.consumer_group_id", "self-managed-test-group-id"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.0.type", string(awstypes.KafkaSchemaRegistryAuthTypeBasicAuth)), + resource.TestCheckResourceAttrPair(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.0.uri", "aws_secretsmanager_secret.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.event_record_format", string(awstypes.SchemaRegistryEventRecordFormatJson)), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_registry_uri", "https://test-schema-registry.com"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeKey), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeValue), + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"last_modified"}, + }, + { + Config: testAccEventSourceMappingConfig_selfManagedKafkaWithEventSourceConfigSchemaRegistryByGlue(rName), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionDestroyBeforeCreate), + }, + }, + Check: resource.ComposeTestCheckFunc( + testAccCheckEventSourceMappingExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.consumer_group_id", "self-managed-test-group-id"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.access_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.event_record_format", string(awstypes.SchemaRegistryEventRecordFormatJson)), + resource.TestCheckResourceAttrPair(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_registry_uri", "aws_glue_registry.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeKey), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "self_managed_kafka_event_source_config.0.schema_registry_config.0.schema_validation_config.*", map[string]string{ + "attribute": string(awstypes.KafkaSchemaValidationAttributeValue), + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"last_modified"}, + }, + }, + }) +} + func TestAccLambdaEventSourceMapping_selfManagedKafkaWithProvisionedPollerConfig(t *testing.T) { ctx := acctest.Context(t) var v lambda.GetEventSourceMappingOutput @@ -1923,7 +2068,9 @@ resource "aws_iam_policy" "test" { "ec2:DescribeVpcs", "logs:CreateLogGroup", "logs:CreateLogStream", - "logs:PutLogEvents" + "logs:PutLogEvents", + "glue:GetRegistry", + "glue:GetSchemaVersion" ], "Resource": "*" } @@ -2241,6 +2388,43 @@ resource "aws_docdb_cluster" "test" { `, rName)) } +func testAccEventSourceMappingConfig_kafkaSchemaRegistryByGlueBase(rName string) string { + return fmt.Sprintf(` +resource "aws_glue_registry" "test" { + registry_name = %[1]q +} + +resource "aws_glue_schema" "test" { + schema_name = %[1]q + registry_arn = aws_glue_registry.test.arn + data_format = "JSON" + compatibility = "NONE" + schema_definition = jsonencode( + { + "$id" : "https://example.com/person.schema.json", + "$schema" : "http://json-schema.org/draft-07/schema#", + "title" : "Person", + "type" : "object", + "properties" : { + "firstName" : { + "type" : "string", + "description" : "The person's first name." + }, + "lastName" : { + "type" : "string", + "description" : "The person's last name." + }, + "age" : { + "description" : "Age in years which must be equal to or greater than zero.", + "type" : "integer", + "minimum" : 0 + } + } + }) +} +`, rName) +} + func testAccEventSourceMappingConfig_sqsKMSKeyARN(rName, pattern string) string { return acctest.ConfigCompose(testAccEventSourceMappingConfig_sqsBase(rName), fmt.Sprintf(` resource "aws_kms_key" "test" { @@ -2550,7 +2734,7 @@ func testAccEventSourceMappingConfig_msk(rName, batchSize string) string { return acctest.ConfigCompose(testAccEventSourceMappingConfig_kafkaBase(rName), fmt.Sprintf(` resource "aws_msk_cluster" "test" { cluster_name = %[1]q - kafka_version = "2.7.1" + kafka_version = "3.8.x" number_of_broker_nodes = 2 broker_node_group_info { @@ -2587,7 +2771,7 @@ func testAccEventSourceMappingConfig_mskWithEventSourceConfig(rName, batchSize s return acctest.ConfigCompose(testAccEventSourceMappingConfig_kafkaBase(rName), fmt.Sprintf(` resource "aws_msk_cluster" "test" { cluster_name = %[1]q - kafka_version = "2.7.1" + kafka_version = "3.8.x" number_of_broker_nodes = 2 broker_node_group_info { @@ -2620,6 +2804,122 @@ resource "aws_lambda_event_source_mapping" "test" { `, rName, batchSize)) } +func testAccEventSourceMappingConfig_mskWithEventSourceConfigSchemaRegistryByConfluent(rName string) string { + return acctest.ConfigCompose(testAccEventSourceMappingConfig_kafkaBase(rName), fmt.Sprintf(` +resource "aws_msk_cluster" "test" { + cluster_name = %[1]q + kafka_version = "3.8.x" + number_of_broker_nodes = 2 + + broker_node_group_info { + client_subnets = aws_subnet.test[*].id + instance_type = "kafka.m5.large" + security_groups = [aws_security_group.test.id] + + storage_info { + ebs_storage_info { + volume_size = 10 + } + } + } +} + +resource "aws_secretsmanager_secret" "test" { + name = %[1]q + recovery_window_in_days = 7 +} + +resource "aws_lambda_event_source_mapping" "test" { + batch_size = 100 + event_source_arn = aws_msk_cluster.test.arn + enabled = true + function_name = aws_lambda_function.test.arn + topics = ["test"] + starting_position = "TRIM_HORIZON" + + provisioned_poller_config { + maximum_pollers = 100 + minimum_pollers = 1 + } + + amazon_managed_kafka_event_source_config { + consumer_group_id = "amazon-managed-test-group-id" + schema_registry_config { + access_config { + type = "BASIC_AUTH" + uri = aws_secretsmanager_secret.test.arn + } + event_record_format = "JSON" + schema_registry_uri = "https://test-schema-registry.com" + schema_validation_config { + attribute = "KEY" + } + schema_validation_config { + attribute = "VALUE" + } + } + } + + depends_on = [aws_iam_policy_attachment.test] +} +`, rName)) +} + +func testAccEventSourceMappingConfig_mskWithEventSourceConfigSchemaRegistryByGlue(rName string) string { + return acctest.ConfigCompose( + testAccEventSourceMappingConfig_kafkaBase(rName), + testAccEventSourceMappingConfig_kafkaSchemaRegistryByGlueBase(rName), + fmt.Sprintf(` +resource "aws_msk_cluster" "test" { + cluster_name = %[1]q + kafka_version = "3.8.x" + number_of_broker_nodes = 2 + + broker_node_group_info { + client_subnets = aws_subnet.test[*].id + instance_type = "kafka.m5.large" + security_groups = [aws_security_group.test.id] + + storage_info { + ebs_storage_info { + volume_size = 10 + } + } + } +} + +resource "aws_lambda_event_source_mapping" "test" { + batch_size = 100 + event_source_arn = aws_msk_cluster.test.arn + enabled = true + function_name = aws_lambda_function.test.arn + topics = ["test"] + starting_position = "TRIM_HORIZON" + + provisioned_poller_config { + maximum_pollers = 100 + minimum_pollers = 1 + } + + amazon_managed_kafka_event_source_config { + consumer_group_id = "amazon-managed-test-group-id" + schema_registry_config { + event_record_format = "JSON" + schema_registry_uri = aws_glue_registry.test.arn + schema_validation_config { + attribute = "KEY" + } + schema_validation_config { + attribute = "VALUE" + } + } + } + + depends_on = [aws_iam_policy_attachment.test] +} +`, rName)) +} + func testAccEventSourceMappingConfig_selfManagedKafka(rName, batchSize, kafkaBootstrapServers string) string { if batchSize == "" { batchSize = "null" @@ -2694,6 +2994,117 @@ resource "aws_lambda_event_source_mapping" "test" { `, rName, batchSize, kafkaBootstrapServers)) } +func testAccEventSourceMappingConfig_selfManagedKafkaWithEventSourceConfigSchemaRegistryByConfluent(rName string) string { + return acctest.ConfigCompose(testAccEventSourceMappingConfig_kafkaBase(rName), fmt.Sprintf(` +resource "aws_secretsmanager_secret" "test" { + name = %[1]q + recovery_window_in_days = 7 +} + +resource "aws_lambda_event_source_mapping" "test" { + batch_size = 100 + enabled = false + function_name = aws_lambda_function.test.arn + topics = ["test"] + starting_position = "TRIM_HORIZON" + + provisioned_poller_config { + maximum_pollers = 100 + minimum_pollers = 1 + } + + self_managed_kafka_event_source_config { + consumer_group_id = "self-managed-test-group-id" + schema_registry_config { + access_config { + type = "BASIC_AUTH" + uri = aws_secretsmanager_secret.test.arn + } + event_record_format = "JSON" + schema_registry_uri = "https://test-schema-registry.com" + schema_validation_config { + attribute = "KEY" + } + schema_validation_config { + attribute = "VALUE" + } + } + } + + self_managed_event_source { + endpoints = { + KAFKA_BOOTSTRAP_SERVERS = "test1:9092,test2:9092" + } + } + + dynamic "source_access_configuration" { + for_each = aws_subnet.test[*].id + content { + type = "VPC_SUBNET" + uri = "subnet:${source_access_configuration.value}" + } + } + + source_access_configuration { + type = "VPC_SECURITY_GROUP" + uri = aws_security_group.test.id + } +} +`, rName)) +} + +func testAccEventSourceMappingConfig_selfManagedKafkaWithEventSourceConfigSchemaRegistryByGlue(rName string) string { + return acctest.ConfigCompose( + testAccEventSourceMappingConfig_kafkaBase(rName), + testAccEventSourceMappingConfig_kafkaSchemaRegistryByGlueBase(rName), ` +resource "aws_lambda_event_source_mapping" "test" { + batch_size = 100 + enabled = false + function_name = aws_lambda_function.test.arn + topics = ["test"] + starting_position = "TRIM_HORIZON" + + provisioned_poller_config { + maximum_pollers = 100 + minimum_pollers = 1 + } + + self_managed_kafka_event_source_config { + consumer_group_id = "self-managed-test-group-id" + schema_registry_config { + event_record_format = "JSON" + schema_registry_uri = aws_glue_registry.test.arn + schema_validation_config { + attribute = "KEY" + } + schema_validation_config { + attribute = "VALUE" + } + } + } + + self_managed_event_source { + endpoints = { + KAFKA_BOOTSTRAP_SERVERS = "test1:9092,test2:9092" + } + } + + dynamic "source_access_configuration" { + for_each = aws_subnet.test[*].id + content { + type = "VPC_SUBNET" + uri = "subnet:${source_access_configuration.value}" + } + } + + source_access_configuration { + type = "VPC_SECURITY_GROUP" + uri = aws_security_group.test.id + } +} +`) +} + func testAccEventSourceMappingConfig_selfManagedKafkaWithProvisionedPollerConfig(rName, batchSize, kafkaBootstrapServers, maxPollers, minPollers string) string { if batchSize == "" { batchSize = "null" diff --git a/internal/service/logs/service_package.go b/internal/service/logs/service_package.go new file mode 100644 index 000000000000..52b37edd1af6 --- /dev/null +++ b/internal/service/logs/service_package.go @@ -0,0 +1,41 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package logs + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/retry" + "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" + awstypes "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/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/internal/vcr" +) + +func (p *servicePackage) withExtraOptions(ctx context.Context, config map[string]any) []func(*cloudwatchlogs.Options) { + cfg := *(config["aws_sdkv2_config"].(*aws.Config)) + + return []func(*cloudwatchlogs.Options){ + func(o *cloudwatchlogs.Options) { + retryables := []retry.IsErrorRetryable{ + retry.IsErrorRetryableFunc(func(err error) aws.Ternary { + if errs.IsAErrorMessageContains[*awstypes.LimitExceededException](err, "Resource limit exceeded") { + return aws.FalseTernary + } + return aws.UnknownTernary // Delegate to configured Retryer. + }), + } + // Include go-vcr retryable to prevent generated client retryer from being overridden + if inContext, ok := conns.FromContext(ctx); ok && inContext.VCREnabled() { + tflog.Info(ctx, "overriding retry behavior to immediately return VCR errors") + retryables = append(retryables, vcr.InteractionNotFoundRetryableFunc) + } + + o.Retryer = conns.AddIsErrorRetryables(cfg.Retryer().(aws.RetryerV2), retryables...) + }, + } +} diff --git a/internal/service/macie2/classification_export_configuration_identity_gen_test.go b/internal/service/macie2/classification_export_configuration_identity_gen_test.go index 441942d976c6..e7643f3fd6ee 100644 --- a/internal/service/macie2/classification_export_configuration_identity_gen_test.go +++ b/internal/service/macie2/classification_export_configuration_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccMacie2ClassificationExportConfiguration_IdentitySerial(t *testing.T) t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccMacie2ClassificationExportConfiguration_Identity_Basic, - "ExistingResource": testAccMacie2ClassificationExportConfiguration_Identity_ExistingResource, - "RegionOverride": testAccMacie2ClassificationExportConfiguration_Identity_RegionOverride, + acctest.CtBasic: testAccMacie2ClassificationExportConfiguration_Identity_Basic, + "ExistingResource": testAccMacie2ClassificationExportConfiguration_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccMacie2ClassificationExportConfiguration_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccMacie2ClassificationExportConfiguration_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/networkfirewall/firewall_policy_data_source.go b/internal/service/networkfirewall/firewall_policy_data_source.go index 6706afb58d19..7b06f1131076 100644 --- a/internal/service/networkfirewall/firewall_policy_data_source.go +++ b/internal/service/networkfirewall/firewall_policy_data_source.go @@ -121,12 +121,12 @@ func dataSourceFirewallPolicy() *schema.Resource { }, "override": { Type: schema.TypeList, - Optional: true, + Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ names.AttrAction: { Type: schema.TypeString, - Optional: true, + Computed: true, }, }, }, diff --git a/internal/service/networkfirewall/firewall_policy_data_source_test.go b/internal/service/networkfirewall/firewall_policy_data_source_test.go index 651aa9b0f1a0..6a1c859c674c 100644 --- a/internal/service/networkfirewall/firewall_policy_data_source_test.go +++ b/internal/service/networkfirewall/firewall_policy_data_source_test.go @@ -223,6 +223,35 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_statefulEngineOptions(t *tes }) } +func TestAccNetworkFirewallFirewallPolicyDataSource_multipleStatefulRuleGroupReferences(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix("resource-test-terraform") + resourceName := "aws_networkfirewall_firewall_policy.test" + datasourceName := "data.aws_networkfirewall_firewall_policy.test" + ruleGroupResourceName1 := "aws_networkfirewall_rule_group.test.0" + ruleGroupResourceName2 := "aws_networkfirewall_rule_group.test.1" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewallServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccFirewallPolicyDataSourceConfig_multipleStatefulRuleGroupReferences(rName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(datasourceName, names.AttrARN, resourceName, names.AttrARN), resource.TestCheckResourceAttrPair(datasourceName, names.AttrDescription, resourceName, names.AttrDescription), + resource.TestCheckResourceAttrPair(datasourceName, "firewall_policy.#", resourceName, "firewall_policy.#"), + resource.TestCheckResourceAttrPair(datasourceName, "firewall_policy.0.stateful_rule_group_reference.#", resourceName, "firewall_policy.0.stateful_rule_group_reference.#"), + resource.TestCheckTypeSetElemAttrPair(datasourceName, "firewall_policy.0.stateful_rule_group_reference.*.resource_arn", ruleGroupResourceName1, names.AttrARN), + resource.TestCheckTypeSetElemAttrPair(datasourceName, "firewall_policy.0.stateful_rule_group_reference.*.resource_arn", ruleGroupResourceName2, names.AttrARN), + resource.TestCheckResourceAttrPair(datasourceName, names.AttrName, resourceName, names.AttrName), + resource.TestCheckResourceAttrPair(datasourceName, acctest.CtTagsPercent, resourceName, acctest.CtTagsPercent), + ), + }, + }, + }) +} + func testAccFirewallPolicyDataSourceConfig_basic(rName string) string { return fmt.Sprintf(` resource "aws_networkfirewall_firewall_policy" "test" { @@ -361,3 +390,11 @@ data "aws_networkfirewall_firewall_policy" "test" { } `, rName) } + +func testAccFirewallPolicyDataSourceConfig_multipleStatefulRuleGroupReferences(rName string) string { + return acctest.ConfigCompose(testAccFirewallPolicyConfig_multipleStatefulRuleGroupReferences(rName), ` +data "aws_networkfirewall_firewall_policy" "test" { + arn = aws_networkfirewall_firewall_policy.test.arn +} +`) +} diff --git a/internal/service/networkfirewall/logging_configuration.go b/internal/service/networkfirewall/logging_configuration.go index f8c07b10d7db..b163bb437e43 100644 --- a/internal/service/networkfirewall/logging_configuration.go +++ b/internal/service/networkfirewall/logging_configuration.go @@ -38,6 +38,11 @@ func resourceLoggingConfiguration() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "enable_monitoring_dashboard": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, "firewall_arn": { Type: schema.TypeString, Required: true, @@ -114,6 +119,19 @@ func resourceLoggingConfigurationCreate(ctx context.Context, d *schema.ResourceD firewallARN := d.Get("firewall_arn").(string) + if v := d.Get("enable_monitoring_dashboard"); v != nil { + input := &networkfirewall.UpdateLoggingConfigurationInput{ + FirewallArn: aws.String(firewallARN), + EnableMonitoringDashboard: aws.Bool(v.(bool)), + } + + _, err := conn.UpdateLoggingConfiguration(ctx, input) + + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + } + if v, ok := d.GetOk(names.AttrLoggingConfiguration); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { tfMap := v.([]any)[0].(map[string]any) @@ -145,6 +163,7 @@ func resourceLoggingConfigurationRead(ctx context.Context, d *schema.ResourceDat return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Logging Configuration (%s): %s", d.Id(), err) } + d.Set("enable_monitoring_dashboard", output.EnableMonitoringDashboard) d.Set("firewall_arn", output.FirewallArn) if err := d.Set(names.AttrLoggingConfiguration, flattenLoggingConfiguration(output.LoggingConfiguration)); err != nil { return sdkdiag.AppendErrorf(diags, "setting logging_configuration: %s", err) @@ -165,12 +184,32 @@ func resourceLoggingConfigurationUpdate(ctx context.Context, d *schema.ResourceD o, n := d.GetChange("logging_configuration.0.log_destination_config") os, ns := o.(*schema.Set), n.(*schema.Set) - add, del := ns.Difference(os), os.Difference(ns) + + var add, del *schema.Set + // To change enable_monitoring_dashboard, all log_destination_config must first be removed. + // Then enable_monitoring_dashboard can be changed, followed by adding log_destination_config back. + if d.HasChanges("enable_monitoring_dashboard") { + add, del = ns, os + } else { + add, del = ns.Difference(os), os.Difference(ns) + } if err := deleteLogDestinationConfigs(ctx, conn, d.Id(), output.LoggingConfiguration, expandLogDestinationConfigs(del.List())); err != nil { return sdkdiag.AppendFromErr(diags, err) } + if d.HasChanges("enable_monitoring_dashboard") { + input := &networkfirewall.UpdateLoggingConfigurationInput{ + FirewallArn: output.FirewallArn, + EnableMonitoringDashboard: aws.Bool(d.Get("enable_monitoring_dashboard").(bool)), + } + _, err := conn.UpdateLoggingConfiguration(ctx, input) + + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + } + if err := addLogDestinationConfigs(ctx, conn, d.Id(), output.LoggingConfiguration, expandLogDestinationConfigs(add.List())); err != nil { return sdkdiag.AppendFromErr(diags, err) } diff --git a/internal/service/networkfirewall/logging_configuration_test.go b/internal/service/networkfirewall/logging_configuration_test.go index 26ef1ea646a5..a98bb142fc8a 100644 --- a/internal/service/networkfirewall/logging_configuration_test.go +++ b/internal/service/networkfirewall/logging_configuration_test.go @@ -36,6 +36,7 @@ func TestAccNetworkFirewallLoggingConfiguration_CloudWatchLogDestination_logGrou Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_monitoring_dashboard", acctest.CtFalse), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "logging_configuration.0.log_destination_config.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ @@ -49,6 +50,7 @@ func TestAccNetworkFirewallLoggingConfiguration_CloudWatchLogDestination_logGrou Config: testAccLoggingConfigurationConfig_cloudWatch(updatedLogGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_monitoring_dashboard", acctest.CtFalse), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "logging_configuration.0.log_destination_config.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ @@ -62,6 +64,7 @@ func TestAccNetworkFirewallLoggingConfiguration_CloudWatchLogDestination_logGrou Config: testAccLoggingConfigurationConfig_cloudWatch(updatedLogGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeTls)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_monitoring_dashboard", acctest.CtFalse), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "logging_configuration.0.log_destination_config.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ @@ -742,6 +745,115 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToSingleTLSTypeLogDestinat }) } +func TestAccNetworkFirewallLoggingConfiguration_enableMonitoringDashboard(t *testing.T) { + ctx := acctest.Context(t) + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + logGroupName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_networkfirewall_logging_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewallServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccLoggingConfigurationConfig_s3AndCloudWatchEnableMonitoringDashboard(bucketName, logGroupName, rName, string(awstypes.LogTypeAlert), string(awstypes.LogTypeFlow), true), + Check: resource.ComposeTestCheckFunc( + testAccCheckLoggingConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_monitoring_dashboard", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.0.log_destination_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.logGroup": logGroupName, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.bucketName": bucketName, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeAlert), + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + // Disable Monitoring Dashboard + Config: testAccLoggingConfigurationConfig_s3AndCloudWatchEnableMonitoringDashboard(bucketName, logGroupName, rName, string(awstypes.LogTypeAlert), string(awstypes.LogTypeFlow), false), + Check: resource.ComposeTestCheckFunc( + testAccCheckLoggingConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_monitoring_dashboard", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.0.log_destination_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.logGroup": logGroupName, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.bucketName": bucketName, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeAlert), + }), + ), + }, + { + // Re-Enable Monitoring Dashboard and change log types at the same time + Config: testAccLoggingConfigurationConfig_s3AndCloudWatchEnableMonitoringDashboard(bucketName, logGroupName, rName, string(awstypes.LogTypeTls), string(awstypes.LogTypeFlow), true), + Check: resource.ComposeTestCheckFunc( + testAccCheckLoggingConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_monitoring_dashboard", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.0.log_destination_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.logGroup": logGroupName, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.bucketName": bucketName, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeTls), + }), + ), + }, + { + // Omit enable_monitoring_dashboard (inherit previous value) + Config: testAccLoggingConfigurationConfig_s3AndCloudWatch(bucketName, logGroupName, rName, string(awstypes.LogTypeTls), string(awstypes.LogTypeFlow)), + Check: resource.ComposeTestCheckFunc( + testAccCheckLoggingConfigurationExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_monitoring_dashboard", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.0.log_destination_config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.logGroup": logGroupName, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ + "log_destination.%": "1", + "log_destination.bucketName": bucketName, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeTls), + }), + ), + }, + }, + }) +} + func TestAccNetworkFirewallLoggingConfiguration_disappears(t *testing.T) { ctx := acctest.Context(t) bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -1151,3 +1263,35 @@ resource "aws_networkfirewall_logging_configuration" "test" { } `, logTypeS3, logTypeCloudWatch)) } + +func testAccLoggingConfigurationConfig_s3AndCloudWatchEnableMonitoringDashboard(bucketName, logGroupName, rName, logTypeS3, logTypeCloudWatch string, enableMonitoringDashboard bool) string { + return acctest.ConfigCompose( + testAccLoggingConfigurationConfig_base(rName), + testAccLoggingConfigurationConfig_baseS3Bucket(bucketName), + testAccLoggingConfigurationConfig_baseCloudWatch(logGroupName), + fmt.Sprintf(` +resource "aws_networkfirewall_logging_configuration" "test" { + firewall_arn = aws_networkfirewall_firewall.test.arn + + enable_monitoring_dashboard = %[3]t + + logging_configuration { + log_destination_config { + log_destination = { + bucketName = aws_s3_bucket.test.bucket + } + log_destination_type = "S3" + log_type = %[1]q + } + + log_destination_config { + log_destination = { + logGroup = aws_cloudwatch_log_group.test.name + } + log_destination_type = "CloudWatchLogs" + log_type = %[2]q + } + } +} +`, logTypeS3, logTypeCloudWatch, enableMonitoringDashboard)) +} diff --git a/internal/service/odb/cloud_autonomous_vm_cluster.go b/internal/service/odb/cloud_autonomous_vm_cluster.go index 805e0622d4a5..02d0b7484ca8 100644 --- a/internal/service/odb/cloud_autonomous_vm_cluster.go +++ b/internal/service/odb/cloud_autonomous_vm_cluster.go @@ -57,8 +57,6 @@ const ( ResNameCloudAutonomousVmCluster = "Cloud Autonomous Vm Cluster" ) -var ResourceCloudAutonomousVMCluster = newResourceCloudAutonomousVmCluster - type resourceCloudAutonomousVmCluster struct { framework.ResourceWithModel[cloudAutonomousVmClusterResourceModel] framework.WithTimeouts @@ -521,7 +519,7 @@ func (r *resourceCloudAutonomousVmCluster) Create(ctx context.Context, req resou } createTimeout := r.CreateTimeout(ctx, plan.Timeouts) - createdAVMC, err := waitCloudAutonomousVmClusterCreated(ctx, conn, *out.CloudAutonomousVmClusterId, createTimeout) + createdAVMC, err := waitCloudAutonomousVmClusterCreated(ctx, conn, aws.ToString(out.CloudAutonomousVmClusterId), createTimeout) resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrID), aws.ToString(out.CloudAutonomousVmClusterId))...) if err != nil { resp.Diagnostics.AddError( @@ -543,7 +541,7 @@ func (r *resourceCloudAutonomousVmCluster) Read(ctx context.Context, req resourc return } - out, err := FindCloudAutonomousVmClusterByID(ctx, conn, state.CloudAutonomousVmClusterId.ValueString()) + out, err := findCloudAutonomousVmClusterByID(ctx, conn, state.CloudAutonomousVmClusterId.ValueString()) if tfresource.NotFound(err) { resp.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) @@ -635,7 +633,7 @@ func waitCloudAutonomousVmClusterDeleted(ctx context.Context, conn *odb.Client, func statusCloudAutonomousVmCluster(ctx context.Context, conn *odb.Client, id string) retry.StateRefreshFunc { return func() (any, string, error) { - out, err := FindCloudAutonomousVmClusterByID(ctx, conn, id) + out, err := findCloudAutonomousVmClusterByID(ctx, conn, id) if tfresource.NotFound(err) { return nil, "", nil } @@ -648,7 +646,7 @@ func statusCloudAutonomousVmCluster(ctx context.Context, conn *odb.Client, id st } } -func FindCloudAutonomousVmClusterByID(ctx context.Context, conn *odb.Client, id string) (*odbtypes.CloudAutonomousVmCluster, error) { +func findCloudAutonomousVmClusterByID(ctx context.Context, conn *odb.Client, id string) (*odbtypes.CloudAutonomousVmCluster, error) { input := odb.GetCloudAutonomousVmClusterInput{ CloudAutonomousVmClusterId: aws.String(id), } diff --git a/internal/service/odb/cloud_exadata_infrastructure.go b/internal/service/odb/cloud_exadata_infrastructure.go index 230212d0b3de..0b4b185e3bb0 100644 --- a/internal/service/odb/cloud_exadata_infrastructure.go +++ b/internal/service/odb/cloud_exadata_infrastructure.go @@ -53,8 +53,6 @@ const ( ResNameCloudExadataInfrastructure = "Cloud Exadata Infrastructure" ) -var ResourceCloudExadataInfrastructure = newResourceCloudExadataInfrastructure - type resourceCloudExadataInfrastructure struct { framework.ResourceWithModel[cloudExadataInfrastructureResourceModel] framework.WithTimeouts @@ -353,7 +351,7 @@ func (r *resourceCloudExadataInfrastructure) Create(ctx context.Context, req res } createTimeout := r.CreateTimeout(ctx, plan.Timeouts) - createdExaInfra, err := waitCloudExadataInfrastructureCreated(ctx, conn, *out.CloudExadataInfrastructureId, createTimeout) + createdExaInfra, err := waitCloudExadataInfrastructureCreated(ctx, conn, aws.ToString(out.CloudExadataInfrastructureId), createTimeout) resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrID), aws.ToString(out.CloudExadataInfrastructureId))...) if err != nil { resp.Diagnostics.AddError( @@ -379,7 +377,7 @@ func (r *resourceCloudExadataInfrastructure) Read(ctx context.Context, req resou return } - out, err := FindExadataInfraResourceByID(ctx, conn, state.CloudExadataInfrastructureId.ValueString()) + out, err := findExadataInfraResourceByID(ctx, conn, state.CloudExadataInfrastructureId.ValueString()) if tfresource.NotFound(err) { resp.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) resp.State.RemoveResource(ctx) @@ -536,7 +534,7 @@ func waitCloudExadataInfrastructureDeleted(ctx context.Context, conn *odb.Client func statusCloudExadataInfrastructure(ctx context.Context, conn *odb.Client, id string) retry.StateRefreshFunc { return func() (any, string, error) { - out, err := FindExadataInfraResourceByID(ctx, conn, id) + out, err := findExadataInfraResourceByID(ctx, conn, id) if tfresource.NotFound(err) { return nil, "", nil } @@ -549,7 +547,7 @@ func statusCloudExadataInfrastructure(ctx context.Context, conn *odb.Client, id } } -func FindExadataInfraResourceByID(ctx context.Context, conn *odb.Client, id string) (*odbtypes.CloudExadataInfrastructure, error) { +func findExadataInfraResourceByID(ctx context.Context, conn *odb.Client, id string) (*odbtypes.CloudExadataInfrastructure, error) { input := odb.GetCloudExadataInfrastructureInput{ CloudExadataInfrastructureId: aws.String(id), } diff --git a/internal/service/odb/cloud_vm_cluster.go b/internal/service/odb/cloud_vm_cluster.go index d15333af21ed..3e144ef00cdf 100644 --- a/internal/service/odb/cloud_vm_cluster.go +++ b/internal/service/odb/cloud_vm_cluster.go @@ -9,12 +9,14 @@ import ( "strings" "time" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/odb" odbtypes "github.com/aws/aws-sdk-go-v2/service/odb/types" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -55,6 +57,7 @@ func newResourceCloudVmCluster(_ context.Context) (resource.ResourceWithConfigur const ( ResNameCloudVmCluster = "Cloud Vm Cluster" + MajorGiVersionPattern = `^\d+\.0\.0\.0$` ) var ResourceCloudVmCluster = newResourceCloudVmCluster @@ -70,6 +73,9 @@ func (r *resourceCloudVmCluster) Schema(ctx context.Context, req resource.Schema licenseModelType := fwtypes.StringEnumType[odbtypes.LicenseModel]() diskRedundancyType := fwtypes.StringEnumType[odbtypes.DiskRedundancy]() computeModelType := fwtypes.StringEnumType[odbtypes.ComputeModel]() + giVersionValidator := []validator.String{ + stringvalidator.RegexMatches(regexache.MustCompile(MajorGiVersionPattern), "Gi version must be of the format 19.0.0.0"), + } resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ names.AttrARN: framework.ARNAttributeComputedOnly(), @@ -98,11 +104,9 @@ func (r *resourceCloudVmCluster) Schema(ctx context.Context, req resource.Schema Description: "The number of CPU cores to enable on the VM cluster. Changing this will create a new resource.", }, "data_storage_size_in_tbs": schema.Float64Attribute{ - Optional: true, - Computed: true, + Required: true, PlanModifiers: []planmodifier.Float64{ float64planmodifier.RequiresReplace(), - float64planmodifier.UseStateForUnknown(), }, Description: "The size of the data disk group, in terabytes (TBs), to allocate for the VM cluster. Changing this will create a new resource.", }, @@ -151,8 +155,18 @@ func (r *resourceCloudVmCluster) Schema(ctx context.Context, req resource.Schema PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), }, + //Note: underlying API only accepts major gi_version. + Validators: giVersionValidator, Description: "A valid software version of Oracle Grid Infrastructure (GI). To get the list of valid values, use the ListGiVersions operation and specify the shape of the Exadata infrastructure. Example: 19.0.0.0 This member is required. Changing this will create a new resource.", }, + //Underlying API returns complete gi version. For example if gi_version 23.0.0.0 then underlying api returns a version starting with 23 + "gi_version_computed": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + Description: "A complete software version of Oracle Grid Infrastructure (GI).", + }, //Underlying API treats Hostname as hostname prefix. Therefore, explicitly setting it. API also returns new hostname prefix by appending the input hostname //prefix. Therefore, we have hostname_prefix and hostname_prefix_computed "hostname_prefix_computed": schema.StringAttribute{ @@ -462,7 +476,7 @@ func (r *resourceCloudVmCluster) Create(ctx context.Context, req resource.Create } createTimeout := r.CreateTimeout(ctx, plan.Timeouts) - createdVmCluster, err := waitCloudVmClusterCreated(ctx, conn, *out.CloudVmClusterId, createTimeout) + createdVmCluster, err := waitCloudVmClusterCreated(ctx, conn, aws.ToString(out.CloudVmClusterId), createTimeout) resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrID), aws.ToString(out.CloudVmClusterId))...) if err != nil { resp.Diagnostics.AddError( @@ -472,10 +486,20 @@ func (r *resourceCloudVmCluster) Create(ctx context.Context, req resource.Create return } hostnamePrefix := strings.Split(*input.Hostname, "-")[0] - plan.HostnamePrefix = types.StringValue(hostnamePrefix) - plan.HostnamePrefixComputed = types.StringValue(*createdVmCluster.Hostname) + plan.HostnamePrefix = flex.StringValueToFramework(ctx, hostnamePrefix) + plan.HostnamePrefixComputed = flex.StringToFramework(ctx, createdVmCluster.Hostname) //scan listener port not returned by API directly - plan.ScanListenerPortTcp = types.Int32PointerValue(createdVmCluster.ListenerPort) + plan.ScanListenerPortTcp = flex.Int32ToFramework(ctx, createdVmCluster.ListenerPort) + plan.GiVersionComputed = flex.StringToFramework(ctx, createdVmCluster.GiVersion) + giVersionMajor, err := getMajorGiVersion(createdVmCluster.GiVersion) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.ODB, create.ErrActionWaitingForCreation, ResNameCloudVmCluster, plan.DisplayName.ValueString(), err), + err.Error(), + ) + return + } + plan.GiVersion = flex.StringToFramework(ctx, giVersionMajor) resp.Diagnostics.Append(flex.Flatten(ctx, createdVmCluster, &plan)...) if resp.Diagnostics.HasError() { return @@ -491,7 +515,7 @@ func (r *resourceCloudVmCluster) Read(ctx context.Context, req resource.ReadRequ return } - out, err := FindCloudVmClusterForResourceByID(ctx, conn, state.CloudVmClusterId.ValueString()) + out, err := findCloudVmClusterForResourceByID(ctx, conn, state.CloudVmClusterId.ValueString()) if tfresource.NotFound(err) { resp.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) resp.State.RemoveResource(ctx) @@ -508,8 +532,17 @@ func (r *resourceCloudVmCluster) Read(ctx context.Context, req resource.ReadRequ state.HostnamePrefix = types.StringValue(hostnamePrefix) state.HostnamePrefixComputed = types.StringValue(*out.Hostname) //scan listener port not returned by API directly - state.ScanListenerPortTcp = types.Int32PointerValue(out.ListenerPort) - + state.ScanListenerPortTcp = flex.Int32ToFramework(ctx, out.ListenerPort) + state.GiVersionComputed = flex.StringToFramework(ctx, out.GiVersion) + giVersionMajor, err := getMajorGiVersion(out.GiVersion) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.ODB, create.ErrActionWaitingForCreation, ResNameCloudVmCluster, state.CloudVmClusterId.ValueString(), err), + err.Error(), + ) + return + } + state.GiVersion = flex.StringToFramework(ctx, giVersionMajor) resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) if resp.Diagnostics.HasError() { return @@ -587,7 +620,7 @@ func waitCloudVmClusterDeleted(ctx context.Context, conn *odb.Client, id string, func statusCloudVmCluster(ctx context.Context, conn *odb.Client, id string) retry.StateRefreshFunc { return func() (any, string, error) { - out, err := FindCloudVmClusterForResourceByID(ctx, conn, id) + out, err := findCloudVmClusterForResourceByID(ctx, conn, id) if tfresource.NotFound(err) { return nil, "", nil } @@ -600,7 +633,7 @@ func statusCloudVmCluster(ctx context.Context, conn *odb.Client, id string) retr } } -func FindCloudVmClusterForResourceByID(ctx context.Context, conn *odb.Client, id string) (*odbtypes.CloudVmCluster, error) { +func findCloudVmClusterForResourceByID(ctx context.Context, conn *odb.Client, id string) (*odbtypes.CloudVmCluster, error) { input := odb.GetCloudVmClusterInput{ CloudVmClusterId: aws.String(id), } @@ -620,6 +653,16 @@ func FindCloudVmClusterForResourceByID(ctx context.Context, conn *odb.Client, id } return out.CloudVmCluster, nil } +func getMajorGiVersion(giVersionComputed *string) (*string, error) { + giVersionMajor := strings.Split(*giVersionComputed, ".")[0] + giVersionMajor = giVersionMajor + ".0.0.0" + regxGiVersionMajor := regexache.MustCompile(MajorGiVersionPattern) + if !regxGiVersionMajor.MatchString(giVersionMajor) { + err := errors.New("gi_version major retrieved from gi_version_computed does not match the pattern 19.0.0.0") + return nil, err + } + return &giVersionMajor, nil +} type cloudVmClusterResourceModel struct { framework.WithRegionModel @@ -635,7 +678,8 @@ type cloudVmClusterResourceModel struct { DiskRedundancy fwtypes.StringEnum[odbtypes.DiskRedundancy] `tfsdk:"disk_redundancy"` DisplayName types.String `tfsdk:"display_name"` Domain types.String `tfsdk:"domain"` - GiVersion types.String `tfsdk:"gi_version"` + GiVersion types.String `tfsdk:"gi_version" autoflex:",noflatten"` + GiVersionComputed types.String `tfsdk:"gi_version_computed" autoflex:",noflatten"` HostnamePrefixComputed types.String `tfsdk:"hostname_prefix_computed" autoflex:",noflatten"` HostnamePrefix types.String `tfsdk:"hostname_prefix" autoflex:"-"` IormConfigCache fwtypes.ListNestedObjectValueOf[cloudVMCExadataIormConfigResourceModel] `tfsdk:"iorm_config_cache"` diff --git a/internal/service/odb/cloud_vm_cluster_test.go b/internal/service/odb/cloud_vm_cluster_test.go index 6f8d5ec35f2f..d45d899ffc26 100644 --- a/internal/service/odb/cloud_vm_cluster_test.go +++ b/internal/service/odb/cloud_vm_cluster_test.go @@ -48,6 +48,7 @@ func TestAccODBCloudVmCluster_basic(t *testing.T) { return } resourceName := "aws_odb_cloud_vm_cluster.test" + basicConfig, _ := vmClusterTestEntity.testAccCloudVmClusterConfigBasic(vmcDisplayName, publicKey) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) @@ -58,7 +59,7 @@ func TestAccODBCloudVmCluster_basic(t *testing.T) { CheckDestroy: vmClusterTestEntity.testAccCheckCloudVmClusterDestroy(ctx), Steps: []resource.TestStep{ { - Config: vmClusterTestEntity.testAccCloudVmClusterConfigBasic(vmcDisplayName, publicKey), + Config: basicConfig, Check: resource.ComposeAggregateTestCheckFunc( vmClusterTestEntity.testAccCheckCloudVmClusterExists(ctx, resourceName, &cloudvmcluster), ), @@ -124,6 +125,7 @@ func TestAccODBCloudVmCluster_taggingTest(t *testing.T) { t.Fatal(err) return } + vmcNoTag, vmcWithTag := vmClusterTestEntity.testAccCloudVmClusterConfigBasic(vmcDisplayName, publicKey) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) @@ -134,7 +136,7 @@ func TestAccODBCloudVmCluster_taggingTest(t *testing.T) { CheckDestroy: vmClusterTestEntity.testAccCheckCloudVmClusterDestroy(ctx), Steps: []resource.TestStep{ { - Config: vmClusterTestEntity.testAccCloudVmClusterConfigBasic(vmcDisplayName, publicKey), + Config: vmcNoTag, Check: resource.ComposeAggregateTestCheckFunc( resource.ComposeTestCheckFunc(func(state *terraform.State) error { return nil @@ -148,7 +150,7 @@ func TestAccODBCloudVmCluster_taggingTest(t *testing.T) { ImportStateVerify: true, }, { - Config: vmClusterTestEntity.testAccCloudVmClusterConfigUpdatedTags(vmcDisplayName, publicKey), + Config: vmcWithTag, Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "2"), resource.TestCheckResourceAttr(resourceName, "tags.env", "dev"), @@ -171,6 +173,68 @@ func TestAccODBCloudVmCluster_taggingTest(t *testing.T) { }) } +func TestAccODBCloudVmCluster_real(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + var cloudvmcluster1 odbtypes.CloudVmCluster + var cloudvmcluster2 odbtypes.CloudVmCluster + vmcDisplayName := sdkacctest.RandomWithPrefix("tf-real") + resourceName := "aws_odb_cloud_vm_cluster.test" + + publicKey, _, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatal(err) + return + } + vmcWithoutTag, vmcWithTag := vmClusterTestEntity.cloudVmClusterReal(vmcDisplayName, publicKey) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + vmClusterTestEntity.testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.ODBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: vmClusterTestEntity.testAccCheckCloudVmClusterDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: vmcWithoutTag, + Check: resource.ComposeAggregateTestCheckFunc( + resource.ComposeTestCheckFunc(func(state *terraform.State) error { + return nil + }), + vmClusterTestEntity.testAccCheckCloudVmClusterExists(ctx, resourceName, &cloudvmcluster1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: vmcWithTag, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, "tags.env", "dev"), + vmClusterTestEntity.testAccCheckCloudVmClusterExists(ctx, resourceName, &cloudvmcluster2), + resource.ComposeTestCheckFunc(func(state *terraform.State) error { + if strings.Compare(*(cloudvmcluster1.CloudVmClusterId), *(cloudvmcluster2.CloudVmClusterId)) != 0 { + return errors.New("Should not create a new cloud vm cluster for tag update") + } + return nil + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccODBCloudVmCluster_disappears(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -184,6 +248,7 @@ func TestAccODBCloudVmCluster_disappears(t *testing.T) { t.Fatal(err) return } + vmcBasicConfig, _ := vmClusterTestEntity.testAccCloudVmClusterConfigBasic(vmClusterDisplayName, publicKey) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) @@ -194,7 +259,7 @@ func TestAccODBCloudVmCluster_disappears(t *testing.T) { CheckDestroy: vmClusterTestEntity.testAccCheckCloudVmClusterDestroy(ctx), Steps: []resource.TestStep{ { - Config: vmClusterTestEntity.testAccCloudVmClusterConfigBasic(vmClusterDisplayName, publicKey), + Config: vmcBasicConfig, Check: resource.ComposeAggregateTestCheckFunc( vmClusterTestEntity.testAccCheckCloudVmClusterExists(ctx, resourceName, &cloudvmcluster), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfodb.ResourceCloudVmCluster, resourceName), @@ -256,12 +321,12 @@ func (cloudVmClusterResourceTest) testAccPreCheck(ctx context.Context, t *testin } } -func (cloudVmClusterResourceTest) testAccCloudVmClusterConfigBasic(vmClusterDisplayName, sshKey string) string { +func (cloudVmClusterResourceTest) testAccCloudVmClusterConfigBasic(vmClusterDisplayName, sshKey string) (string, string) { exaInfraDisplayName := sdkacctest.RandomWithPrefix(vmClusterTestEntity.exaInfraDisplayNamePrefix) odbNetDisplayName := sdkacctest.RandomWithPrefix(vmClusterTestEntity.odbNetDisplayNamePrefix) exaInfra := vmClusterTestEntity.exaInfra(exaInfraDisplayName) odbNet := vmClusterTestEntity.oracleDBNetwork(odbNetDisplayName) - res := fmt.Sprintf(` + vmcNoTag := fmt.Sprintf(` %s @@ -294,21 +359,13 @@ resource "aws_odb_cloud_vm_cluster" "test" { } `, exaInfra, odbNet, vmClusterDisplayName, sshKey) - return res -} -func (cloudVmClusterResourceTest) cloudVmClusterWithAllParameters(vmClusterDisplayName, sshKey string) string { - exaInfraDisplayName := sdkacctest.RandomWithPrefix(vmClusterTestEntity.exaInfraDisplayNamePrefix) - odbNetDisplayName := sdkacctest.RandomWithPrefix(vmClusterTestEntity.odbNetDisplayNamePrefix) - exaInfra := vmClusterTestEntity.exaInfra(exaInfraDisplayName) - odbNet := vmClusterTestEntity.oracleDBNetwork(odbNetDisplayName) - res := fmt.Sprintf(` + vmcWithTag := fmt.Sprintf(` %s %s - data "aws_odb_db_servers" "test" { cloud_exadata_infrastructure_id = aws_odb_cloud_exadata_infrastructure.test.id } @@ -328,32 +385,34 @@ resource "aws_odb_cloud_vm_cluster" "test" { db_servers = [for db_server in data.aws_odb_db_servers.test.db_servers : db_server.id] db_node_storage_size_in_gbs = 120.0 memory_size_in_gbs = 60 - cluster_name = "julia-13" - timezone = "UTC" - scan_listener_port_tcp = 1521 + data_collection_options { + is_diagnostics_events_enabled = false + is_health_monitoring_enabled = false + is_incident_logs_enabled = false + } tags = { "env" = "dev" + "foo" = "bar" } - data_collection_options { - is_diagnostics_events_enabled = true - is_health_monitoring_enabled = true - is_incident_logs_enabled = true - } + } `, exaInfra, odbNet, vmClusterDisplayName, sshKey) - return res + return vmcNoTag, vmcWithTag } -func (cloudVmClusterResourceTest) testAccCloudVmClusterConfigUpdatedTags(vmClusterDisplayName, sshKey string) string { +func (cloudVmClusterResourceTest) cloudVmClusterWithAllParameters(vmClusterDisplayName, sshKey string) string { exaInfraDisplayName := sdkacctest.RandomWithPrefix(vmClusterTestEntity.exaInfraDisplayNamePrefix) odbNetDisplayName := sdkacctest.RandomWithPrefix(vmClusterTestEntity.odbNetDisplayNamePrefix) exaInfra := vmClusterTestEntity.exaInfra(exaInfraDisplayName) odbNet := vmClusterTestEntity.oracleDBNetwork(odbNetDisplayName) + res := fmt.Sprintf(` + %s %s + data "aws_odb_db_servers" "test" { cloud_exadata_infrastructure_id = aws_odb_cloud_exadata_infrastructure.test.id } @@ -373,16 +432,17 @@ resource "aws_odb_cloud_vm_cluster" "test" { db_servers = [for db_server in data.aws_odb_db_servers.test.db_servers : db_server.id] db_node_storage_size_in_gbs = 120.0 memory_size_in_gbs = 60 - data_collection_options { - is_diagnostics_events_enabled = false - is_health_monitoring_enabled = false - is_incident_logs_enabled = false - } + cluster_name = "julia-13" + timezone = "UTC" + scan_listener_port_tcp = 1521 tags = { "env" = "dev" - "foo" = "bar" } - + data_collection_options { + is_diagnostics_events_enabled = true + is_health_monitoring_enabled = true + is_incident_logs_enabled = true + } } `, exaInfra, odbNet, vmClusterDisplayName, sshKey) return res @@ -420,3 +480,82 @@ resource "aws_odb_network" "test" { `, rName) return resource } + +func (cloudVmClusterResourceTest) cloudVmClusterReal(vmClusterDisplayName, sshKey string) (string, string) { + exaInfraDisplayName := sdkacctest.RandomWithPrefix("tf-real") + odbNetDisplayName := sdkacctest.RandomWithPrefix(vmClusterTestEntity.odbNetDisplayNamePrefix) + exaInfra := vmClusterTestEntity.exaInfra(exaInfraDisplayName) + odbNet := vmClusterTestEntity.oracleDBNetwork(odbNetDisplayName) + vmClusterResourceNoTag := fmt.Sprintf(` + +%s + +%s + +data "aws_odb_db_servers" "test" { + cloud_exadata_infrastructure_id = aws_odb_cloud_exadata_infrastructure.test.id +} + +resource "aws_odb_cloud_vm_cluster" "test" { + display_name = %[3]q + cloud_exadata_infrastructure_id = aws_odb_cloud_exadata_infrastructure.test.id + cpu_core_count = 16 + gi_version = "23.0.0.0" + hostname_prefix = "apollo12" + ssh_public_keys = ["%[4]s"] + odb_network_id = aws_odb_network.test.id + is_local_backup_enabled = true + is_sparse_diskgroup_enabled = true + license_model = "LICENSE_INCLUDED" + data_storage_size_in_tbs = 20.0 + db_servers = [for db_server in data.aws_odb_db_servers.test.db_servers : db_server.id] + db_node_storage_size_in_gbs = 120.0 + memory_size_in_gbs = 60 + data_collection_options { + is_diagnostics_events_enabled = false + is_health_monitoring_enabled = false + is_incident_logs_enabled = false + } + +} +`, exaInfra, odbNet, vmClusterDisplayName, sshKey) + + vmClusterResourceWithTag := fmt.Sprintf(` + +%s + +%s + +data "aws_odb_db_servers" "test" { + cloud_exadata_infrastructure_id = aws_odb_cloud_exadata_infrastructure.test.id +} + +resource "aws_odb_cloud_vm_cluster" "test" { + display_name = %[3]q + cloud_exadata_infrastructure_id = aws_odb_cloud_exadata_infrastructure.test.id + cpu_core_count = 16 + gi_version = "23.0.0.0" + hostname_prefix = "apollo12" + ssh_public_keys = ["%[4]s"] + odb_network_id = aws_odb_network.test.id + is_local_backup_enabled = true + is_sparse_diskgroup_enabled = true + license_model = "LICENSE_INCLUDED" + data_storage_size_in_tbs = 20.0 + db_servers = [for db_server in data.aws_odb_db_servers.test.db_servers : db_server.id] + db_node_storage_size_in_gbs = 120.0 + memory_size_in_gbs = 60 + data_collection_options { + is_diagnostics_events_enabled = false + is_health_monitoring_enabled = false + is_incident_logs_enabled = false + } + tags = { + "env" = "dev" + } + +} +`, exaInfra, odbNet, vmClusterDisplayName, sshKey) + + return vmClusterResourceNoTag, vmClusterResourceWithTag +} diff --git a/internal/service/odb/db_system_shapes_data_source.go b/internal/service/odb/db_system_shapes_data_source.go new file mode 100644 index 000000000000..d559fdc9a435 --- /dev/null +++ b/internal/service/odb/db_system_shapes_data_source.go @@ -0,0 +1,116 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package odb + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/service/odb" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// Function annotations are used for datasource registration to the Provider. DO NOT EDIT. +// @FrameworkDataSource("aws_odb_db_system_shapes", name="Db System Shapes") +func newDataSourceDBSystemShapes(context.Context) (datasource.DataSourceWithConfigure, error) { + return &dataSourceDBSystemShapesList{}, nil +} + +const ( + DSNameDBSystemShapesList = "Db System Shapes List Data Source" +) + +type dataSourceDBSystemShapesList struct { + framework.DataSourceWithModel[dbSystemShapesListDataSourceModel] +} + +func (d *dataSourceDBSystemShapesList) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "availability_zone_id": schema.StringAttribute{ + Optional: true, + Description: "The physical ID of the AZ, for example, use1-az4. This ID persists across accounts.", + }, + "db_system_shapes": schema.ListAttribute{ + Computed: true, + CustomType: fwtypes.NewListNestedObjectTypeOf[dbSystemShapeDataSourceModel](ctx), + Description: "The list of shapes and their properties. Information about a hardware system model (shape) that's available for an Exadata infrastructure." + + "The shape determines resources, such as CPU cores, memory, and storage, to allocate to the Exadata infrastructure.", + }, + }, + } +} + +func (d *dataSourceDBSystemShapesList) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().ODBClient(ctx) + + var data dbSystemShapesListDataSourceModel + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + input := odb.ListDbSystemShapesInput{} + if !data.AvailabilityZoneId.IsNull() && !data.AvailabilityZoneId.IsUnknown() { + input.AvailabilityZoneId = data.AvailabilityZoneId.ValueStringPointer() + } + paginator := odb.NewListDbSystemShapesPaginator(conn, &input) + var out odb.ListDbSystemShapesOutput + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.ODB, create.ErrActionReading, DSNameDBSystemShapesList, "", err), + err.Error(), + ) + return + } + + if page != nil && len(page.DbSystemShapes) > 0 { + out.DbSystemShapes = append(out.DbSystemShapes, page.DbSystemShapes...) + } + } + resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +type dbSystemShapesListDataSourceModel struct { + framework.WithRegionModel + AvailabilityZoneId types.String `tfsdk:"availability_zone_id"` + DbSystemShapes fwtypes.ListNestedObjectValueOf[dbSystemShapeDataSourceModel] `tfsdk:"db_system_shapes"` +} + +type dbSystemShapeDataSourceModel struct { + AvailableCoreCount types.Int32 `tfsdk:"available_core_count"` + AvailableCoreCountPerNode types.Int32 `tfsdk:"available_core_count_per_node"` + AvailableDataStorageInTBs types.Int32 `tfsdk:"available_data_storage_in_tbs"` + AvailableDataStoragePerServerInTBs types.Int32 `tfsdk:"available_data_storage_per_server_in_tbs"` + AvailableDbNodePerNodeInGBs types.Int32 `tfsdk:"available_db_node_per_node_in_gbs"` + AvailableDbNodeStorageInGBs types.Int32 `tfsdk:"available_db_node_storage_in_gbs"` + AvailableMemoryInGBs types.Int32 `tfsdk:"available_memory_in_gbs"` + AvailableMemoryPerNodeInGBs types.Int32 `tfsdk:"available_memory_per_node_in_gbs"` + CoreCountIncrement types.Int32 `tfsdk:"core_count_increment"` + MaxStorageCount types.Int32 `tfsdk:"max_storage_count"` + MaximumNodeCount types.Int32 `tfsdk:"maximum_node_count"` + MinCoreCountPerNode types.Int32 `tfsdk:"min_core_count_per_node"` + MinDataStorageInTBs types.Int32 `tfsdk:"min_data_storage_in_tbs"` + MinDbNodeStoragePerNodeInGBs types.Int32 `tfsdk:"min_db_node_storage_per_node_in_gbs"` + MinMemoryPerNodeInGBs types.Int32 `tfsdk:"min_memory_per_node_in_gbs"` + MinStorageCount types.Int32 `tfsdk:"min_storage_count"` + MinimumCoreCount types.Int32 `tfsdk:"minimum_core_count"` + MinimumNodeCount types.Int32 `tfsdk:"minimum_node_count"` + Name types.String `tfsdk:"name"` + RuntimeMinimumCoreCount types.Int32 `tfsdk:"runtime_minimum_core_count"` + ShapeFamily types.String `tfsdk:"shape_family"` + ShapeType types.String `tfsdk:"shape_type"` +} diff --git a/internal/service/odb/db_system_shapes_data_source_test.go b/internal/service/odb/db_system_shapes_data_source_test.go new file mode 100644 index 000000000000..deca70e80397 --- /dev/null +++ b/internal/service/odb/db_system_shapes_data_source_test.go @@ -0,0 +1,44 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package odb_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccODBDBSystemShapesListDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + dataSourceName := "data.aws_odb_db_system_shapes.test" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.ODBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: basicConfigDBSystemShapeDataSource("use1-az6"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "db_system_shapes.#", "2"), + ), + }, + }, + }) +} + +func basicConfigDBSystemShapeDataSource(availabilityZoneId string) string { + return fmt.Sprintf(` +data "aws_odb_db_system_shapes" "test"{ + availability_zone_id = %[1]q +} +`, availabilityZoneId) +} diff --git a/internal/service/odb/exports_test.go b/internal/service/odb/exports_test.go new file mode 100644 index 000000000000..182c9d8606fa --- /dev/null +++ b/internal/service/odb/exports_test.go @@ -0,0 +1,14 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package odb + +// Exports for use in tests only. +var ( + ResourceCloudAutonomousVMCluster = newResourceCloudAutonomousVmCluster + ResourceCloudExadataInfrastructure = newResourceCloudExadataInfrastructure + + FindCloudAutonomousVmClusterByID = findCloudAutonomousVmClusterByID + FindExadataInfraResourceByID = findExadataInfraResourceByID + FindCloudVmClusterForResourceByID = findCloudVmClusterForResourceByID +) diff --git a/internal/service/odb/gi_versions_data_source.go b/internal/service/odb/gi_versions_data_source.go new file mode 100644 index 000000000000..bc314b60919d --- /dev/null +++ b/internal/service/odb/gi_versions_data_source.go @@ -0,0 +1,91 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package odb + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/service/odb" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// Function annotations are used for datasource registration to the Provider. DO NOT EDIT. +// @FrameworkDataSource("aws_odb_gi_versions", name="Gi Versions") +func newDataSourceGiVersions(context.Context) (datasource.DataSourceWithConfigure, error) { + return &dataSourceGiVersionsList{}, nil +} + +const ( + DSNameGiVersionsList = "Gi Versions List Data Source" +) + +type dataSourceGiVersionsList struct { + framework.DataSourceWithModel[giVersionDataSourceModel] +} + +func (d *dataSourceGiVersionsList) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "shape": schema.StringAttribute{ + Optional: true, + Description: "The system shape.", + }, + "gi_versions": schema.ListAttribute{ + Computed: true, + CustomType: fwtypes.NewListNestedObjectTypeOf[giVersionSummaryModel](ctx), + Description: "Information about a specific version of Oracle Grid Infrastructure (GI) software that can be installed on a VM cluster.", + }, + }, + } +} + +func (d *dataSourceGiVersionsList) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().ODBClient(ctx) + var data giVersionDataSourceModel + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + var input odb.ListGiVersionsInput + if !data.Shape.IsNull() { + input.Shape = data.Shape.ValueStringPointer() + } + paginator := odb.NewListGiVersionsPaginator(conn, &input) + var out odb.ListGiVersionsOutput + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.ODB, create.ErrActionReading, DSNameGiVersionsList, "", err), + err.Error(), + ) + return + } + if page != nil && len(page.GiVersions) > 0 { + out.GiVersions = append(out.GiVersions, page.GiVersions...) + } + } + resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...) + if resp.Diagnostics.HasError() { + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +type giVersionDataSourceModel struct { + framework.WithRegionModel + GiVersions fwtypes.ListNestedObjectValueOf[giVersionSummaryModel] `tfsdk:"gi_versions"` + Shape types.String `tfsdk:"shape"` +} + +type giVersionSummaryModel struct { + Version types.String `tfsdk:"version"` +} diff --git a/internal/service/odb/gi_versions_data_source_test.go b/internal/service/odb/gi_versions_data_source_test.go new file mode 100644 index 000000000000..ed6398f5f769 --- /dev/null +++ b/internal/service/odb/gi_versions_data_source_test.go @@ -0,0 +1,71 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package odb_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccODBGiVersionsListDataSource_basicX9M(t *testing.T) { + ctx := acctest.Context(t) + + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + dataSourceName := "data.aws_odb_gi_versions.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.ODBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccGiVersionsListConfigBasic("Exadata.X9M"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "gi_versions.#", "2"), + ), + }, + }, + }) +} + +func TestAccODBGiVersionsListDataSource_basicX11M(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + dataSourceName := "data.aws_odb_gi_versions.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.ODBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccGiVersionsListConfigBasic("Exadata.X11M"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "gi_versions.#", "2"), + ), + }, + }, + }) +} + +func testAccGiVersionsListConfigBasic(shape string) string { + return fmt.Sprintf(` + + +data "aws_odb_gi_versions" "test" { + shape = %[1]q +} +`, shape) +} diff --git a/internal/service/odb/service_package_gen.go b/internal/service/odb/service_package_gen.go index f842f63a38d1..68ba71950000 100644 --- a/internal/service/odb/service_package_gen.go +++ b/internal/service/odb/service_package_gen.go @@ -70,6 +70,18 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*inttypes.S Name: "Db Servers", Region: unique.Make(inttypes.ResourceRegionDefault()), }, + { + Factory: newDataSourceDBSystemShapes, + TypeName: "aws_odb_db_system_shapes", + Name: "Db System Shapes", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, + { + Factory: newDataSourceGiVersions, + TypeName: "aws_odb_gi_versions", + Name: "Gi Versions", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, { Factory: newDataSourceNetwork, TypeName: "aws_odb_network", diff --git a/internal/service/opensearch/domain.go b/internal/service/opensearch/domain.go index f60de1838c7a..8a77505f0cb3 100644 --- a/internal/service/opensearch/domain.go +++ b/internal/service/opensearch/domain.go @@ -52,7 +52,6 @@ func resourceDomain() *schema.Resource { name := d.Id() ds, err := findDomainByName(ctx, conn, name) - if err != nil { return nil, fmt.Errorf("reading OpenSearch Domain (%s): %w", name, err) } @@ -172,6 +171,47 @@ func resourceDomain() *schema.Resource { }, }, }, + "aiml_options": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "natural_language_query_generation_options": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "desired_state": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateDiagFunc: enum.Validate[awstypes.NaturalLanguageQueryGenerationDesiredState](), + }, + }, + }, + }, + "s3_vectors_engine": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrEnabled: { + Type: schema.TypeBool, + Computed: true, + Optional: true, + }, + }, + }, + }, + }, + }, + }, names.AttrARN: { Type: schema.TypeString, Computed: true, @@ -716,6 +756,10 @@ func resourceDomainCreate(ctx context.Context, d *schema.ResourceData, meta any) input.AdvancedSecurityOptions = expandAdvancedSecurityOptions(v.([]any)) } + if v, ok := d.GetOk("aiml_options"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { + input.AIMLOptions = expandAIMLOptionsInput(v.([]any)[0].(map[string]any)) + } + if v, ok := d.GetOk("auto_tune_options"); ok && len(v.([]any)) > 0 { input.AutoTuneOptions = expandAutoTuneOptionsInput(v.([]any)[0].(map[string]any)) } @@ -831,7 +875,6 @@ func resourceDomainCreate(ctx context.Context, d *schema.ResourceData, meta any) }, domainErrorRetryable, ) - if err != nil { return sdkdiag.AppendErrorf(diags, "creating OpenSearch Domain (%s): %s", name, err) } @@ -854,7 +897,6 @@ func resourceDomainCreate(ctx context.Context, d *schema.ResourceData, meta any) }, domainErrorRetryable, ) - if err != nil { return sdkdiag.AppendErrorf(diags, "updating OpenSearch Domain (%s) Config: %s", d.Id(), err) } @@ -887,7 +929,6 @@ func resourceDomainRead(ctx context.Context, d *schema.ResourceData, meta any) d output, err := conn.DescribeDomainConfig(ctx, &opensearch.DescribeDomainConfigInput{ DomainName: aws.String(name), }) - if err != nil { return sdkdiag.AppendErrorf(diags, "reading OpenSearch Domain (%s) Config: %s", d.Id(), err) } @@ -916,6 +957,13 @@ func resourceDomainRead(ctx context.Context, d *schema.ResourceData, meta any) d return sdkdiag.AppendErrorf(diags, "setting advanced_security_options: %s", err) } } + if ds.AIMLOptions != nil { + if err := d.Set("aiml_options", []any{flattenAIMLOptionsOutput(ds.AIMLOptions)}); err != nil { + return sdkdiag.AppendErrorf(diags, "setting aiml_options: %s", err) + } + } else { + d.Set("aiml_options", nil) + } d.Set(names.AttrARN, ds.ARN) if v := dc.AutoTuneOptions; v != nil { if err := d.Set("auto_tune_options", []any{flattenAutoTuneOptions(v.Options)}); err != nil { @@ -1044,6 +1092,12 @@ func resourceDomainUpdate(ctx context.Context, d *schema.ResourceData, meta any) input.AdvancedSecurityOptions = expandAdvancedSecurityOptions(d.Get("advanced_security_options").([]any)) } + if d.HasChange("aiml_options") { + if v, ok := d.GetOk("aiml_options"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { + input.AIMLOptions = expandAIMLOptionsInput(v.([]any)[0].(map[string]any)) + } + } + if d.HasChange("auto_tune_options") { input.AutoTuneOptions = expandAutoTuneOptions(d.Get("auto_tune_options").([]any)[0].(map[string]any)) } @@ -1172,7 +1226,6 @@ func resourceDomainUpdate(ctx context.Context, d *schema.ResourceData, meta any) }, domainErrorRetryable, ) - if err != nil { return sdkdiag.AppendErrorf(diags, "updating OpenSearch Domain (%s) Config: %s", d.Id(), err) } @@ -1188,7 +1241,6 @@ func resourceDomainUpdate(ctx context.Context, d *schema.ResourceData, meta any) } _, err := conn.UpgradeDomain(ctx, &input) - if err != nil { return sdkdiag.AppendErrorf(diags, "upgrading OpenSearch Domain (%s): %s", d.Id(), err) } diff --git a/internal/service/opensearch/domain_structure.go b/internal/service/opensearch/domain_structure.go index 7d676e30e4c9..3f5bab082406 100644 --- a/internal/service/opensearch/domain_structure.go +++ b/internal/service/opensearch/domain_structure.go @@ -54,6 +54,52 @@ func expandAdvancedSecurityOptions(m []any) *awstypes.AdvancedSecurityOptionsInp return &config } +func expandAIMLOptionsInput(tfMap map[string]any) *awstypes.AIMLOptionsInput { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.AIMLOptionsInput{} + + if v, ok := tfMap["natural_language_query_generation_options"].([]any); ok && len(v) > 0 && v[0] != nil { + apiObject.NaturalLanguageQueryGenerationOptions = expandNaturalLanguageQueryGenerationOptionsInput(v[0].(map[string]any)) + } + + if v, ok := tfMap["s3_vectors_engine"].([]any); ok && len(v) > 0 && v[0] != nil { + apiObject.S3VectorsEngine = expandS3VectorsEngine(v[0].(map[string]any)) + } + + return apiObject +} + +func expandNaturalLanguageQueryGenerationOptionsInput(tfMap map[string]any) *awstypes.NaturalLanguageQueryGenerationOptionsInput { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.NaturalLanguageQueryGenerationOptionsInput{} + + if v, ok := tfMap["desired_state"].(string); ok && v != "" { + apiObject.DesiredState = awstypes.NaturalLanguageQueryGenerationDesiredState(v) + } + + return apiObject +} + +func expandS3VectorsEngine(tfMap map[string]any) *awstypes.S3VectorsEngine { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.S3VectorsEngine{} + + if v, ok := tfMap[names.AttrEnabled].(bool); ok { + apiObject.Enabled = aws.Bool(v) + } + + return apiObject +} + func expandAutoTuneOptions(tfMap map[string]any) *awstypes.AutoTuneOptions { if tfMap == nil { return nil @@ -248,6 +294,48 @@ func flattenAdvancedSecurityOptions(advancedSecurityOptions *awstypes.AdvancedSe return []map[string]any{m} } +func flattenAIMLOptionsOutput(apiObject *awstypes.AIMLOptionsOutput) map[string]any { + if apiObject == nil { + return nil + } + + tfMap := map[string]any{} + + if v := apiObject.NaturalLanguageQueryGenerationOptions; v != nil { + tfMap["natural_language_query_generation_options"] = []any{flattenNaturalLanguageQueryGenerationOptionsOutput(v)} + } + + if v := apiObject.S3VectorsEngine; v != nil { + tfMap["s3_vectors_engine"] = []any{flattenS3VectorsEngine(v)} + } + + return tfMap +} + +func flattenNaturalLanguageQueryGenerationOptionsOutput(apiObject *awstypes.NaturalLanguageQueryGenerationOptionsOutput) map[string]any { + if apiObject == nil { + return nil + } + + tfMap := map[string]any{ + "desired_state": apiObject.DesiredState, + } + + return tfMap +} + +func flattenS3VectorsEngine(apiObject *awstypes.S3VectorsEngine) map[string]any { + if apiObject == nil { + return nil + } + + tfMap := map[string]any{ + names.AttrEnabled: aws.ToBool(apiObject.Enabled), + } + + return tfMap +} + func flattenAutoTuneOptions(autoTuneOptions *awstypes.AutoTuneOptions) map[string]any { if autoTuneOptions == nil { return nil diff --git a/internal/service/opensearch/domain_test.go b/internal/service/opensearch/domain_test.go index 870895e18b41..435cc479ba08 100644 --- a/internal/service/opensearch/domain_test.go +++ b/internal/service/opensearch/domain_test.go @@ -155,6 +155,7 @@ func TestAccOpenSearchDomain_basic(t *testing.T) { Config: testAccDomainConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckDomainExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "aiml_options.#", "1"), resource.TestMatchResourceAttr(resourceName, "dashboard_endpoint", regexache.MustCompile(`.*(opensearch|es)\..*/_dashboards`)), resource.TestCheckResourceAttrSet(resourceName, names.AttrEngineVersion), resource.TestCheckResourceAttr(resourceName, "off_peak_window_options.#", "1"), @@ -541,7 +542,8 @@ func TestAccOpenSearchDomain_Cluster_update(t *testing.T) { testAccCheckSnapshotHour(23, &input), ), }, - }}) + }, + }) } func TestAccOpenSearchDomain_Cluster_multiAzWithStandbyEnabled(t *testing.T) { @@ -2088,7 +2090,8 @@ func TestAccOpenSearchDomain_VolumeType_update(t *testing.T) { testAccCheckEBSVolumeIops(3000, &input), ), }, - }}) + }, + }) } // Verifies that EBS volume_type can be changed from gp3 to a type which does not @@ -2137,7 +2140,8 @@ func TestAccOpenSearchDomain_VolumeType_gp3ToGP2(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "ebs_options.0.volume_type", "gp2"), ), }, - }}) + }, + }) } // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/13867 @@ -2221,7 +2225,8 @@ func TestAccOpenSearchDomain_versionUpdate(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrEngineVersion, "Elasticsearch_6.3"), ), }, - }}) + }, + }) } func TestAccOpenSearchDomain_softwareUpdateOptions(t *testing.T) { @@ -2257,6 +2262,132 @@ func TestAccOpenSearchDomain_softwareUpdateOptions(t *testing.T) { }, }) } + +func TestAccOpenSearchDomain_AIMLOptions_createEnabled(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var domain awstypes.DomainStatus + rName := testAccRandomDomainName() + resourceName := "aws_opensearch_domain.test" + enabledState := "ENABLED" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckIAMServiceLinkedRole(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.OpenSearchServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDomainDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDomainConfig_AIMLOptions(rName, enabledState, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckDomainExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "aiml_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.0.desired_state", enabledState), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.0.enabled", acctest.CtFalse), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateId: rName, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "advanced_security_options", + }, + }, + }, + }) +} + +func TestAccOpenSearchDomain_AIMLOptions_createDisabled(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var domain awstypes.DomainStatus + rName := testAccRandomDomainName() + resourceName := "aws_opensearch_domain.test" + enabledState := "ENABLED" + disabledState := "DISABLED" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckIAMServiceLinkedRole(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.OpenSearchServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDomainDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDomainConfig_AIMLOptions(rName, disabledState, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckDomainExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "aiml_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.0.desired_state", disabledState), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.0.enabled", acctest.CtTrue), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateId: rName, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "advanced_security_options", + }, + }, + { + Config: testAccDomainConfig_AIMLOptions(rName, enabledState, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckDomainExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "aiml_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.0.desired_state", enabledState), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.0.enabled", acctest.CtFalse), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + }, + }, + }, + { + Config: testAccDomainConfig_AIMLOptions(rName, disabledState, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckDomainExists(ctx, resourceName, &domain), + resource.TestCheckResourceAttr(resourceName, "aiml_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.natural_language_query_generation_options.0.desired_state", disabledState), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.#", "1"), + resource.TestCheckResourceAttr(resourceName, "aiml_options.0.s3_vectors_engine.0.enabled", acctest.CtTrue), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + }, + }, + }, + }, + }) +} + func TestAccOpenSearchDomain_disappears(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -2469,7 +2600,6 @@ func testAccCheckDomainExists(ctx context.Context, n string, v *awstypes.DomainS conn := acctest.Provider.Meta().(*conns.AWSClient).OpenSearchClient(ctx) output, err := tfopensearch.FindDomainByName(ctx, conn, rs.Primary.Attributes[names.AttrDomainName]) - if err != nil { return err } @@ -4200,3 +4330,53 @@ resource "aws_opensearch_domain" "test" { } `, rName, option) } + +func testAccDomainConfig_AIMLOptions(rName, desiredState string, S3VecotrsEnabled bool) string { + return fmt.Sprintf(` +resource "aws_opensearch_domain" "test" { + domain_name = %[1]q + + cluster_config { + instance_type = "or1.medium.search" + instance_count = 1 + } + + advanced_security_options { + enabled = true + internal_user_database_enabled = true + master_user_options { + master_user_name = "testmasteruser" + master_user_password = "Barbarbarbar1!" + } + } + + domain_endpoint_options { + enforce_https = true + tls_security_policy = "Policy-Min-TLS-1-2-2019-07" + } + + node_to_node_encryption { + enabled = true + } + + ebs_options { + ebs_enabled = true + volume_size = 20 + } + + encrypt_at_rest { + enabled = true + } + + aiml_options { + natural_language_query_generation_options { + desired_state = %[2]q + } + + s3_vectors_engine { + enabled = %[3]t + } + } +} +`, rName, desiredState, S3VecotrsEnabled) +} diff --git a/internal/service/organizations/organization_identity_gen_test.go b/internal/service/organizations/organization_identity_gen_test.go index aaa5de8cea4b..ae34174c2f13 100644 --- a/internal/service/organizations/organization_identity_gen_test.go +++ b/internal/service/organizations/organization_identity_gen_test.go @@ -23,8 +23,9 @@ func testAccOrganizationsOrganization_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccOrganizationsOrganization_Identity_Basic, - "ExistingResource": testAccOrganizationsOrganization_Identity_ExistingResource, + acctest.CtBasic: testAccOrganizationsOrganization_Identity_Basic, + "ExistingResource": testAccOrganizationsOrganization_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccOrganizationsOrganization_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/organizations/organizational_unit_identity_gen_test.go b/internal/service/organizations/organizational_unit_identity_gen_test.go index 2a5109addf37..1a096f4473f0 100644 --- a/internal/service/organizations/organizational_unit_identity_gen_test.go +++ b/internal/service/organizations/organizational_unit_identity_gen_test.go @@ -24,8 +24,9 @@ func testAccOrganizationsOrganizationalUnit_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccOrganizationsOrganizationalUnit_Identity_Basic, - "ExistingResource": testAccOrganizationsOrganizationalUnit_Identity_ExistingResource, + acctest.CtBasic: testAccOrganizationsOrganizationalUnit_Identity_Basic, + "ExistingResource": testAccOrganizationsOrganizationalUnit_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccOrganizationsOrganizationalUnit_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/organizations/policy_attachment_identity_gen_test.go b/internal/service/organizations/policy_attachment_identity_gen_test.go index 892d2c8c4e3e..5286146ae3d0 100644 --- a/internal/service/organizations/policy_attachment_identity_gen_test.go +++ b/internal/service/organizations/policy_attachment_identity_gen_test.go @@ -23,8 +23,9 @@ func testAccOrganizationsPolicyAttachment_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccOrganizationsPolicyAttachment_Identity_Basic, - "ExistingResource": testAccOrganizationsPolicyAttachment_Identity_ExistingResource, + acctest.CtBasic: testAccOrganizationsPolicyAttachment_Identity_Basic, + "ExistingResource": testAccOrganizationsPolicyAttachment_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccOrganizationsPolicyAttachment_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/organizations/policy_identity_gen_test.go b/internal/service/organizations/policy_identity_gen_test.go index 6d5907bcf71d..fb28cbf86ef9 100644 --- a/internal/service/organizations/policy_identity_gen_test.go +++ b/internal/service/organizations/policy_identity_gen_test.go @@ -24,8 +24,9 @@ func testAccOrganizationsPolicy_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccOrganizationsPolicy_Identity_Basic, - "ExistingResource": testAccOrganizationsPolicy_Identity_ExistingResource, + acctest.CtBasic: testAccOrganizationsPolicy_Identity_Basic, + "ExistingResource": testAccOrganizationsPolicy_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccOrganizationsPolicy_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/organizations/resource_policy_identity_gen_test.go b/internal/service/organizations/resource_policy_identity_gen_test.go index f7945d0f3bfe..b0587a1bcc9d 100644 --- a/internal/service/organizations/resource_policy_identity_gen_test.go +++ b/internal/service/organizations/resource_policy_identity_gen_test.go @@ -24,8 +24,9 @@ func testAccOrganizationsResourcePolicy_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccOrganizationsResourcePolicy_Identity_Basic, - "ExistingResource": testAccOrganizationsResourcePolicy_Identity_ExistingResource, + acctest.CtBasic: testAccOrganizationsResourcePolicy_Identity_Basic, + "ExistingResource": testAccOrganizationsResourcePolicy_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccOrganizationsResourcePolicy_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/pinpointsmsvoicev2/phone_number.go b/internal/service/pinpointsmsvoicev2/phone_number.go index 963aa8b6d507..51eb16bff18b 100644 --- a/internal/service/pinpointsmsvoicev2/phone_number.go +++ b/internal/service/pinpointsmsvoicev2/phone_number.go @@ -35,6 +35,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/framework" fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + fwvalidators "github.com/hashicorp/terraform-provider-aws/internal/framework/validators" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" @@ -128,12 +129,15 @@ func (r *phoneNumberResource) Schema(ctx context.Context, request resource.Schem names.AttrTags: tftags.TagsAttribute(), names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), "two_way_channel_arn": schema.StringAttribute{ - CustomType: fwtypes.ARNType, - Optional: true, + Optional: true, Validators: []validator.String{ stringvalidator.AlsoRequires( path.MatchRelative().AtParent().AtName("two_way_channel_enabled"), ), + stringvalidator.Any( + fwvalidators.ARN(), + stringvalidator.RegexMatches(regexache.MustCompile(`^connect\.[a-z0-9-]+\.amazonaws.com$`), "Must be connect.{region}.amazonaws.com"), + ), }, }, "two_way_channel_role": schema.StringAttribute{ @@ -390,7 +394,7 @@ type phoneNumberResourceModel struct { Tags tftags.Map `tfsdk:"tags"` TagsAll tftags.Map `tfsdk:"tags_all"` Timeouts timeouts.Value `tfsdk:"timeouts"` - TwoWayChannelARN fwtypes.ARN `tfsdk:"two_way_channel_arn"` + TwoWayChannelARN types.String `tfsdk:"two_way_channel_arn"` TwoWayEnabled types.Bool `tfsdk:"two_way_channel_enabled"` TwoWayChannelRole fwtypes.ARN `tfsdk:"two_way_channel_role"` } diff --git a/internal/service/pinpointsmsvoicev2/phone_number_test.go b/internal/service/pinpointsmsvoicev2/phone_number_test.go index 916f23a682eb..13f67610d794 100644 --- a/internal/service/pinpointsmsvoicev2/phone_number_test.go +++ b/internal/service/pinpointsmsvoicev2/phone_number_test.go @@ -176,6 +176,42 @@ func TestAccPinpointSMSVoiceV2PhoneNumber_twoWayChannelRole(t *testing.T) { }, }) } + +func TestAccPinpointSMSVoiceV2PhoneNumber_twoWayChannelConnect(t *testing.T) { + ctx := acctest.Context(t) + + iamRoleName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_pinpointsmsvoicev2_phone_number.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckPhoneNumber(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.PinpointSMSVoiceV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckPhoneNumberDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccPhoneNumberConfig_two_way_channel_connect(iamRoleName), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("iso_country_code"), knownvalue.StringExact("US")), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("message_type"), knownvalue.StringExact("TRANSACTIONAL")), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("number_type"), knownvalue.StringExact("SIMULATOR")), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("two_way_channel_enabled"), knownvalue.Bool(true)), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("two_way_channel_arn"), knownvalue.StringRegexp(regexache.MustCompile(`^connect\.[a-z0-9-]+\.amazonaws\.com`))), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("two_way_channel_role"), tfknownvalue.GlobalARNRegexp("iam", regexache.MustCompile(fmt.Sprintf(`role/%s`, iamRoleName)))), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccPinpointSMSVoiceV2PhoneNumber_disappears(t *testing.T) { ctx := acctest.Context(t) var phoneNumber awstypes.PhoneNumberInformation @@ -441,6 +477,64 @@ resource "aws_pinpointsmsvoicev2_phone_number" "test" { `, snsTopicName, iamRoleName) } +func testAccPhoneNumberConfig_two_way_channel_connect(iamRoleName string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} +data "aws_region" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = "sts:AssumeRole", + Effect = "Allow", + Principal = { + Service = "sms-voice.amazonaws.com" + } + Condition = { + StringEquals = { + "aws:SourceAccount" = data.aws_caller_identity.current.account_id + } + } + } + ] + }) +} + +resource "aws_iam_role_policy" "test" { + name = "pinpointsmsvoicev2-sns-policy" + role = aws_iam_role.test.id + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "connect:SendChatIntegrationEvent", + ], + Resource = ["*"] + } + ] + }) +} + +resource "aws_pinpointsmsvoicev2_phone_number" "test" { + iso_country_code = "US" + message_type = "TRANSACTIONAL" + number_type = "SIMULATOR" + two_way_channel_arn = "connect.${data.aws_region.current.region}.amazonaws.com" + two_way_channel_role = aws_iam_role.test.arn + two_way_channel_enabled = true + number_capabilities = [ + "SMS", + "VOICE", + ] +} +`, iamRoleName) +} + func testAccPhoneNumberConfig_tags1(tagKey1, tagValue1 string) string { return fmt.Sprintf(` resource "aws_pinpointsmsvoicev2_phone_number" "test" { diff --git a/internal/service/rds/certificate_identity_gen_test.go b/internal/service/rds/certificate_identity_gen_test.go index 799578da978d..0b619fd409db 100644 --- a/internal/service/rds/certificate_identity_gen_test.go +++ b/internal/service/rds/certificate_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccRDSCertificate_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccRDSCertificate_Identity_Basic, - "ExistingResource": testAccRDSCertificate_Identity_ExistingResource, - "RegionOverride": testAccRDSCertificate_Identity_RegionOverride, + acctest.CtBasic: testAccRDSCertificate_Identity_Basic, + "ExistingResource": testAccRDSCertificate_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccRDSCertificate_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccRDSCertificate_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/rds/cluster_instance.go b/internal/service/rds/cluster_instance.go index 1431ea7674af..ae518f1d01d7 100644 --- a/internal/service/rds/cluster_instance.go +++ b/internal/service/rds/cluster_instance.go @@ -15,13 +15,13 @@ import ( "github.com/aws/aws-sdk-go-v2/service/rds" "github.com/aws/aws-sdk-go-v2/service/rds/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/retry" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -593,7 +593,7 @@ func waitDBClusterInstanceAvailable(ctx context.Context, conn *rds.Client, id st instanceStatusUpgrading, }, Target: []string{instanceStatusAvailable, instanceStatusStorageOptimization}, - Refresh: statusDBInstance(ctx, conn, id), + Refresh: statusDBInstance(conn, id), Timeout: timeout, MinTimeout: 10 * time.Second, Delay: 30 * time.Second, @@ -617,7 +617,7 @@ func waitDBClusterInstanceDeleted(ctx context.Context, conn *rds.Client, id stri instanceStatusModifying, }, Target: []string{}, - Refresh: statusDBInstance(ctx, conn, id), + Refresh: statusDBInstance(conn, id), Timeout: timeout, MinTimeout: 10 * time.Second, Delay: 30 * time.Second, diff --git a/internal/service/rds/instance.go b/internal/service/rds/instance.go index ab53ccc5d2b6..bba122a47706 100644 --- a/internal/service/rds/instance.go +++ b/internal/service/rds/instance.go @@ -23,7 +23,7 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + sdkretry "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -32,6 +32,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" + "github.com/hashicorp/terraform-provider-aws/internal/retry" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -2851,7 +2852,7 @@ func findDBInstances(ctx context.Context, conn *rds.Client, input *rds.DescribeD page, err := pages.NextPage(ctx, optFns...) if errs.IsA[*types.DBInstanceNotFoundFault](err) { - return nil, &retry.NotFoundError{ + return nil, &sdkretry.NotFoundError{ LastError: err, LastRequest: input, } @@ -2871,8 +2872,8 @@ func findDBInstances(ctx context.Context, conn *rds.Client, input *rds.DescribeD return output, nil } -func statusDBInstance(ctx context.Context, conn *rds.Client, id string, optFns ...func(*rds.Options)) retry.StateRefreshFunc { - return func() (any, string, error) { +func statusDBInstance(conn *rds.Client, id string, optFns ...func(*rds.Options)) retry.StateRefreshFunc { + return func(ctx context.Context) (any, string, error) { output, err := findDBInstanceByID(ctx, conn, id, optFns...) if tfresource.NotFound(err) { @@ -2916,7 +2917,7 @@ func waitDBInstanceAvailable(ctx context.Context, conn *rds.Client, id string, t instanceStatusUpgrading, }, Target: []string{instanceStatusAvailable, instanceStatusStorageOptimization}, - Refresh: statusDBInstance(ctx, conn, id), + Refresh: statusDBInstance(conn, id), Timeout: timeout, } options.Apply(stateConf) @@ -2950,7 +2951,7 @@ func waitDBInstanceStopped(ctx context.Context, conn *rds.Client, id string, tim instanceStatusUpgrading, }, Target: []string{instanceStatusStopped}, - Refresh: statusDBInstance(ctx, conn, id), + Refresh: statusDBInstance(conn, id), Timeout: timeout, ContinuousTargetOccurence: 2, Delay: 10 * time.Second, @@ -2994,7 +2995,7 @@ func waitDBInstanceDeleted(ctx context.Context, conn *rds.Client, id string, tim instanceStatusStorageOptimization, }, Target: []string{}, - Refresh: statusDBInstance(ctx, conn, id), + Refresh: statusDBInstance(conn, id), Timeout: timeout, } options.Apply(stateConf) @@ -3021,7 +3022,7 @@ func findBlueGreenDeploymentByID(ctx context.Context, conn *rds.Client, id strin // Eventual consistency check. if aws.ToString(output.BlueGreenDeploymentIdentifier) != id { - return nil, &retry.NotFoundError{ + return nil, &sdkretry.NotFoundError{ LastRequest: input, } } @@ -3047,7 +3048,7 @@ func findBlueGreenDeployments(ctx context.Context, conn *rds.Client, input *rds. page, err := pages.NextPage(ctx) if errs.IsA[*types.BlueGreenDeploymentNotFoundFault](err) { - return nil, &retry.NotFoundError{ + return nil, &sdkretry.NotFoundError{ LastError: err, LastRequest: input, } @@ -3067,8 +3068,8 @@ func findBlueGreenDeployments(ctx context.Context, conn *rds.Client, input *rds. return output, nil } -func statusBlueGreenDeployment(ctx context.Context, conn *rds.Client, id string) retry.StateRefreshFunc { - return func() (any, string, error) { +func statusBlueGreenDeployment(conn *rds.Client, id string) retry.StateRefreshFunc { + return func(ctx context.Context) (any, string, error) { output, err := findBlueGreenDeploymentByID(ctx, conn, id) if tfresource.NotFound(err) { @@ -3094,7 +3095,7 @@ func waitBlueGreenDeploymentAvailable(ctx context.Context, conn *rds.Client, id stateConf := &retry.StateChangeConf{ Pending: []string{"PROVISIONING"}, Target: []string{"AVAILABLE"}, - Refresh: statusBlueGreenDeployment(ctx, conn, id), + Refresh: statusBlueGreenDeployment(conn, id), Timeout: timeout, } options.Apply(stateConf) @@ -3120,7 +3121,7 @@ func waitBlueGreenDeploymentSwitchoverCompleted(ctx context.Context, conn *rds.C stateConf := &retry.StateChangeConf{ Pending: []string{"AVAILABLE", "SWITCHOVER_IN_PROGRESS"}, Target: []string{"SWITCHOVER_COMPLETED"}, - Refresh: statusBlueGreenDeployment(ctx, conn, id), + Refresh: statusBlueGreenDeployment(conn, id), Timeout: timeout, } options.Apply(stateConf) @@ -3150,7 +3151,7 @@ func waitBlueGreenDeploymentDeleted(ctx context.Context, conn *rds.Client, id st stateConf := &retry.StateChangeConf{ Pending: []string{"PROVISIONING", "AVAILABLE", "SWITCHOVER_IN_PROGRESS", "SWITCHOVER_COMPLETED", "INVALID_CONFIGURATION", "SWITCHOVER_FAILED", "DELETING"}, Target: []string{}, - Refresh: statusBlueGreenDeployment(ctx, conn, id), + Refresh: statusBlueGreenDeployment(conn, id), Timeout: timeout, } options.Apply(stateConf) diff --git a/internal/service/rds/instance_test.go b/internal/service/rds/instance_test.go index 4baada4cf577..c71372e93732 100644 --- a/internal/service/rds/instance_test.go +++ b/internal/service/rds/instance_test.go @@ -3065,7 +3065,6 @@ func TestAccRDSInstance_ReplicateSourceDB_mssqlDomain(t *testing.T) { rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) sourceResourceName := "aws_db_instance.source" resourceName := "aws_db_instance.test" - domain := acctest.RandomDomain().String() resource.ParallelTest(t, resource.TestCase{ @@ -11112,11 +11111,10 @@ resource "aws_security_group_rule" "test" { } resource "aws_directory_service_directory" "directory" { - name = %[2]q - password_wo = ephemeral.aws_secretsmanager_random_password.test.random_password - password_wo_version = 1 - type = "MicrosoftAD" - edition = "Standard" + name = %[2]q + password = "SuperSecretPassw0rd" + type = "MicrosoftAD" + edition = "Standard" vpc_settings { vpc_id = aws_vpc.test.id diff --git a/internal/service/rds/proxy.go b/internal/service/rds/proxy.go index 5845e8cfd496..07db1160be0b 100644 --- a/internal/service/rds/proxy.go +++ b/internal/service/rds/proxy.go @@ -54,7 +54,7 @@ func resourceProxy() *schema.Resource { }, "auth": { Type: schema.TypeSet, - Required: true, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "auth_scheme": { @@ -94,6 +94,12 @@ func resourceProxy() *schema.Resource { Type: schema.TypeBool, Optional: true, }, + "default_auth_scheme": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateDiagFunc: enum.Validate[types.DefaultAuthScheme](), + }, names.AttrEndpoint: { Type: schema.TypeString, Computed: true, @@ -147,7 +153,6 @@ func resourceProxyCreate(ctx context.Context, d *schema.ResourceData, meta any) name := d.Get(names.AttrName).(string) input := &rds.CreateDBProxyInput{ - Auth: expandUserAuthConfigs(d.Get("auth").(*schema.Set).List()), DBProxyName: aws.String(name), EngineFamily: types.EngineFamily(d.Get("engine_family").(string)), RoleArn: aws.String(d.Get(names.AttrRoleARN).(string)), @@ -155,10 +160,20 @@ func resourceProxyCreate(ctx context.Context, d *schema.ResourceData, meta any) VpcSubnetIds: flex.ExpandStringValueSet(d.Get("vpc_subnet_ids").(*schema.Set)), } + if v, ok := d.GetOk("auth"); ok && v.(*schema.Set).Len() > 0 { + input.Auth = expandUserAuthConfigs(v.(*schema.Set).List()) + } else { + input.Auth = []types.UserAuthConfig{} + } + if v, ok := d.GetOk("debug_logging"); ok { input.DebugLogging = aws.Bool(v.(bool)) } + if v, ok := d.GetOk("default_auth_scheme"); ok { + input.DefaultAuthScheme = types.DefaultAuthScheme(v.(string)) + } + if v, ok := d.GetOk("idle_client_timeout"); ok { input.IdleClientTimeout = aws.Int32(int32(v.(int))) } @@ -206,6 +221,7 @@ func resourceProxyRead(ctx context.Context, d *schema.ResourceData, meta any) di d.Set("auth", flattenUserAuthConfigInfos(dbProxy.Auth)) d.Set(names.AttrName, dbProxy.DBProxyName) d.Set("debug_logging", dbProxy.DebugLogging) + d.Set("default_auth_scheme", dbProxy.DefaultAuthScheme) d.Set("engine_family", dbProxy.EngineFamily) d.Set("idle_client_timeout", dbProxy.IdleClientTimeout) d.Set("require_tls", dbProxy.RequireTLS) @@ -224,7 +240,6 @@ func resourceProxyUpdate(ctx context.Context, d *schema.ResourceData, meta any) if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) { oName, nName := d.GetChange(names.AttrName) input := &rds.ModifyDBProxyInput{ - Auth: expandUserAuthConfigs(d.Get("auth").(*schema.Set).List()), DBProxyName: aws.String(oName.(string)), DebugLogging: aws.Bool(d.Get("debug_logging").(bool)), NewDBProxyName: aws.String(nName.(string)), @@ -232,6 +247,16 @@ func resourceProxyUpdate(ctx context.Context, d *schema.ResourceData, meta any) RoleArn: aws.String(d.Get(names.AttrRoleARN).(string)), } + if v, ok := d.GetOk("auth"); ok && v.(*schema.Set).Len() > 0 { + input.Auth = expandUserAuthConfigs(v.(*schema.Set).List()) + } else { + input.Auth = []types.UserAuthConfig{} + } + + if v, ok := d.GetOk("default_auth_scheme"); ok { + input.DefaultAuthScheme = types.DefaultAuthScheme(v.(string)) + } + if v, ok := d.GetOk("idle_client_timeout"); ok { input.IdleClientTimeout = aws.Int32(int32(v.(int))) } diff --git a/internal/service/rds/proxy_data_source.go b/internal/service/rds/proxy_data_source.go index 585640e03e9c..c4d8a2a254cf 100644 --- a/internal/service/rds/proxy_data_source.go +++ b/internal/service/rds/proxy_data_source.go @@ -59,6 +59,10 @@ func dataSourceProxy() *schema.Resource { Type: schema.TypeBool, Computed: true, }, + "default_auth_scheme": { + Type: schema.TypeString, + Computed: true, + }, names.AttrEndpoint: { Type: schema.TypeString, Computed: true, @@ -116,6 +120,7 @@ func dataSourceProxyRead(ctx context.Context, d *schema.ResourceData, meta any) d.Set(names.AttrARN, dbProxy.DBProxyArn) d.Set("auth", flattenUserAuthConfigInfos(dbProxy.Auth)) d.Set("debug_logging", dbProxy.DebugLogging) + d.Set("default_auth_scheme", dbProxy.DefaultAuthScheme) d.Set(names.AttrEndpoint, dbProxy.Endpoint) d.Set("engine_family", dbProxy.EngineFamily) d.Set("idle_client_timeout", dbProxy.IdleClientTimeout) diff --git a/internal/service/rds/proxy_data_source_test.go b/internal/service/rds/proxy_data_source_test.go index e614974350f3..3987b3a4f4c7 100644 --- a/internal/service/rds/proxy_data_source_test.go +++ b/internal/service/rds/proxy_data_source_test.go @@ -33,6 +33,7 @@ func TestAccRDSProxyDataSource_basic(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceName, names.AttrARN, resourceName, names.AttrARN), resource.TestCheckResourceAttrPair(dataSourceName, "auth.#", resourceName, "auth.#"), resource.TestCheckResourceAttrPair(dataSourceName, "debug_logging", resourceName, "debug_logging"), + resource.TestCheckResourceAttrPair(dataSourceName, "default_auth_scheme", resourceName, "default_auth_scheme"), resource.TestCheckResourceAttrPair(dataSourceName, names.AttrEndpoint, resourceName, names.AttrEndpoint), resource.TestCheckResourceAttrPair(dataSourceName, "engine_family", resourceName, "engine_family"), resource.TestCheckResourceAttrPair(dataSourceName, "idle_client_timeout", resourceName, "idle_client_timeout"), diff --git a/internal/service/rds/proxy_test.go b/internal/service/rds/proxy_test.go index 884f83084b82..81262141b61a 100644 --- a/internal/service/rds/proxy_test.go +++ b/internal/service/rds/proxy_test.go @@ -48,11 +48,12 @@ func TestAccRDSProxy_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "auth.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "auth.*", map[string]string{ "auth_scheme": "SECRETS", - "client_password_auth_type": "MYSQL_NATIVE_PASSWORD", + "client_password_auth_type": "MYSQL_CACHING_SHA2_PASSWORD", names.AttrDescription: "test", "iam_auth": "DISABLED", }), resource.TestCheckResourceAttr(resourceName, "debug_logging", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "default_auth_scheme", string(types.DefaultAuthSchemeNone)), resource.TestMatchResourceAttr(resourceName, names.AttrEndpoint, regexache.MustCompile(`^[\w\-\.]+\.rds\.amazonaws\.com$`)), resource.TestCheckResourceAttr(resourceName, "idle_client_timeout", "1800"), resource.TestCheckResourceAttr(resourceName, "require_tls", acctest.CtTrue), @@ -446,6 +447,97 @@ func TestAccRDSProxy_authSecretARN(t *testing.T) { }) } +func TestAccRDSProxy_defaultAuthScheme(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var v types.DBProxy + resourceName := "aws_db_proxy.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccDBProxyPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.RDSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckProxyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccProxyConfig_defaultAuthSchemeIAMAUTH(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckProxyExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, "engine_family", "MYSQL"), + acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "rds", regexache.MustCompile(`db-proxy:.+`)), + resource.TestCheckResourceAttr(resourceName, "auth.#", "0"), + resource.TestCheckResourceAttr(resourceName, "debug_logging", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "default_auth_scheme", string(types.DefaultAuthSchemeIamAuth)), + resource.TestMatchResourceAttr(resourceName, names.AttrEndpoint, regexache.MustCompile(`^[\w\-\.]+\.rds\.amazonaws\.com$`)), + resource.TestCheckResourceAttr(resourceName, "idle_client_timeout", "1800"), + resource.TestCheckResourceAttr(resourceName, "require_tls", acctest.CtTrue), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, "vpc_subnet_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "vpc_subnet_ids.*", "aws_subnet.test.0", names.AttrID), + resource.TestCheckTypeSetElemAttrPair(resourceName, "vpc_subnet_ids.*", "aws_subnet.test.1", names.AttrID), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccProxyConfig_defaultAuthSchemeNONE(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckProxyExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, "engine_family", "MYSQL"), + acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "rds", regexache.MustCompile(`db-proxy:.+`)), + resource.TestCheckResourceAttr(resourceName, "auth.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "auth.*", map[string]string{ + "auth_scheme": "SECRETS", + "client_password_auth_type": "MYSQL_CACHING_SHA2_PASSWORD", + names.AttrDescription: "test", + "iam_auth": "DISABLED", + }), + resource.TestCheckResourceAttr(resourceName, "debug_logging", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "default_auth_scheme", string(types.DefaultAuthSchemeNone)), + resource.TestMatchResourceAttr(resourceName, names.AttrEndpoint, regexache.MustCompile(`^[\w\-\.]+\.rds\.amazonaws\.com$`)), + resource.TestCheckResourceAttr(resourceName, "idle_client_timeout", "1800"), + resource.TestCheckResourceAttr(resourceName, "require_tls", acctest.CtTrue), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, "vpc_subnet_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "vpc_subnet_ids.*", "aws_subnet.test.0", names.AttrID), + resource.TestCheckTypeSetElemAttrPair(resourceName, "vpc_subnet_ids.*", "aws_subnet.test.1", names.AttrID), + ), + }, + { + Config: testAccProxyConfig_defaultAuthSchemeIAMAUTH(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckProxyExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, "engine_family", "MYSQL"), + acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "rds", regexache.MustCompile(`db-proxy:.+`)), + resource.TestCheckResourceAttr(resourceName, "auth.#", "0"), + resource.TestCheckResourceAttr(resourceName, "debug_logging", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "default_auth_scheme", string(types.DefaultAuthSchemeIamAuth)), + resource.TestMatchResourceAttr(resourceName, names.AttrEndpoint, regexache.MustCompile(`^[\w\-\.]+\.rds\.amazonaws\.com$`)), + resource.TestCheckResourceAttr(resourceName, "idle_client_timeout", "1800"), + resource.TestCheckResourceAttr(resourceName, "require_tls", acctest.CtTrue), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, "vpc_subnet_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "vpc_subnet_ids.*", "aws_subnet.test.0", names.AttrID), + resource.TestCheckTypeSetElemAttrPair(resourceName, "vpc_subnet_ids.*", "aws_subnet.test.1", names.AttrID), + ), + }, + }, + }) +} + func TestAccRDSProxy_tags(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -955,6 +1047,57 @@ resource "aws_secretsmanager_secret_version" "test2" { `, rName, nName)) } +func testAccProxyConfig_defaultAuthSchemeIAMAUTH(rName string) string { + return acctest.ConfigCompose(testAccProxyConfig_base(rName), fmt.Sprintf(` +resource "aws_db_proxy" "test" { + depends_on = [ + aws_secretsmanager_secret_version.test, + aws_iam_role_policy.test + ] + + name = %[1]q + debug_logging = false + engine_family = "MYSQL" + idle_client_timeout = 1800 + require_tls = true + role_arn = aws_iam_role.test.arn + vpc_security_group_ids = [aws_security_group.test.id] + vpc_subnet_ids = aws_subnet.test[*].id + + default_auth_scheme = "IAM_AUTH" +} +`, rName)) +} + +func testAccProxyConfig_defaultAuthSchemeNONE(rName string) string { + return acctest.ConfigCompose(testAccProxyConfig_base(rName), fmt.Sprintf(` +resource "aws_db_proxy" "test" { + depends_on = [ + aws_secretsmanager_secret_version.test, + aws_iam_role_policy.test + ] + + name = %[1]q + debug_logging = false + engine_family = "MYSQL" + idle_client_timeout = 1800 + require_tls = true + role_arn = aws_iam_role.test.arn + vpc_security_group_ids = [aws_security_group.test.id] + vpc_subnet_ids = aws_subnet.test[*].id + + auth { + auth_scheme = "SECRETS" + description = "test" + iam_auth = "DISABLED" + secret_arn = aws_secretsmanager_secret.test.arn + } + + default_auth_scheme = "NONE" +} +`, rName)) +} + func testAccProxyConfig_tags1(rName, tagKey1, tagValue1 string) string { return acctest.ConfigCompose(testAccProxyConfig_base(rName), fmt.Sprintf(` resource "aws_db_proxy" "test" { diff --git a/internal/service/redshiftserverless/namespace.go b/internal/service/redshiftserverless/namespace.go index 715867a1a4a7..316ba2a9ccb4 100644 --- a/internal/service/redshiftserverless/namespace.go +++ b/internal/service/redshiftserverless/namespace.go @@ -226,7 +226,7 @@ func resourceNamespaceRead(ctx context.Context, d *schema.ResourceData, meta any d.Set("default_iam_role_arn", output.DefaultIamRoleArn) d.Set("iam_roles", flattenNamespaceIAMRoles(output.IamRoles)) d.Set(names.AttrKMSKeyID, output.KmsKeyId) - d.Set("log_exports", flex.FlattenStringyValueSet[awstypes.LogExport](output.LogExports)) + d.Set("log_exports", output.LogExports) d.Set("namespace_id", output.NamespaceId) d.Set("namespace_name", output.NamespaceName) diff --git a/internal/service/resourceexplorer2/index_identity_gen_test.go b/internal/service/resourceexplorer2/index_identity_gen_test.go index 90b507d641d4..5b1db46af303 100644 --- a/internal/service/resourceexplorer2/index_identity_gen_test.go +++ b/internal/service/resourceexplorer2/index_identity_gen_test.go @@ -22,9 +22,10 @@ func testAccResourceExplorer2Index_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccResourceExplorer2Index_Identity_Basic, - "ExistingResource": testAccResourceExplorer2Index_Identity_ExistingResource, - "RegionOverride": testAccResourceExplorer2Index_Identity_RegionOverride, + acctest.CtBasic: testAccResourceExplorer2Index_Identity_Basic, + "ExistingResource": testAccResourceExplorer2Index_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccResourceExplorer2Index_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccResourceExplorer2Index_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/resourceexplorer2/view_identity_gen_test.go b/internal/service/resourceexplorer2/view_identity_gen_test.go index 2ba6c9be33e4..6c5e115dc002 100644 --- a/internal/service/resourceexplorer2/view_identity_gen_test.go +++ b/internal/service/resourceexplorer2/view_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccResourceExplorer2View_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccResourceExplorer2View_Identity_Basic, - "ExistingResource": testAccResourceExplorer2View_Identity_ExistingResource, - "RegionOverride": testAccResourceExplorer2View_Identity_RegionOverride, + acctest.CtBasic: testAccResourceExplorer2View_Identity_Basic, + "ExistingResource": testAccResourceExplorer2View_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccResourceExplorer2View_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccResourceExplorer2View_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/route53recoverycontrolconfig/cluster.go b/internal/service/route53recoverycontrolconfig/cluster.go index ca885bd83dac..e7d1e2801dd6 100644 --- a/internal/service/route53recoverycontrolconfig/cluster.go +++ b/internal/service/route53recoverycontrolconfig/cluster.go @@ -18,11 +18,13 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) // @SDKResource("aws_route53recoverycontrolconfig_cluster", name="Cluster") +// @Tags(identifierAttribute="arn") func resourceCluster() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceClusterCreate, @@ -69,6 +71,8 @@ func resourceCluster() *schema.Resource { Type: schema.TypeString, Computed: true, }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), }, } } @@ -103,6 +107,10 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta any return sdkdiag.AppendErrorf(diags, "waiting for Route53 Recovery Control Config Cluster (%s) to be Deployed: %s", d.Id(), err) } + if err := createTags(ctx, conn, d.Id(), getTagsIn(ctx)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting Route53 Recovery Control Config Cluster (%s) tags: %s", d.Id(), err) + } + return append(diags, resourceClusterRead(ctx, d, meta)...) } @@ -138,26 +146,28 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta any var diags diag.Diagnostics conn := meta.(*conns.AWSClient).Route53RecoveryControlConfigClient(ctx) - input := &r53rcc.UpdateClusterInput{ - ClusterArn: aws.String(d.Id()), - } + if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) { + input := &r53rcc.UpdateClusterInput{ + ClusterArn: aws.String(d.Id()), + } - if d.HasChanges("network_type") { - input.NetworkType = awstypes.NetworkType(d.Get("network_type").(string)) - } + if d.HasChanges("network_type") { + input.NetworkType = awstypes.NetworkType(d.Get("network_type").(string)) + } - output, err := conn.UpdateCluster(ctx, input) + output, err := conn.UpdateCluster(ctx, input) - if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Cluster: %s", err) - } + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Cluster: %s", err) + } - if output == nil || output.Cluster == nil { - return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Cluster: empty response") - } + if output == nil || output.Cluster == nil { + return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Cluster: empty response") + } - if _, err := waitClusterUpdated(ctx, conn, d.Id()); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Route53 Recovery Control Config Cluster (%s) to be Updated: %s", d.Id(), err) + if _, err := waitClusterUpdated(ctx, conn, d.Id()); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Route53 Recovery Control Config Cluster (%s) to be Updated: %s", d.Id(), err) + } } return append(diags, resourceClusterRead(ctx, d, meta)...) diff --git a/internal/service/route53recoverycontrolconfig/cluster_test.go b/internal/service/route53recoverycontrolconfig/cluster_test.go index aa049df6e925..ff5d597bb4d0 100644 --- a/internal/service/route53recoverycontrolconfig/cluster_test.go +++ b/internal/service/route53recoverycontrolconfig/cluster_test.go @@ -42,6 +42,8 @@ func testAccCluster_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), resource.TestCheckResourceAttr(resourceName, "cluster_endpoints.#", "5"), resource.TestCheckResourceAttr(resourceName, "network_type", string(awstypes.NetworkTypeIpv4)), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsAllPercent, "0"), ), }, { @@ -114,6 +116,65 @@ func testAccCluster_networkType(t *testing.T) { }) } +func testAccCluster_tags(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_route53recoverycontrolconfig_cluster.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.Route53RecoveryControlConfigEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.Route53RecoveryControlConfigServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckClusterDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccClusterConfig_tags1(rName, acctest.CtKey1, acctest.CtValue1), + Check: resource.ComposeTestCheckFunc( + testAccCheckClusterExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "cluster_endpoints.#", "5"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_endpoints"}, + }, + + { + Config: testAccClusterConfig_tags2(rName, acctest.CtKey1, acctest.CtValue1Updated, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckClusterExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "cluster_endpoints.#", "5"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "2"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1Updated), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + { + Config: testAccClusterConfig_tags1(rName, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckClusterExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "cluster_endpoints.#", "5"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + }, + }) +} + func testAccCluster_disappears(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -197,3 +258,26 @@ resource "aws_route53recoverycontrolconfig_cluster" "test" { } `, rName, networkType) } + +func testAccClusterConfig_tags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_route53recoverycontrolconfig_cluster" "test" { + name = %[1]q + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccClusterConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_route53recoverycontrolconfig_cluster" "test" { + name = %[1]q + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} diff --git a/internal/service/route53recoverycontrolconfig/control_panel.go b/internal/service/route53recoverycontrolconfig/control_panel.go index 5cf0d3180604..877e34d6f03d 100644 --- a/internal/service/route53recoverycontrolconfig/control_panel.go +++ b/internal/service/route53recoverycontrolconfig/control_panel.go @@ -17,11 +17,13 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) // @SDKResource("aws_route53recoverycontrolconfig_control_panel", name="Control Panel") +// @Tags(identifierAttribute="arn") func resourceControlPanel() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceControlPanelCreate, @@ -57,6 +59,8 @@ func resourceControlPanel() *schema.Resource { Type: schema.TypeString, Computed: true, }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), }, } } @@ -88,6 +92,10 @@ func resourceControlPanelCreate(ctx context.Context, d *schema.ResourceData, met return sdkdiag.AppendErrorf(diags, "waiting for Route53 Recovery Control Config Control Panel (%s) to be Deployed: %s", d.Id(), err) } + if err := createTags(ctx, conn, d.Id(), getTagsIn(ctx)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting Route53 Recovery Control Config Control Panel (%s) tags: %s", d.Id(), err) + } + return append(diags, resourceControlPanelRead(ctx, d, meta)...) } @@ -121,15 +129,17 @@ func resourceControlPanelUpdate(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).Route53RecoveryControlConfigClient(ctx) - input := &r53rcc.UpdateControlPanelInput{ - ControlPanelName: aws.String(d.Get(names.AttrName).(string)), - ControlPanelArn: aws.String(d.Get(names.AttrARN).(string)), - } + if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) { + input := &r53rcc.UpdateControlPanelInput{ + ControlPanelName: aws.String(d.Get(names.AttrName).(string)), + ControlPanelArn: aws.String(d.Get(names.AttrARN).(string)), + } - _, err := conn.UpdateControlPanel(ctx, input) + _, err := conn.UpdateControlPanel(ctx, input) - if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Control Panel: %s", err) + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Control Panel: %s", err) + } } return append(diags, resourceControlPanelRead(ctx, d, meta)...) diff --git a/internal/service/route53recoverycontrolconfig/control_panel_test.go b/internal/service/route53recoverycontrolconfig/control_panel_test.go index 69e272a7a22e..b0b383be6b65 100644 --- a/internal/service/route53recoverycontrolconfig/control_panel_test.go +++ b/internal/service/route53recoverycontrolconfig/control_panel_test.go @@ -40,6 +40,8 @@ func testAccControlPanel_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), resource.TestCheckResourceAttr(resourceName, "default_control_panel", acctest.CtFalse), resource.TestCheckResourceAttr(resourceName, "routing_control_count", "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsAllPercent, "0"), ), }, { @@ -51,6 +53,65 @@ func testAccControlPanel_basic(t *testing.T) { }) } +func testAccControlPanel_tags(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_route53recoverycontrolconfig_control_panel.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.Route53RecoveryControlConfigEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.Route53RecoveryControlConfigServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckControlPanelDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccControlPanelConfig_tags1(rName, acctest.CtKey1, acctest.CtValue1), + Check: resource.ComposeTestCheckFunc( + testAccCheckControlPanelExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "default_control_panel", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "routing_control_count", "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccControlPanelConfig_tags2(rName, acctest.CtKey1, acctest.CtValue1Updated, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckControlPanelExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "default_control_panel", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "routing_control_count", "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "2"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1Updated), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + { + Config: testAccControlPanelConfig_tags1(rName, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckControlPanelExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "default_control_panel", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "routing_control_count", "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + }, + }) +} func testAccControlPanel_disappears(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -134,3 +195,28 @@ resource "aws_route53recoverycontrolconfig_control_panel" "test" { } `, rName)) } + +func testAccControlPanelConfig_tags1(rName, tagKey1, tagValue1 string) string { + return acctest.ConfigCompose(testAccClusterSetUp(rName), fmt.Sprintf(` +resource "aws_route53recoverycontrolconfig_control_panel" "test" { + name = %[1]q + cluster_arn = aws_route53recoverycontrolconfig_cluster.test.arn + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1)) +} + +func testAccControlPanelConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return acctest.ConfigCompose(testAccClusterSetUp(rName), fmt.Sprintf(` +resource "aws_route53recoverycontrolconfig_control_panel" "test" { + name = %[1]q + cluster_arn = aws_route53recoverycontrolconfig_cluster.test.arn + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) +} diff --git a/internal/service/route53recoverycontrolconfig/generate.go b/internal/service/route53recoverycontrolconfig/generate.go index 18b8964a30ff..6dadefa662d5 100644 --- a/internal/service/route53recoverycontrolconfig/generate.go +++ b/internal/service/route53recoverycontrolconfig/generate.go @@ -1,6 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 +//go:generate go run ../../generate/tags/main.go -ServiceTagsMap -CreateTags -ListTags -UpdateTags -KVTValues //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. diff --git a/internal/service/route53recoverycontrolconfig/route53recoverycontrolconfig_test.go b/internal/service/route53recoverycontrolconfig/route53recoverycontrolconfig_test.go index 961b61d0e0d6..4f26adf58d75 100644 --- a/internal/service/route53recoverycontrolconfig/route53recoverycontrolconfig_test.go +++ b/internal/service/route53recoverycontrolconfig/route53recoverycontrolconfig_test.go @@ -19,10 +19,12 @@ func TestAccRoute53RecoveryControlConfig_serial(t *testing.T) { acctest.CtBasic: testAccCluster_basic, acctest.CtDisappears: testAccCluster_disappears, "networkType": testAccCluster_networkType, + "tags": testAccCluster_tags, }, "ControlPanel": { acctest.CtBasic: testAccControlPanel_basic, acctest.CtDisappears: testAccControlPanel_disappears, + "tags": testAccControlPanel_tags, }, "RoutingControl": { acctest.CtBasic: testAccRoutingControl_basic, @@ -33,6 +35,7 @@ func TestAccRoute53RecoveryControlConfig_serial(t *testing.T) { "assertionRule": testAccSafetyRule_assertionRule, "gatingRule": testAccSafetyRule_gatingRule, acctest.CtDisappears: testAccSafetyRule_disappears, + "tags": testAccSafetyRule_tags, }, } diff --git a/internal/service/route53recoverycontrolconfig/safety_rule.go b/internal/service/route53recoverycontrolconfig/safety_rule.go index ce1f9e18f207..7c2be625d463 100644 --- a/internal/service/route53recoverycontrolconfig/safety_rule.go +++ b/internal/service/route53recoverycontrolconfig/safety_rule.go @@ -19,11 +19,13 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) // @SDKResource("aws_route53recoverycontrolconfig_safety_rule", name="Safety Rule") +// @Tags(identifierAttribute="arn") func resourceSafetyRule() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceSafetyRuleCreate, @@ -99,6 +101,8 @@ func resourceSafetyRule() *schema.Resource { Type: schema.TypeString, Computed: true, }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), "target_controls": { Type: schema.TypeList, Optional: true, @@ -271,6 +275,10 @@ func createAssertionRule(ctx context.Context, d *schema.ResourceData, meta any) return sdkdiag.AppendErrorf(diags, "waiting for Route53 Recovery Control Config Assertion Rule (%s) to be Deployed: %s", d.Id(), err) } + if err := createTags(ctx, conn, d.Id(), getTagsIn(ctx)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting Route53 Recovery Control Config Assertion Rule (%s) tags: %s", d.Id(), err) + } + return append(diags, resourceSafetyRuleRead(ctx, d, meta)...) } @@ -306,7 +314,11 @@ func createGatingRule(ctx context.Context, d *schema.ResourceData, meta any) dia d.SetId(aws.ToString(result.SafetyRuleArn)) if _, err := waitSafetyRuleCreated(ctx, conn, d.Id()); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Route53 Recovery Control Config Assertion Rule (%s) to be Deployed: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Route53 Recovery Control Config Gating Rule (%s) to be Deployed: %s", d.Id(), err) + } + + if err := createTags(ctx, conn, d.Id(), getTagsIn(ctx)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting Route53 Recovery Control Config Gating Rule (%s) tags: %s", d.Id(), err) } return append(diags, resourceSafetyRuleRead(ctx, d, meta)...) @@ -316,60 +328,63 @@ func updateAssertionRule(ctx context.Context, d *schema.ResourceData, meta any) var diags diag.Diagnostics conn := meta.(*conns.AWSClient).Route53RecoveryControlConfigClient(ctx) - assertionRuleUpdate := &awstypes.AssertionRuleUpdate{ - SafetyRuleArn: aws.String(d.Get(names.AttrARN).(string)), - } + if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) { + assertionRuleUpdate := &awstypes.AssertionRuleUpdate{ + SafetyRuleArn: aws.String(d.Get(names.AttrARN).(string)), + } - if d.HasChange(names.AttrName) { - assertionRuleUpdate.Name = aws.String(d.Get(names.AttrName).(string)) - } + if d.HasChange(names.AttrName) { + assertionRuleUpdate.Name = aws.String(d.Get(names.AttrName).(string)) + } - if d.HasChange("wait_period_ms") { - assertionRuleUpdate.WaitPeriodMs = aws.Int32(int32(d.Get("wait_period_ms").(int))) - } + if d.HasChange("wait_period_ms") { + assertionRuleUpdate.WaitPeriodMs = aws.Int32(int32(d.Get("wait_period_ms").(int))) + } - input := &r53rcc.UpdateSafetyRuleInput{ - AssertionRuleUpdate: assertionRuleUpdate, - } + input := &r53rcc.UpdateSafetyRuleInput{ + AssertionRuleUpdate: assertionRuleUpdate, + } - _, err := conn.UpdateSafetyRule(ctx, input) + _, err := conn.UpdateSafetyRule(ctx, input) - if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Assertion Rule: %s", err) + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Assertion Rule: %s", err) + } } - return append(diags, sdkdiag.WrapDiagsf(resourceControlPanelRead(ctx, d, meta), "updating Route53 Recovery Control Config Assertion Rule")...) + return append(diags, sdkdiag.WrapDiagsf(resourceSafetyRuleRead(ctx, d, meta), "updating Route53 Recovery Control Config Assertion Rule")...) } func updateGatingRule(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).Route53RecoveryControlConfigClient(ctx) - gatingRuleUpdate := &awstypes.GatingRuleUpdate{ - SafetyRuleArn: aws.String(d.Get(names.AttrARN).(string)), - } + if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) { + gatingRuleUpdate := &awstypes.GatingRuleUpdate{ + SafetyRuleArn: aws.String(d.Get(names.AttrARN).(string)), + } - if d.HasChange(names.AttrName) { - gatingRuleUpdate.Name = aws.String(d.Get(names.AttrName).(string)) - } + if d.HasChange(names.AttrName) { + gatingRuleUpdate.Name = aws.String(d.Get(names.AttrName).(string)) + } - if d.HasChange("wait_period_ms") { - gatingRuleUpdate.WaitPeriodMs = aws.Int32(int32(d.Get("wait_period_ms").(int))) - } + if d.HasChange("wait_period_ms") { + gatingRuleUpdate.WaitPeriodMs = aws.Int32(int32(d.Get("wait_period_ms").(int))) + } - input := &r53rcc.UpdateSafetyRuleInput{ - GatingRuleUpdate: gatingRuleUpdate, - } + input := &r53rcc.UpdateSafetyRuleInput{ + GatingRuleUpdate: gatingRuleUpdate, + } - _, err := conn.UpdateSafetyRule(ctx, input) + _, err := conn.UpdateSafetyRule(ctx, input) - if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Gating Rule: %s", err) + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating Route53 Recovery Control Config Gating Rule: %s", err) + } } - return append(diags, sdkdiag.WrapDiagsf(resourceControlPanelRead(ctx, d, meta), "updating Route53 Recovery Control Config Gating Rule")...) + return append(diags, sdkdiag.WrapDiagsf(resourceSafetyRuleRead(ctx, d, meta), "updating Route53 Recovery Control Config Gating Rule")...) } - func findSafetyRuleByARN(ctx context.Context, conn *r53rcc.Client, arn string) (*r53rcc.DescribeSafetyRuleOutput, error) { input := &r53rcc.DescribeSafetyRuleInput{ SafetyRuleArn: aws.String(arn), diff --git a/internal/service/route53recoverycontrolconfig/safety_rule_test.go b/internal/service/route53recoverycontrolconfig/safety_rule_test.go index 0e74d801b115..2c7ad180fa97 100644 --- a/internal/service/route53recoverycontrolconfig/safety_rule_test.go +++ b/internal/service/route53recoverycontrolconfig/safety_rule_test.go @@ -41,6 +41,8 @@ func testAccSafetyRule_assertionRule(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "wait_period_ms", "5000"), resource.TestCheckResourceAttr(resourceName, "asserted_controls.#", "1"), resource.TestCheckResourceAttrPair(resourceName, "control_panel_arn", "aws_route53recoverycontrolconfig_control_panel.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsAllPercent, "0"), ), }, { @@ -113,6 +115,72 @@ func testAccSafetyRule_gatingRule(t *testing.T) { }) } +func testAccSafetyRule_tags(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_route53recoverycontrolconfig_safety_rule.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.Route53RecoveryControlConfigEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.Route53RecoveryControlConfigServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSafetyRuleDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSafetyRuleConfig_routingControl_tags1(rName, acctest.CtKey1, acctest.CtValue1), + Check: resource.ComposeTestCheckFunc( + testAccCheckSafetyRuleExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "wait_period_ms", "5000"), + resource.TestCheckResourceAttr(resourceName, "target_controls.#", "1"), + resource.TestCheckResourceAttr(resourceName, "gating_controls.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "control_panel_arn", "aws_route53recoverycontrolconfig_control_panel.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccSafetyRuleConfig_routingControl_tags2(rName, acctest.CtKey1, acctest.CtValue1Updated, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckSafetyRuleExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "wait_period_ms", "5000"), + resource.TestCheckResourceAttr(resourceName, "target_controls.#", "1"), + resource.TestCheckResourceAttr(resourceName, "gating_controls.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "control_panel_arn", "aws_route53recoverycontrolconfig_control_panel.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "2"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1Updated), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + { + Config: testAccSafetyRuleConfig_routingControl_tags1(rName, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckSafetyRuleExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, "DEPLOYED"), + resource.TestCheckResourceAttr(resourceName, "wait_period_ms", "5000"), + resource.TestCheckResourceAttr(resourceName, "target_controls.#", "1"), + resource.TestCheckResourceAttr(resourceName, "gating_controls.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "control_panel_arn", "aws_route53recoverycontrolconfig_control_panel.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + }, + }) +} + func testAccCheckSafetyRuleDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).Route53RecoveryControlConfigClient(ctx) @@ -218,3 +286,76 @@ resource "aws_route53recoverycontrolconfig_safety_rule" "test" { } `, rName) } + +func testAccSafetyRuleConfig_routingControl_tags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_route53recoverycontrolconfig_cluster" "test" { + name = %[1]q +} + +resource "aws_route53recoverycontrolconfig_control_panel" "test" { + name = %[1]q + cluster_arn = aws_route53recoverycontrolconfig_cluster.test.arn +} + +resource "aws_route53recoverycontrolconfig_routing_control" "test" { + name = %[1]q + cluster_arn = aws_route53recoverycontrolconfig_cluster.test.arn + control_panel_arn = aws_route53recoverycontrolconfig_control_panel.test.arn +} + +resource "aws_route53recoverycontrolconfig_safety_rule" "test" { + name = %[1]q + control_panel_arn = aws_route53recoverycontrolconfig_control_panel.test.arn + wait_period_ms = 5000 + gating_controls = [aws_route53recoverycontrolconfig_routing_control.test.arn] + target_controls = [aws_route53recoverycontrolconfig_routing_control.test.arn] + + rule_config { + inverted = false + threshold = 0 + type = "AND" + } + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccSafetyRuleConfig_routingControl_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_route53recoverycontrolconfig_cluster" "test" { + name = %[1]q +} + +resource "aws_route53recoverycontrolconfig_control_panel" "test" { + name = %[1]q + cluster_arn = aws_route53recoverycontrolconfig_cluster.test.arn +} + +resource "aws_route53recoverycontrolconfig_routing_control" "test" { + name = %[1]q + cluster_arn = aws_route53recoverycontrolconfig_cluster.test.arn + control_panel_arn = aws_route53recoverycontrolconfig_control_panel.test.arn +} + +resource "aws_route53recoverycontrolconfig_safety_rule" "test" { + name = %[1]q + control_panel_arn = aws_route53recoverycontrolconfig_control_panel.test.arn + wait_period_ms = 5000 + gating_controls = [aws_route53recoverycontrolconfig_routing_control.test.arn] + target_controls = [aws_route53recoverycontrolconfig_routing_control.test.arn] + + rule_config { + inverted = false + threshold = 0 + type = "AND" + } + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} diff --git a/internal/service/route53recoverycontrolconfig/service_package_gen.go b/internal/service/route53recoverycontrolconfig/service_package_gen.go index e45e202f6571..a79003fd959e 100644 --- a/internal/service/route53recoverycontrolconfig/service_package_gen.go +++ b/internal/service/route53recoverycontrolconfig/service_package_gen.go @@ -36,13 +36,19 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*inttypes.ServicePa Factory: resourceCluster, TypeName: "aws_route53recoverycontrolconfig_cluster", Name: "Cluster", - Region: unique.Make(inttypes.ResourceRegionDisabled()), + Tags: unique.Make(inttypes.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrARN, + }), + Region: unique.Make(inttypes.ResourceRegionDisabled()), }, { Factory: resourceControlPanel, TypeName: "aws_route53recoverycontrolconfig_control_panel", Name: "Control Panel", - Region: unique.Make(inttypes.ResourceRegionDisabled()), + Tags: unique.Make(inttypes.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrARN, + }), + Region: unique.Make(inttypes.ResourceRegionDisabled()), }, { Factory: resourceRoutingControl, @@ -54,7 +60,10 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*inttypes.ServicePa Factory: resourceSafetyRule, TypeName: "aws_route53recoverycontrolconfig_safety_rule", Name: "Safety Rule", - Region: unique.Make(inttypes.ResourceRegionDisabled()), + Tags: unique.Make(inttypes.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrARN, + }), + Region: unique.Make(inttypes.ResourceRegionDisabled()), }, } } diff --git a/internal/service/route53recoverycontrolconfig/tags_gen.go b/internal/service/route53recoverycontrolconfig/tags_gen.go new file mode 100644 index 000000000000..98e5fd46b7bd --- /dev/null +++ b/internal/service/route53recoverycontrolconfig/tags_gen.go @@ -0,0 +1,137 @@ +// Code generated by internal/generate/tags/main.go; DO NOT EDIT. +package route53recoverycontrolconfig + +import ( + "context" + + "github.com/YakDriver/smarterr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/logging" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/types/option" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// listTags lists route53recoverycontrolconfig service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func listTags(ctx context.Context, conn *route53recoverycontrolconfig.Client, identifier string, optFns ...func(*route53recoverycontrolconfig.Options)) (tftags.KeyValueTags, error) { + input := route53recoverycontrolconfig.ListTagsForResourceInput{ + ResourceArn: aws.String(identifier), + } + + output, err := conn.ListTagsForResource(ctx, &input, optFns...) + + if err != nil { + return tftags.New(ctx, nil), smarterr.NewError(err) + } + + return keyValueTags(ctx, output.Tags), nil +} + +// ListTags lists route53recoverycontrolconfig service tags and set them in Context. +// It is called from outside this package. +func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { + tags, err := listTags(ctx, meta.(*conns.AWSClient).Route53RecoveryControlConfigClient(ctx), identifier) + + if err != nil { + return smarterr.NewError(err) + } + + if inContext, ok := tftags.FromContext(ctx); ok { + inContext.TagsOut = option.Some(tags) + } + + return nil +} + +// map[string]string handling + +// svcTags returns route53recoverycontrolconfig service tags. +func svcTags(tags tftags.KeyValueTags) map[string]string { + return tags.Map() +} + +// keyValueTags creates tftags.KeyValueTags from route53recoverycontrolconfig service tags. +func keyValueTags(ctx context.Context, tags map[string]string) tftags.KeyValueTags { + return tftags.New(ctx, tags) +} + +// getTagsIn returns route53recoverycontrolconfig service tags from Context. +// nil is returned if there are no input tags. +func getTagsIn(ctx context.Context) map[string]string { + if inContext, ok := tftags.FromContext(ctx); ok { + if tags := svcTags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { + return tags + } + } + + return nil +} + +// setTagsOut sets route53recoverycontrolconfig service tags in Context. +func setTagsOut(ctx context.Context, tags map[string]string) { + if inContext, ok := tftags.FromContext(ctx); ok { + inContext.TagsOut = option.Some(keyValueTags(ctx, tags)) + } +} + +// createTags creates route53recoverycontrolconfig service tags for new resources. +func createTags(ctx context.Context, conn *route53recoverycontrolconfig.Client, identifier string, tags map[string]string, optFns ...func(*route53recoverycontrolconfig.Options)) error { + if len(tags) == 0 { + return nil + } + + return updateTags(ctx, conn, identifier, nil, tags, optFns...) +} + +// updateTags updates route53recoverycontrolconfig service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func updateTags(ctx context.Context, conn *route53recoverycontrolconfig.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*route53recoverycontrolconfig.Options)) error { + oldTags := tftags.New(ctx, oldTagsMap) + newTags := tftags.New(ctx, newTagsMap) + + ctx = tflog.SetField(ctx, logging.KeyResourceId, identifier) + + removedTags := oldTags.Removed(newTags) + removedTags = removedTags.IgnoreSystem(names.Route53RecoveryControlConfig) + if len(removedTags) > 0 { + input := route53recoverycontrolconfig.UntagResourceInput{ + ResourceArn: aws.String(identifier), + TagKeys: removedTags.Keys(), + } + + _, err := conn.UntagResource(ctx, &input, optFns...) + + if err != nil { + return smarterr.NewError(err) + } + } + + updatedTags := oldTags.Updated(newTags) + updatedTags = updatedTags.IgnoreSystem(names.Route53RecoveryControlConfig) + if len(updatedTags) > 0 { + input := route53recoverycontrolconfig.TagResourceInput{ + ResourceArn: aws.String(identifier), + Tags: svcTags(updatedTags), + } + + _, err := conn.TagResource(ctx, &input, optFns...) + + if err != nil { + return smarterr.NewError(err) + } + } + + return nil +} + +// UpdateTags updates route53recoverycontrolconfig service tags. +// It is called from outside this package. +func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { + return updateTags(ctx, meta.(*conns.AWSClient).Route53RecoveryControlConfigClient(ctx), identifier, oldTags, newTags) +} diff --git a/internal/service/s3/bucket_lifecycle_configuration.go b/internal/service/s3/bucket_lifecycle_configuration.go index 9b30f64f51aa..fe2014ccaa35 100644 --- a/internal/service/s3/bucket_lifecycle_configuration.go +++ b/internal/service/s3/bucket_lifecycle_configuration.go @@ -110,12 +110,6 @@ func (r *bucketLifecycleConfigurationResource) Schema(ctx context.Context, reque listvalidator.SizeAtLeast(1), }, NestedObject: schema.NestedBlockObject{ - Validators: []validator.Object{ - tfobjectvalidator.WarnExactlyOneOfChildren( - path.MatchRelative().AtName(names.AttrFilter), - path.MatchRelative().AtName(names.AttrPrefix), - ), - }, Attributes: map[string]schema.Attribute{ names.AttrID: schema.StringAttribute{ Required: true, @@ -298,11 +292,6 @@ func (r *bucketLifecycleConfigurationResource) Schema(ctx context.Context, reque Attributes: map[string]schema.Attribute{ "newer_noncurrent_versions": schema.Int32Attribute{ Optional: true, - Computed: true, // Because of schema change - PlanModifiers: []planmodifier.Int32{ - tfint32planmodifier.NullValue(), - int32planmodifier.UseStateForUnknown(), - }, Validators: []validator.Int32{ int32validator.AtLeast(1), }, @@ -325,11 +314,6 @@ func (r *bucketLifecycleConfigurationResource) Schema(ctx context.Context, reque Attributes: map[string]schema.Attribute{ "newer_noncurrent_versions": schema.Int32Attribute{ Optional: true, - Computed: true, // Because of schema change - PlanModifiers: []planmodifier.Int32{ - tfint32planmodifier.NullValue(), - int32planmodifier.UseStateForUnknown(), - }, Validators: []validator.Int32{ int32validator.AtLeast(1), }, @@ -484,9 +468,6 @@ func (r *bucketLifecycleConfigurationResource) Read(ctx context.Context, request return nil }) - if err != nil { - return - } if tfresource.NotFound(err) { response.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) response.State.RemoveResource(ctx) diff --git a/internal/service/s3/bucket_lifecycle_configuration_test.go b/internal/service/s3/bucket_lifecycle_configuration_test.go index 3e530ae6d88e..0ff0d3d23d33 100644 --- a/internal/service/s3/bucket_lifecycle_configuration_test.go +++ b/internal/service/s3/bucket_lifecycle_configuration_test.go @@ -1665,6 +1665,112 @@ func TestAccS3BucketLifecycleConfiguration_nonCurrentVersionExpiration(t *testin }) } +func TestAccS3BucketLifecycleConfiguration_nonCurrentVersionExpiration_RemoveNoncurrentVersions(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket_lifecycle_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.S3ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckBucketLifecycleConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccBucketLifecycleConfigurationConfig_nonCurrentVersionExpiration_RemoveNoncurrentVersions_Setup(rName, 5, 90), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketLifecycleConfigurationExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(resourceName, tfjsonpath.New(names.AttrBucket), "aws_s3_bucket.test", tfjsonpath.New(names.AttrBucket), compare.ValuesSame()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrExpectedBucketOwner), knownvalue.StringExact("")), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New(names.AttrID), resourceName, tfjsonpath.New(names.AttrBucket), compare.ValuesSame()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRule), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "abort_incomplete_multipart_upload": checkAbortIncompleteMultipartUpload_None(), + "expiration": checkExpiration_None(), + names.AttrFilter: checkFilter_Prefix("config/"), + names.AttrID: knownvalue.StringExact(rName), + "noncurrent_version_expiration": checkNoncurrentVersionExpiration_VersionsAndDays(5, 90), + "noncurrent_version_transition": checkNoncurrentVersionTransitions(), + names.AttrPrefix: knownvalue.StringExact(""), + names.AttrStatus: knownvalue.StringExact(tfs3.LifecycleRuleStatusEnabled), + "transition": checkTransitions(), + }), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("transition_default_minimum_object_size"), knownvalue.StringExact("all_storage_classes_128K")), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRule), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "abort_incomplete_multipart_upload": checkAbortIncompleteMultipartUpload_None(), + "expiration": checkExpiration_None(), + names.AttrFilter: checkFilter_Prefix("config/"), + names.AttrID: knownvalue.StringExact(rName), + "noncurrent_version_expiration": checkNoncurrentVersionExpiration_VersionsAndDays(5, 90), + "noncurrent_version_transition": checkNoncurrentVersionTransitions(), + names.AttrPrefix: knownvalue.StringExact(""), + names.AttrStatus: knownvalue.StringExact(tfs3.LifecycleRuleStatusEnabled), + "transition": checkTransitions(), + }), + })), + }, + }, + }, + { + Config: testAccBucketLifecycleConfigurationConfig_nonCurrentVersionExpiration_RemoveNoncurrentVersions_Apply(rName, 90), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckBucketLifecycleConfigurationExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(resourceName, tfjsonpath.New(names.AttrBucket), "aws_s3_bucket.test", tfjsonpath.New(names.AttrBucket), compare.ValuesSame()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrExpectedBucketOwner), knownvalue.StringExact("")), + statecheck.CompareValuePairs(resourceName, tfjsonpath.New(names.AttrID), resourceName, tfjsonpath.New(names.AttrBucket), compare.ValuesSame()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRule), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "abort_incomplete_multipart_upload": checkAbortIncompleteMultipartUpload_None(), + "expiration": checkExpiration_None(), + names.AttrFilter: checkFilter_Prefix("config/"), + names.AttrID: knownvalue.StringExact(rName), + "noncurrent_version_expiration": checkNoncurrentVersionExpiration_Days(90), + "noncurrent_version_transition": checkNoncurrentVersionTransitions(), + names.AttrPrefix: knownvalue.StringExact(""), + names.AttrStatus: knownvalue.StringExact(tfs3.LifecycleRuleStatusEnabled), + "transition": checkTransitions(), + }), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("transition_default_minimum_object_size"), knownvalue.StringExact("all_storage_classes_128K")), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRule), knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "abort_incomplete_multipart_upload": checkAbortIncompleteMultipartUpload_None(), + "expiration": checkExpiration_None(), + names.AttrFilter: checkFilter_Prefix("config/"), + names.AttrID: knownvalue.StringExact(rName), + "noncurrent_version_expiration": checkNoncurrentVersionExpiration_Days(90), + "noncurrent_version_transition": checkNoncurrentVersionTransitions(), + names.AttrPrefix: knownvalue.StringExact(""), + names.AttrStatus: knownvalue.StringExact(tfs3.LifecycleRuleStatusEnabled), + "transition": checkTransitions(), + }), + })), + }, + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccS3BucketLifecycleConfiguration_nonCurrentVersionTransition(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -4593,6 +4699,59 @@ resource "aws_s3_bucket_lifecycle_configuration" "test" { `, rName, nonCurrentDays) } +func testAccBucketLifecycleConfigurationConfig_nonCurrentVersionExpiration_RemoveNoncurrentVersions_Setup(rName string, nonCurrentVersions, nonCurrentDays int) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q +} + +resource "aws_s3_bucket_lifecycle_configuration" "test" { + bucket = aws_s3_bucket.test.bucket + + rule { + id = %[1]q + + filter { + prefix = "config/" + } + + noncurrent_version_expiration { + newer_noncurrent_versions = %[2]d + noncurrent_days = %[3]d + } + + status = "Enabled" + } +} +`, rName, nonCurrentVersions, nonCurrentDays) +} + +func testAccBucketLifecycleConfigurationConfig_nonCurrentVersionExpiration_RemoveNoncurrentVersions_Apply(rName string, nonCurrentDays int) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q +} + +resource "aws_s3_bucket_lifecycle_configuration" "test" { + bucket = aws_s3_bucket.test.bucket + + rule { + id = %[1]q + + filter { + prefix = "config/" + } + + noncurrent_version_expiration { + noncurrent_days = %[2]d + } + + status = "Enabled" + } +} +`, rName, nonCurrentDays) +} + func testAccBucketLifecycleConfigurationConfig_nonCurrentVersionTransition(rName string, standardDays, glacierDays int) string { return fmt.Sprintf(` resource "aws_s3_bucket" "test" { diff --git a/internal/service/s3/sweep.go b/internal/service/s3/sweep.go index 09b0c30a247c..be25ff27f133 100644 --- a/internal/service/s3/sweep.go +++ b/internal/service/s3/sweep.go @@ -25,6 +25,7 @@ import ( func RegisterSweepers() { awsv2.Register("aws_s3_bucket", sweepBuckets, + "aws_datazone_domain", "aws_s3_access_point", "aws_s3_object_gp_bucket", "aws_s3control_access_grants_instance", diff --git a/internal/service/s3control/account_public_access_block_identity_gen_test.go b/internal/service/s3control/account_public_access_block_identity_gen_test.go index 568fd6b8b920..1bd617e6966c 100644 --- a/internal/service/s3control/account_public_access_block_identity_gen_test.go +++ b/internal/service/s3control/account_public_access_block_identity_gen_test.go @@ -23,8 +23,9 @@ func testAccS3ControlAccountPublicAccessBlock_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccS3ControlAccountPublicAccessBlock_Identity_Basic, - "ExistingResource": testAccS3ControlAccountPublicAccessBlock_Identity_ExistingResource, + acctest.CtBasic: testAccS3ControlAccountPublicAccessBlock_Identity_Basic, + "ExistingResource": testAccS3ControlAccountPublicAccessBlock_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccS3ControlAccountPublicAccessBlock_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/sagemaker/servicecatalog_portfolio_status_identity_gen_test.go b/internal/service/sagemaker/servicecatalog_portfolio_status_identity_gen_test.go index 1c663754f0c2..e3051b80d806 100644 --- a/internal/service/sagemaker/servicecatalog_portfolio_status_identity_gen_test.go +++ b/internal/service/sagemaker/servicecatalog_portfolio_status_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccSageMakerServicecatalogPortfolioStatus_IdentitySerial(t *testing.T) t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccSageMakerServicecatalogPortfolioStatus_Identity_Basic, - "ExistingResource": testAccSageMakerServicecatalogPortfolioStatus_Identity_ExistingResource, - "RegionOverride": testAccSageMakerServicecatalogPortfolioStatus_Identity_RegionOverride, + acctest.CtBasic: testAccSageMakerServicecatalogPortfolioStatus_Identity_Basic, + "ExistingResource": testAccSageMakerServicecatalogPortfolioStatus_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccSageMakerServicecatalogPortfolioStatus_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccSageMakerServicecatalogPortfolioStatus_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/sagemaker/user_profile_identity_gen_test.go b/internal/service/sagemaker/user_profile_identity_gen_test.go index 13e74a83da75..39177e6c9eba 100644 --- a/internal/service/sagemaker/user_profile_identity_gen_test.go +++ b/internal/service/sagemaker/user_profile_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccSageMakerUserProfile_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccSageMakerUserProfile_Identity_Basic, - "ExistingResource": testAccSageMakerUserProfile_Identity_ExistingResource, - "RegionOverride": testAccSageMakerUserProfile_Identity_RegionOverride, + acctest.CtBasic: testAccSageMakerUserProfile_Identity_Basic, + "ExistingResource": testAccSageMakerUserProfile_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccSageMakerUserProfile_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccSageMakerUserProfile_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/securityhub/automation_rule_identity_gen_test.go b/internal/service/securityhub/automation_rule_identity_gen_test.go index ef802b56083d..f0e1f306a717 100644 --- a/internal/service/securityhub/automation_rule_identity_gen_test.go +++ b/internal/service/securityhub/automation_rule_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccSecurityHubAutomationRule_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccSecurityHubAutomationRule_Identity_Basic, - "ExistingResource": testAccSecurityHubAutomationRule_Identity_ExistingResource, - "RegionOverride": testAccSecurityHubAutomationRule_Identity_RegionOverride, + acctest.CtBasic: testAccSecurityHubAutomationRule_Identity_Basic, + "ExistingResource": testAccSecurityHubAutomationRule_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccSecurityHubAutomationRule_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccSecurityHubAutomationRule_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/servicequotas/service_quota_data_source.go b/internal/service/servicequotas/service_quota_data_source.go index 8fd65ca1d60b..de2e029458b7 100644 --- a/internal/service/servicequotas/service_quota_data_source.go +++ b/internal/service/servicequotas/service_quota_data_source.go @@ -128,7 +128,6 @@ func dataSourceServiceQuotaRead(ctx context.Context, d *schema.ResourceData, met // A Service Quota will always have a default value, but will only have a current value if it has been set. if quotaName != "" { defaultQuota, err = findDefaultServiceQuotaByServiceCodeAndQuotaName(ctx, conn, serviceCode, quotaName) - quotaCode = aws.ToString(defaultQuota.QuotaCode) } else { defaultQuota, err = findDefaultServiceQuotaByServiceCodeAndQuotaCode(ctx, conn, serviceCode, quotaCode) } @@ -137,6 +136,10 @@ func dataSourceServiceQuotaRead(ctx context.Context, d *schema.ResourceData, met return sdkdiag.AppendFromErr(diags, tfresource.SingularDataSourceFindError("Service Quotas Service Quota", err)) } + if quotaName != "" { + quotaCode = aws.ToString(defaultQuota.QuotaCode) + } + arn := aws.ToString(defaultQuota.QuotaArn) d.SetId(arn) d.Set("adjustable", defaultQuota.Adjustable) diff --git a/internal/service/servicequotas/service_quota_data_source_test.go b/internal/service/servicequotas/service_quota_data_source_test.go index 665203a7ca12..a573014d8379 100644 --- a/internal/service/servicequotas/service_quota_data_source_test.go +++ b/internal/service/servicequotas/service_quota_data_source_test.go @@ -151,6 +151,10 @@ func TestAccServiceQuotasServiceQuotaDataSource_quotaName(t *testing.T) { ErrorCheck: acctest.ErrorCheck(t, names.ServiceQuotasServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ + { + Config: testAccServiceQuotaDataSourceConfig_name("vpc", setQuotaQuotaName+"nonexist"), + ExpectError: regexache.MustCompile(`Service Quotas Service Quota`), + }, { Config: testAccServiceQuotaDataSourceConfig_name("vpc", setQuotaQuotaName), Check: resource.ComposeAggregateTestCheckFunc( diff --git a/internal/service/sfn/service_package_gen.go b/internal/service/sfn/service_package_gen.go index 5f038957da03..a90121de97bb 100644 --- a/internal/service/sfn/service_package_gen.go +++ b/internal/service/sfn/service_package_gen.go @@ -17,6 +17,17 @@ import ( type servicePackage struct{} +func (p *servicePackage) Actions(ctx context.Context) []*inttypes.ServicePackageAction { + return []*inttypes.ServicePackageAction{ + { + Factory: newStartExecutionAction, + TypeName: "aws_sfn_start_execution", + Name: "Start Execution", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, + } +} + func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*inttypes.ServicePackageFrameworkDataSource { return []*inttypes.ServicePackageFrameworkDataSource{} } diff --git a/internal/service/sfn/start_execution_action.go b/internal/service/sfn/start_execution_action.go new file mode 100644 index 000000000000..3bb9a1a60ba9 --- /dev/null +++ b/internal/service/sfn/start_execution_action.go @@ -0,0 +1,129 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package sfn + +import ( + "context" + "fmt" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/sfn" + "github.com/hashicorp/terraform-plugin-framework/action" + "github.com/hashicorp/terraform-plugin-framework/action/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/validators" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @Action(aws_sfn_start_execution, name="Start Execution") +func newStartExecutionAction(_ context.Context) (action.ActionWithConfigure, error) { + return &startExecutionAction{}, nil +} + +var ( + _ action.Action = (*startExecutionAction)(nil) +) + +type startExecutionAction struct { + framework.ActionWithModel[startExecutionActionModel] +} + +type startExecutionActionModel struct { + framework.WithRegionModel + StateMachineArn types.String `tfsdk:"state_machine_arn"` + Input types.String `tfsdk:"input"` + Name types.String `tfsdk:"name"` + TraceHeader types.String `tfsdk:"trace_header"` +} + +func (a *startExecutionAction) Schema(ctx context.Context, req action.SchemaRequest, resp *action.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Starts a Step Functions state machine execution with the specified input data.", + Attributes: map[string]schema.Attribute{ + "state_machine_arn": schema.StringAttribute{ + Description: "The ARN of the state machine to execute. Can be unqualified, version-qualified, or alias-qualified.", + Required: true, + }, + "input": schema.StringAttribute{ + Description: "JSON input data for the execution. Defaults to '{}'.", + Optional: true, + Validators: []validator.String{ + validators.JSON(), + }, + }, + names.AttrName: schema.StringAttribute{ + Description: "Name of the execution. Must be unique within the account/region/state machine for 90 days. Auto-generated if not provided.", + Optional: true, + }, + "trace_header": schema.StringAttribute{ + Description: "AWS X-Ray trace header for distributed tracing.", + Optional: true, + }, + }, + } +} + +func (a *startExecutionAction) Invoke(ctx context.Context, req action.InvokeRequest, resp *action.InvokeResponse) { + var config startExecutionActionModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + conn := a.Meta().SFNClient(ctx) + + stateMachineArn := config.StateMachineArn.ValueString() + input := "{}" + if !config.Input.IsNull() { + input = config.Input.ValueString() + } + + tflog.Info(ctx, "Starting Step Functions execution", map[string]any{ + "state_machine_arn": stateMachineArn, + "input_length": len(input), + "has_name": !config.Name.IsNull(), + "has_trace_header": !config.TraceHeader.IsNull(), + }) + + resp.SendProgress(action.InvokeProgressEvent{ + Message: fmt.Sprintf("Starting execution for state machine %s...", stateMachineArn), + }) + + startInput := &sfn.StartExecutionInput{ + StateMachineArn: aws.String(stateMachineArn), + Input: aws.String(input), + } + + if !config.Name.IsNull() { + startInput.Name = config.Name.ValueStringPointer() + } + + if !config.TraceHeader.IsNull() { + startInput.TraceHeader = config.TraceHeader.ValueStringPointer() + } + + output, err := conn.StartExecution(ctx, startInput) + if err != nil { + resp.Diagnostics.AddError( + "Failed to Start Step Functions Execution", + fmt.Sprintf("Could not start execution for state machine %s: %s", stateMachineArn, err), + ) + return + } + + executionArn := aws.ToString(output.ExecutionArn) + resp.SendProgress(action.InvokeProgressEvent{ + Message: fmt.Sprintf("Execution started successfully with ARN %s", executionArn), + }) + + tflog.Info(ctx, "Step Functions execution started successfully", map[string]any{ + "state_machine_arn": stateMachineArn, + "execution_arn": executionArn, + "start_date": output.StartDate, + }) +} diff --git a/internal/service/sfn/start_execution_action_test.go b/internal/service/sfn/start_execution_action_test.go new file mode 100644 index 000000000000..b1b5087b2a38 --- /dev/null +++ b/internal/service/sfn/start_execution_action_test.go @@ -0,0 +1,370 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package sfn_test + +import ( + "context" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/sfn" + awstypes "github.com/aws/aws-sdk-go-v2/service/sfn/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccSFNStartExecutionAction_basic(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + inputJSON := `{"key1":"value1","key2":"value2"}` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SFNServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccStartExecutionActionConfig_basic(rName, inputJSON), + Check: resource.ComposeTestCheckFunc( + testAccCheckStartExecutionAction(ctx, rName, inputJSON), + ), + }, + }, + }) +} + +func TestAccSFNStartExecutionAction_withName(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + executionName := sdkacctest.RandomWithPrefix("execution") + inputJSON := `{"test":"data"}` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SFNServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccStartExecutionActionConfig_withName(rName, executionName, inputJSON), + Check: resource.ComposeTestCheckFunc( + testAccCheckStartExecutionActionWithName(ctx, rName, executionName, inputJSON), + ), + }, + }, + }) +} + +func TestAccSFNStartExecutionAction_emptyInput(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SFNServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccStartExecutionActionConfig_emptyInput(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStartExecutionAction(ctx, rName, "{}"), + ), + }, + }, + }) +} + +// Test helper functions + +func testAccCheckStartExecutionAction(ctx context.Context, stateMachineName, expectedInput string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).SFNClient(ctx) + + // Get the state machine ARN + stateMachines, err := conn.ListStateMachines(ctx, &sfn.ListStateMachinesInput{}) + if err != nil { + return fmt.Errorf("failed to list state machines: %w", err) + } + + var stateMachineArn string + for _, sm := range stateMachines.StateMachines { + if *sm.Name == stateMachineName { + stateMachineArn = *sm.StateMachineArn + break + } + } + + if stateMachineArn == "" { + return fmt.Errorf("state machine %s not found", stateMachineName) + } + + // List executions to verify one was created (check all statuses) + executions, err := conn.ListExecutions(ctx, &sfn.ListExecutionsInput{ + StateMachineArn: &stateMachineArn, + }) + if err != nil { + return fmt.Errorf("failed to list executions for state machine %s: %w", stateMachineName, err) + } + + if len(executions.Executions) == 0 { + return fmt.Errorf("no executions found for state machine %s", stateMachineName) + } + + // Verify the execution input matches expected + execution := executions.Executions[0] + executionDetails, err := conn.DescribeExecution(ctx, &sfn.DescribeExecutionInput{ + ExecutionArn: execution.ExecutionArn, + }) + if err != nil { + return fmt.Errorf("failed to describe execution %s: %w", *execution.ExecutionArn, err) + } + + if *executionDetails.Input != expectedInput { + return fmt.Errorf("execution input mismatch. Expected: %s, Got: %s", expectedInput, *executionDetails.Input) + } + + return nil + } +} + +func testAccCheckStartExecutionActionWithName(ctx context.Context, stateMachineName, executionName, expectedInput string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).SFNClient(ctx) + + // Get the state machine ARN + stateMachines, err := conn.ListStateMachines(ctx, &sfn.ListStateMachinesInput{}) + if err != nil { + return fmt.Errorf("failed to list state machines: %w", err) + } + + var stateMachineArn string + for _, sm := range stateMachines.StateMachines { + if *sm.Name == stateMachineName { + stateMachineArn = *sm.StateMachineArn + break + } + } + + if stateMachineArn == "" { + return fmt.Errorf("state machine %s not found", stateMachineName) + } + + // Find execution by name (check all statuses) + executions, err := conn.ListExecutions(ctx, &sfn.ListExecutionsInput{ + StateMachineArn: &stateMachineArn, + }) + if err != nil { + return fmt.Errorf("failed to list executions for state machine %s: %w", stateMachineName, err) + } + + var foundExecution *awstypes.ExecutionListItem + for _, execution := range executions.Executions { + if *execution.Name == executionName { + foundExecution = &execution + break + } + } + + if foundExecution == nil { + return fmt.Errorf("execution with name %s not found for state machine %s", executionName, stateMachineName) + } + + // Verify the execution input + executionDetails, err := conn.DescribeExecution(ctx, &sfn.DescribeExecutionInput{ + ExecutionArn: foundExecution.ExecutionArn, + }) + if err != nil { + return fmt.Errorf("failed to describe execution %s: %w", *foundExecution.ExecutionArn, err) + } + + if *executionDetails.Input != expectedInput { + return fmt.Errorf("execution input mismatch. Expected: %s, Got: %s", expectedInput, *executionDetails.Input) + } + + return nil + } +} + +// Configuration functions + +func testAccStartExecutionActionConfig_basic(rName, inputJSON string) string { + return acctest.ConfigCompose( + testAccStartExecutionActionConfig_base(rName), + fmt.Sprintf(` +action "aws_sfn_start_execution" "test" { + config { + state_machine_arn = aws_sfn_state_machine.test.arn + input = %[1]q + } +} + +resource "terraform_data" "trigger" { + input = "trigger" + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_sfn_start_execution.test] + } + } +} +`, inputJSON)) +} + +func testAccStartExecutionActionConfig_withName(rName, executionName, inputJSON string) string { + return acctest.ConfigCompose( + testAccStartExecutionActionConfig_base(rName), + fmt.Sprintf(` +action "aws_sfn_start_execution" "test" { + config { + state_machine_arn = aws_sfn_state_machine.test.arn + name = %[1]q + input = %[2]q + } +} + +resource "terraform_data" "trigger" { + input = "trigger" + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_sfn_start_execution.test] + } + } +} +`, executionName, inputJSON)) +} + +func testAccStartExecutionActionConfig_emptyInput(rName string) string { + return acctest.ConfigCompose( + testAccStartExecutionActionConfig_base(rName), + ` +action "aws_sfn_start_execution" "test" { + config { + state_machine_arn = aws_sfn_state_machine.test.arn + } +} + +resource "terraform_data" "trigger" { + input = "trigger" + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_sfn_start_execution.test] + } + } +} +`) +} + +func testAccStartExecutionActionConfig_base(rName string) string { + return fmt.Sprintf(` +resource "aws_iam_role" "for_lambda" { + name = "%[1]s-lambda" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "sts:AssumeRole" + Principal = { + Service = "lambda.amazonaws.com" + } + Effect = "Allow" + }] + }) +} + +resource "aws_iam_role_policy" "for_lambda" { + name = "%[1]s-lambda" + role = aws_iam_role.for_lambda.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + Resource = "arn:${data.aws_partition.current.partition}:logs:*:*:*" + }] + }) +} + +resource "aws_lambda_function" "test" { + filename = "test-fixtures/lambdatest.zip" + function_name = %[1]q + role = aws_iam_role.for_lambda.arn + handler = "exports.example" + runtime = "nodejs20.x" +} + +resource "aws_iam_role" "for_sfn" { + name = "%[1]s-sfn" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Principal = { + Service = "states.${data.aws_region.current.region}.amazonaws.com" + } + Action = "sts:AssumeRole" + }] + }) +} + +resource "aws_iam_role_policy" "for_sfn" { + name = "%[1]s-sfn" + role = aws_iam_role.for_sfn.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Action = [ + "lambda:InvokeFunction" + ] + Resource = "*" + }] + }) +} + +resource "aws_sfn_state_machine" "test" { + name = %[1]q + role_arn = aws_iam_role.for_sfn.arn + + definition = jsonencode({ + Comment = "A simple minimal example" + StartAt = "Hello" + States = { + Hello = { + Type = "Task" + Resource = aws_lambda_function.test.arn + End = true + } + } + }) +} + +data "aws_region" "current" {} +data "aws_partition" "current" {} +`, rName) +} diff --git a/internal/service/ssmcontacts/contact.go b/internal/service/ssmcontacts/contact.go index 7885b3b917d1..b328273aeae1 100644 --- a/internal/service/ssmcontacts/contact.go +++ b/internal/service/ssmcontacts/contact.go @@ -21,9 +21,12 @@ import ( ) // @SDKResource("aws_ssmcontacts_contact", name="Contact") +// @ArnIdentity // @Tags(identifierAttribute="arn") // @Testing(skipEmptyTags=true, skipNullTags=true) +// @Testing(identityRegionOverrideTest=false) // @Testing(serialize=true) +// @Testing(preIdentityVersion="v6.15.0") func ResourceContact() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceContactCreate, @@ -31,10 +34,6 @@ func ResourceContact() *schema.Resource { UpdateWithoutTimeout: resourceContactUpdate, DeleteWithoutTimeout: resourceContactDelete, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - Schema: map[string]*schema.Schema{ names.AttrARN: { Type: schema.TypeString, diff --git a/internal/service/ssmcontacts/contact_channel.go b/internal/service/ssmcontacts/contact_channel.go index d75fbdbc6af7..83a9188c0d2a 100644 --- a/internal/service/ssmcontacts/contact_channel.go +++ b/internal/service/ssmcontacts/contact_channel.go @@ -20,6 +20,10 @@ import ( ) // @SDKResource("aws_ssmcontacts_contact_channel", name="Contact Channel") +// @ArnIdentity +// @Testing(identityRegionOverrideTest=false) +// @Testing(serialize=true) +// @Testing(preIdentityVersion="v6.14.1") func ResourceContactChannel() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceContactChannelCreate, @@ -27,10 +31,6 @@ func ResourceContactChannel() *schema.Resource { UpdateWithoutTimeout: resourceContactChannelUpdate, DeleteWithoutTimeout: resourceContactChannelDelete, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - Schema: map[string]*schema.Schema{ "activation_status": { Type: schema.TypeString, diff --git a/internal/service/ssmcontacts/contact_channel_identity_gen_test.go b/internal/service/ssmcontacts/contact_channel_identity_gen_test.go new file mode 100644 index 000000000000..292732bce5a0 --- /dev/null +++ b/internal/service/ssmcontacts/contact_channel_identity_gen_test.go @@ -0,0 +1,229 @@ +// Code generated by internal/generate/identitytests/main.go; DO NOT EDIT. + +package ssmcontacts_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/compare" + "github.com/hashicorp/terraform-plugin-testing/config" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + tfstatecheck "github.com/hashicorp/terraform-provider-aws/internal/acctest/statecheck" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func testAccSSMContactsContactChannel_IdentitySerial(t *testing.T) { + t.Helper() + + testCases := map[string]func(t *testing.T){ + acctest.CtBasic: testAccSSMContactsContactChannel_Identity_Basic, + "ExistingResource": testAccSSMContactsContactChannel_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccSSMContactsContactChannel_Identity_ExistingResource_NoRefresh_NoChange, + } + + acctest.RunSerialTests1Level(t, testCases, 0) +} + +func testAccSSMContactsContactChannel_Identity_Basic(t *testing.T) { + ctx := acctest.Context(t) + + resourceName := "aws_ssmcontacts_contact_channel.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.Test(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SSMContactsServiceID), + CheckDestroy: testAccCheckContactChannelDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + // Step 1: Setup + { + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckContactChannelExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(resourceName, tfjsonpath.New(names.AttrID), resourceName, tfjsonpath.New(names.AttrARN), compare.ValuesSame()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + statecheck.ExpectIdentity(resourceName, map[string]knownvalue.Check{ + names.AttrARN: knownvalue.NotNull(), + }), + statecheck.ExpectIdentityValueMatchesState(resourceName, tfjsonpath.New(names.AttrARN)), + }, + }, + + // Step 2: Import command + { + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ImportStateKind: resource.ImportCommandWithID, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + + // Step 3: Import block with Import ID + { + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithID, + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrARN), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + }, + }, + }, + + // Step 4: Import block with Resource Identity + { + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrARN), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + }, + }, + }, + }, + }) +} + +// Resource Identity was added after v6.14.1 +func testAccSSMContactsContactChannel_Identity_ExistingResource(t *testing.T) { + ctx := acctest.Context(t) + + resourceName := "aws_ssmcontacts_contact_channel.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.Test(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SSMContactsServiceID), + CheckDestroy: testAccCheckContactChannelDestroy(ctx), + Steps: []resource.TestStep{ + // Step 1: Create pre-Identity + { + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic_v6.14.1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckContactChannelExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + + // Step 2: Current version + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectIdentity(resourceName, map[string]knownvalue.Check{ + names.AttrARN: knownvalue.NotNull(), + }), + statecheck.ExpectIdentityValueMatchesState(resourceName, tfjsonpath.New(names.AttrARN)), + }, + }, + }, + }) +} + +// Resource Identity was added after v6.14.1 +func testAccSSMContactsContactChannel_Identity_ExistingResource_NoRefresh_NoChange(t *testing.T) { + ctx := acctest.Context(t) + + resourceName := "aws_ssmcontacts_contact_channel.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.Test(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SSMContactsServiceID), + CheckDestroy: testAccCheckContactChannelDestroy(ctx), + AdditionalCLIOptions: &resource.AdditionalCLIOptions{ + Plan: resource.PlanOptions{ + NoRefresh: true, + }, + }, + Steps: []resource.TestStep{ + // Step 1: Create pre-Identity + { + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic_v6.14.1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckContactChannelExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + + // Step 2: Current version + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/ContactChannel/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + }, + }) +} diff --git a/internal/service/ssmcontacts/contact_identity_gen_test.go b/internal/service/ssmcontacts/contact_identity_gen_test.go new file mode 100644 index 000000000000..d17ce8a96e59 --- /dev/null +++ b/internal/service/ssmcontacts/contact_identity_gen_test.go @@ -0,0 +1,229 @@ +// Code generated by internal/generate/identitytests/main.go; DO NOT EDIT. + +package ssmcontacts_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/compare" + "github.com/hashicorp/terraform-plugin-testing/config" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + tfstatecheck "github.com/hashicorp/terraform-provider-aws/internal/acctest/statecheck" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func testAccSSMContactsContact_IdentitySerial(t *testing.T) { + t.Helper() + + testCases := map[string]func(t *testing.T){ + acctest.CtBasic: testAccSSMContactsContact_Identity_Basic, + "ExistingResource": testAccSSMContactsContact_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccSSMContactsContact_Identity_ExistingResource_NoRefresh_NoChange, + } + + acctest.RunSerialTests1Level(t, testCases, 0) +} + +func testAccSSMContactsContact_Identity_Basic(t *testing.T) { + ctx := acctest.Context(t) + + resourceName := "aws_ssmcontacts_contact.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.Test(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SSMContactsServiceID), + CheckDestroy: testAccCheckContactDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + // Step 1: Setup + { + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckContactExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(resourceName, tfjsonpath.New(names.AttrID), resourceName, tfjsonpath.New(names.AttrARN), compare.ValuesSame()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + statecheck.ExpectIdentity(resourceName, map[string]knownvalue.Check{ + names.AttrARN: knownvalue.NotNull(), + }), + statecheck.ExpectIdentityValueMatchesState(resourceName, tfjsonpath.New(names.AttrARN)), + }, + }, + + // Step 2: Import command + { + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ImportStateKind: resource.ImportCommandWithID, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + + // Step 3: Import block with Import ID + { + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithID, + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrARN), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + }, + }, + }, + + // Step 4: Import block with Resource Identity + { + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + ImportPlanChecks: resource.ImportPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrARN), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrID), knownvalue.NotNull()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrRegion), knownvalue.StringExact(acctest.Region())), + }, + }, + }, + }, + }) +} + +// Resource Identity was added after v6.15.0 +func testAccSSMContactsContact_Identity_ExistingResource(t *testing.T) { + ctx := acctest.Context(t) + + resourceName := "aws_ssmcontacts_contact.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.Test(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SSMContactsServiceID), + CheckDestroy: testAccCheckContactDestroy(ctx), + Steps: []resource.TestStep{ + // Step 1: Create pre-Identity + { + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic_v6.15.0/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckContactExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + + // Step 2: Current version + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectIdentity(resourceName, map[string]knownvalue.Check{ + names.AttrARN: knownvalue.NotNull(), + }), + statecheck.ExpectIdentityValueMatchesState(resourceName, tfjsonpath.New(names.AttrARN)), + }, + }, + }, + }) +} + +// Resource Identity was added after v6.15.0 +func testAccSSMContactsContact_Identity_ExistingResource_NoRefresh_NoChange(t *testing.T) { + ctx := acctest.Context(t) + + resourceName := "aws_ssmcontacts_contact.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + acctest.Test(ctx, t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SSMContactsServiceID), + CheckDestroy: testAccCheckContactDestroy(ctx), + AdditionalCLIOptions: &resource.AdditionalCLIOptions{ + Plan: resource.PlanOptions{ + NoRefresh: true, + }, + }, + Steps: []resource.TestStep{ + // Step 1: Create pre-Identity + { + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic_v6.15.0/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckContactExists(ctx, resourceName), + ), + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + + // Step 2: Current version + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/Contact/basic/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + tfstatecheck.ExpectNoIdentity(resourceName), + }, + }, + }, + }) +} diff --git a/internal/service/ssmcontacts/rotation_identity_gen_test.go b/internal/service/ssmcontacts/rotation_identity_gen_test.go index 0bddebfd1696..cea554a2bd8c 100644 --- a/internal/service/ssmcontacts/rotation_identity_gen_test.go +++ b/internal/service/ssmcontacts/rotation_identity_gen_test.go @@ -23,8 +23,9 @@ func testAccSSMContactsRotation_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccSSMContactsRotation_Identity_Basic, - "ExistingResource": testAccSSMContactsRotation_Identity_ExistingResource, + acctest.CtBasic: testAccSSMContactsRotation_Identity_Basic, + "ExistingResource": testAccSSMContactsRotation_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccSSMContactsRotation_Identity_ExistingResource_NoRefresh_NoChange, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/ssmcontacts/service_package_gen.go b/internal/service/ssmcontacts/service_package_gen.go index 7d3bfddc3dd9..13443fe78592 100644 --- a/internal/service/ssmcontacts/service_package_gen.go +++ b/internal/service/ssmcontacts/service_package_gen.go @@ -85,12 +85,24 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*inttypes.ServicePa IdentifierAttribute: names.AttrARN, }), Region: unique.Make(inttypes.ResourceRegionDefault()), + Identity: inttypes.RegionalARNIdentity( + inttypes.WithIdentityDuplicateAttrs(names.AttrID), + ), + Import: inttypes.SDKv2Import{ + WrappedImport: true, + }, }, { Factory: ResourceContactChannel, TypeName: "aws_ssmcontacts_contact_channel", Name: "Contact Channel", Region: unique.Make(inttypes.ResourceRegionDefault()), + Identity: inttypes.RegionalARNIdentity( + inttypes.WithIdentityDuplicateAttrs(names.AttrID), + ), + Import: inttypes.SDKv2Import{ + WrappedImport: true, + }, }, { Factory: ResourcePlan, diff --git a/internal/service/ssmcontacts/ssmcontacts_test.go b/internal/service/ssmcontacts/ssmcontacts_test.go index 3c0f241c1abe..fa217825b6f0 100644 --- a/internal/service/ssmcontacts/ssmcontacts_test.go +++ b/internal/service/ssmcontacts/ssmcontacts_test.go @@ -22,6 +22,7 @@ func TestAccSSMContacts_serial(t *testing.T) { "updateDisplayName": testAccContact_updateDisplayName, "tags": testAccSSMContactsContact_tagsSerial, "updateType": testAccContact_updateType, + "identity": testAccSSMContactsContact_IdentitySerial, }, "ContactDataSource": { acctest.CtBasic: testAccContactDataSource_basic, @@ -34,6 +35,7 @@ func TestAccSSMContacts_serial(t *testing.T) { acctest.CtDisappears: testAccContactChannel_disappears, acctest.CtName: testAccContactChannel_name, "type": testAccContactChannel_type, + "identity": testAccSSMContactsContactChannel_IdentitySerial, }, "ContactChannelDataSource": { acctest.CtBasic: testAccContactChannelDataSource_basic, @@ -53,15 +55,15 @@ func TestAccSSMContacts_serial(t *testing.T) { "channelTargetInfo": testAccPlanDataSource_channelTargetInfo, }, "RotationResource": { - acctest.CtBasic: testAccRotation_basic, - acctest.CtDisappears: testAccRotation_disappears, - "update": testAccRotation_updateRequiredFields, - "startTime": testAccRotation_startTime, - "contactIds": testAccRotation_contactIds, - "recurrence": testAccRotation_recurrence, - "tags": testAccSSMContactsRotation_tagsSerial, - "Identity": testAccSSMContactsRotation_IdentitySerial, - "Identity_RegionOverride": testAccSSMContactsRotation_Identity_RegionOverride, + acctest.CtBasic: testAccRotation_basic, + acctest.CtDisappears: testAccRotation_disappears, + "update": testAccRotation_updateRequiredFields, + "startTime": testAccRotation_startTime, + "contactIds": testAccRotation_contactIds, + "recurrence": testAccRotation_recurrence, + "tags": testAccSSMContactsRotation_tagsSerial, + "identity": testAccSSMContactsRotation_IdentitySerial, + "identityRegionOverride": testAccSSMContactsRotation_Identity_RegionOverride, }, "RotationDataSource": { acctest.CtBasic: testAccRotationDataSource_basic, diff --git a/internal/service/ssmcontacts/testdata/Contact/basic/main_gen.tf b/internal/service/ssmcontacts/testdata/Contact/basic/main_gen.tf new file mode 100644 index 000000000000..50e93d236640 --- /dev/null +++ b/internal/service/ssmcontacts/testdata/Contact/basic/main_gen.tf @@ -0,0 +1,25 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_ssmcontacts_contact" "test" { + alias = var.rName + type = "PERSONAL" + + depends_on = [aws_ssmincidents_replication_set.test] +} + +# testAccContactConfig_base + +resource "aws_ssmincidents_replication_set" "test" { + region { + name = data.aws_region.current.region + } +} + +data "aws_region" "current" {} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} diff --git a/internal/service/ssmcontacts/testdata/Contact/basic_v6.15.0/main_gen.tf b/internal/service/ssmcontacts/testdata/Contact/basic_v6.15.0/main_gen.tf new file mode 100644 index 000000000000..291e0f8d6daa --- /dev/null +++ b/internal/service/ssmcontacts/testdata/Contact/basic_v6.15.0/main_gen.tf @@ -0,0 +1,35 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_ssmcontacts_contact" "test" { + alias = var.rName + type = "PERSONAL" + + depends_on = [aws_ssmincidents_replication_set.test] +} + +# testAccContactConfig_base + +resource "aws_ssmincidents_replication_set" "test" { + region { + name = data.aws_region.current.region + } +} + +data "aws_region" "current" {} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "6.15.0" + } + } +} + +provider "aws" {} diff --git a/internal/service/ssmcontacts/testdata/ContactChannel/basic/main_gen.tf b/internal/service/ssmcontacts/testdata/ContactChannel/basic/main_gen.tf new file mode 100644 index 000000000000..bd33ccfc9bf3 --- /dev/null +++ b/internal/service/ssmcontacts/testdata/ContactChannel/basic/main_gen.tf @@ -0,0 +1,36 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_ssmcontacts_contact_channel" "test" { + contact_id = aws_ssmcontacts_contact.test.arn + + delivery_address { + simple_address = "test@example.com" + } + + name = var.rName + type = "EMAIL" +} + +resource "aws_ssmcontacts_contact" "test" { + alias = "test-contact-for-${var.rName}" + type = "PERSONAL" + + depends_on = [aws_ssmincidents_replication_set.test] +} + +# testAccContactChannelConfig_base + +resource "aws_ssmincidents_replication_set" "test" { + region { + name = data.aws_region.current.region + } +} + +data "aws_region" "current" {} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} diff --git a/internal/service/ssmcontacts/testdata/ContactChannel/basic_v6.14.1/main_gen.tf b/internal/service/ssmcontacts/testdata/ContactChannel/basic_v6.14.1/main_gen.tf new file mode 100644 index 000000000000..7cd14404a0b3 --- /dev/null +++ b/internal/service/ssmcontacts/testdata/ContactChannel/basic_v6.14.1/main_gen.tf @@ -0,0 +1,46 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_ssmcontacts_contact_channel" "test" { + contact_id = aws_ssmcontacts_contact.test.arn + + delivery_address { + simple_address = "test@example.com" + } + + name = var.rName + type = "EMAIL" +} + +resource "aws_ssmcontacts_contact" "test" { + alias = "test-contact-for-${var.rName}" + type = "PERSONAL" + + depends_on = [aws_ssmincidents_replication_set.test] +} + +# testAccContactChannelConfig_base + +resource "aws_ssmincidents_replication_set" "test" { + region { + name = data.aws_region.current.region + } +} + +data "aws_region" "current" {} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "6.14.1" + } + } +} + +provider "aws" {} diff --git a/internal/service/ssmcontacts/testdata/tmpl/contact_channel_basic.gtpl b/internal/service/ssmcontacts/testdata/tmpl/contact_channel_basic.gtpl new file mode 100644 index 000000000000..18bdd14f3006 --- /dev/null +++ b/internal/service/ssmcontacts/testdata/tmpl/contact_channel_basic.gtpl @@ -0,0 +1,31 @@ +resource "aws_ssmcontacts_contact_channel" "test" { +{{- template "region" }} + contact_id = aws_ssmcontacts_contact.test.arn + + delivery_address { + simple_address = "test@example.com" + } + + name = var.rName + type = "EMAIL" +} + +resource "aws_ssmcontacts_contact" "test" { +{{- template "region" }} + alias = "test-contact-for-${var.rName}" + type = "PERSONAL" + + depends_on = [aws_ssmincidents_replication_set.test] +} + +# testAccContactChannelConfig_base + +resource "aws_ssmincidents_replication_set" "test" { + region { + name = data.aws_region.current.region + } +} + +data "aws_region" "current" { +{{- template "region" -}} +} diff --git a/internal/service/ssoadmin/trusted_token_issuer_identity_gen_test.go b/internal/service/ssoadmin/trusted_token_issuer_identity_gen_test.go index 25a987ff6427..3259e6c225c9 100644 --- a/internal/service/ssoadmin/trusted_token_issuer_identity_gen_test.go +++ b/internal/service/ssoadmin/trusted_token_issuer_identity_gen_test.go @@ -24,9 +24,10 @@ func testAccSSOAdminTrustedTokenIssuer_IdentitySerial(t *testing.T) { t.Helper() testCases := map[string]func(t *testing.T){ - acctest.CtBasic: testAccSSOAdminTrustedTokenIssuer_Identity_Basic, - "ExistingResource": testAccSSOAdminTrustedTokenIssuer_Identity_ExistingResource, - "RegionOverride": testAccSSOAdminTrustedTokenIssuer_Identity_RegionOverride, + acctest.CtBasic: testAccSSOAdminTrustedTokenIssuer_Identity_Basic, + "ExistingResource": testAccSSOAdminTrustedTokenIssuer_Identity_ExistingResource, + "ExistingResourceNoRefresh": testAccSSOAdminTrustedTokenIssuer_Identity_ExistingResource_NoRefresh_NoChange, + "RegionOverride": testAccSSOAdminTrustedTokenIssuer_Identity_RegionOverride, } acctest.RunSerialTests1Level(t, testCases, 0) diff --git a/internal/service/transcribe/service_package_gen.go b/internal/service/transcribe/service_package_gen.go index 2a2667ced41c..6e52d43f88bc 100644 --- a/internal/service/transcribe/service_package_gen.go +++ b/internal/service/transcribe/service_package_gen.go @@ -17,6 +17,17 @@ import ( type servicePackage struct{} +func (p *servicePackage) Actions(ctx context.Context) []*inttypes.ServicePackageAction { + return []*inttypes.ServicePackageAction{ + { + Factory: newStartTranscriptionJobAction, + TypeName: "aws_transcribe_start_transcription_job", + Name: "Start Transcription Job", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, + } +} + func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*inttypes.ServicePackageFrameworkDataSource { return []*inttypes.ServicePackageFrameworkDataSource{} } diff --git a/internal/service/transcribe/start_transcription_job_action.go b/internal/service/transcribe/start_transcription_job_action.go new file mode 100644 index 000000000000..7ca04345ba7d --- /dev/null +++ b/internal/service/transcribe/start_transcription_job_action.go @@ -0,0 +1,284 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package transcribe + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/transcribe" + awstypes "github.com/aws/aws-sdk-go-v2/service/transcribe/types" + "github.com/hashicorp/terraform-plugin-framework/action" + "github.com/hashicorp/terraform-plugin-framework/action/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/actionwait" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +const ( + transcriptionJobPollInterval = 5 * time.Second + transcriptionJobProgressInterval = 30 * time.Second +) + +// @Action(aws_transcribe_start_transcription_job, name="Start Transcription Job") +func newStartTranscriptionJobAction(_ context.Context) (action.ActionWithConfigure, error) { + return &startTranscriptionJobAction{}, nil +} + +var ( + _ action.Action = (*startTranscriptionJobAction)(nil) +) + +type startTranscriptionJobAction struct { + framework.ActionWithModel[startTranscriptionJobActionModel] +} + +type startTranscriptionJobActionModel struct { + framework.WithRegionModel + TranscriptionJobName types.String `tfsdk:"transcription_job_name"` + MediaFileUri types.String `tfsdk:"media_file_uri"` + LanguageCode fwtypes.StringEnum[awstypes.LanguageCode] `tfsdk:"language_code"` + IdentifyLanguage types.Bool `tfsdk:"identify_language"` + IdentifyMultipleLanguages types.Bool `tfsdk:"identify_multiple_languages"` + MediaFormat fwtypes.StringEnum[awstypes.MediaFormat] `tfsdk:"media_format"` + MediaSampleRateHertz types.Int64 `tfsdk:"media_sample_rate_hertz"` + OutputBucketName types.String `tfsdk:"output_bucket_name"` + OutputKey types.String `tfsdk:"output_key"` + Timeout types.Int64 `tfsdk:"timeout"` +} + +func (a *startTranscriptionJobAction) Schema(ctx context.Context, req action.SchemaRequest, resp *action.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Starts an Amazon Transcribe transcription job to transcribe audio from a media file. The media file must be uploaded to an Amazon S3 bucket before starting the transcription job.", + Attributes: map[string]schema.Attribute{ + "transcription_job_name": schema.StringAttribute{ + Description: "A unique name for the transcription job within your AWS account.", + Required: true, + }, + "media_file_uri": schema.StringAttribute{ + Description: "The Amazon S3 location of the media file to transcribe (e.g., s3://bucket-name/file.mp3).", + Required: true, + }, + names.AttrLanguageCode: schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.LanguageCode](), + Description: "The language code for the language used in the input media file. Required if identify_language and identify_multiple_languages are both false.", + Optional: true, + }, + "identify_language": schema.BoolAttribute{ + Description: "Enable automatic language identification for single-language media files. Cannot be used with identify_multiple_languages.", + Optional: true, + }, + "identify_multiple_languages": schema.BoolAttribute{ + Description: "Enable automatic language identification for multi-language media files. Cannot be used with identify_language.", + Optional: true, + }, + "media_format": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.MediaFormat](), + Description: "The format of the input media file. If not specified, Amazon Transcribe will attempt to determine the format automatically.", + Optional: true, + }, + "media_sample_rate_hertz": schema.Int64Attribute{ + Description: "The sample rate of the input media file in Hertz. If not specified, Amazon Transcribe will attempt to determine the sample rate automatically.", + Optional: true, + }, + "output_bucket_name": schema.StringAttribute{ + Description: "The name of the Amazon S3 bucket where you want your transcription output stored. If not specified, output is stored in a service-managed bucket.", + Optional: true, + }, + "output_key": schema.StringAttribute{ + Description: "The Amazon S3 object key for your transcription output. If not specified, a default key is generated.", + Optional: true, + }, + names.AttrTimeout: schema.Int64Attribute{ + Description: "Maximum time in seconds to wait for the transcription job to start. Defaults to 300 seconds (5 minutes).", + Optional: true, + }, + }, + } +} + +func (a *startTranscriptionJobAction) Invoke(ctx context.Context, req action.InvokeRequest, resp *action.InvokeResponse) { + var config startTranscriptionJobActionModel + + // Parse configuration + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + // Get AWS client + conn := a.Meta().TranscribeClient(ctx) + + transcriptionJobName := config.TranscriptionJobName.ValueString() + mediaFileUri := config.MediaFileUri.ValueString() + + // Set default timeout + timeout := 5 * time.Minute + if !config.Timeout.IsNull() { + timeout = time.Duration(config.Timeout.ValueInt64()) * time.Second + } + + tflog.Info(ctx, "Starting transcription job action", map[string]any{ + "transcription_job_name": transcriptionJobName, + "media_file_uri": mediaFileUri, + "timeout_seconds": int64(timeout.Seconds()), + }) + + // Send initial progress update + resp.SendProgress(action.InvokeProgressEvent{ + Message: fmt.Sprintf("Starting transcription job %s...", transcriptionJobName), + }) + + // Build the start transcription job input + input := &transcribe.StartTranscriptionJobInput{ + TranscriptionJobName: aws.String(transcriptionJobName), + Media: &awstypes.Media{ + MediaFileUri: aws.String(mediaFileUri), + }, + } + + // Validate language configuration - exactly one must be specified + languageOptions := []bool{ + !config.LanguageCode.IsNull() && !config.LanguageCode.IsUnknown(), + !config.IdentifyLanguage.IsNull() && config.IdentifyLanguage.ValueBool(), + !config.IdentifyMultipleLanguages.IsNull() && config.IdentifyMultipleLanguages.ValueBool(), + } + + activeCount := 0 + for _, active := range languageOptions { + if active { + activeCount++ + } + } + + switch activeCount { + case 0: + resp.Diagnostics.AddError( + "Missing Language Configuration", + "You must specify exactly one of: language_code, identify_language, or identify_multiple_languages", + ) + return + case 1: + // Valid - continue + default: + resp.Diagnostics.AddError( + "Conflicting Language Configuration", + "You can only specify one of: language_code, identify_language, or identify_multiple_languages", + ) + return + } + + // Set language configuration + if languageOptions[0] { + input.LanguageCode = config.LanguageCode.ValueEnum() + } + if languageOptions[1] { + input.IdentifyLanguage = aws.Bool(true) + } + if languageOptions[2] { + input.IdentifyMultipleLanguages = aws.Bool(true) + } + + // Set optional parameters + if !config.MediaFormat.IsNull() && !config.MediaFormat.IsUnknown() { + input.MediaFormat = config.MediaFormat.ValueEnum() + } + + if !config.MediaSampleRateHertz.IsNull() { + input.MediaSampleRateHertz = aws.Int32(int32(config.MediaSampleRateHertz.ValueInt64())) + } + + if !config.OutputBucketName.IsNull() { + input.OutputBucketName = config.OutputBucketName.ValueStringPointer() + } + + if !config.OutputKey.IsNull() { + input.OutputKey = config.OutputKey.ValueStringPointer() + } + + // Start the transcription job + _, err := conn.StartTranscriptionJob(ctx, input) + if err != nil { + resp.Diagnostics.AddError( + "Failed to Start Transcription Job", + fmt.Sprintf("Could not start transcription job %s: %s", transcriptionJobName, err), + ) + return + } + + // Wait for job to move beyond QUEUED: treat IN_PROGRESS or COMPLETED as success, FAILED as failure, QUEUED transitional. + fr, err := actionwait.WaitForStatus(ctx, func(ctx context.Context) (actionwait.FetchResult[*awstypes.TranscriptionJob], error) { + input := transcribe.GetTranscriptionJobInput{TranscriptionJobName: aws.String(transcriptionJobName)} + getOutput, gerr := conn.GetTranscriptionJob(ctx, &input) + if gerr != nil { + return actionwait.FetchResult[*awstypes.TranscriptionJob]{}, fmt.Errorf("get transcription job: %w", gerr) + } + if getOutput.TranscriptionJob == nil { + return actionwait.FetchResult[*awstypes.TranscriptionJob]{}, fmt.Errorf("transcription job %s not found", transcriptionJobName) + } + status := getOutput.TranscriptionJob.TranscriptionJobStatus + return actionwait.FetchResult[*awstypes.TranscriptionJob]{Status: actionwait.Status(status), Value: getOutput.TranscriptionJob}, nil + }, actionwait.Options[*awstypes.TranscriptionJob]{ + Timeout: timeout, + Interval: actionwait.FixedInterval(transcriptionJobPollInterval), + ProgressInterval: transcriptionJobProgressInterval, + SuccessStates: []actionwait.Status{ + actionwait.Status(awstypes.TranscriptionJobStatusInProgress), + actionwait.Status(awstypes.TranscriptionJobStatusCompleted), + }, + TransitionalStates: []actionwait.Status{ + actionwait.Status(awstypes.TranscriptionJobStatusQueued), + }, + FailureStates: []actionwait.Status{ + actionwait.Status(awstypes.TranscriptionJobStatusFailed), + }, + ProgressSink: func(fr actionwait.FetchResult[any], meta actionwait.ProgressMeta) { + resp.SendProgress(action.InvokeProgressEvent{Message: fmt.Sprintf("Transcription job %s is currently %s", transcriptionJobName, fr.Status)}) + }, + }) + if err != nil { + var timeoutErr *actionwait.TimeoutError + var failureErr *actionwait.FailureStateError + var unexpectedErr *actionwait.UnexpectedStateError + + if errors.As(err, &timeoutErr) { + resp.Diagnostics.AddError( + "Timeout Waiting for Transcription Job", + fmt.Sprintf("Transcription job %s did not reach a running state within %v", transcriptionJobName, timeout), + ) + } else if errors.As(err, &failureErr) { + resp.Diagnostics.AddError( + "Transcription Job Failed", + fmt.Sprintf("Transcription job %s failed: %s", transcriptionJobName, failureErr.Status), + ) + } else if errors.As(err, &unexpectedErr) { + resp.Diagnostics.AddError( + "Unexpected Transcription Job Status", + fmt.Sprintf("Transcription job %s entered unexpected status: %s", transcriptionJobName, unexpectedErr.Status), + ) + } else { + resp.Diagnostics.AddError( + "Error Waiting for Transcription Job", + fmt.Sprintf("Error while waiting for transcription job %s: %s", transcriptionJobName, err), + ) + } + return + } + + resp.SendProgress(action.InvokeProgressEvent{Message: fmt.Sprintf("Transcription job %s started successfully and is %s", transcriptionJobName, fr.Status)}) + logFields := map[string]any{ + "transcription_job_name": transcriptionJobName, + "job_status": fr.Status, + } + if fr.Value != nil { + logFields[names.AttrCreationTime] = fr.Value.CreationTime + } + tflog.Info(ctx, "Transcription job started successfully", logFields) +} diff --git a/internal/service/transcribe/start_transcription_job_action_test.go b/internal/service/transcribe/start_transcription_job_action_test.go new file mode 100644 index 000000000000..3ca225096593 --- /dev/null +++ b/internal/service/transcribe/start_transcription_job_action_test.go @@ -0,0 +1,270 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package transcribe_test + +import ( + "context" + "fmt" + "slices" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/transcribe" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccTranscribeStartTranscriptionJobAction_basic(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + bucketName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccStartTranscriptionJobActionConfig_basic(rName, bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTranscriptionJobExists(ctx, rName), + testAccCheckTranscriptionJobStatus(ctx, rName, "IN_PROGRESS", "COMPLETED"), + ), + }, + }, + }) +} + +func TestAccTranscribeStartTranscriptionJobAction_identifyLanguage(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + bucketName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccStartTranscriptionJobActionConfig_identifyLanguage(rName, bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTranscriptionJobExists(ctx, rName), + testAccCheckTranscriptionJobStatus(ctx, rName, "IN_PROGRESS", "COMPLETED"), + testAccCheckTranscriptionJobIdentifyLanguage(ctx, rName, true), + ), + }, + }, + }) +} + +func TestAccTranscribeStartTranscriptionJobAction_withOutputLocation(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + bucketName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccStartTranscriptionJobActionConfig_withOutputLocation(rName, bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTranscriptionJobExists(ctx, rName), + testAccCheckTranscriptionJobStatus(ctx, rName, "IN_PROGRESS", "COMPLETED"), + ), + }, + }, + }) +} + +func testAccCheckTranscriptionJobExists(ctx context.Context, jobName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeClient(ctx) + + input := &transcribe.GetTranscriptionJobInput{ + TranscriptionJobName: &jobName, + } + + _, err := conn.GetTranscriptionJob(ctx, input) + if err != nil { + return fmt.Errorf("transcription job %s not found: %w", jobName, err) + } + + return nil + } +} + +func testAccCheckTranscriptionJobStatus(ctx context.Context, jobName string, expectedStatuses ...string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeClient(ctx) + + input := &transcribe.GetTranscriptionJobInput{ + TranscriptionJobName: &jobName, + } + + output, err := conn.GetTranscriptionJob(ctx, input) + if err != nil { + return fmt.Errorf("error getting transcription job %s: %w", jobName, err) + } + + if output.TranscriptionJob == nil { + return fmt.Errorf("transcription job %s not found", jobName) + } + + actualStatus := string(output.TranscriptionJob.TranscriptionJobStatus) + if slices.Contains(expectedStatuses, actualStatus) { + return nil + } + + return fmt.Errorf("expected transcription job %s status to be one of %v, got %s", jobName, expectedStatuses, actualStatus) + } +} + +func testAccCheckTranscriptionJobIdentifyLanguage(ctx context.Context, jobName string, expected bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeClient(ctx) + + input := &transcribe.GetTranscriptionJobInput{ + TranscriptionJobName: &jobName, + } + + output, err := conn.GetTranscriptionJob(ctx, input) + if err != nil { + return fmt.Errorf("error getting transcription job %s: %w", jobName, err) + } + + if output.TranscriptionJob == nil { + return fmt.Errorf("transcription job %s not found", jobName) + } + + actual := output.TranscriptionJob.IdentifyLanguage != nil && *output.TranscriptionJob.IdentifyLanguage + if actual != expected { + return fmt.Errorf("expected transcription job %s identify_language to be %t, got %t", jobName, expected, actual) + } + + return nil + } +} + +func testAccStartTranscriptionJobActionConfig_basic(rName, bucketName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[2]q + force_destroy = true +} + +resource "aws_s3_object" "test" { + bucket = aws_s3_bucket.test.bucket + key = "test-audio.wav" + source = "test-fixtures/test-audio.wav" +} + +action "aws_transcribe_start_transcription_job" "test" { + config { + transcription_job_name = %[1]q + media_file_uri = "s3://${aws_s3_bucket.test.bucket}/${aws_s3_object.test.key}" + language_code = "en-US" + timeout = 600 + } +} + +resource "terraform_data" "test" { + triggers_replace = [ + aws_s3_object.test.etag + ] + + input = "completed" + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.test] + } + } +} +`, rName, bucketName) +} + +func testAccStartTranscriptionJobActionConfig_identifyLanguage(rName, bucketName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[2]q + force_destroy = true +} + +resource "aws_s3_object" "test" { + bucket = aws_s3_bucket.test.bucket + key = "test-audio.wav" + source = "test-fixtures/test-audio.wav" +} + +action "aws_transcribe_start_transcription_job" "test" { + config { + transcription_job_name = %[1]q + media_file_uri = "s3://${aws_s3_bucket.test.bucket}/${aws_s3_object.test.key}" + identify_language = true + timeout = 600 + } +} + +resource "terraform_data" "test" { + triggers_replace = [ + aws_s3_object.test.etag + ] + + input = "completed" + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.test] + } + } +} +`, rName, bucketName) +} + +func testAccStartTranscriptionJobActionConfig_withOutputLocation(rName, bucketName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[2]q + force_destroy = true +} + +resource "aws_s3_object" "test" { + bucket = aws_s3_bucket.test.bucket + key = "test-audio.wav" + source = "test-fixtures/test-audio.wav" +} + +action "aws_transcribe_start_transcription_job" "test" { + config { + transcription_job_name = %[1]q + media_file_uri = "s3://${aws_s3_bucket.test.bucket}/${aws_s3_object.test.key}" + language_code = "en-US" + output_bucket_name = aws_s3_bucket.test.bucket + output_key = "transcripts/%[1]s.json" + timeout = 600 + } +} + +resource "terraform_data" "test" { + triggers_replace = [ + aws_s3_object.test.etag + ] + + input = "completed" + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.test] + } + } +} +`, rName, bucketName) +} diff --git a/internal/service/transcribe/test-fixtures/test-audio.wav b/internal/service/transcribe/test-fixtures/test-audio.wav new file mode 100644 index 000000000000..b33814b96b91 Binary files /dev/null and b/internal/service/transcribe/test-fixtures/test-audio.wav differ diff --git a/internal/service/transfer/exports_test.go b/internal/service/transfer/exports_test.go index bee2d12e1deb..a09ed3d4839c 100644 --- a/internal/service/transfer/exports_test.go +++ b/internal/service/transfer/exports_test.go @@ -5,25 +5,31 @@ package transfer // Exports for use in tests only. var ( - ResourceAccess = resourceAccess - ResourceAgreement = resourceAgreement - ResourceCertificate = resourceCertificate - ResourceConnector = resourceConnector - ResourceProfile = resourceProfile - ResourceServer = resourceServer - ResourceSSHKey = resourceSSHKey - ResourceTag = resourceTag - ResourceUser = resourceUser - ResourceWorkflow = resourceWorkflow + ResourceAccess = resourceAccess + ResourceAgreement = resourceAgreement + ResourceCertificate = resourceCertificate + ResourceConnector = resourceConnector + ResourceHostKey = newHostKeyResource + ResourceProfile = resourceProfile + ResourceServer = resourceServer + ResourceSSHKey = resourceSSHKey + ResourceTag = resourceTag + ResourceUser = resourceUser + ResourceWebApp = newWebAppResource + ResourceWebAppCustomization = newWebAppCustomizationResource + ResourceWorkflow = resourceWorkflow FindAccessByTwoPartKey = findAccessByTwoPartKey FindAgreementByTwoPartKey = findAgreementByTwoPartKey FindCertificateByID = findCertificateByID FindConnectorByID = findConnectorByID + FindHostKeyByTwoPartKey = findHostKeyByTwoPartKey FindProfileByID = findProfileByID FindServerByID = findServerByID FindTag = findTag FindUserByTwoPartKey = findUserByTwoPartKey FindUserSSHKeyByThreePartKey = findUserSSHKeyByThreePartKey FindWorkflowByID = findWorkflowByID + FindWebAppByID = findWebAppByID + FindWebAppCustomizationByID = findWebAppCustomizationByID ) diff --git a/internal/service/transfer/host_key.go b/internal/service/transfer/host_key.go new file mode 100644 index 000000000000..33f688bd85b3 --- /dev/null +++ b/internal/service/transfer/host_key.go @@ -0,0 +1,315 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package transfer + +import ( + "context" + "fmt" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/transfer" + awstypes "github.com/aws/aws-sdk-go-v2/service/transfer/types" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag" + intflex "github.com/hashicorp/terraform-provider-aws/internal/flex" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + tfstringplanmodifier "github.com/hashicorp/terraform-provider-aws/internal/framework/planmodifiers/stringplanmodifier" + "github.com/hashicorp/terraform-provider-aws/internal/framework/privatestate" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource("aws_transfer_host_key", name="Host Key") +// @Tags(identifierAttribute="arn") +func newHostKeyResource(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &hostKeyResource{} + + return r, nil +} + +type hostKeyResource struct { + framework.ResourceWithModel[hostKeyResourceModel] +} + +const ( + hostKeyBodyWOKey = "host_key_body_wo" +) + +func (r *hostKeyResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + names.AttrARN: framework.ARNAttributeComputedOnly(), + names.AttrDescription: schema.StringAttribute{ + Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(0, 200), + }, + }, + "host_key_body": schema.StringAttribute{ + Optional: true, + Sensitive: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(0, 4096), + stringvalidator.ExactlyOneOf( + path.MatchRoot("host_key_body"), + path.MatchRoot("host_key_body_wo"), + ), + stringvalidator.PreferWriteOnlyAttribute(path.MatchRoot("host_key_body_wo")), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "host_key_body_wo": schema.StringAttribute{ + Optional: true, + Sensitive: true, + WriteOnly: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(0, 4096), + }, + PlanModifiers: []planmodifier.String{ + tfstringplanmodifier.RequiresReplaceWO(hostKeyBodyWOKey), + }, + }, + "host_key_fingerprint": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "host_key_id": framework.IDAttribute(), + "server_id": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + names.AttrTags: tftags.TagsAttribute(), + names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), + }, + } +} + +func (r *hostKeyResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var plan, config hostKeyResourceModel + response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...) + if response.Diagnostics.HasError() { + return + } + response.Diagnostics.Append(request.Config.Get(ctx, &config)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().TransferClient(ctx) + + serverID := fwflex.StringValueFromFramework(ctx, plan.ServerID) + var input transfer.ImportHostKeyInput + response.Diagnostics.Append(fwflex.Expand(ctx, plan, &input)...) + if response.Diagnostics.HasError() { + return + } + + // Prefer write-only value. It's only in Config, not Plan. + if !config.HostKeyBodyWO.IsNull() { + input.HostKeyBody = fwflex.StringFromFramework(ctx, config.HostKeyBodyWO) + } + + // Additional fields. + input.Tags = getTagsIn(ctx) + + out, err := conn.ImportHostKey(ctx, &input) + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("creating Transfer Host Key (%s)", serverID), err.Error()) + + return + } + + // Store hash of write-only value. + if !config.HostKeyBodyWO.IsNull() { + woStore := privatestate.NewWriteOnlyValueStore(response.Private, hostKeyBodyWOKey) + response.Diagnostics.Append(woStore.SetValue(ctx, config.HostKeyBodyWO)...) + if response.Diagnostics.HasError() { + return + } + } + + hostKeyID := aws.ToString(out.HostKeyId) + hostKey, err := findHostKeyByTwoPartKey(ctx, conn, serverID, hostKeyID) + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("reading Transfer Host Key (%s)", hostKeyID), err.Error()) + + return + } + + // Set values for unknowns. + response.Diagnostics.Append(fwflex.Flatten(ctx, hostKey, &plan)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, plan)...) +} + +func (r *hostKeyResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var data hostKeyResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().TransferClient(ctx) + + serverID, hostKeyID := fwflex.StringValueFromFramework(ctx, data.ServerID), fwflex.StringValueFromFramework(ctx, data.HostKeyID) + out, err := findHostKeyByTwoPartKey(ctx, conn, serverID, hostKeyID) + if tfresource.NotFound(err) { + response.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) + response.State.RemoveResource(ctx) + return + } + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("reading Transfer Host Key (%s)", hostKeyID), err.Error()) + + return + } + + response.Diagnostics.Append(fwflex.Flatten(ctx, out, &data)...) + if response.Diagnostics.HasError() { + return + } + + setTagsOut(ctx, out.Tags) + + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} + +func (r *hostKeyResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var new, old hostKeyResourceModel + response.Diagnostics.Append(request.Plan.Get(ctx, &new)...) + response.Diagnostics.Append(request.State.Get(ctx, &old)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().TransferClient(ctx) + + diff, d := fwflex.Diff(ctx, new, old) + response.Diagnostics.Append(d...) + if response.Diagnostics.HasError() { + return + } + + if diff.HasChanges() { + hostKeyID := fwflex.StringValueFromFramework(ctx, new.HostKeyID) + var input transfer.UpdateHostKeyInput + response.Diagnostics.Append(fwflex.Expand(ctx, new, &input)...) + if response.Diagnostics.HasError() { + return + } + + _, err := conn.UpdateHostKey(ctx, &input) + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("updating Transfer Host Key (%s)", hostKeyID), err.Error()) + + return + } + } + + response.Diagnostics.Append(response.State.Set(ctx, &new)...) +} + +func (r *hostKeyResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data hostKeyResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().TransferClient(ctx) + + serverID, hostKeyID := fwflex.StringValueFromFramework(ctx, data.ServerID), fwflex.StringValueFromFramework(ctx, data.HostKeyID) + input := transfer.DeleteHostKeyInput{ + HostKeyId: aws.String(hostKeyID), + ServerId: aws.String(serverID), + } + _, err := conn.DeleteHostKey(ctx, &input) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("deleting Transfer Host Key (%s)", hostKeyID), err.Error()) + + return + } +} + +func (r *hostKeyResource) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + const ( + hostKeyIDParts = 2 + ) + parts, err := intflex.ExpandResourceId(request.ID, hostKeyIDParts, true) + + if err != nil { + response.Diagnostics.Append(fwdiag.NewParsingResourceIDErrorDiagnostic(err)) + + return + } + + response.Diagnostics.Append(response.State.SetAttribute(ctx, path.Root("server_id"), parts[0])...) + response.Diagnostics.Append(response.State.SetAttribute(ctx, path.Root("host_key_id"), parts[1])...) +} + +func findHostKeyByTwoPartKey(ctx context.Context, conn *transfer.Client, serverID, hostKeyID string) (*awstypes.DescribedHostKey, error) { + input := transfer.DescribeHostKeyInput{ + HostKeyId: aws.String(hostKeyID), + ServerId: aws.String(serverID), + } + + return findHostKey(ctx, conn, &input) +} + +func findHostKey(ctx context.Context, conn *transfer.Client, input *transfer.DescribeHostKeyInput) (*awstypes.DescribedHostKey, error) { + output, err := conn.DescribeHostKey(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.HostKey == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.HostKey, nil +} + +type hostKeyResourceModel struct { + framework.WithRegionModel + ARN types.String `tfsdk:"arn"` + Description types.String `tfsdk:"description"` + HostKeyBody types.String `tfsdk:"host_key_body"` + HostKeyBodyWO types.String `tfsdk:"host_key_body_wo"` + HostKeyFingerprint types.String `tfsdk:"host_key_fingerprint"` + HostKeyID types.String `tfsdk:"host_key_id"` + ServerID types.String `tfsdk:"server_id"` + Tags tftags.Map `tfsdk:"tags"` + TagsAll tftags.Map `tfsdk:"tags_all"` +} diff --git a/internal/service/transfer/host_key_test.go b/internal/service/transfer/host_key_test.go new file mode 100644 index 000000000000..096a19a6a859 --- /dev/null +++ b/internal/service/transfer/host_key_test.go @@ -0,0 +1,504 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package transfer_test + +import ( + "context" + "fmt" + "testing" + + "github.com/YakDriver/regexache" + awstypes "github.com/aws/aws-sdk-go-v2/service/transfer/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + tfknownvalue "github.com/hashicorp/terraform-provider-aws/internal/acctest/knownvalue" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tftransfer "github.com/hashicorp/terraform-provider-aws/internal/service/transfer" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func testAccHostKey_basic(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.DescribedHostKey + resourceName := "aws_transfer_host_key.test" + _, privateKey, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TransferServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckHostKeyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccHostKeyConfig_basic(privateKey), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrARN), tfknownvalue.RegionalARNRegexp("transfer", regexache.MustCompile(`host-key/.+/.+`))), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrDescription), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("host_key_fingerprint"), knownvalue.NotNull()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("host_key_id"), knownvalue.NotNull()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIdentifierAttribute: "host_key_id", + ImportStateIdFunc: acctest.AttrsImportStateIdFunc(resourceName, ",", "server_id", "host_key_id"), + ImportStateVerifyIgnore: []string{"host_key_body"}, + }, + }, + }) +} + +func testAccHostKey_disappears(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.DescribedHostKey + resourceName := "aws_transfer_host_key.test" + _, privateKey, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TransferServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckHostKeyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccHostKeyConfig_basic(privateKey), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tftransfer.ResourceHostKey, resourceName), + ), + ExpectNonEmptyPlan: true, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + }, + }, + }) +} + +func testAccHostKey_tags(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.DescribedHostKey + resourceName := "aws_transfer_host_key.test" + _, privateKey, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TransferServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckHostKeyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccHostKeyConfig_tags1(privateKey, acctest.CtKey1, acctest.CtValue1), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIdentifierAttribute: "host_key_id", + ImportStateIdFunc: acctest.AttrsImportStateIdFunc(resourceName, ",", "server_id", "host_key_id"), + ImportStateVerifyIgnore: []string{"host_key_body"}, + }, + { + Config: testAccHostKeyConfig_tags2(privateKey, acctest.CtKey1, acctest.CtValue1Updated, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1Updated), + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + }, + { + Config: testAccHostKeyConfig_tags1(privateKey, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + }, + }, + }) +} + +func testAccHostKey_description(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.DescribedHostKey + resourceName := "aws_transfer_host_key.test" + _, privateKey, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TransferServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckHostKeyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccHostKeyConfig_description(privateKey, "description1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrDescription), knownvalue.StringExact("description1")), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIdentifierAttribute: "host_key_id", + ImportStateIdFunc: acctest.AttrsImportStateIdFunc(resourceName, ",", "server_id", "host_key_id"), + ImportStateVerifyIgnore: []string{"host_key_body"}, + }, + { + Config: testAccHostKeyConfig_description(privateKey, "description2"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrDescription), knownvalue.StringExact("description2")), + }, + }, + }, + }) +} + +func testAccHostKey_updateHostKeyBody(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.DescribedHostKey + resourceName := "aws_transfer_host_key.test" + _, privateKey1, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + _, privateKey2, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TransferServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckHostKeyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccHostKeyConfig_basic(privateKey1), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + }, + { + Config: testAccHostKeyConfig_basic(privateKey2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionReplace), + }, + }, + }, + }, + }) +} + +func testAccHostKey_hostKeyBodyWO(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.DescribedHostKey + resourceName := "aws_transfer_host_key.test" + _, privateKey, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TransferServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckHostKeyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccHostKeyConfig_hostKeyBodyWO(privateKey), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrARN), tfknownvalue.RegionalARNRegexp("transfer", regexache.MustCompile(`host-key/.+/.+`))), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrDescription), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("host_key_fingerprint"), knownvalue.NotNull()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("host_key_id"), knownvalue.NotNull()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + }, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIdentifierAttribute: "host_key_id", + ImportStateIdFunc: acctest.AttrsImportStateIdFunc(resourceName, ",", "server_id", "host_key_id"), + ImportStateVerifyIgnore: []string{"host_key_body"}, + }, + }, + }) +} + +func testAccHostKey_updateHostKeyBodyWO(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.DescribedHostKey + resourceName := "aws_transfer_host_key.test" + _, privateKey1, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + _, privateKey2, err := sdkacctest.RandSSHKeyPair(acctest.DefaultEmailAddress) + if err != nil { + t.Fatalf("error generating random SSH key: %s", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TransferServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckHostKeyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccHostKeyConfig_hostKeyBodyWO(privateKey1), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + }, + }, + }, + { + Config: testAccHostKeyConfig_hostKeyBodyWO(privateKey2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHostKeyExists(ctx, resourceName, &v), + ), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionReplace), + }, + }, + }, + }, + }) +} + +func testAccCheckHostKeyExists(ctx context.Context, n string, v *awstypes.DescribedHostKey) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).TransferClient(ctx) + + output, err := tftransfer.FindHostKeyByTwoPartKey(ctx, conn, rs.Primary.Attributes["server_id"], rs.Primary.Attributes["host_key_id"]) + + if err != nil { + return err + } + + *v = *output + + return nil + } +} + +func testAccCheckHostKeyDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TransferClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_transfer_host_key" { + continue + } + + _, err := tftransfer.FindHostKeyByTwoPartKey(ctx, conn, rs.Primary.Attributes["server_id"], rs.Primary.Attributes["host_key_id"]) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("Transfer Host Key %s still exists", rs.Primary.Attributes["host_key_id"]) + } + + return nil + } +} + +func testAccHostKeyConfig_basic(privateKey string) string { + return fmt.Sprintf(` +resource "aws_transfer_server" "test" { + identity_provider_type = "SERVICE_MANAGED" +} + +resource "aws_transfer_host_key" "test" { + server_id = aws_transfer_server.test.id + host_key_body = < 0 { c.Delay = o.Delay } diff --git a/internal/tfresource/retry_test.go b/internal/tfresource/retry_test.go index dd2acc25f527..e7ba630190d3 100644 --- a/internal/tfresource/retry_test.go +++ b/internal/tfresource/retry_test.go @@ -11,7 +11,6 @@ import ( "testing" "time" - sdkretry "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/retry" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) @@ -479,7 +478,7 @@ func TestOptionsApply(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - conf := sdkretry.StateChangeConf{} + conf := retry.StateChangeConf{} testCase.options.Apply(&conf) diff --git a/internal/types/aws_region.go b/internal/types/aws_region.go index 227c157b9390..17df8f75c87b 100644 --- a/internal/types/aws_region.go +++ b/internal/types/aws_region.go @@ -9,5 +9,5 @@ import ( // IsAWSRegion returns whether or not the specified string is a valid AWS Region. func IsAWSRegion(s string) bool { // nosemgrep:ci.aws-in-func-name - return regexache.MustCompile(`^[a-z]{2}(-[a-z]+)+-\d{1,2}$`).MatchString(s) + return regexache.MustCompile(`^[a-z]{2,4}(-[a-z]+)+-\d{1,2}$`).MatchString(s) } diff --git a/internal/types/aws_region_test.go b/internal/types/aws_region_test.go index bbcb4665163d..8cd9969d2a76 100644 --- a/internal/types/aws_region_test.go +++ b/internal/types/aws_region_test.go @@ -18,6 +18,7 @@ func TestIsAWSRegion(t *testing.T) { // nosemgrep:ci.aws-in-func-name {"", false}, {"eu-isoe-west-1", true}, {"mars", false}, + {"eusc-de-east-1", true}, } { ok := IsAWSRegion(tc.id) if got, want := ok, tc.valid; got != want { diff --git a/internal/verify/validate.go b/internal/verify/validate.go index 087c8ab59951..5238ab7d18b5 100644 --- a/internal/verify/validate.go +++ b/internal/verify/validate.go @@ -330,7 +330,7 @@ func ValidLaunchTemplateID(v any, k string) (ws []string, errors []error) { errors = append(errors, fmt.Errorf("%q cannot be longer than 255 characters", k)) } else if !regexache.MustCompile(`^lt\-[0-9a-z]+$`).MatchString(value) { errors = append(errors, fmt.Errorf( - "%q must begin with 'lt-' and be comprised of only alphanumeric characters: %v", k, value)) + "%q must begin with 'lt-' and only contain alphanumeric characters: %v", k, value)) } return } diff --git a/internal/verify/validate_test.go b/internal/verify/validate_test.go index 7712b35aacb6..8c67824dfd43 100644 --- a/internal/verify/validate_test.go +++ b/internal/verify/validate_test.go @@ -176,6 +176,7 @@ func TestValidARN(t *testing.T) { "arn:aws-us-gov:s3:::bucket/object", // lintignore:AWSAT005 // GovCloud S3 ARN "arn:aws:cloudwatch::cw0000000000:alarm:my-alarm", // lintignore:AWSAT005 // CloudWatch Alarm "arn:aws:imagebuilder:eu-central-1:aws-marketplace:component/crowdstrike-falcon-install-linux-prod-nhzsem4gwwfja/1.2.2/1", // lintignore:AWSAT003,AWSAT005 // EC2 image builder marketplace subscription ARN + "arn:aws-eusc:acm-pca:eusc-de-east-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012", // lintignore:AWSAT003,AWSAT005 // ESC ACMPCA ARN } for _, v := range validNames { _, errors := ValidARN(v, "arn") diff --git a/skaff/go.mod b/skaff/go.mod index 614915d036dc..798a430cbb74 100644 --- a/skaff/go.mod +++ b/skaff/go.mod @@ -13,7 +13,7 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect diff --git a/skaff/go.sum b/skaff/go.sum index 597c36d88848..115b773a23e7 100644 --- a/skaff/go.sum +++ b/skaff/go.sum @@ -13,8 +13,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 h1:HA6blfR0h6kGnw4oJ92tZzghubreIkWbQJ4NVNqS688= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66/go.mod h1:7kTJVbY5+igob9Q5N6KO81EGEKDNI9FpjujB31uI/n0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 h1:IS4mjtvkLHXWI5yn/t9ILOUiBqPePMFaO4IRh5pcMk4= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67/go.mod h1:l81jrdpcZSWUsJs4BGFfdGScefSYEFQRLMQRG3uyvT0= github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= diff --git a/tools/tfsdk2fw/go.mod b/tools/tfsdk2fw/go.mod index 43bef2ac009e..073838deb544 100644 --- a/tools/tfsdk2fw/go.mod +++ b/tools/tfsdk2fw/go.mod @@ -18,277 +18,277 @@ require ( github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.39.1 // indirect + github.com/aws/aws-sdk-go-v2 v1.39.2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect - github.com/aws/aws-sdk-go-v2/config v1.31.10 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.18.14 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.8 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.8 // indirect + github.com/aws/aws-sdk-go-v2/config v1.31.12 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.18.16 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.11 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.8 // indirect - github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.5 // indirect - github.com/aws/aws-sdk-go-v2/service/account v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/service/acm v1.37.5 // indirect - github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.4 // indirect - github.com/aws/aws-sdk-go-v2/service/amp v1.40.2 // indirect - github.com/aws/aws-sdk-go-v2/service/amplify v1.37.4 // indirect - github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.5 // indirect - github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.5 // indirect - github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.5 // indirect - github.com/aws/aws-sdk-go-v2/service/appflow v1.50.5 // indirect - github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.5 // indirect - github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.4 // indirect - github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.4 // indirect - github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.15.7 // indirect - github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.5 // indirect - github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.6 // indirect - github.com/aws/aws-sdk-go-v2/service/appstream v1.49.5 // indirect - github.com/aws/aws-sdk-go-v2/service/appsync v1.51.5 // indirect - github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.7 // indirect - github.com/aws/aws-sdk-go-v2/service/athena v1.55.5 // indirect - github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.5 // indirect - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.2 // indirect - github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.4 // indirect - github.com/aws/aws-sdk-go-v2/service/backup v1.47.5 // indirect - github.com/aws/aws-sdk-go-v2/service/batch v1.57.9 // indirect - github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.7 // indirect - github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.1 // indirect - github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.5 // indirect - github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.5.1 // indirect - github.com/aws/aws-sdk-go-v2/service/billing v1.7.6 // indirect - github.com/aws/aws-sdk-go-v2/service/budgets v1.39.1 // indirect - github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.5 // indirect - github.com/aws/aws-sdk-go-v2/service/chime v1.40.4 // indirect - github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.5 // indirect - github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.26.4 // indirect - github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.34.0 // indirect - github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.4 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudformation v1.66.3 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.3 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.7 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.4 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.5 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.5 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.50.2 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.1 // indirect - github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.5 // indirect - github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.4 // indirect - github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.7 // indirect - github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.4 // indirect - github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.4 // indirect - github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.4 // indirect - github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.4 // indirect - github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.5 // indirect - github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.5 // indirect - github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.5 // indirect - github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.5 // indirect - github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.6 // indirect - github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.5 // indirect - github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.4 // indirect - github.com/aws/aws-sdk-go-v2/service/configservice v1.58.1 // indirect - github.com/aws/aws-sdk-go-v2/service/connect v1.140.1 // indirect - github.com/aws/aws-sdk-go-v2/service/connectcases v1.30.5 // indirect - github.com/aws/aws-sdk-go-v2/service/controltower v1.26.5 // indirect - github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.5 // indirect - github.com/aws/aws-sdk-go-v2/service/costexplorer v1.56.1 // indirect - github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.5 // indirect - github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.52.5 // indirect - github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.5 // indirect - github.com/aws/aws-sdk-go-v2/service/databrew v1.38.4 // indirect - github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.4 // indirect - github.com/aws/aws-sdk-go-v2/service/datasync v1.54.5 // indirect - github.com/aws/aws-sdk-go-v2/service/datazone v1.41.2 // indirect - github.com/aws/aws-sdk-go-v2/service/dax v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/service/detective v1.37.6 // indirect - github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.5 // indirect - github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.5 // indirect - github.com/aws/aws-sdk-go-v2/service/directoryservice v1.37.4 // indirect - github.com/aws/aws-sdk-go-v2/service/dlm v1.34.5 // indirect - github.com/aws/aws-sdk-go-v2/service/docdb v1.46.5 // indirect - github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.5 // indirect - github.com/aws/aws-sdk-go-v2/service/drs v1.35.5 // indirect - github.com/aws/aws-sdk-go-v2/service/dsql v1.9.7 // indirect - github.com/aws/aws-sdk-go-v2/service/dynamodb v1.50.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.50.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ecs v1.64.1 // indirect - github.com/aws/aws-sdk-go-v2/service/efs v1.40.6 // indirect - github.com/aws/aws-sdk-go-v2/service/eks v1.74.1 // indirect - github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.4 // indirect - github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.6 // indirect - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.5 // indirect - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.5 // indirect - github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.5 // indirect - github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/emr v1.54.4 // indirect - github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.1 // indirect - github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.5 // indirect - github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.4 // indirect - github.com/aws/aws-sdk-go-v2/service/evidently v1.28.4 // indirect - github.com/aws/aws-sdk-go-v2/service/evs v1.5.1 // indirect - github.com/aws/aws-sdk-go-v2/service/finspace v1.33.5 // indirect - github.com/aws/aws-sdk-go-v2/service/firehose v1.41.5 // indirect - github.com/aws/aws-sdk-go-v2/service/fis v1.37.4 // indirect - github.com/aws/aws-sdk-go-v2/service/fms v1.44.4 // indirect - github.com/aws/aws-sdk-go-v2/service/fsx v1.61.5 // indirect - github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.5 // indirect - github.com/aws/aws-sdk-go-v2/service/glacier v1.31.5 // indirect - github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.5 // indirect - github.com/aws/aws-sdk-go-v2/service/glue v1.128.4 // indirect - github.com/aws/aws-sdk-go-v2/service/grafana v1.31.5 // indirect - github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.5 // indirect - github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.1 // indirect - github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.4 // indirect - github.com/aws/aws-sdk-go-v2/service/iam v1.47.6 // indirect - github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.47.1 // indirect - github.com/aws/aws-sdk-go-v2/service/inspector v1.30.4 // indirect - github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 // indirect + github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.6 // indirect + github.com/aws/aws-sdk-go-v2/service/account v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/service/acm v1.37.6 // indirect + github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.5 // indirect + github.com/aws/aws-sdk-go-v2/service/amp v1.40.3 // indirect + github.com/aws/aws-sdk-go-v2/service/amplify v1.37.5 // indirect + github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.6 // indirect + github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.6 // indirect + github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.6 // indirect + github.com/aws/aws-sdk-go-v2/service/appflow v1.50.6 // indirect + github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.5 // indirect + github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.5 // indirect + github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.16.0 // indirect + github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.6 // indirect + github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.7 // indirect + github.com/aws/aws-sdk-go-v2/service/appstream v1.49.7 // indirect + github.com/aws/aws-sdk-go-v2/service/appsync v1.51.6 // indirect + github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.8 // indirect + github.com/aws/aws-sdk-go-v2/service/athena v1.55.6 // indirect + github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.6 // indirect + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.3 // indirect + github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.5 // indirect + github.com/aws/aws-sdk-go-v2/service/backup v1.48.0 // indirect + github.com/aws/aws-sdk-go-v2/service/batch v1.57.10 // indirect + github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.8 // indirect + github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.2 // indirect + github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.6 // indirect + github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.7.0 // indirect + github.com/aws/aws-sdk-go-v2/service/billing v1.8.0 // indirect + github.com/aws/aws-sdk-go-v2/service/budgets v1.39.2 // indirect + github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.6 // indirect + github.com/aws/aws-sdk-go-v2/service/chime v1.40.5 // indirect + github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.6 // indirect + github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.27.0 // indirect + github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.36.0 // indirect + github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.5 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.67.0 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.8 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.5 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.6 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.6 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.51.1 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.2 // indirect + github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.6 // indirect + github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.5 // indirect + github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.8 // indirect + github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.5 // indirect + github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.5 // indirect + github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.5 // indirect + github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.5 // indirect + github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.6 // indirect + github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.6 // indirect + github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.6 // indirect + github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.6 // indirect + github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.7 // indirect + github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.6 // indirect + github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.5 // indirect + github.com/aws/aws-sdk-go-v2/service/configservice v1.58.2 // indirect + github.com/aws/aws-sdk-go-v2/service/connect v1.141.0 // indirect + github.com/aws/aws-sdk-go-v2/service/connectcases v1.32.0 // indirect + github.com/aws/aws-sdk-go-v2/service/controltower v1.26.6 // indirect + github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.6 // indirect + github.com/aws/aws-sdk-go-v2/service/costexplorer v1.57.0 // indirect + github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.6 // indirect + github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.53.0 // indirect + github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.7 // indirect + github.com/aws/aws-sdk-go-v2/service/databrew v1.38.5 // indirect + github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.5 // indirect + github.com/aws/aws-sdk-go-v2/service/datasync v1.55.0 // indirect + github.com/aws/aws-sdk-go-v2/service/datazone v1.42.0 // indirect + github.com/aws/aws-sdk-go-v2/service/dax v1.29.1 // indirect + github.com/aws/aws-sdk-go-v2/service/detective v1.37.7 // indirect + github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.6 // indirect + github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.6 // indirect + github.com/aws/aws-sdk-go-v2/service/directoryservice v1.38.0 // indirect + github.com/aws/aws-sdk-go-v2/service/dlm v1.34.6 // indirect + github.com/aws/aws-sdk-go-v2/service/docdb v1.46.6 // indirect + github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.6 // indirect + github.com/aws/aws-sdk-go-v2/service/drs v1.35.6 // indirect + github.com/aws/aws-sdk-go-v2/service/dsql v1.9.8 // indirect + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.51.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.50.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ecs v1.65.1 // indirect + github.com/aws/aws-sdk-go-v2/service/efs v1.40.8 // indirect + github.com/aws/aws-sdk-go-v2/service/eks v1.74.2 // indirect + github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.5 // indirect + github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.7 // indirect + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.6 // indirect + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.6 // indirect + github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.6 // indirect + github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/service/emr v1.54.5 // indirect + github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.2 // indirect + github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.5 // indirect + github.com/aws/aws-sdk-go-v2/service/evidently v1.28.5 // indirect + github.com/aws/aws-sdk-go-v2/service/evs v1.5.2 // indirect + github.com/aws/aws-sdk-go-v2/service/finspace v1.33.6 // indirect + github.com/aws/aws-sdk-go-v2/service/firehose v1.41.6 // indirect + github.com/aws/aws-sdk-go-v2/service/fis v1.37.5 // indirect + github.com/aws/aws-sdk-go-v2/service/fms v1.44.6 // indirect + github.com/aws/aws-sdk-go-v2/service/fsx v1.62.0 // indirect + github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.6 // indirect + github.com/aws/aws-sdk-go-v2/service/glacier v1.31.6 // indirect + github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.6 // indirect + github.com/aws/aws-sdk-go-v2/service/glue v1.130.0 // indirect + github.com/aws/aws-sdk-go-v2/service/grafana v1.31.6 // indirect + github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.6 // indirect + github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.3 // indirect + github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.5 // indirect + github.com/aws/aws-sdk-go-v2/service/iam v1.47.7 // indirect + github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.48.0 // indirect + github.com/aws/aws-sdk-go-v2/service/inspector v1.30.5 // indirect + github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.8 // indirect - github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.4 // indirect - github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.7 // indirect - github.com/aws/aws-sdk-go-v2/service/iot v1.69.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ivs v1.47.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.4 // indirect - github.com/aws/aws-sdk-go-v2/service/kafka v1.43.5 // indirect - github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.4 // indirect - github.com/aws/aws-sdk-go-v2/service/kendra v1.60.5 // indirect - github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.5 // indirect - github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.4 // indirect - github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.5 // indirect - github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.6 // indirect - github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.4 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.45.4 // indirect - github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.4 // indirect - github.com/aws/aws-sdk-go-v2/service/lambda v1.77.5 // indirect - github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.5 // indirect - github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.4 // indirect - github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.5 // indirect - github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.5 // indirect - github.com/aws/aws-sdk-go-v2/service/lightsail v1.48.5 // indirect - github.com/aws/aws-sdk-go-v2/service/location v1.49.5 // indirect - github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.5 // indirect - github.com/aws/aws-sdk-go-v2/service/m2 v1.25.5 // indirect - github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.5 // indirect - github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.44.5 // indirect - github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.5 // indirect - github.com/aws/aws-sdk-go-v2/service/medialive v1.83.1 // indirect - github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.2 // indirect - github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.5 // indirect - github.com/aws/aws-sdk-go-v2/service/memorydb v1.31.5 // indirect - github.com/aws/aws-sdk-go-v2/service/mgn v1.37.4 // indirect - github.com/aws/aws-sdk-go-v2/service/mq v1.34.3 // indirect - github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/neptune v1.42.3 // indirect - github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.4 // indirect - github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.56.1 // indirect - github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.6 // indirect - github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.5 // indirect - github.com/aws/aws-sdk-go-v2/service/notifications v1.7.3 // indirect - github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.7 // indirect - github.com/aws/aws-sdk-go-v2/service/oam v1.22.4 // indirect - github.com/aws/aws-sdk-go-v2/service/odb v1.4.5 // indirect - github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.4 // indirect - github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.3 // indirect - github.com/aws/aws-sdk-go-v2/service/organizations v1.45.2 // indirect - github.com/aws/aws-sdk-go-v2/service/osis v1.20.1 // indirect - github.com/aws/aws-sdk-go-v2/service/outposts v1.56.6 // indirect - github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.1 // indirect - github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.5 // indirect - github.com/aws/aws-sdk-go-v2/service/pcs v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.4 // indirect - github.com/aws/aws-sdk-go-v2/service/pipes v1.23.4 // indirect - github.com/aws/aws-sdk-go-v2/service/polly v1.53.5 // indirect - github.com/aws/aws-sdk-go-v2/service/pricing v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.5 // indirect - github.com/aws/aws-sdk-go-v2/service/qldb v1.30.5 // indirect - github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ram v1.34.5 // indirect - github.com/aws/aws-sdk-go-v2/service/rbin v1.26.5 // indirect - github.com/aws/aws-sdk-go-v2/service/rds v1.107.1 // indirect - github.com/aws/aws-sdk-go-v2/service/redshift v1.58.4 // indirect - github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.5 // indirect - github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.7 // indirect - github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.4 // indirect - github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.5 // indirect - github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.21.5 // indirect - github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.6 // indirect - github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.5 // indirect - github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.5 // indirect - github.com/aws/aws-sdk-go-v2/service/route53 v1.58.3 // indirect - github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.3 // indirect - github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.5 // indirect - github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.6 // indirect - github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.5 // indirect - github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.5 // indirect - github.com/aws/aws-sdk-go-v2/service/rum v1.28.6 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.88.2 // indirect - github.com/aws/aws-sdk-go-v2/service/s3control v1.66.1 // indirect - github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.5 // indirect - github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.4 // indirect - github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.7 // indirect - github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.2 // indirect - github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.4 // indirect - github.com/aws/aws-sdk-go-v2/service/schemas v1.33.4 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.3 // indirect - github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.5 // indirect - github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.5 // indirect - github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.5 // indirect - github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.5 // indirect - github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.8 // indirect - github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ses v1.34.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sfn v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/shield v1.34.5 // indirect - github.com/aws/aws-sdk-go-v2/service/signer v1.31.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sns v1.38.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sqs v1.42.7 // indirect - github.com/aws/aws-sdk-go-v2/service/ssm v1.65.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.7 // indirect - github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.29.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.0 // indirect - github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.38.5 // indirect - github.com/aws/aws-sdk-go-v2/service/swf v1.32.4 // indirect - github.com/aws/aws-sdk-go-v2/service/synthetics v1.40.5 // indirect - github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.5 // indirect - github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.5 // indirect - github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.4 // indirect - github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.4 // indirect - github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.5 // indirect - github.com/aws/aws-sdk-go-v2/service/transfer v1.65.6 // indirect - github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.3 // indirect - github.com/aws/aws-sdk-go-v2/service/vpclattice v1.18.4 // indirect - github.com/aws/aws-sdk-go-v2/service/waf v1.30.4 // indirect - github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.5 // indirect - github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.6 // indirect - github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.5 // indirect - github.com/aws/aws-sdk-go-v2/service/workmail v1.36.3 // indirect - github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.5 // indirect - github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/xray v1.36.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.5 // indirect + github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.8 // indirect + github.com/aws/aws-sdk-go-v2/service/iot v1.69.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ivs v1.47.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.5 // indirect + github.com/aws/aws-sdk-go-v2/service/kafka v1.43.6 // indirect + github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.5 // indirect + github.com/aws/aws-sdk-go-v2/service/kendra v1.60.6 // indirect + github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.6 // indirect + github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.5 // indirect + github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.6 // indirect + github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.7 // indirect + github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.45.6 // indirect + github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.5 // indirect + github.com/aws/aws-sdk-go-v2/service/lambda v1.77.6 // indirect + github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.6 // indirect + github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.5 // indirect + github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.6 // indirect + github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/service/lightsail v1.49.1 // indirect + github.com/aws/aws-sdk-go-v2/service/location v1.49.6 // indirect + github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/service/m2 v1.25.6 // indirect + github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.6 // indirect + github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.45.0 // indirect + github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.6 // indirect + github.com/aws/aws-sdk-go-v2/service/medialive v1.84.0 // indirect + github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.3 // indirect + github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.6 // indirect + github.com/aws/aws-sdk-go-v2/service/memorydb v1.32.0 // indirect + github.com/aws/aws-sdk-go-v2/service/mgn v1.37.5 // indirect + github.com/aws/aws-sdk-go-v2/service/mq v1.34.4 // indirect + github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/neptune v1.42.5 // indirect + github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.5 // indirect + github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.57.1 // indirect + github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.7 // indirect + github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/notifications v1.7.4 // indirect + github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.8 // indirect + github.com/aws/aws-sdk-go-v2/service/oam v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/odb v1.4.6 // indirect + github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.5 // indirect + github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.4 // indirect + github.com/aws/aws-sdk-go-v2/service/organizations v1.45.3 // indirect + github.com/aws/aws-sdk-go-v2/service/osis v1.20.2 // indirect + github.com/aws/aws-sdk-go-v2/service/outposts v1.56.7 // indirect + github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.2 // indirect + github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.6 // indirect + github.com/aws/aws-sdk-go-v2/service/pcs v1.14.0 // indirect + github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.5 // indirect + github.com/aws/aws-sdk-go-v2/service/pipes v1.23.5 // indirect + github.com/aws/aws-sdk-go-v2/service/polly v1.53.6 // indirect + github.com/aws/aws-sdk-go-v2/service/pricing v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.6 // indirect + github.com/aws/aws-sdk-go-v2/service/qldb v1.30.6 // indirect + github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.4 // indirect + github.com/aws/aws-sdk-go-v2/service/ram v1.34.6 // indirect + github.com/aws/aws-sdk-go-v2/service/rbin v1.26.6 // indirect + github.com/aws/aws-sdk-go-v2/service/rds v1.108.1 // indirect + github.com/aws/aws-sdk-go-v2/service/redshift v1.59.0 // indirect + github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.6 // indirect + github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.8 // indirect + github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.5 // indirect + github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.6 // indirect + github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.22.0 // indirect + github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.7 // indirect + github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.6 // indirect + github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.6 // indirect + github.com/aws/aws-sdk-go-v2/service/route53 v1.58.4 // indirect + github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.4 // indirect + github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.6 // indirect + github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.7 // indirect + github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.6 // indirect + github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.6 // indirect + github.com/aws/aws-sdk-go-v2/service/rum v1.28.7 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.88.3 // indirect + github.com/aws/aws-sdk-go-v2/service/s3control v1.66.2 // indirect + github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.6 // indirect + github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.5 // indirect + github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.3 // indirect + github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.5 // indirect + github.com/aws/aws-sdk-go-v2/service/schemas v1.33.5 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.4 // indirect + github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.6 // indirect + github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.6 // indirect + github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.6 // indirect + github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.6 // indirect + github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.9 // indirect + github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ses v1.34.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sfn v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/shield v1.34.6 // indirect + github.com/aws/aws-sdk-go-v2/service/signer v1.31.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sns v1.38.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sqs v1.42.8 // indirect + github.com/aws/aws-sdk-go-v2/service/ssm v1.65.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.8 // indirect + github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect + github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect + github.com/aws/aws-sdk-go-v2/service/swf v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/service/synthetics v1.41.0 // indirect + github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.6 // indirect + github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.6 // indirect + github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.5 // indirect + github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.5 // indirect + github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.6 // indirect + github.com/aws/aws-sdk-go-v2/service/transfer v1.66.0 // indirect + github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.5 // indirect + github.com/aws/aws-sdk-go-v2/service/vpclattice v1.19.0 // indirect + github.com/aws/aws-sdk-go-v2/service/waf v1.30.5 // indirect + github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.6 // indirect + github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.7 // indirect + github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.6 // indirect + github.com/aws/aws-sdk-go-v2/service/workmail v1.36.4 // indirect + github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.6 // indirect + github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/service/xray v1.36.4 // indirect github.com/aws/smithy-go v1.23.0 // indirect github.com/beevik/etree v1.6.0 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect @@ -304,7 +304,7 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.23.0 // indirect - github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 // indirect github.com/hashicorp/awspolicyequivalence v1.7.0 // indirect github.com/hashicorp/cli v1.1.7 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -322,7 +322,7 @@ require ( github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.24.0 // indirect github.com/hashicorp/terraform-json v0.27.2 // indirect - github.com/hashicorp/terraform-plugin-framework v1.16.0 // indirect + github.com/hashicorp/terraform-plugin-framework v1.16.1 // indirect github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0 // indirect github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 // indirect github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 // indirect @@ -357,7 +357,7 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/zclconf/go-cty v1.17.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.63.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect diff --git a/tools/tfsdk2fw/go.sum b/tools/tfsdk2fw/go.sum index 766b8a81917d..b1e8fbf0d868 100644 --- a/tools/tfsdk2fw/go.sum +++ b/tools/tfsdk2fw/go.sum @@ -23,548 +23,548 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.39.1 h1:fWZhGAwVRK/fAN2tmt7ilH4PPAE11rDj7HytrmbZ2FE= -github.com/aws/aws-sdk-go-v2 v1.39.1/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= +github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I= +github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00= -github.com/aws/aws-sdk-go-v2/config v1.31.10 h1:7LllDZAegXU3yk41mwM6KcPu0wmjKGQB1bg99bNdQm4= -github.com/aws/aws-sdk-go-v2/config v1.31.10/go.mod h1:Ge6gzXPjqu4v0oHvgAwvGzYcK921GU0hQM25WF/Kl+8= -github.com/aws/aws-sdk-go-v2/credentials v1.18.14 h1:TxkI7QI+sFkTItN/6cJuMZEIVMFXeu2dI1ZffkXngKI= -github.com/aws/aws-sdk-go-v2/credentials v1.18.14/go.mod h1:12x4Uw/vijC11XkctTjy92TNCQ+UnNJkT7fzX0Yd93E= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.8 h1:gLD09eaJUdiszm7vd1btiQUYE0Hj+0I2b8AS+75z9AY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.8/go.mod h1:4RW3oMPt1POR74qVOC4SbubxAwdP4pCT0nSw3jycOU4= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.8 h1:QcAh/TNGM3MWe95ilMWwnieXWXsyM33Mb/RuTGlWLm4= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.8/go.mod h1:72m/ZCCgYpXJzsgI8uJFYMnXEjtZ4kkaolL9NRXLSnU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.8 h1:6bgAZgRyT4RoFWhxS+aoGMFyE0cD1bSzFnEEi4bFPGI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.8/go.mod h1:KcGkXFVU8U28qS4KvLEcPxytPZPBcRawaH2Pf/0jptE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.8 h1:HhJYoES3zOz34yWEpGENqJvRVPqpmJyR3+AFg9ybhdY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.8/go.mod h1:JnA+hPWeYAVbDssp83tv+ysAG8lTfLVXvSsyKg/7xNA= +github.com/aws/aws-sdk-go-v2/config v1.31.12 h1:pYM1Qgy0dKZLHX2cXslNacbcEFMkDMl+Bcj5ROuS6p8= +github.com/aws/aws-sdk-go-v2/config v1.31.12/go.mod h1:/MM0dyD7KSDPR+39p9ZNVKaHDLb9qnfDurvVS2KAhN8= +github.com/aws/aws-sdk-go-v2/credentials v1.18.16 h1:4JHirI4zp958zC026Sm+V4pSDwW4pwLefKrc0bF2lwI= +github.com/aws/aws-sdk-go-v2/credentials v1.18.16/go.mod h1:qQMtGx9OSw7ty1yLclzLxXCRbrkjWAM7JnObZjmCB7I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 h1:Mv4Bc0mWmv6oDuSWTKnk+wgeqPL5DRFu5bQL9BGPQ8Y= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9/go.mod h1:IKlKfRppK2a1y0gy1yH6zD+yX5uplJ6UuPlgd48dJiQ= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.11 h1:w4GjasReY0m9vZA/3YhoBUBi1ZIWUHYQRm61v0BKcZg= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.11/go.mod h1:IPS1CSYQ8lfLYGytpMEPW4erZmVFUdxLpC0RCI/RCn8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.8 h1:1/bT9kDdLQzfZ1e6J6hpW+SfNDd6xrV8F3M2CuGyUz8= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.8/go.mod h1:RbdwTONAIi59ej/+1H+QzZORt5bcyAtbrS7FQb2pvz0= -github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.5 h1:ahcmzpmxwWG+/G67+QVEZK7GBWywTSG6jDEJ4PzpYgo= -github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.5/go.mod h1:9usigGMimzM79Y4yFdqgqC1SasoUKDVTmwpeHBrw6yw= -github.com/aws/aws-sdk-go-v2/service/account v1.28.5 h1:VDhBmhdDYFqzT4jBo/+dlK8OQBzCNdxbbvmVFOxIGhE= -github.com/aws/aws-sdk-go-v2/service/account v1.28.5/go.mod h1:LhQR+JAtexjWOFlTHqdqTv/BTbvs9xY68KTzCEx8woo= -github.com/aws/aws-sdk-go-v2/service/acm v1.37.5 h1:vTmyvkmMJEKZgyhSuaEv8gZCJJlgNpSpYy/4CExjHoA= -github.com/aws/aws-sdk-go-v2/service/acm v1.37.5/go.mod h1:TmyW/AiLmFEXwFsm5hh2T86BpgFbcB1icshuzFu8LgY= -github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.4 h1:1SdrKkB7zWf/jzV1NCECWGaK/tW+hDFein1Bx+zlmM0= -github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.4/go.mod h1:fEljIacWp3QN6OhEeSdETPP1QAon5eqOFQNNU870EiQ= -github.com/aws/aws-sdk-go-v2/service/amp v1.40.2 h1:LeNARz0HYUAPNF9SvUE+7YuWH9EfVV6lXyDSS/IJGZk= -github.com/aws/aws-sdk-go-v2/service/amp v1.40.2/go.mod h1:FvXvxRCSJ+C4GXgypn3JO42MrQpuw/82xT/w+pgZ9eo= -github.com/aws/aws-sdk-go-v2/service/amplify v1.37.4 h1:8yMWsijdMvnkK2CY1JfVu5hV8r0yprDaecgiacf1jrM= -github.com/aws/aws-sdk-go-v2/service/amplify v1.37.4/go.mod h1:k2qW1S0NN8fi7hLuQjqOdQvMIbzFsvM3qm+oS1SfX60= -github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.5 h1:skBoXAddT8Kj8Hu6B/+rpDd8btytsDuQtV91j4yv9Kw= -github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.5/go.mod h1:17HIwZjGn7CtmiRV4Q2AO6srqQZRC0c+KlAiyAGK+uQ= -github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.5 h1:6XVaF2fTNZThz5n/3YObHIIFS1WaaGnbQI/6aJasdas= -github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.5/go.mod h1:MYkXmYhWdgLwkzyjfbRchnSf53boo7m6QAS3ZRXaZKg= -github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.5 h1:ZWyYnXjlZ+48zYLyzOZ9t6BrDCJlDzd3A8TnGtYjDRI= -github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.5/go.mod h1:LpxhBlp1oM7R0CErx8+KR9VpiSS1UUb9UEM0GivB5WM= -github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.5 h1:DK+9MD7xMUFGJiqW+kJiMSIxaGoO8F3KJL5tAXZbnWc= -github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.5/go.mod h1:2x1+Rk0RpGfGhYX3dWyA21YiF/v65J3Y6GywC4VxiWA= -github.com/aws/aws-sdk-go-v2/service/appflow v1.50.5 h1:G4mGauYPPnWffLrZGLSBHMlSVZmJ6hlyMlL0UhMWuJA= -github.com/aws/aws-sdk-go-v2/service/appflow v1.50.5/go.mod h1:DG3i/cd3uEHB6gWWLPhI2+GNOW5Mcq0zq+9jpmQ+uEE= -github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.5 h1:gL9t5HYLKImIwtSmYOT/mrmFei/9w0OHRaImNkqO8gg= -github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.5/go.mod h1:mpG4rVlLYCIRESFlZlKoTmzGkeSLLTiHPHJtbGS6xPk= -github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.4 h1:iO8udIPScJgk8U53hl8psGVig+HFFY513vFw+DvJTJ0= -github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.4/go.mod h1:ybHG1Hx4EKsZs9lfWeBrx6UJf59niCybxdJoUD6KjOg= -github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.4 h1:hxfrwha8FOWp1H7sVb4qIVSezWSMOgamUCadRR4S58o= -github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.4/go.mod h1:vU4xegG7YujyiBgOqPbx1IGg1OeijviwP1rAK/p5U6w= -github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.15.7 h1:zOvYvWJQUI0amCkaUhS9d6ObzYkBodn31G9GkbdMSRk= -github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.15.7/go.mod h1:FgQ2k88o4rBYovSJ0Vi9Qo6/0KdoCc9GEydhsOkhAn4= -github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.5 h1:8vAgM2KvQL63O335li4QwvVcrMaABAAr38bbi6cniNU= -github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.5/go.mod h1:/LON1mHNfDZfZDuPKjl7qCavUC4d/rBZnjDwLdkNJAQ= -github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.6 h1:4FqI5E/fw0pH6HgflI1eyn25Ss1BxtE8Vy1ubVzQpFY= -github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.6/go.mod h1:QBuxmH6jvBz+VbBZRabFZ2z7sdPYS32OwSzzcPSbFso= -github.com/aws/aws-sdk-go-v2/service/appstream v1.49.5 h1:gbc/S8roq3jl9hdaIDdEYnK7oOhU23ET+rjidn045R4= -github.com/aws/aws-sdk-go-v2/service/appstream v1.49.5/go.mod h1:VHqX7t1TFzCW6c0/baFjL+c/uTLHTve9QvGnIl2t68E= -github.com/aws/aws-sdk-go-v2/service/appsync v1.51.5 h1:pZACTcwJMzHYlmqnF5V9QHTeRvHqCcRoKBVRs1b8tKw= -github.com/aws/aws-sdk-go-v2/service/appsync v1.51.5/go.mod h1:9peX7FKIuilf8nao3Sj6HqSyxq1cyxyS8hGOowUgw0s= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.7 h1:9WFtb9NflqlsC9/qoMYSMuHTPjefC9QjztCiWXroprM= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.7/go.mod h1:3NAtNcNccpi/I1R0UPcvYhroarbJKfxCewqIq+skiow= -github.com/aws/aws-sdk-go-v2/service/athena v1.55.5 h1:rZi1Qid0n2V4gnzxfmn6FEMEU6zKtCmcUV3VL9UiuRM= -github.com/aws/aws-sdk-go-v2/service/athena v1.55.5/go.mod h1:aLJfNa+nondGTH2gZ16OWEs9shuG2R1kM8XAFeyzMp8= -github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.5 h1:uzwUV8J0g+/tbZvfZxC/n7l7hurf7jQN+ZWEHwj784Q= -github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.5/go.mod h1:uMLfGaVbHvrR9i6RbRV+tuLqb659g9kkMEWpqkSo+S8= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.2 h1:YOWVoIjUoiwAVIRVU3PG2yNldh9dQT5OegnO99RO4ls= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.2/go.mod h1:t08UbddtoRQcKiIW2ZTfxX5x6vRaTj6KrKcf1R0I4tw= -github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.4 h1:qwgy4hxeCZmoYKMoxvY0DYNKmtJXv9exHVeVr0UVE4s= -github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.4/go.mod h1:jzCzRhms7J54Vx+T+OzbAPXu66H967Kx2pDBcQp1ebM= -github.com/aws/aws-sdk-go-v2/service/backup v1.47.5 h1:hXI1ic7LxVqoLJSifY9NRynWgKOV8MBqzRwqqlN+I+g= -github.com/aws/aws-sdk-go-v2/service/backup v1.47.5/go.mod h1:wFR/78TqeXIgQoFqu8m0SmwFx+ofSV3Mg7j1pyVTX4s= -github.com/aws/aws-sdk-go-v2/service/batch v1.57.9 h1:4zrkNVi3V20XlQ3tYJ8gLUyYWTGl1uAdES74M+mM//o= -github.com/aws/aws-sdk-go-v2/service/batch v1.57.9/go.mod h1:fWHsie3W5XBYLYlamL+Jv/zPhbjaSnOwoX6/2XvgXBA= -github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.7 h1:392wLo7mSsuSpYK61ozSmvSDThF7Xn6DOZltb8SOQjo= -github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.7/go.mod h1:CnVBOLm1nyq4dbS1Xl44GpxfOGZf4DiNn4d8kBJlQ6A= -github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.1 h1:vAnqxsmlnEYUzKUQLFjfy+YhilvIGqhBACU5vZPuP6I= -github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.1/go.mod h1:q/R1CT6xFa6YcVvNQtenUSMEs7tVd4S1oLulUd8+RCw= -github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.5 h1:M7a27wtqblMxOE8RnsCKXPO2xnuU8IVLl7nWpLOy27o= -github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.5/go.mod h1:NcYZhLyy4mnuIweU0K4WmE3GcxRzD/X6VqR5+3L6K/M= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.5.1 h1:r5tPK5Z9S0GxQCkVu5uDfMKiJUKyhR75aoVV9sIw+Tw= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.5.1/go.mod h1:cX30dTXPoDwf1ZVgnZU2wWaCV7QJdQvjBoMoWiJsnt4= -github.com/aws/aws-sdk-go-v2/service/billing v1.7.6 h1:dXylOk+JWTe/L3qzumnwz5CwO7+YLD9eacHOCJhtizI= -github.com/aws/aws-sdk-go-v2/service/billing v1.7.6/go.mod h1:NBTn4pyQeXa4/QT+wch5FqSPbZ41VfMZQmiBBePsL7k= -github.com/aws/aws-sdk-go-v2/service/budgets v1.39.1 h1:grOdaAKovx1HngbE3uFDzLqUXtGmnfMJP3WAiHA0jBs= -github.com/aws/aws-sdk-go-v2/service/budgets v1.39.1/go.mod h1:EDsMEIAC4BXqdkY/iTme86MCHd12edsjk5whpNyO6Bw= -github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.5 h1:HYVk9Mcs5/UtGov0QFkbee6kiJpFj+AXNQuDbHUi0T0= -github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.5/go.mod h1:PGj+XRbKggjufbcjSgl+FduG4flALTsKtjeSkG6UpKE= -github.com/aws/aws-sdk-go-v2/service/chime v1.40.4 h1:1mQj+E0k1DX9EgHFlSZT7ECVJt7acH2ZsVOCB5H9jbI= -github.com/aws/aws-sdk-go-v2/service/chime v1.40.4/go.mod h1:kGoQl88Hso174Z29Q/dodAmfWDZ7EHhqRbO1i9E2Xx0= -github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.5 h1:26+20xlISJWcOldgHLNY+Yuxbu2Tk/oDhuty3Zyjlpo= -github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.5/go.mod h1:eYayIHn6FawTcUhAqXd30b/pP8z3p0zfhfyse2qGWqE= -github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.26.4 h1:jFefKM709nuyV6uAYg6z/gxe2PidH/Vk3yADnjwSw18= -github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.26.4/go.mod h1:MBoFrOMGcstb0S5dglAEQ7SpX4TL+6Hn5FYZqWZI6qQ= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.34.0 h1:7zhXcQjI6YmzEyXWFIpGQl4IF6JzQSvFxmHu/oUMDSw= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.34.0/go.mod h1:poFTlKjRrbKjBOYKNTqfqsqoA4yM47e8Mk5HYHOeZ/k= -github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.4 h1:nWw9IVwWMylobwf2hR5uBhOMQ8+lj+xWNk4jP7w2skE= -github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.4/go.mod h1:rxayeoxnwqMBBypasFD2HL0taPiqntanftVq/raOkh0= -github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.5 h1:P6orsPAkseLLWPvAnniFTnpUFT43PLKXUFMwzHz7RLI= -github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.5/go.mod h1:xBedDPPftxA9mt/zRNFA5EZEtqEmBJEtEYbW+qJo5tM= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.66.3 h1:P+Jr65DtpIuYme6a3pjsvDIpCfNDk8oCFVzGsfhWqz0= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.66.3/go.mod h1:J5tabKm/zD5b3Uz4LKdZytESCQu0MGEzxUX7XYOOhNw= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.3 h1:JgzZxb/9UhqBwkRXrEVyHZMeGsjyovdERq15L3U9A0I= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.3/go.mod h1:uaoE1dsE7W/qZbWnAAfX46QEKpB4rrbdfnp3HRN4dDI= -github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.7 h1:tHmNsJ/QUJqBeUUD2gtpCJi1lQgDVNNkSGMxeRbsb6g= -github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.7/go.mod h1:cjvhAmUH3dIWLzOfxG3oVomq1w5etRw8PhxMU1Bu3LU= -github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.4 h1:F0f5RWjICiTvM9h5BP6U8tsdP6VdfSsy7euvha3hHTQ= -github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.4/go.mod h1:yztjcwCBIa6NSm6P4akOysMegI8AG7zwk62BQGYTuxA= -github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.5 h1:OemDTmq9D69Ur8gTtEpkdcGuD8LHOjeHfVcq/Rb6Sz8= -github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.5/go.mod h1:PzvSXLkE8mlOqSJl5ayXr1nc8+kaic9okDKL0F3rvZQ= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.5 h1:o6/qcMBLZ4YAfoDnRsPwE/xeM3kAU0nnnGP9ZPy4kTs= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.5/go.mod h1:RUoiEWrOYweLJemA9hLIuCaaJSXFiZryzZqK/AA9DYs= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.50.2 h1:RJJSBxXt3gEcZiWUDzTl0sLtknsfzGj7GrpGtZ81bDI= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.50.2/go.mod h1:6TdW6zAw6JIlaGSgRb/kV6pX7k7JfxiqKbymr6qB7ko= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.1 h1:JMYpgsJ31l0wjJCerJtIBo39HznZJ/ENJJzOSTcJh68= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.1/go.mod h1:zqtpx8Y/EydPCFy5MA9AJJBfJ+mCQz8BNHj2CvDvaYA= -github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.5 h1:Et3l7Yne0ZoMiaDS0fbq75oe6PbTr7hA1N0YOuXkpjM= -github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.5/go.mod h1:IwqSdfgHrMtfVwW5FFv0xj9sq3HM6z06DD2e1kselpQ= -github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.4 h1:2N3W0bdr/SxLQDfUGi1SPIORcuRSZ6FKm6FWBqGDo9g= -github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.4/go.mod h1:Pwyp2lLtt5/LXi53uMbJ13TXEwo3VPyYnHGP6N3hZOk= -github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.7 h1:+YQlq7rUHLV7B2szK9NfGjAhjun+MLiBQkCRSra0LMk= -github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.7/go.mod h1:vqJ0MON1UMGvFB3A+2LIuvVGRHdU9BFA2IaCcLSZ7zg= -github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.5 h1:IFvx5VOZbggY1Bpd/dFkMs9H6YtzZ4rBdEnkRaWA9i8= -github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.5/go.mod h1:vNYxiEmvRccYA7JJHtH4L4FoOGMSRiOvrczqh2FgxZg= -github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.4 h1:+HtFvo99RMfpgJN2mh/hn67UOY65y5RNU0S2uy9T+VM= -github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.4/go.mod h1:6CwXuWejMnqXkWdf3uskATk0EQ+v23e2pvgEn1TdqPk= -github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.4 h1:Wutz+Xyb863LzHbqhHftHXeAvIC0wrwmBASQY6c9f/M= -github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.4/go.mod h1:6M1YeHkMmOWtutcNJpkQ6Pm2lTcJhk5HlxOAXmOGDRo= -github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.4 h1:9qMax0S94rKAHoAuF1NJrD+okFd1rtBwgtPzfBNuYyA= -github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.4/go.mod h1:Nbt0nq5uPu0ejS5anjrSI3tBkERY8SL8rhBBn8M32Is= -github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.4 h1:mHsv+CicazS3rB1bUNj/ffwKbjQiHdY3PiJYb8SXYyw= -github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.4/go.mod h1:ZqROoQ6lpqfswK4A7MP31WgIGZxNp2hclWYIutHSbG8= -github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.5 h1:N2pNKqg02mEXeD+IBkzBMusuD/hLBAXh9Lwtbrj4xJk= -github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.5/go.mod h1:Bz8cpvViXoCeAdnVq5Z/lx8aAdPFXrH/LVYAgtbUHOU= -github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.5 h1:evPerbXm4GHFvROmQx7WZkKpvaP4zV86avDtcNEUdnE= -github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.5/go.mod h1:klJRj93ROIhdBewNs4ELuTq4fpqLahtFxy9BdFSDhqs= -github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.5 h1:CCBfmIsF8sIHv1E9mn/GJPui/R3BW5IJ10TUH04hyDc= -github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.5/go.mod h1:ZvOQmePGGdpBFiLqccrxzge8ggjjtSa8qpxmf5p1duQ= -github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.5 h1:3nYmv9oWR0rrG2q9jDtikenvpSjX5/YUTfznhxsIPgc= -github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.5/go.mod h1:h2tMUR2y5anI0f4DkuVcBH8exNYTTZ8BrLVypoiv7+w= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.6 h1:/EOZnHaz44R8IUPqmvdmwrRGs3I3fRjEIR8pSlqz5cQ= -github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.6/go.mod h1:gOSEL+GyAVlcUMPbw8P7qBZknGEhp8ShMw6gizLngE0= -github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.5 h1:oBCJmk5ZtWKY7yevlVVpUNmUzGYA5XFNEf9TCB1h3Pk= -github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.5/go.mod h1:Ftk2FokqewDroksWg0P02kASc+uoYtqbV3oGgi3YQJM= -github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.4 h1:f3VPBDMuIEA76JDNRXQ823SXQ922L200q5va1o37lUU= -github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.4/go.mod h1:rKRZAKXwLgUZOdXrjHfB3ko1zYj8KoQK6bpXTpUjan8= -github.com/aws/aws-sdk-go-v2/service/configservice v1.58.1 h1:YjwT6oWNI0KJANny3bZpMMLg6hKZajPIkHbAJ8fgYkI= -github.com/aws/aws-sdk-go-v2/service/configservice v1.58.1/go.mod h1:TDu0is6KJd6igH/aLiMY3ePszwUUL9srFr4eOUHzLVs= -github.com/aws/aws-sdk-go-v2/service/connect v1.140.1 h1:0APQTulMHxW9co+fScETtA0qmdeuIfqCK28uWU6Lmak= -github.com/aws/aws-sdk-go-v2/service/connect v1.140.1/go.mod h1:zkPWvG+gvw5UGyP9Iu/6FPaFHiSX94f9Fhffw2kgcvY= -github.com/aws/aws-sdk-go-v2/service/connectcases v1.30.5 h1:dO/ryGBzpxLh1028JG19CzZBZ7oHowbHjzVLhD0vZS4= -github.com/aws/aws-sdk-go-v2/service/connectcases v1.30.5/go.mod h1:mk7Q8p+AcP4xjdwGmBQSdof1pM5PIm+H9BO8Q/uzCW4= -github.com/aws/aws-sdk-go-v2/service/controltower v1.26.5 h1:sbORD+4WSo4hvVdIpUbE4CU+RrsoqDCoqBkI7S7+hJM= -github.com/aws/aws-sdk-go-v2/service/controltower v1.26.5/go.mod h1:jgAoCJvvCNC/OOtzyIvl11BZPASz5ATSNCknbUonX+w= -github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.5 h1:RabBaEOLoAvWVdqDwQ2cW4PF8DwXMmgarl2c6iuVaEc= -github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.5/go.mod h1:xmuTn3EtMz3rL35w3iUzR1nmKuAlLT7SM8PftOkIugQ= -github.com/aws/aws-sdk-go-v2/service/costexplorer v1.56.1 h1:HLDIBVSZkgZUpulXq9qccFzuCNbRgw+Tw4P6fLN7BsQ= -github.com/aws/aws-sdk-go-v2/service/costexplorer v1.56.1/go.mod h1:7DTxZXKffJHHcbPp9+0sRwFcXj2KL0fGpqB6DduPLhE= -github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.5 h1:P4vBeJGUzeWHZpZdyMXVSiIDx+Zw5zTnL374tQsfhjk= -github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.5/go.mod h1:ylrE0RKseaqxY7ERcqvwwCzdK6pvD+LDNJZYpil5RhA= -github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.52.5 h1:HIe9Q4h2mBPI6AMk4pzEEEDjG8vAukh7U63H9jDbPFw= -github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.52.5/go.mod h1:Th5Y0G4TvOMYN6lyCVEYgsLDz059NJXdDqlUOaeYDuM= -github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.5 h1:6T/CR26/V53CC4VvAK3bJlD4ibeXOO6tbt+DA+U9yYQ= -github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.5/go.mod h1:mn/2X3QkGZ7JW7Tb3dMwPing2cTzkYGuhyKUJzVEX/Y= -github.com/aws/aws-sdk-go-v2/service/databrew v1.38.4 h1:JgImAlmECnFCkhvnH9TCd553pzNTIRfH2Ul4R+p3d8k= -github.com/aws/aws-sdk-go-v2/service/databrew v1.38.4/go.mod h1:mL62FXgGPTF/Q/hepi1Qxh3HXU8Q5yp0y1wIIWANiFo= -github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.5 h1:+yel2bZWZRuhBqKX8PWFfXwr2HlTOHgnHPwXE9beoQU= -github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.5/go.mod h1:2D4PoeboTeeNKZ479TsSjl3B1F2pcQ5+GkOCgAZnzrI= -github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.4 h1:9mkH/ONm9RWxi3Ixym6LL1kvV6vo8orYBxQWPp6oExc= -github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.4/go.mod h1:OlSaTD0J8/KjGDsM+DnPhHiJVBamykRGLsAAg8A/OcA= -github.com/aws/aws-sdk-go-v2/service/datasync v1.54.5 h1:8BsejEevu0F/XLzi1Hc2GyU9t2qHMBl7OacFpmi8Jc8= -github.com/aws/aws-sdk-go-v2/service/datasync v1.54.5/go.mod h1:F0aJUK0TTE5AQAyWj8Dv9COO0t6UMoAyMnFESeZ/O+Q= -github.com/aws/aws-sdk-go-v2/service/datazone v1.41.2 h1:KA+OaZ1boO6q/Da+1pO0t4sjt42K9/dL0qqXMRiZyr8= -github.com/aws/aws-sdk-go-v2/service/datazone v1.41.2/go.mod h1:759UsQUMGOf3cm1iz9vsL+Epj7Wlddq58sldKqtJCFQ= -github.com/aws/aws-sdk-go-v2/service/dax v1.28.5 h1:jXqWwWs49FSwlfdkiNXFT82ZVyTou3oRGnd2QdUqAQk= -github.com/aws/aws-sdk-go-v2/service/dax v1.28.5/go.mod h1:lowvEGtcFbTbtL639HA0sek1VtvMtoQsflFi0ttTy8c= -github.com/aws/aws-sdk-go-v2/service/detective v1.37.6 h1:VvwWzJpBk4sup+mSuzX7Vmm30sW3y64czrCGUES8JUE= -github.com/aws/aws-sdk-go-v2/service/detective v1.37.6/go.mod h1:jXwgyIaSOaRuri9AWmyMDU39dAMMJ61RZ+YblT2R/6w= -github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.5 h1:40nKr1dmfn9f0doUxmvgC76QPGJ2F/1Mwh0+BXQBd7A= -github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.5/go.mod h1:++N+f27/Ne2Slli6+Yd8xomkzODF/cewRZZcfLqYc54= -github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.5 h1:POEwKseaALiTsWq5+aSb+sNg8+HzKOkVpSUrBI7i7d4= -github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.5/go.mod h1:RvU+42eaaSBXjDf5Og9Pswu+Gft/0fqvrJpSWkSlv6E= -github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.5 h1:ZeG7A3l7aMJE4/nxr4f8JKkPpbmMvg5/5A8DBJ99Cdc= -github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.5/go.mod h1:SQFyOg6kGN9d8NENqgQ3zjdVX610JXzyt+uN446hkhg= -github.com/aws/aws-sdk-go-v2/service/directoryservice v1.37.4 h1:ZDouCjBOrNmXq+GCCwC1fhoOzBpXQ/Usx05SHVpskjI= -github.com/aws/aws-sdk-go-v2/service/directoryservice v1.37.4/go.mod h1:rEEFx+xIPrVlhzJXFJiu79o6N13mys3LUCtHvHIygVo= -github.com/aws/aws-sdk-go-v2/service/dlm v1.34.5 h1:INJ+fEUVw4LwKU86UQv5OFQLg7U7Df3IxXtWZ1HDDaI= -github.com/aws/aws-sdk-go-v2/service/dlm v1.34.5/go.mod h1:CofHoDNqn6ZWkAgE3QuCJdvylmgp+IWh7gRssUnNyV8= -github.com/aws/aws-sdk-go-v2/service/docdb v1.46.5 h1:m7u48GaFM9XvDdSJGwHaHA5cmnE4/ioVjIeP60iQMXc= -github.com/aws/aws-sdk-go-v2/service/docdb v1.46.5/go.mod h1:9IAjRrIMPh5LFnWo4S2r1ZN+xq7qgKkC6RW8abBN1Go= -github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.5 h1:6aD1/jZBwjstYgB2wGpnuIohUqspeRvRmh0RFe1MI9A= -github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.5/go.mod h1:stxVYTXiIoyTTq+Gd/e1tVbi8AwGuSqi3m+1Itn0pmc= -github.com/aws/aws-sdk-go-v2/service/drs v1.35.5 h1:9HJvlrlqXyVo/5xYtnz30U3f6MifAQQTe/h4J/5Uuvw= -github.com/aws/aws-sdk-go-v2/service/drs v1.35.5/go.mod h1:TGMcQ5H9FecvGjhZqT8ozXOAFO+6a8sSTyFCEZ1EJ7g= -github.com/aws/aws-sdk-go-v2/service/dsql v1.9.7 h1:rwSOOhEKZXWYAqtqGjvIdslUOdOnbTYGpn83HPXJoL0= -github.com/aws/aws-sdk-go-v2/service/dsql v1.9.7/go.mod h1:kkU1xXHdCh7alFRoZA1qZPbB41Yy/uAINV2K6D79UbQ= -github.com/aws/aws-sdk-go-v2/service/dynamodb v1.50.4 h1:3EE5TTeBHPTKQNNeIHdXcJ6ENDsN7c2rCQUtbdolwV8= -github.com/aws/aws-sdk-go-v2/service/dynamodb v1.50.4/go.mod h1:8rWv4Lq/jrlspgd/wpdFeKrxLByJlfpFEk9g0Tw5iOw= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.0 h1:fTLR6dLDTGChAjecRPlVrKeznT0rVdzR4yn9Z68MTGk= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.0/go.mod h1:V0jbRy1/IPapnkqgXSwVOFB+u5pnCwd9S+R3pKWULC4= -github.com/aws/aws-sdk-go-v2/service/ecr v1.50.4 h1:kPe1ZLqERYZxxDi6ysoX4oYavSJ6lkGaadsN1ogg3I8= -github.com/aws/aws-sdk-go-v2/service/ecr v1.50.4/go.mod h1:cAJR/1pLXISKFSSJsrsTZPw05PLL5xOIpbbzxM7GLiI= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.5 h1:98e3/QHaQ14WdBt3tZTFSyDGRh8BTVmGE6DICjN2iHo= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.5/go.mod h1:z8vly/P3m0RZ5CsZyKESSjcdmVvCjqKQUIfj5VwaLO0= -github.com/aws/aws-sdk-go-v2/service/ecs v1.64.1 h1:kAzHjjqQnu3ET5/cX1N5tKPqtExYk97wpD6MpRadq/A= -github.com/aws/aws-sdk-go-v2/service/ecs v1.64.1/go.mod h1:HIaZTpBD7+mgQEIv2wMzXYJw2T23sMFVNp2Mkw/ODFk= -github.com/aws/aws-sdk-go-v2/service/efs v1.40.6 h1:+Iry/PsJmm0m99bGpU00ubukGCG9G6N48Hqj5WMrvv4= -github.com/aws/aws-sdk-go-v2/service/efs v1.40.6/go.mod h1:6bFGewZgq0SC5QGUIBHl1BYZihIOi/ZPipEJMIBfbHs= -github.com/aws/aws-sdk-go-v2/service/eks v1.74.1 h1:/twnp/d6RQaccM/hEin33E5iYG0vLQY9DDRDleB6UGw= -github.com/aws/aws-sdk-go-v2/service/eks v1.74.1/go.mod h1:YfA/RHfplvaNVxukwg3e4KWJpsL7Ic7bfvCXhJnhbzQ= -github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.4 h1:9KuzJb9bUyMwNJyyh0pHfsTMR2OJZNtp9WTfcV2Vj3s= -github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.4/go.mod h1:2nKJzgK0+jae6diDJ7Fo9IyYkQMuE4U3LZotgLJZY3A= -github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.6 h1:NLE0iKGz29Oq45OQg+CkpaDP1BqftKmM74H/VX5HOkI= -github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.6/go.mod h1:+FEEAJlFxEGU5bYPE0/NhxMZGpMJ/TCmd7WicVc3Qhs= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.5 h1:3WQ2wo4l7zwu0IWzvbI5QVtzsN7+Eg42QR4D5qYkr2s= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.5/go.mod h1:7KZQYpEEZg47FYjzxWNz3Gc7xY0xYl0vGyXMltWplKE= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.5 h1:q7goP7oXfAvRlBxP7oMYlUzKUA8MpMpRkUxxmHEHNes= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.5/go.mod h1:BrvdV5vYXNjnsO5tM5CLWGkxj7pCa6E67wVVt+yXt1E= -github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.5 h1:HKdMcWFqzUlobL80o9WNMFNuOQsdE5xdf+qwQUUFco4= -github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.5/go.mod h1:ke8t2vaPfy1jzUrBCPaXSVww3uauW/VVd8CCzDxL16U= -github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.5 h1:Nc1bF38DmDyDwebbR7BgxxuIH1Yhl1EfPkPaKH0xQ1U= -github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.5/go.mod h1:9tF20YvxWfJ7WTYt5A45oqPUoLReFTjWITxDXnbAONA= -github.com/aws/aws-sdk-go-v2/service/emr v1.54.4 h1:ZC0c/fOSA9Yy/BXTGJlqv+QkvDgM7a/an0EhOmWAopY= -github.com/aws/aws-sdk-go-v2/service/emr v1.54.4/go.mod h1:yCZW7KzmSSuWxLKfLrrmriZxuE/rolBic2WsFZkfsIA= -github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.1 h1:fQQoDSorzE5J4jXsef/97ekcYODbvKaph3+rCzfnuZE= -github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.1/go.mod h1:QB1EyqZPQS8UKslM0as2eT3GXDkAgwTUQOR/iKzLI6k= -github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.5 h1:BobchIW2pMeagzST84A3ICzCZDwNjsYLopOKwsGioYE= -github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.5/go.mod h1:d5C/KgwOZXr7Mxf/ZymiwgwvutFEqQB9lMooWMp7Uww= -github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.4 h1:Qc0hIguje+lCQ78VSx70qVPG0nrajvWRbC5mkYc1W7Q= -github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.4/go.mod h1:bOMdhYMX+c/AQzi20lbWmO0U8hWRawDo9kNxvKutwSk= -github.com/aws/aws-sdk-go-v2/service/evidently v1.28.4 h1:iti9VdkeC7Z78qId7zw32Lo1RnsU9kjfJ8qSsIsWhCU= -github.com/aws/aws-sdk-go-v2/service/evidently v1.28.4/go.mod h1:cv8RDvuN+5Y2/qvtljWMR5grqefjkGhSivf/kot/IQY= -github.com/aws/aws-sdk-go-v2/service/evs v1.5.1 h1:Kvu09SgEie1SoW3MCGu7bsizpMZqFKrhZ0g2myl3MMQ= -github.com/aws/aws-sdk-go-v2/service/evs v1.5.1/go.mod h1:O7A46zFyZAePaEHIBWzpuxWBFAVxtaJkUDD/4FD2bG0= -github.com/aws/aws-sdk-go-v2/service/finspace v1.33.5 h1:SrudNTicBccapfNU3IKO1uW9A8WVRJH9h1pRI0hWt7Q= -github.com/aws/aws-sdk-go-v2/service/finspace v1.33.5/go.mod h1:BmK10iWdy5WqBV5G2hFIqqS8hszTg3gkdQQWK4Jw1s0= -github.com/aws/aws-sdk-go-v2/service/firehose v1.41.5 h1:Osa/8apMLAe2WY2yVaB8kTTPdrEfzXd13uKCJd7lt18= -github.com/aws/aws-sdk-go-v2/service/firehose v1.41.5/go.mod h1:K7ecJD6/1hejYb7lSc4JczwNS9leHGq9RMTLuyEg4ko= -github.com/aws/aws-sdk-go-v2/service/fis v1.37.4 h1:HmEC/I6kWPZ1gixODkajwr/M/vxZtjLT6o5z3mB2/5U= -github.com/aws/aws-sdk-go-v2/service/fis v1.37.4/go.mod h1:xqDZvBdIoE0FE35rljgotQyT/+I/Fvuc337dWyWApgk= -github.com/aws/aws-sdk-go-v2/service/fms v1.44.4 h1:rA6Q75idyG1SQYIUeTNYUQZ8oe3koEnqmceJRAuXDl8= -github.com/aws/aws-sdk-go-v2/service/fms v1.44.4/go.mod h1:Gy9MDI0yRrBenHa9Jzg1ud2u0ZI9yAThQTjX+0IamDg= -github.com/aws/aws-sdk-go-v2/service/fsx v1.61.5 h1:hIAuUn0uFjFnmg8WGncoEpyfxf7Y/t9eFhd8PpKnF18= -github.com/aws/aws-sdk-go-v2/service/fsx v1.61.5/go.mod h1:WO+0YogiUvQcY7FchHpdQ7vnBjNzl1v+rM34JpoSRaI= -github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.5 h1:dtYIF39DQ1IhFQBnDqGB1pes/UPfUjP0VgHoYMnX5Eg= -github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.5/go.mod h1:z2n/O9ruWRawdzCKHSwh0aFib/3q73aPYFXkoygmH7k= -github.com/aws/aws-sdk-go-v2/service/glacier v1.31.5 h1:SghWxcZVyI7Iu14jng5dColevrhl9sJGJWduQ/sD83w= -github.com/aws/aws-sdk-go-v2/service/glacier v1.31.5/go.mod h1:/CyArR40faf3oHIYTkXGqYOkSQ07i9/kJP8T1ghbgf0= -github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.5 h1:W2UcvAIYBFAkz7fsLLbRUIIyT0bT6L7aChxItt7Tes0= -github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.5/go.mod h1:O8zO9cNML7tuG38unyE/vO7z01stN90R4PKH/pPyw1o= -github.com/aws/aws-sdk-go-v2/service/glue v1.128.4 h1:kuB0Y0rBB8ktzMer1aAkRr97VcMOV3htrK5ozwk+IXY= -github.com/aws/aws-sdk-go-v2/service/glue v1.128.4/go.mod h1:hkEsN8mLtY+OlMapw83O6YPjKnBpV/Xrlaqk/HFmM1M= -github.com/aws/aws-sdk-go-v2/service/grafana v1.31.5 h1:p3uJu5V5c/o2PePeELynpedWi+zBv5HGyeJxhvuLqnQ= -github.com/aws/aws-sdk-go-v2/service/grafana v1.31.5/go.mod h1:kRsZsMlOY+IRQjl7ENV4zeJJeJVhUvNmnvGmDPaxovw= -github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.5 h1:8FCU0h/3dbf5ElK5wwbKNgt4tKPCIRIwmSjaY6sFeDI= -github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.5/go.mod h1:S8KznekVEeSHkKl+5NvxhSelRR5pT3MBsHXGfmMaKp8= -github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.5 h1:SlAT6W1uY0XW7s8x69OelXX2OWopTbCBqu/G98z1ikA= -github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.5/go.mod h1:Jccq9CeVAqBaeBppITbzWP/roisx1dj1fE0AmRhyJXg= -github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.1 h1:gjjiS2bSuqxmN3YZgyivU5bji7lhByp5x0yDNcCirbU= -github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.1/go.mod h1:N/9Md/EYVqAOUB93qUF+SAQKwNL3LCaeVF/Bf8Le4kY= -github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.4 h1:42woA14NMIht4st8dzBp8nJjlM7bRm6fEf2pIlUUUU8= -github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.4/go.mod h1:E0EosqrhvVN1kr4GTNPQ3S0B/+WJrzEjymQ7wI4ry6k= -github.com/aws/aws-sdk-go-v2/service/iam v1.47.6 h1:EWehQXACWr+6hzfZPwZChlfoVhiUCfLHE0Xh3kAfzWQ= -github.com/aws/aws-sdk-go-v2/service/iam v1.47.6/go.mod h1:qRXgEBWPIltrWHQwU+HkyBvwh1QgeigFcaCGCIVrWk0= -github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.5 h1:trORK1psQM+4hgsOt+Hm53bc/AABOl7nGTP7zQT4PzU= -github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.5/go.mod h1:yHjAOYH1Y+2Ne18ZyiRPETfmOuGovtZ7jKnieO4RPnw= -github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.47.1 h1:lfBxnqWxgeLoN7Nx48eoEPdwt+umHOvTM1SHLyexJ1U= -github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.47.1/go.mod h1:MyVok3M4Be3gH7wf1vu0hYAC91XR7XWkRvVaBfYAR/M= -github.com/aws/aws-sdk-go-v2/service/inspector v1.30.4 h1:jBy3o4eCas8qTF32sYjkVMDaPi5F91eRpyDaKE7Ldns= -github.com/aws/aws-sdk-go-v2/service/inspector v1.30.4/go.mod h1:BqgWCL5RDqMH9lO7CmPzOYH9I+F/WRus88PmRCBNBp4= -github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.5 h1:KTtccDNYtBmnJ00hz3pM8OndRMI+FTKZXs2KQ61xv80= -github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.5/go.mod h1:IhhaIu8jGcyQTTn7Yu8qJe9JeeH7l3ZGBVjduQEN7ho= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 h1:w9LnHqTq8MEdlnyhV4Bwfizd65lfNCNgdlNC6mM5paE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9/go.mod h1:LGEP6EK4nj+bwWNdrvX/FnDTFowdBNwcSPuZu/ouFys= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.6 h1:OXJuITvU8R/Npo5Wv2dgIFBYROm42kXAD16rk8qirs8= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.44.6/go.mod h1:PvvoZ5HHC38O5xDu4yKotP0ZLvnlbaJbHFOD8vppMQ8= +github.com/aws/aws-sdk-go-v2/service/account v1.28.6 h1:eEtL3V2CHjO4IDRwBelx1sZLRrz7vAsNUrDIb967FkI= +github.com/aws/aws-sdk-go-v2/service/account v1.28.6/go.mod h1:qi8Mmk5TSynuGi1KWkzrFIYfiKSaCv/lIxPPyPOlVfs= +github.com/aws/aws-sdk-go-v2/service/acm v1.37.6 h1:48oGbMpBSzihrU145gpjrxySIs+VNGCXu9kLTLAdJJg= +github.com/aws/aws-sdk-go-v2/service/acm v1.37.6/go.mod h1:4Xgg9iUMFMpWd19UokmUwBCU6fqNJ7LPo11YYt3/xl4= +github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.5 h1:0aROQbnQ6nGlI1idLYuxx/mv4s+2I02RFyOA5MOlMQk= +github.com/aws/aws-sdk-go-v2/service/acmpca v1.44.5/go.mod h1:1whQS1vMFP9KQPLTc9dtqnJGjgJ6Sb80bkPoN8CPQ2k= +github.com/aws/aws-sdk-go-v2/service/amp v1.40.3 h1:pAbmvpyEwOX5OphEvNCjDMTZS+I4mNOBBK5Z6Ga6Zgo= +github.com/aws/aws-sdk-go-v2/service/amp v1.40.3/go.mod h1:Kaiyw5xthjYIWNvilHLlRiNwZa3owNXd+YgJs53hzDE= +github.com/aws/aws-sdk-go-v2/service/amplify v1.37.5 h1:mCxlw2Vuh5XZP6qwuUxr7bXWZ7drfbquJieS8VCIb+k= +github.com/aws/aws-sdk-go-v2/service/amplify v1.37.5/go.mod h1:HeH9qb/ftrO1k18S+BoWN3P/p83yS06x/Opny3ATXDs= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.6 h1:v8RqEs++cq7uAYUusuwrHLNEFACv0nlICCBwV11p5sY= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.6/go.mod h1:5EVcku5uDhMks5w1FwPL8hLKqJwCgIIbuF5th+vGQhE= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.6 h1:k78ulhtPtIqMiZqq8bPkpJlx66VN8DmDIeRgrYpzehc= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.6/go.mod h1:A5+OX0k1IIqRR4jR+zPgHpzKmEoLfpyY2xIrrJj8O98= +github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.6 h1:e81OBhEpYUKh7Wg3hHiRE5zHpYPTgB4Sja0YWCBMivU= +github.com/aws/aws-sdk-go-v2/service/appconfig v1.42.6/go.mod h1:3lk8tz+bmjQEPEmdDF7zTDFHlqRFdn0zZvTa2cIe0r8= +github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.6 h1:L50VB8yUNNequjYNhUm+MCjFCxfN6KMaIcpLgo679y8= +github.com/aws/aws-sdk-go-v2/service/appfabric v1.16.6/go.mod h1:v0gYYyI3wXm6R1nxhW068lcxbmh8wTBKIPafxXI7rf4= +github.com/aws/aws-sdk-go-v2/service/appflow v1.50.6 h1:Q30ADINfdo4matzYAGq4rPuQrjQKinuvdaHGnR9/Ksk= +github.com/aws/aws-sdk-go-v2/service/appflow v1.50.6/go.mod h1:2W0SilTCqSFglsMuZYKFmuZCOaBxGLnWvpik/GP+bT8= +github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.6 h1:kwnjEvDnDXPGC2yGF3ygvNs8EGnZFxzsX6bKWFA+j4c= +github.com/aws/aws-sdk-go-v2/service/appintegrations v1.36.6/go.mod h1:DqUWf8yC60AYaDfwq1zMLRxP9uT5R41FZwpZzIgEsWU= +github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.5 h1:0t/Dr8fwxkc5fkhoeuYRpGiPowbLKi424s3oeLCusRU= +github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.40.5/go.mod h1:NUciQYiEOln3pubY8iovZkWZdJrBTnoPPW3JTIk9QAI= +github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.5 h1:HWvL7MWRel0n6W5msGcS2BllKX8OEH168656YH8IRNg= +github.com/aws/aws-sdk-go-v2/service/applicationinsights v1.34.5/go.mod h1:9jEkcPD8H2x5XTr4JKfuftpz4EoKAhrom5lQzLLCI6I= +github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.16.0 h1:k5Gds31CrXttYeulwB6VjflGSXnRegRG2jKiWLimgHo= +github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.16.0/go.mod h1:dB7ydHt6geh960yqkPjZZfA+qqLK577b0jifWU1ahy0= +github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.6 h1:Wupdnc/3bA0GPzEEZInLvu4FHEmkHNHsG/xahSggcGw= +github.com/aws/aws-sdk-go-v2/service/appmesh v1.34.6/go.mod h1:yHte17Vasn4Ows3YO5zLC1MWX2Dw8by5KvgDm6XGSm8= +github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.7 h1:gJCGw8gwiTYjLeTpCdwHFE60SRPN7tH2m0ScVYUZ4+Y= +github.com/aws/aws-sdk-go-v2/service/apprunner v1.38.7/go.mod h1:UiPYznwe6WwKIOwLlWgrjdKvfOVVQ7eaRzf+OC4BzM4= +github.com/aws/aws-sdk-go-v2/service/appstream v1.49.7 h1:RlPnZlTvnNxjOm9XuYxcUqzrcR4VoHrMHrrWoa3pj+w= +github.com/aws/aws-sdk-go-v2/service/appstream v1.49.7/go.mod h1:aPmkM5vZVr/vBeP+czUKCYWAlewa3QCaCZGh6gWZfm8= +github.com/aws/aws-sdk-go-v2/service/appsync v1.51.6 h1:YsjIVoljoczbCUYFzTUhNkYjJlEreqXeuicq2wyvO9A= +github.com/aws/aws-sdk-go-v2/service/appsync v1.51.6/go.mod h1:j4cEEClULtta5LEg7OgxqGTz4k0ipCAvue7P7GGRLQI= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.8 h1:01m2bIxzwrVbFB6XADodX2JwSSlpKfarYZWczIdYNSU= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.8/go.mod h1:h5EaGwLxZGbeUEkwE9BWg+4lPwv42YgTqqQ/SH2bbB0= +github.com/aws/aws-sdk-go-v2/service/athena v1.55.6 h1:OC3hqQ29uyNsftVHwdbfHpDopEBViNFypjy9N5eDsMw= +github.com/aws/aws-sdk-go-v2/service/athena v1.55.6/go.mod h1:I1paYl0qAaXc+6AmLtylg4ApBC0/HEs5myhVIcy4Nng= +github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.6 h1:QD02o1P75R198cYX9Nt3flwM5HmXxsmWAhG+8Wef2ig= +github.com/aws/aws-sdk-go-v2/service/auditmanager v1.45.6/go.mod h1:ZZh2P2Vy29z/3Occ3o40d0P4IuwkaZJPKrSD1gukI6Y= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.3 h1:2tVkkifL19ZmmCRJyOudUuTNRzA1SYN7D32iEkB8CvE= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.59.3/go.mod h1:/Utcw7rzRwiW7C9ypYInnEtgyU7Nr8eG3+RFUUvuE1o= +github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.5 h1:YUHawBzbCFAqJzMjyIwHYRNyCJ2cF3cNmqZZcm2/Zqc= +github.com/aws/aws-sdk-go-v2/service/autoscalingplans v1.29.5/go.mod h1:3YNMqOSRPyr23RKCv8RRQz2B2xflT/nk1bZuogMnO8g= +github.com/aws/aws-sdk-go-v2/service/backup v1.48.0 h1:o5T+4iVi6R+czsshTXZJoTpldwYWJw+kvO6lWPdmZeQ= +github.com/aws/aws-sdk-go-v2/service/backup v1.48.0/go.mod h1:5er5+2GO9YgfAvZ9VqDSf9HKrwKAtjVA5Fm83eXtkfM= +github.com/aws/aws-sdk-go-v2/service/batch v1.57.10 h1:C9unOW8pT063iGGpnNWonK+iRMnVR86iPnYdFaRmnqA= +github.com/aws/aws-sdk-go-v2/service/batch v1.57.10/go.mod h1:fl2yc8ac4mmMPh3ByJ6LRgdL25iPcQ3cUqhZl4R5chE= +github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.8 h1:4O1siNWkg2oMPNzma7AR1GZCQIkH233tl9bTtOaweUg= +github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.11.8/go.mod h1:Mm4OxLblLwMOAZjrNfDrltCqO/RKSa516DNDrapaZyw= +github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.2 h1:5Bq66lHNfiPHM9WBwzQfhqqctRTxXF3+Un1bm9ZyThE= +github.com/aws/aws-sdk-go-v2/service/bedrock v1.47.2/go.mod h1:3sUHFSHdoib4v7JdqEGgxD2sIdTDikr4IpjBOgUAa0g= +github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.6 h1:SQcm5+AnLYVNJP0K8yFRWTfEifhQenCaF+aPfqXf+fk= +github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.50.6/go.mod h1:Jl3eDtXBZAze9w+aJO1oPzdk55CqOh+Tq9VhLTLQSRA= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.7.0 h1:g9JK8P5l42MhwGRwGT46vrDpPUtm1lQu7ojq7yq6ZX8= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.7.0/go.mod h1:Es+CYDVSPzyRIJaDDzxvoBNRc+AZbevIL8d+q1+3J5w= +github.com/aws/aws-sdk-go-v2/service/billing v1.8.0 h1:qffsTlqnTPtokF6Y4dlw4YUWPYtOw+PCQyv0gJ8o1PE= +github.com/aws/aws-sdk-go-v2/service/billing v1.8.0/go.mod h1:HaQjETFBieRL+1p0qWCYDzDe/JnI4oJM4UiO3qNEPTo= +github.com/aws/aws-sdk-go-v2/service/budgets v1.39.2 h1:HxSdjcZ9NPVG4ZdznJMUjqjR0DPBWSId0xKUbTfl/Eg= +github.com/aws/aws-sdk-go-v2/service/budgets v1.39.2/go.mod h1:+0hQkFGrrsp6x9hxk/n7EOscPVfwrBkTojUCthoHquM= +github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.6 h1:QWlDo8QuBHtT6LYYf5opmQtUY4ntkcU0mjmmmbZiMoM= +github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.6/go.mod h1:QSe+uEkQQHwIPKFfaZtbZWrNaRq5esdmdQspTPV4apY= +github.com/aws/aws-sdk-go-v2/service/chime v1.40.5 h1:kaAYFY5mvQHeyEX9pamOBly0Vx7f3Al3dCD9p3JJAnE= +github.com/aws/aws-sdk-go-v2/service/chime v1.40.5/go.mod h1:gXN/LFE/H9vql+trNeg5MwcHYB2brbgv4j0pnphrxXU= +github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.6 h1:JT7X1tDbHo/0D0UQh7zi2YlHbH8zaLTgH1zKEPx/kUo= +github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.6/go.mod h1:ROgSEKmD43CMB1KWQSPNovieWq6DPPSu/MCdVbwO6II= +github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.27.0 h1:NMNhVPuxmv+8l/XktsHQTqyk7vhVsqzKEzePMdQWvgE= +github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.27.0/go.mod h1:8y4H/7OXnf2YSf2ybz8aqQzxbl5pW/yiolNFSSaZ41g= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.36.0 h1:AI06e0v0FtjcNk3XNsJmp8fiAAOceRzErDjdwN0WPj8= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.36.0/go.mod h1:VyV0Il6a4RYvrqhA6tvNpV13LEBFk77Vu1FMTJs4qyA= +github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.5 h1:ZoUqKpdIPkGeGRY1v81GCaVoELHgtUYEV0WF67skUhk= +github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.5/go.mod h1:Q2RJfC6edAyk5hr3gJMS8WANFoTPGIo2SlAzQkZsT0A= +github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.6 h1:jqP2tyJOEj7qDoLyqyKGnDMAW+Lmi0WwNB2OruNao6w= +github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.28.6/go.mod h1:GIOHLcWXFDrHSzJJFMNRxLsfA++pOENXO2QVvMT0mJI= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.67.0 h1:dXbv06SZ39MYWL70KgFdMgFl9ZLfHe3AWIiTs0V2LAE= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.67.0/go.mod h1:/q63oDWCyO4xLLRiVYpwufJDwSkL0IbC5epFNJne8JQ= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4 h1:tVpbQcr1A0c+VTqtKEN9vfB0qer2SjfxX3LYojSGUq0= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4/go.mod h1:dYwFVhUsRZt7COcGP23ei0lY8gX8ZSHrbyX49VB93MA= +github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.8 h1:dlFZVF9TpiFvPsNO8uN20iHsrpJrALbQbwGbs7cVL9c= +github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.12.8/go.mod h1:MylnqogyYEsq0wODWlXmewzDOLXvDuhPpyAORIDSOOc= +github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.5 h1:vjOGGSctnKWctwndBRg6fnUQnXiIQ/zuf5km/L4q/zg= +github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.34.5/go.mod h1:WvZiU3vTIX6sm3FLFNHe05MWjKM4cqOPkfwT1lSj7hw= +github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.6 h1:WqphYeWJNaQRl5taLdy6ipI8EHsQGi8rxghXGvBSpkM= +github.com/aws/aws-sdk-go-v2/service/cloudsearch v1.31.6/go.mod h1:pOvrSeFE/QezgirkaSVZcEtEo1UvlnZy/XlYo5pAJ8c= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.6 h1:lo/qOnIAmeBGsfXa92XpKFolYCEVRqxRYd2V171eU24= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.53.6/go.mod h1:q4HzizMPYR4kPnUmcY7sjTCdB0hoxw84mQTgtjJ50ug= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.51.1 h1:GqVafesryYki8Lw/yRzLcoSeaT06qSAIbLoZLqeY0ks= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.51.1/go.mod h1:Kg/y+WTU5U8KtZ8vYYz0CyiR8UCBbZkpsT7TeqIkQ2M= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.2 h1:JPW6ND8muLsBwALrf/VXikyokUmGWNKZa88qZWwFGWA= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.58.2/go.mod h1:3Dh12t3s/KrpEm7HNfg5RH+XWzi9LW2QI7velkc61ac= +github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.6 h1:adRnHtafjEL6BdPyNvVvsljxGlI3wQALwnTLDGDyu3o= +github.com/aws/aws-sdk-go-v2/service/codeartifact v1.38.6/go.mod h1:Jo4nWheCppk/3QfXOcYBouw3XfQSLS/lqXn7GQIhYEQ= +github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.5 h1:IjkLl7nLhE8w32Zv9NKBUdbB6YsFHIN0Y7qek4LO7wQ= +github.com/aws/aws-sdk-go-v2/service/codebuild v1.67.5/go.mod h1:1ayIXbJj20GhTn4zvTQ5mKmDYMg5gs9ICsqR+WvjWrw= +github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.8 h1:ngiN4E8pNW15lffBIVfbO6IOSR/3NiRbBTL6XprV2UA= +github.com/aws/aws-sdk-go-v2/service/codecatalyst v1.20.8/go.mod h1:u8qstOf0Jhr2PB2Xko0PirjruTv4Cp/Rwhw7ZGxgpcI= +github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.6 h1:11qvnjhmVnkb9UFQdagNFmAZV8CNb0hznYUGIEIVMZM= +github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.6/go.mod h1:RLtIEolTsnW3TOw3fHTAXb4H2xNjcpKa/b1nKsTmAh8= +github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.5 h1:wcDfIGYi7pNS33qRzewQhvAs1FGZA+GrypDce+5m3TU= +github.com/aws/aws-sdk-go-v2/service/codeconnections v1.10.5/go.mod h1:XVNEBA5S5hDvYpzK0//pWFemUsx2LKxYa9Ymkg62Z5E= +github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.5 h1:chybWfKqesOGi/JZosjMFCUzEQ5180xOZAfDs0iY1Yo= +github.com/aws/aws-sdk-go-v2/service/codedeploy v1.34.5/go.mod h1:00HnOuKp1Q/g5sCAzV8dDJWq6fts0D/1xC5DlLWjXwA= +github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.5 h1:sQevsmx5Sg8WkyR/P+Vq/tqpJCDzKr+tvZYhuP6lMtE= +github.com/aws/aws-sdk-go-v2/service/codeguruprofiler v1.29.5/go.mod h1:6vjCrFSI1R02YCIFRqCqcKxOzKWSgib4Q9RPK8yhHS0= +github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.5 h1:WByNI1rera7rLq8qRSh+0uhQSVMDM228fZqOiUyeJb0= +github.com/aws/aws-sdk-go-v2/service/codegurureviewer v1.34.5/go.mod h1:oYDh1yjbugYgvcdCWMbsZcZmp8QQ1OBCqaX2qdXiPvI= +github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.6 h1:z/82UoTxxmA27/yygFEnx+uIdYY1zyK37vCPKZoXyb4= +github.com/aws/aws-sdk-go-v2/service/codepipeline v1.46.6/go.mod h1:8n32TPTWAAHJ0kAuD0z8TGR0z84ZfYFm9ILkHgkV5Do= +github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.6 h1:jSXTzwJsreMbTdUaBRhB0PnB+sWfq+awXxZJorfP8U8= +github.com/aws/aws-sdk-go-v2/service/codestarconnections v1.34.6/go.mod h1:bkkAghnfsExMwlQ9u3NIoMbhUhpUDq1VL5vaaD6KrKI= +github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.6 h1:q0ma8a3t28BbHb0/DSMF6VXOouvdk42kqjLzP1YGMMM= +github.com/aws/aws-sdk-go-v2/service/codestarnotifications v1.31.6/go.mod h1:lOY7xQqacZtC8sN+BEH8S3NCBoSEvLSeMHBVZfCynsk= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.6 h1:75RJ5nNarn2EViDSYRPV18H4PXAkugQy1Xjr4HJ9R3M= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.33.6/go.mod h1:dN8D7VkYmVwbH+MVVxiqtldtkTO7ovQiVUkCWa8v6PU= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.7 h1:1LPBlVrceFenrbWOZBGu8KTmX8TTMpZfRxX0HCnSjz0= +github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.57.7/go.mod h1:l8KDrD4EZQwTuM69YK3LFZ4c9VbNHrzaQJjJsoIFqfo= +github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.6 h1:LtBU4r66PzkAdivreTlrlNWH/CQ6PG7sAKlrcdz1d4Y= +github.com/aws/aws-sdk-go-v2/service/comprehend v1.40.6/go.mod h1:tbNB6UTE8b8fVgKsLl8IOc50jyxZ0fGqiVgQTWfNdLg= +github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.5 h1:dilS2NJ0F1Jwhi4A8NuZJAGq7HwFQ/GE4GJ+IoHWzx4= +github.com/aws/aws-sdk-go-v2/service/computeoptimizer v1.47.5/go.mod h1:GP4KTSWjdb7GofokIXNbVP9CQDIKTv13nfqSBiq2hnA= +github.com/aws/aws-sdk-go-v2/service/configservice v1.58.2 h1:sfLW2pTtZZHGM7Ksp3PdMqyoLjoD7dHzPblLLjcYnBk= +github.com/aws/aws-sdk-go-v2/service/configservice v1.58.2/go.mod h1:/+Y1FQ6hhvY+6moAqnf/lrSgNbckvrHoNmxTMJ5WhaU= +github.com/aws/aws-sdk-go-v2/service/connect v1.141.0 h1:n6229inzrafV1+2LIa3ltwi2PeGgsD76eLVg6sTW/iE= +github.com/aws/aws-sdk-go-v2/service/connect v1.141.0/go.mod h1:RlZrDWMyt5HH92j6fpBcBLjo5FiJw61jNAgTjCAQY5g= +github.com/aws/aws-sdk-go-v2/service/connectcases v1.32.0 h1:4nmhQ24WaJ4e38AKtFJzFSPvoiLDZCK0e2Edm7u+Tdk= +github.com/aws/aws-sdk-go-v2/service/connectcases v1.32.0/go.mod h1:pWZuObOfZSGHvL29N0S0JvGpsvk8xDlJPgX92QTxnTE= +github.com/aws/aws-sdk-go-v2/service/controltower v1.26.6 h1:xJchWovBC1h9lvvcysi4kjDT+ZxycuJc+jt/Y6YELho= +github.com/aws/aws-sdk-go-v2/service/controltower v1.26.6/go.mod h1:7T5FMpZ7QYi3p35ugZH2Wdebzw/bAAQ+HVsdtxT31LI= +github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.6 h1:Fy5Lp0Gn0aHairTF8nj3HNsml9NuLGuKFXsGlSCXMK0= +github.com/aws/aws-sdk-go-v2/service/costandusagereportservice v1.33.6/go.mod h1:WjmUookbSIF13EUgmIm3iJbsOR4ig0BZtPtLojlmiEo= +github.com/aws/aws-sdk-go-v2/service/costexplorer v1.57.0 h1:OPm/yHm06nNtL47/ITE/TEUgB1yZV7GU20cmH4qUe2A= +github.com/aws/aws-sdk-go-v2/service/costexplorer v1.57.0/go.mod h1:5PEFaK4UypksO7xXX+aZ2zJkTA4WYOCaCJ7jfHtvlrs= +github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.6 h1:bm/4K9y+tPlOm7LCw7Oul6j4+twkYN9pMZgf6czWEIE= +github.com/aws/aws-sdk-go-v2/service/costoptimizationhub v1.20.6/go.mod h1:Ind97CkUL/Sp8b9+eXlZoJzOyAjgSl+zX2NODYGl/5M= +github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.53.0 h1:MgnY9bNxeOQ2jPCwkQ5PdNVNJtdLlGWsql4BCEA3oKs= +github.com/aws/aws-sdk-go-v2/service/customerprofiles v1.53.0/go.mod h1:Zp3IfPlmLCI1qU7It4GyqNKmTNLjNP33ZS9XdJSHY38= +github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.7 h1:ARnadIHN7MAAMkjNsBScWgV7pRhrhXtBnXMG8YDkDNE= +github.com/aws/aws-sdk-go-v2/service/databasemigrationservice v1.57.7/go.mod h1:ct/KZc7aF1iJDdvVtIMUBjbZrIespvcZDXfiobANsVw= +github.com/aws/aws-sdk-go-v2/service/databrew v1.38.5 h1:uAyzLnETV1vpvVakHdGNOSnpYtmCPbc8F3e+rjooC+E= +github.com/aws/aws-sdk-go-v2/service/databrew v1.38.5/go.mod h1:TyoXF8AvpXcKkxjlW7E+Aax/FBDLoObTyby6zRffi14= +github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.6 h1:ywlBAsu4TUhGcocmioq7k6709WHhVZx6yHHcuAma1C8= +github.com/aws/aws-sdk-go-v2/service/dataexchange v1.39.6/go.mod h1:uu4l98l3f19G6MGsNf3EWcbrpRTwyErJ9PLvI/XaXwg= +github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.5 h1:lIw4H3QLLfAV6OFUFNf2rSQOD8ufSfN9sXciRpUIsv8= +github.com/aws/aws-sdk-go-v2/service/datapipeline v1.30.5/go.mod h1:lOMJLtcZ8roDJadGeAVnqdvva6RpG66Rzl3qmyHibQU= +github.com/aws/aws-sdk-go-v2/service/datasync v1.55.0 h1:K2gDOAe8OdZ6lnau8ran0va1vL97/JxANxJ1d5VYHz4= +github.com/aws/aws-sdk-go-v2/service/datasync v1.55.0/go.mod h1:GN+XSZ4Gv+QAfsCkBTEqLlmI766xItwX1KIsNJlPCJo= +github.com/aws/aws-sdk-go-v2/service/datazone v1.42.0 h1:RWvJP55ZGnWKuJadS8a/TjgYt5rrVg9YooDOLNHLbA8= +github.com/aws/aws-sdk-go-v2/service/datazone v1.42.0/go.mod h1:JtfS1guKOGCe3cKwSGrTm0grzQiMy1cfxfEAoMjygLM= +github.com/aws/aws-sdk-go-v2/service/dax v1.29.1 h1:sYEBub6ZSeElTUaelJkffTHj6HdmUsTF5H4B2XI/OiQ= +github.com/aws/aws-sdk-go-v2/service/dax v1.29.1/go.mod h1:FQ3H4KZGNJ7xNstwjgtKtWM99QtU1y2Y2vGdOSqEPZ8= +github.com/aws/aws-sdk-go-v2/service/detective v1.37.7 h1:VlbfflT4Weqvq2cRzhbGv3gKvG2T7rhdwLvl8QohkIU= +github.com/aws/aws-sdk-go-v2/service/detective v1.37.7/go.mod h1:JpUF7Kimgvqm5MBT3YiqVFmLRNqf+9xgzXzaJrCnlts= +github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.6 h1:HCNMZXY/HhpvwpesD0foAVzSqOqkK7QQdgRkIqrUbBM= +github.com/aws/aws-sdk-go-v2/service/devicefarm v1.35.6/go.mod h1:D2NbfDF3qEeaPwl+EDLGIhq5sD4jqoTkv8o1rw37IaE= +github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.6 h1:251cRFp3KrRyboVXOFhpurd9SlJ7GOk+lMxsRlfKb7Y= +github.com/aws/aws-sdk-go-v2/service/devopsguru v1.39.6/go.mod h1:XhFyJv1IDmCaKiPUwWlj9+gV1mgpoR4BspX8CpfRbR8= +github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.6 h1:xlqasn95WDPq8rFwMuLft8K6EXiBXA4gbElNy3k1qAE= +github.com/aws/aws-sdk-go-v2/service/directconnect v1.37.6/go.mod h1:ihMttb6cmTsmRw8/jdBT0WSR2cmxP+IdU9gIBbDs5mc= +github.com/aws/aws-sdk-go-v2/service/directoryservice v1.38.0 h1:/SjJpaHDl2Tcjq7wu0BXBr3y+iVhJGCUySBd40C38dQ= +github.com/aws/aws-sdk-go-v2/service/directoryservice v1.38.0/go.mod h1:9OhFQ4k8x6wvJRY3T3qQe4F/YQLo0iZB0Opq+2Mh80o= +github.com/aws/aws-sdk-go-v2/service/dlm v1.34.6 h1:x1q9I5nwC6JBo/k0CHPRUOtLsMTBoKTYBWQXbS0s0lU= +github.com/aws/aws-sdk-go-v2/service/dlm v1.34.6/go.mod h1:GMoqS22ylKwRmUIqPv2yQiYyfi9p4sv7D345nawzTgk= +github.com/aws/aws-sdk-go-v2/service/docdb v1.46.6 h1:AJ8DEg97/hOGfCMjXH/bJpodMKR5ZyXDPNjPTjGHMAw= +github.com/aws/aws-sdk-go-v2/service/docdb v1.46.6/go.mod h1:yK1MzY7O/rmmti02gkvk+IdJZ/tCvKpcGZU2YxoWUPg= +github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.6 h1:ZDolNXobqGnz7sLKh1b8yI4T4BrMjFbtIbmZRKmMmrI= +github.com/aws/aws-sdk-go-v2/service/docdbelastic v1.19.6/go.mod h1:oOz1QSkosu6fWaSQPmS9HYIkeqPs7FH+jugGa/bGQdA= +github.com/aws/aws-sdk-go-v2/service/drs v1.35.6 h1:awl8S++TupDDTsCRvrdNHUicQljM6liiHIBAJk+ej2w= +github.com/aws/aws-sdk-go-v2/service/drs v1.35.6/go.mod h1:p72nRrztE6ntt9W54vgPV3M5b520x8kbxqiDmHjFyjA= +github.com/aws/aws-sdk-go-v2/service/dsql v1.9.8 h1:9SzhOaXCRSMmyKariyaeP7hYcAdFkQk/1x3Z88V5t6o= +github.com/aws/aws-sdk-go-v2/service/dsql v1.9.8/go.mod h1:2Oz6G8F+PlNW4RK40ISLe8fTyLRvSlFOjdaWFcaFl9c= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.51.0 h1:TfglMkeRNYNGkyJ+XOTQJJ/RQb+MBlkiMn2H7DYuZok= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.51.0/go.mod h1:AdM9p8Ytg90UaNYrZIsOivYeC5cDvTPC2Mqw4/2f2aM= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.1 h1:7p9bJCZ/b3EJXXARW7JMEs2IhsnI4YFHpfXQfgMh0eg= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.254.1/go.mod h1:M8WWWIfXmxA4RgTXcI/5cSByxRqjgne32Sh0VIbrn0A= +github.com/aws/aws-sdk-go-v2/service/ecr v1.50.5 h1:jzjNyiIrXJHumV1hwofcQLpIZtcDw+vPQL00rLI3s4g= +github.com/aws/aws-sdk-go-v2/service/ecr v1.50.5/go.mod h1:UtPKcYVHY6RrV9EaaM1KZGNaf9dgviFdsT6xoFMLQsM= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.6 h1:pc4te9Px2oORmxWlJXaX/OkHQsdQ3RiPvuZU7525FZc= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.37.6/go.mod h1:BeseuedjcZNw+lGyqDIbapD3hvvsEVkjkISUIQLzem4= +github.com/aws/aws-sdk-go-v2/service/ecs v1.65.1 h1:pBbXc1fGRbrYl7NFujuubMmEFEp7CJiKTBsoDOIUkuk= +github.com/aws/aws-sdk-go-v2/service/ecs v1.65.1/go.mod h1:fu6WrWUHYyPRjzYO13UDXA7O6OShI8QbH5YSl9SOJwQ= +github.com/aws/aws-sdk-go-v2/service/efs v1.40.8 h1:vwqXyeluOHOgkonTOxvFqGgMNh0y5H6r23+8RA5ifZo= +github.com/aws/aws-sdk-go-v2/service/efs v1.40.8/go.mod h1:xJFehblB1voatQStn4hPPTnr+ueQ3UKxjSCro66JliE= +github.com/aws/aws-sdk-go-v2/service/eks v1.74.2 h1:GKqBur7gp6rnYbMZXh2+89f8g+/bu26ZKwpXfXrno80= +github.com/aws/aws-sdk-go-v2/service/eks v1.74.2/go.mod h1:f1/1x766rRjLVUk94exobjhggT1MR3vO4wxglqOvpY4= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.5 h1:VEdPmtEs1EzHXOcKmKwaN6rwwatgw4k12n08U7qML5w= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.5/go.mod h1:venvSIu8icYqJTZ2meX3NIQypX5t4R2E6Cr9wdgHCQ8= +github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.7 h1:zWmgdRblU92HDqT37r+kvORdWAZCiG3z6SvPKcE2D8M= +github.com/aws/aws-sdk-go-v2/service/elasticbeanstalk v1.33.7/go.mod h1:6hnLvLpLNgqMXL2uaEf/FacDYErGspeQHZn/3U+6H6k= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.6 h1:+YIp+dygyeHjUd7u9kv2MluNwnbiNeUITH4aZ4UgiPs= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.6/go.mod h1:iyqISGdbs/IFj3D7GyiRcVjNnbEYcF3NZrRlZnp7IWs= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.6 h1:qhVfq2WIqvxPTywVrznCkX1ad+5p6E85XTEjXpQN7RM= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.50.6/go.mod h1:RuZwE3p8IrWqK1kZhwH2TymlHLPuiI/taBMb8vrD39Q= +github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.6 h1:+f1A4QwqPiWy71nr5qlvLMeaR7UjpzDgCAG2MhhmJeo= +github.com/aws/aws-sdk-go-v2/service/elasticsearchservice v1.37.6/go.mod h1:pFAUfULfSY46LfS7WPd9q6IcdM/tWm3qTpEZhCSgtKI= +github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.6 h1:81IE+qNRipRKlwOUZzVI3NSOtewZnLqUqOA5UGAV3ME= +github.com/aws/aws-sdk-go-v2/service/elastictranscoder v1.32.6/go.mod h1:k9An7RySCxNbERamBuwDoXaXMTWXQqEusn3/eAoyN94= +github.com/aws/aws-sdk-go-v2/service/emr v1.54.5 h1:tA10GZKqcDLOD5JfeRTpu72X5KqxBDJBqWnn720HhzA= +github.com/aws/aws-sdk-go-v2/service/emr v1.54.5/go.mod h1:zESYrv3WuVUTyMIXwR8OoRAkcgj941Mdp154AXjONAY= +github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.2 h1:DXc0q23esbZXny49LUg289Yoy6Vjd58z0TV6jsGdKgM= +github.com/aws/aws-sdk-go-v2/service/emrcontainers v1.40.2/go.mod h1:btaFcfwXxksqE0d6wBhIy3VopO0dWw1KWctELo7P+wk= +github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.6 h1:jBV+JfRW8laF4hQrPoVj7Xxd45hrXg6fvNn0/nOEm3s= +github.com/aws/aws-sdk-go-v2/service/emrserverless v1.36.6/go.mod h1:6jyzPmx8zLW3K5oP/CBMH3VFhQyf3G6vPR1vaz3HsTI= +github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.5 h1:MoTJpDDOR1gmfIC6Qc7gS+uS0hlqF7RcphMqAfp8r2U= +github.com/aws/aws-sdk-go-v2/service/eventbridge v1.45.5/go.mod h1:fgyvv0FpfhbcmGgcgyDltW9K2UMs1DOBBjnkyX9JC1I= +github.com/aws/aws-sdk-go-v2/service/evidently v1.28.5 h1:TCJCjCNhQ79VvthLKT3r4Ku3SU19rGpoAovI6rydRIs= +github.com/aws/aws-sdk-go-v2/service/evidently v1.28.5/go.mod h1:UOLThVkUgc5apzB1G4oemgrigr3BYpQEbD183CX1k5s= +github.com/aws/aws-sdk-go-v2/service/evs v1.5.2 h1:RrUB7uEIO4LYwaqRwK7KL+zH7irCQDfFOueZCHXFig8= +github.com/aws/aws-sdk-go-v2/service/evs v1.5.2/go.mod h1:0j+d5nDYF1oBpk7MWqkl5VIWnSNhWD9KiWTj+t/U7Y4= +github.com/aws/aws-sdk-go-v2/service/finspace v1.33.6 h1:H3llnOFZFz/g5v4cAA6gUQ54XUJf74SQCyKuLlCZfi4= +github.com/aws/aws-sdk-go-v2/service/finspace v1.33.6/go.mod h1:a2D/sV/YKWlPNmGYZ0OVmX2typzjwO7IwZ2NUfBgaEI= +github.com/aws/aws-sdk-go-v2/service/firehose v1.41.6 h1:BaLiLj0REx6fAxK6KYTeHXv9njpyqnLqrARYC8QhkLQ= +github.com/aws/aws-sdk-go-v2/service/firehose v1.41.6/go.mod h1:kKWlKjg9gI2uOLNQG1GnTBaYfBVQKJC0z99GIPQLFXw= +github.com/aws/aws-sdk-go-v2/service/fis v1.37.5 h1:yqaWoYLetwAKcnR74PvZjgaFRabbWDnllrFOYu6EEV0= +github.com/aws/aws-sdk-go-v2/service/fis v1.37.5/go.mod h1:htMJekf0GQU+ZgqHm5nkrpGrFQk9Sd/VX3mazLer3M4= +github.com/aws/aws-sdk-go-v2/service/fms v1.44.6 h1:Kkp6omiLoa7KDN8I/YesQzQ+Czi8a7iFsz18a2I0avE= +github.com/aws/aws-sdk-go-v2/service/fms v1.44.6/go.mod h1:0MmE+RS7FFf+ld2RVTLQSJumC56UPfnYj20jwC0F7IA= +github.com/aws/aws-sdk-go-v2/service/fsx v1.62.0 h1:by2Uy4YkY+kddlqUXziLUo+ORa5d5Zba7+9tDyB+nSc= +github.com/aws/aws-sdk-go-v2/service/fsx v1.62.0/go.mod h1:IYOHN0ZkhnOc76Wq3jA9p7EBmcyUrD7ovglUA7thwAA= +github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.6 h1:gbD+Jd5bKvfkeieI9nBk4pyBEGUCKGuC3uubBcnfjPQ= +github.com/aws/aws-sdk-go-v2/service/gamelift v1.46.6/go.mod h1:qG2t3ko7BtX5Ix+c9V8xNiQbHyMhL3Cci8NemnNGU9M= +github.com/aws/aws-sdk-go-v2/service/glacier v1.31.6 h1:iwc7B/ZCzm8dhAunHXYU3ppf+OKjtxQmFaVWAi0KVCw= +github.com/aws/aws-sdk-go-v2/service/glacier v1.31.6/go.mod h1:diGbfsRR7oW+2CZPfdR/IC1LC9Vt33OVKHbSmmKaUo8= +github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.6 h1:1up3eQrlvZ0FEzNLFCpRa06ZnBO+w43MqgGjeQJVoXI= +github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.34.6/go.mod h1:z4vejjg7HKiZPR12s6irgnDOpFw0hTJukQm/tkwmgJU= +github.com/aws/aws-sdk-go-v2/service/glue v1.130.0 h1:Sbrmxv4PODlzPR70fbX8rnlpU00EVv6U5eihZsXmr1A= +github.com/aws/aws-sdk-go-v2/service/glue v1.130.0/go.mod h1:iH5M4d6X8IdmFUwOVdnoCEt7eqhjYZuw4gEI0ebsQjs= +github.com/aws/aws-sdk-go-v2/service/grafana v1.31.6 h1:SoVlnBHm+Gq5LI4Z4tIxLAfOG1wCFA5puE1vwB/ldHA= +github.com/aws/aws-sdk-go-v2/service/grafana v1.31.6/go.mod h1:ABsoTppDCXrP8CFfMIkaoYdC87U51t0mMxZbDFZGKkQ= +github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.6 h1:olwkT6lMeGYJ18lPObZKMaXOS3a69GoecEtGmR2Umyc= +github.com/aws/aws-sdk-go-v2/service/greengrass v1.32.6/go.mod h1:GS2vTGoqO4jHpYqP0avBbcVmkojcOYKtiBvCrVCg8Pc= +github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.6 h1:LhXUztHSIjfmUHkahRMI+NeYBwv5XcFMyXAcw1+/5W0= +github.com/aws/aws-sdk-go-v2/service/groundstation v1.37.6/go.mod h1:h6rk6CTK+SoxaYWtdwyrjgWI01Q2+figfhS4fLJCtD4= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.3 h1:vp2qkFD6u3TN3ACRLFshg1/lWIx0+ZnQc5vIAeKmtic= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.64.3/go.mod h1:0cFCtC9mK9eNAHpKNc5/A59dqjYdwPnE1vL5STupNsk= +github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.5 h1:FP9XMTzx31mocJLJjPJEpaQIDy9cAfYRdclIV/YfRVw= +github.com/aws/aws-sdk-go-v2/service/healthlake v1.35.5/go.mod h1:kVyA+EB5+V1zoCKEd7DR2isRChxswqaafB3kFl5eM0Q= +github.com/aws/aws-sdk-go-v2/service/iam v1.47.7 h1:0EDAdmMTzsgXl++8a0JZ+Yx0/dOqT8o/EONknxlQK94= +github.com/aws/aws-sdk-go-v2/service/iam v1.47.7/go.mod h1:NkNbn/8/mFrPUq0Kg6EM6c0+GaTLG+aPzXxwB7RF5xo= +github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.6 h1:yJG8OLDpUK/U/BDClI+McQi5zzcIxV+kf1q2WxjWzNo= +github.com/aws/aws-sdk-go-v2/service/identitystore v1.32.6/go.mod h1:4xOhHo77B1qfs09L1DJq5luMO2cSILnc+8UkLvzvtHw= +github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.48.0 h1:F3LuF59HfxqQqWA8lrjZmRwvScpfc6pvkrzHwFZwryA= +github.com/aws/aws-sdk-go-v2/service/imagebuilder v1.48.0/go.mod h1:B44b3XYDjkYgLbEpyTWrK+0k8+N1PZoBO8PdJUF4Cn4= +github.com/aws/aws-sdk-go-v2/service/inspector v1.30.5 h1:a9Yl3PlsRSiOlfg7qCpAPTnL/yhfsEFrPuyMjnnmUkA= +github.com/aws/aws-sdk-go-v2/service/inspector v1.30.5/go.mod h1:WPIOZddPJtTqr0mjtd6YfwXyKJiSlOCb6ZWZ3f3xIac= +github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.6 h1:G3SqMciqPsatTbPmq2lLebpGjanwqfkBGCKStf4nSbE= +github.com/aws/aws-sdk-go-v2/service/inspector2 v1.44.6/go.mod h1:idr72RZY3+DwomnH2ZTYE0Y/+rwKdtdneJWWGLlylmU= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.8 h1:tIN8MFT1z5STK5kTdOT1TCfMN/bn5fSEnlKsTL8qBOU= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.8/go.mod h1:VKS56txtNWjKI8FqD/hliL0BcshyF4ZaLBa1rm2Y+5s= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.8 h1:0lJ7+zL81zesTu1nd1ocKpEoYi6BqDppjoAJLn18Vr0= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.8/go.mod h1:5t+iImUczd3RYSVnc20t/ohBrmrkpdcy89pm62BSDQo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.8 h1:M6JI2aGFEzYxsF6CXIuRBnkge9Wf9a2xU39rNeXgu10= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.8/go.mod h1:Fw+MyTwlwjFsSTE31mH211Np+CUslml8mzc0AFEG09s= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.8 h1:AgYCo1Rb8XChJXA871BXHDNxNWOTAr6V5YdsRIBbgv0= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.8/go.mod h1:Au9dvIGm1Hbqnt29d3VakOCQuN9l0WrkDDTRq8biWS4= -github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.4 h1:pqXQW3DS4n+LvhbMnI0dYu48/ezMZHyQ3hgZmqppWDA= -github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.4/go.mod h1:LlNojdmrHYdc58JiW4d1iiVauXMR67I6w7AOuNO/7QM= -github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.7 h1:ZwuNG7d6j3BIelPU/cjuU2WnbPPPr6HzTtkQHhCfVDg= -github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.7/go.mod h1:ro6V5D4DB4GTNjElv465FEbFLkArIZk8dfwlQu0CDVk= -github.com/aws/aws-sdk-go-v2/service/iot v1.69.4 h1:aE6flqYMH7oN70XXJ8NAzM6jsTK6dwv5DlYU/tTO9iE= -github.com/aws/aws-sdk-go-v2/service/iot v1.69.4/go.mod h1:JlM6Y9/lpdIu6Nbm2PHKsWBl4pEEjzeKcIwaceNzI8A= -github.com/aws/aws-sdk-go-v2/service/ivs v1.47.5 h1:aJ1AE3Dt/mwkFcR3Ak8HGJ8ack7sD21r3/oJJ1CzvIo= -github.com/aws/aws-sdk-go-v2/service/ivs v1.47.5/go.mod h1:ulDEMSCfB7GJPlDkbN8VZTQwuY+gzQS7uMhkPKc08Xk= -github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.4 h1:sRozLJvRu6LW2LNdjI7vNGz85BaHDTgrpnlxg0kjWfo= -github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.4/go.mod h1:Zz8GTvGWBPnle4TVu0fWZrWnEJM/ohy1AEvz72Q8T0o= -github.com/aws/aws-sdk-go-v2/service/kafka v1.43.5 h1:GD6O4rGwvpuXMW3G+LGmcAisxwEJ/qWTEHVh2EJ9YAg= -github.com/aws/aws-sdk-go-v2/service/kafka v1.43.5/go.mod h1:3JzaPchevdU28xVcUGvZihkHEgcxj6mc1M0jmIPBZCk= -github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.4 h1:sqxHUxLuh47E1yfvyIpqJ3Rlq86/Zp+qY3qdg1CwZls= -github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.4/go.mod h1:WD/XxqAT+x1ALiZh2mFgSZ2w7hhK1bgJyxrGczg5FeY= -github.com/aws/aws-sdk-go-v2/service/kendra v1.60.5 h1:wl1Jvy+LnplN3DA63LvFaiNRKAQQ/RJWJxNMhNc6uvk= -github.com/aws/aws-sdk-go-v2/service/kendra v1.60.5/go.mod h1:z6MqqmaBB0jB7j6TtqU74wZX43HuOAjW+xcPhlVtcLU= -github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.5 h1:WbkAo6akNMmDSY14aTX2P5JfLBPYaky3KowtTpUu+Dg= -github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.5/go.mod h1:V5N6Q6xPxATXIYhnINepbmj8v7SFjH/RvcR2tvwemqc= -github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.4 h1:EklnkOC4Hvk0qz7JEyj1lUQwuzhxNQwoWGzn+B9p/SQ= -github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.4/go.mod h1:P3rzrvQKKDJdr8DSQ+HrnPe0vZHObzGArI8VjS8TD/c= -github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.5 h1:rtFOjsNi/FF/ccQOWKJJ0DLJUmAjYHhrtKd21Vgis1k= -github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.5/go.mod h1:s5gBWn3mAmbzP1VH4gKCrZ8cvoPT3O4PFf2iqgnFv7o= -github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.6 h1:JqYFrkvba3uTBNT9SnHX3zY8xwAMIf67AAE9gKM6Wqg= -github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.6/go.mod h1:blmPmauXqE222j/1bBnWbnu5HmOFKaq57TDVEp5TY6E= -github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.4 h1:AtXxx3T2m3MtsOx6RYECZ9CY/xR+bs9IBpRcWjfYm7k= -github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.4/go.mod h1:Jw474eZ6bJAkOCNDip0lAwPIpGhaPumFuZ3WBftEZAI= -github.com/aws/aws-sdk-go-v2/service/kms v1.45.4 h1:6gzIbiRNs6o/K/WaLta0Vwac0bI9ou3gfx8ASSMf3wU= -github.com/aws/aws-sdk-go-v2/service/kms v1.45.4/go.mod h1:ooAdc5n3rjgEznIXncCYY6V9+YQDcJAYyZDJ4TwLSDM= -github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.4 h1:SkLIob+eQ2x917Dm6J8ZYBOKJQcubfnDvlFtBDTj3HA= -github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.4/go.mod h1:Llzlro6KcIlCQ9XlF67XWmWwB/SiSQ4E3+FAW9MF2P0= -github.com/aws/aws-sdk-go-v2/service/lambda v1.77.5 h1:rKc5Ad3PJlXGo5pigWii+m/hSPgxbNJtOicEP5nbV2E= -github.com/aws/aws-sdk-go-v2/service/lambda v1.77.5/go.mod h1:fPYDox6U6puh6xhMyWpUWd19QIIqMlcQ6iCdC1jk2cE= -github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.5 h1:kzVE1YGQzh2EsH2/2rru9KlTT1EcnyzPFh/ziT0bjmA= -github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.5/go.mod h1:Cj8DwO1GPQM1am9utweFWdc1l/hIPacK5NHukImj0/I= -github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.4 h1:4EXJ0zche8Tcb459h2JGnYTxBY5ipAWttvV+2UcPDn4= -github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.4/go.mod h1:fJv0jAIV2g4lLrIol3kE/2zt6P8l+66L2UFGMtD8I1Y= -github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.5 h1:0T2rzgz1a/snpBVTIen7eSwnGhWvAPd6437/yZ99tss= -github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.5/go.mod h1:E4DRF4KQX1XZN8t28fSq5W+BMksVqnV6U2ce2A4gXUQ= -github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.5 h1:0O5ABLP0OFZzFvj28caDllk2YH4mc1fP6i+4HuNfHek= -github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.5/go.mod h1:nxxXvBLZEm+j3hsKeTQ+nWnXlgHRaI9WDiagMPeT59M= -github.com/aws/aws-sdk-go-v2/service/lightsail v1.48.5 h1:w5f4GFD4VPp92gw8Lu+5bLNta8PQpi1Uc5TZCR05F6g= -github.com/aws/aws-sdk-go-v2/service/lightsail v1.48.5/go.mod h1:PYBtpUhvxpPQcFHNezTW+7S2q0EMm1tHmMxZ8EL17IA= -github.com/aws/aws-sdk-go-v2/service/location v1.49.5 h1:cRtSrpvv27SdsdAPlol8T2nnM3O66VdenjcPCKSIXHA= -github.com/aws/aws-sdk-go-v2/service/location v1.49.5/go.mod h1:Y+SWwVf3QLr3rW2ys+e4EdaXKfVkzXskNqdRda6XOJ0= -github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.5 h1:ETYc5MpIm5WSDShGfbSYTmklAB76FFuuxGfOsX+M+nc= -github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.5/go.mod h1:9orzVPgSp0QB6sBj7bJ14uA5p+/4JmpoFMZEST2WeWU= -github.com/aws/aws-sdk-go-v2/service/m2 v1.25.5 h1:ZdpvRHcAsuS+r68qUCpC/J9jeVr2hjQupXHej5pdp5Y= -github.com/aws/aws-sdk-go-v2/service/m2 v1.25.5/go.mod h1:mkXvkEK6xuq9HQyMcb+8OxFN08JEIHUiSLYZtvIUynk= -github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.5 h1:gc6xw799PWQwqSPiCUjSUeJFwktPxdu4EEv/JjtbaHg= -github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.5/go.mod h1:SJrA0S1rZf+hJZ8A14qyGSKEfo0+xgcHybOMuso4pGo= -github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.44.5 h1:SlM5+NZGTGDle6ttbPKF/WHJcwxbj3oEgdzDZ9Qw3Qw= -github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.44.5/go.mod h1:Qf4V6X3IK9jRR830+XweeOn1xjewIeLn2D3e2NCkobA= -github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.5 h1:FhZZhB3XgafXOd7GRTDPNie3n/HrF3Zv8bB4LBn/tuM= -github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.5/go.mod h1:jdqkPR7VkqoYZSFDaWNJO5117OB5ahm1OsdpL3N+FMA= -github.com/aws/aws-sdk-go-v2/service/medialive v1.83.1 h1:8uRoFG6r/9RxWNPpuyHj508tMBvZThOWzNFN6ulTt30= -github.com/aws/aws-sdk-go-v2/service/medialive v1.83.1/go.mod h1:QkW7SVV35Eq52NiDipbbq5Fdjprxdt0BevJGMOSI3cg= -github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.5 h1:cqAHLMgzD7lRgev2a1Mo+Yx1lrbQeUMrdYMG0tXTHDQ= -github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.5/go.mod h1:anm0e41ZROI5kucwbWCuL9Nuk/gIBhh+bOnwEKnyPaI= -github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.2 h1:bJf3EQ7U9YhLX0LZ/mWb2Ca4VDB0RHMXn7JHv9H1H+o= -github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.2/go.mod h1:3iKCnq745r5o1cK5T8sWPdBlca92hkOV9MRjkyLSoPs= -github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.5 h1:NpMBTC1/EUDCiR1QsAaJx5B5aQxfRAa3LI3o8o/ygzg= -github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.5/go.mod h1:ClEQ25nOCArJXha4xw1SKmNRBqokGa5wUWrY0CSljQc= -github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.5 h1:z8YzBokMM+ACy+VAt9ML6t15bl4PWg2Qa+gLZxSMzsI= -github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.5/go.mod h1:pX/zpqdhpMeXOgf4IaTj0R7huKhqmrz4Ycmqgd0OBVM= -github.com/aws/aws-sdk-go-v2/service/memorydb v1.31.5 h1:2RFdzA+rAgOh+pvBPniDT0SApO5klmNUHUFegbxq924= -github.com/aws/aws-sdk-go-v2/service/memorydb v1.31.5/go.mod h1:XFXsu3EXiGwEG4R64MkML234uPPXQBxcAY7qUXCyHaM= -github.com/aws/aws-sdk-go-v2/service/mgn v1.37.4 h1:g2h94C45Mqi88liuvo0IcH2eSL/FwgKOBXTVgp0Zy7U= -github.com/aws/aws-sdk-go-v2/service/mgn v1.37.4/go.mod h1:jSgQjRJnBdoNJEGHnpQ2PgOLys7ohNJkQKmzBQ8FYw4= -github.com/aws/aws-sdk-go-v2/service/mq v1.34.3 h1:Rz/lroysK+RqrcTY7J6psFC0EG0+lc/wDNITYhyZqS8= -github.com/aws/aws-sdk-go-v2/service/mq v1.34.3/go.mod h1:Xii/g+EJLpxVHa4A1dbKfp+beF9dbqFVwtsmcYoRjnk= -github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.5 h1:Nf2+SGxaMZ3KfRZ+DIYjrzWWhBUICOUG5+RrvdTNttQ= -github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.5/go.mod h1:T1nupRx4k6E8GYN/fqcV9e+Ezn8s6RyrDxcyBd0ylH4= -github.com/aws/aws-sdk-go-v2/service/neptune v1.42.3 h1:wQZ3ZoxMhSWeI+Gx04TdnPGVyiyse0JbnU8H/RnHVmc= -github.com/aws/aws-sdk-go-v2/service/neptune v1.42.3/go.mod h1:GrbX2ileXVUAUK8aqjYOpf7XsmkMwhtM5FL6L08REDs= -github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.4 h1:BwUXxuGTkfCJBxSeCyj9FGXzAORVGpW1vJeNDuljzaU= -github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.4/go.mod h1:63FrdK0c39o4iZR2SXgRVm5HAR4UO52U3aUAtsyiCFU= -github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.56.1 h1:9C74Am5h6+Zq8MFuq/LS8Kd6le8Jqoy/W2BES5HMnWY= -github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.56.1/go.mod h1:fdoS8BPmAwWCsz/T5z4Gj6rzgAJjSAsf88e+Qic7cQs= -github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.6 h1:gkW089f1iICPJKVq0UbtK57znJBbyLv0ryYpC3d3nHw= -github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.6/go.mod h1:u3gTjlgiO+GaYHD7mjiXTHEAkHzmv1jlqA27JaJCLAQ= -github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.5 h1:LVzNnDazY/+KJQfmzmy296vHVAsjt+KlBXKvK3RLAP4= -github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.5/go.mod h1:72XMlkVojEDuZTW9InSxprH/s18r6tOI/p3/Rjxd/e8= -github.com/aws/aws-sdk-go-v2/service/notifications v1.7.3 h1:yKNPjCC/kINzsM6V//q4gKeBkXjko3DOlLZ5XvvkW0w= -github.com/aws/aws-sdk-go-v2/service/notifications v1.7.3/go.mod h1:3JeNkPARZA8cQWkggggJRAWfn8YYL7IyR/Ng9fi8QWk= -github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.7 h1:LXBCZlJsWU9P/2wQJG+aOEBzzVkeqytNvVSP/AiM2xo= -github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.7/go.mod h1:1/9XnEIGQt6i7wFXCBTaFNBj2vmzc7g5O0YrrOoLZcM= -github.com/aws/aws-sdk-go-v2/service/oam v1.22.4 h1:hc6vhGJR/Oo3wUirrCdk2kcjUEbaAgKY/MaUoHdR7dc= -github.com/aws/aws-sdk-go-v2/service/oam v1.22.4/go.mod h1:yJfcx5ndz1LTXA3WQ7qZWmPQXOtE3d4Rx7fwF9CMeAs= -github.com/aws/aws-sdk-go-v2/service/odb v1.4.5 h1:g3WQYf6RoN7x0dqdf9edQROEw13c+rhU6ztseY3cfuo= -github.com/aws/aws-sdk-go-v2/service/odb v1.4.5/go.mod h1:YcfGEDn5kPX/cObRuQbLj0kaGgfJ62mg6vKwk261gY0= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.4 h1:dFR3ire/PYB9qIdAKes2dsIWSPSbmXDR+hYoWBOSvNM= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.4/go.mod h1:aglzJEixBNrJcfZkRFo9zUIiqgqau71VgMUpNF9aq20= -github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.3 h1:FcB0JD+m42HH2xQebadyl1w4nBsaXy3CezzLotSW5U0= -github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.3/go.mod h1:Kq0rlqHHSo8NhLze+I63WipfRDQ8RE5xwmUD6CbhRYI= -github.com/aws/aws-sdk-go-v2/service/organizations v1.45.2 h1:UrgNIo7nnNcJ41RSZ8I6mz0t5j6M19KPzb+XW9QF5U0= -github.com/aws/aws-sdk-go-v2/service/organizations v1.45.2/go.mod h1:g24aovax3vUoQp2D3+XAOPlJ7VeeM3MdI+3k/U2gg2s= -github.com/aws/aws-sdk-go-v2/service/osis v1.20.1 h1:iNDGJwuGrWFQgaUYSZ5V+0bqBGy91HrZYmvAVsPvdMg= -github.com/aws/aws-sdk-go-v2/service/osis v1.20.1/go.mod h1:WtOr7MJmClnNHHimDVC3uknN7UKiT8bnjnowP7DDPDM= -github.com/aws/aws-sdk-go-v2/service/outposts v1.56.6 h1:XcTh52znPsNYzIWyozFwu8Uu+XLkoGxL6grXNwxMAKs= -github.com/aws/aws-sdk-go-v2/service/outposts v1.56.6/go.mod h1:ffRwILonyjECbO5dHGK5HOXMUVmKX23X0PUOBecZeRo= -github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.1 h1:ko0VIzCAX4cT3gcoh0XE8GIzQNjYYwXVJfcbiCmJ1mM= -github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.1/go.mod h1:Rl6JV2tdH5DbnBiRzu2+N8Q3nnZaUofdvk+9EpRH/0A= -github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.5 h1:RPJr4Eavdpw9lrcKzcmWBaButkGxdZHXYLKuhhNDTcs= -github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.5/go.mod h1:ziQOjxhY7/5u/s50cq/rIixwBY4pFvuMz2WZfDGWvAg= -github.com/aws/aws-sdk-go-v2/service/pcs v1.13.1 h1:Dj5rB1dYKFBGbCC1ju0XnNnc/ww4MYOGu6NKCDkcSRQ= -github.com/aws/aws-sdk-go-v2/service/pcs v1.13.1/go.mod h1:/koo7XUOt4SD7GWfe+aJmVvQRFWc3qxg/V3J7GSKwtQ= -github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.5 h1:1w+7cQ8xLV5HHqXLsU951goCUuoMSz5LOUpmzCwC6As= -github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.5/go.mod h1:ioCORBoHu2o16hJpLFZg/e4S0f0yuPB9W+JjYMMNfu0= -github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.4 h1:f8GjAtK/4vlm8smVV6rJxlbYhzUfkGu1/BTPcFYRZwY= -github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.4/go.mod h1:X3wPHDPz8ned4UQ+a+kViPTNlIkY4Ccm6XpcN71/et8= -github.com/aws/aws-sdk-go-v2/service/pipes v1.23.4 h1:b7/6w7OW1h1OdpiJbtRTDxB1cNVBOEjm8iHWcRVCsws= -github.com/aws/aws-sdk-go-v2/service/pipes v1.23.4/go.mod h1:8SPFrFynF5Wn1iU2w4scParKYA9jDimBHFeDbyoGQTE= -github.com/aws/aws-sdk-go-v2/service/polly v1.53.5 h1:B8FqAPzKZYuTSF+iWzOdh2yuayZqDaz0rHeY7r7+Czw= -github.com/aws/aws-sdk-go-v2/service/polly v1.53.5/go.mod h1:sMQztn8/ymRqblrKqYi8Tp5WR2u75rDJsnmm23F+y6I= -github.com/aws/aws-sdk-go-v2/service/pricing v1.39.5 h1:6XZD3eQtNzrLQGjs5afZn1lW2TZRDWVfA/3SaQB412Y= -github.com/aws/aws-sdk-go-v2/service/pricing v1.39.5/go.mod h1:9AbXh+nl1DAjTjoSiDYz6IeKO5xeGJ05H/JIjb1Siwk= -github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.5 h1:2yXmH6W2446BciTlCzYlGEZeBt4IwwqIgkaXR5Q3i7U= -github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.5/go.mod h1:thMIBdJa0cHBOpqpUXjZVKJItdp5nYvAtd0OwtxUc30= -github.com/aws/aws-sdk-go-v2/service/qldb v1.30.5 h1:1s/KnPcDCWFcESJe5kg9Insc1cpM7kOJZxbmHF8Yy5w= -github.com/aws/aws-sdk-go-v2/service/qldb v1.30.5/go.mod h1:MuSf1hpqGEl5HzjSV2p5N1uJMykHP8YmX/QS0mugRTo= -github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.1 h1:O7hHDZF/5+DN4oPRQq1u3zd1SHnxwDgpvvxThUhP1+Q= -github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.1/go.mod h1:/Mot6Jj1Qd2/B8WxiOwOkxRv8nVtu7TVTCKgQcpgbJk= -github.com/aws/aws-sdk-go-v2/service/ram v1.34.5 h1:PvZedq8Nr3QiAOx3tXbZhD3uqvijB7AqgtjSK9HH1vE= -github.com/aws/aws-sdk-go-v2/service/ram v1.34.5/go.mod h1:6T048C/TFPVH5LDnuB27uZiWz4neaMX/k4PQuwsSGYI= -github.com/aws/aws-sdk-go-v2/service/rbin v1.26.5 h1:cIKPk2ps8dwc5Eb16VZnYMKQW+9FMbz+qDRgTzglXPU= -github.com/aws/aws-sdk-go-v2/service/rbin v1.26.5/go.mod h1:COEStyfI/PSW8awNT1HoHlRgYQqVjCdRhJZ1Sw7qpjI= -github.com/aws/aws-sdk-go-v2/service/rds v1.107.1 h1:j7GQZWF0CbHCObPEZUK6QuP3yUQwjBJmlaojHPRZ6f8= -github.com/aws/aws-sdk-go-v2/service/rds v1.107.1/go.mod h1:OW/mwGWAs6l1HnZpJupatcUFt1V0y6OiUMUp+Wd0DEc= -github.com/aws/aws-sdk-go-v2/service/redshift v1.58.4 h1:3/K+FgsR6//ZSK/Uv2QTeb8Ug1IdKjNgwb7205a4n4M= -github.com/aws/aws-sdk-go-v2/service/redshift v1.58.4/go.mod h1:t+6WfvYqxtwQ0MDg56sYFfH07EKT+Jz+NHamFAulkwg= -github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.5 h1:2hyuttSMbpJzTdpPAA6pbsmdcQSb3t7AQPGYKb8Pbw8= -github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.5/go.mod h1:l8JdskDXH9DHRDCXrUQeLwJMmuViPtTz/iz+MvBnSCc= -github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.7 h1:7ISSWB8eMzpZt4X3KeDd5yF0sOPQKbFaYikeElWgzIM= -github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.7/go.mod h1:o1kE7Aq8tpQm0aalh8i0wcwK0Yhrj/JB9FfvBAnbwjQ= -github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.4 h1:A0+WSnZw5q6HRbmql7OLmHuUHnaWUXgjmjSv4xshn8Y= -github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.4/go.mod h1:mxURAM325+JC3eHlWei2+mzWCxNZ5feN1uoRzT8miTs= -github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.5 h1:7ibWyVXWXpXoqaeoxRBl6FWKvDAYxpCEmjpjSQGum7M= -github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.5/go.mod h1:gBH/5F+DqH6XdzzHk3cmKGWmQbea1+nQM25S0dNKBFw= -github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.21.5 h1:/osdwwAdfwUJslToz4OetbXS1IZdNK0uYJ7UvhuJTIY= -github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.21.5/go.mod h1:47z4n+dkh/oTmOlaWxSy6RT3x7GkR9K7NCNHSN97NBk= -github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.6 h1:3jUHJ+wceveycmaOrwQXZSBv/7XRhtv68sLoQ+/zj4M= -github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.6/go.mod h1:ScoN6z1s8UGadFNYNsTYwXgztfW0r7+FyINMkmJmOgo= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.5 h1:UA3sejPQHzCKU16k1VY+AnTDr4FCWWQxLYKxlslKEU0= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.5/go.mod h1:yyo15Q/sYN7ztaSSP/kpAx+DdMNaQO0mP4GGBAm7BRw= -github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.5 h1:dVj+l4NIKnDsOMtlW1e1tWM1s1jO51Pm2QStoU13Y68= -github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.5/go.mod h1:doLe0bLdFnLMfaF9JacaeWritZRGLW9Nm6p+bNDUpRg= -github.com/aws/aws-sdk-go-v2/service/route53 v1.58.3 h1:jQzRC+0eI/l5mFXVoPTyyolrqyZtKIYaKHSuKJoIJKs= -github.com/aws/aws-sdk-go-v2/service/route53 v1.58.3/go.mod h1:1GNaojT/gG4Ru9tT39ton6kRZ3FvptJ/QRKBoqUOVX4= -github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.3 h1:sfRAFot/FdWktEsGAPS2sUFOjd7FJM8FQiRr7F3bNmo= -github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.3/go.mod h1:Fu3cGFzUxs17sZS5NJnaBPZTrZufyRDDPQX/D1erARA= -github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.5 h1:2jOEIGAK54GVbprEefZL9TtcIIdN3XAnzYvqn6NuGME= -github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.5/go.mod h1:nHZv5ixEJObIzWNp61Gg69rUPd2pCkrgOJB5Rvx2MXY= -github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.6 h1:oHhQ63HSIH6LNwMMdE/vo/DgXB8ro3H8x1DgNb8x62Q= -github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.6/go.mod h1:4nDaomeiHh3Se3hq0dNOKJFU5hmomS0F66afMsuYq2o= -github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.5 h1:SIyhgC6Yn9AepbdFEXYA9+NyM0M++QhUNVLAjZdMZMk= -github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.5/go.mod h1:NYmSbafb2MHeTQiQC0de+czBefxkM+5+6MthkmZTI4Y= -github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.5 h1:s4bVZWDzxzbZI0n943TUlvUoPLdUKUeBknowTUKWS0Q= -github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.5/go.mod h1:zsGRe0oBLauYWlFrj6FHK1mNhR4NCbuqj+JQelGFC3M= -github.com/aws/aws-sdk-go-v2/service/rum v1.28.6 h1:vYgurgqbwV9vkW34/bYqIfEahxe1vScs9ttre2nYEw8= -github.com/aws/aws-sdk-go-v2/service/rum v1.28.6/go.mod h1:qzw/AMuwYDbiaF31RS28qwtaDENs6uDk/KpgV8OBS0k= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.2 h1:T7b3qniouutV5Wwa9B1q7gW+Y8s1B3g9RE9qa7zLBIM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.88.2/go.mod h1:tW9TsLb6t1eaTdBE6LITyJW1m/+DjQPU78Q/jT2FJu8= -github.com/aws/aws-sdk-go-v2/service/s3control v1.66.1 h1:E2w689yRS6Goe3khBmlBrJvH1EdXKRbPajF28qvlus8= -github.com/aws/aws-sdk-go-v2/service/s3control v1.66.1/go.mod h1:R+UodcuiGX37eSCau+g8HfeOU8eINOYBmUF5F2Bh1K4= -github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.5 h1:F1yNtV8GCt4R1sN4eM0HxS1g4yFypBdN1jg8f8Y7wdI= -github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.5/go.mod h1:o9uktj0GTuXRPjzlf6LL8bYe5Maf/2efObAwtqBanhI= -github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.4 h1:unOY5Zy8JPGTto/ceP+fWbBRJbR+nv0iVmgQxzhl/MU= -github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.4/go.mod h1:n67J7pPexZgufeaQNdYrEugPZAWB5cPo7T1Z5aiZAN4= -github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.7 h1:gCinGWsye9fd57h+ZUrqJU2D0HEVwAOa4Y300Hilzwo= -github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.7/go.mod h1:gWGWfs4Firg447Gr4VnPcCpGzof+8+HEQTmJJGIj2nM= -github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.2 h1:3PzLhyagzne3V9s0lcYr9rwqmhFMuwa3IboGUai+s58= -github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.2/go.mod h1:nEk9o0OcHc6ZtCS9hYSHdnMVzUZLVr2M6VeWpKA7NQY= -github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.4 h1:YMt6+3drr9IcU4SUyG7O5+kIEjbR17xhis7QyGelHcg= -github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.4/go.mod h1:X026FtKGqEZm6e5Cgj8uus2v0EJEMU3h+YjGwUHYGGQ= -github.com/aws/aws-sdk-go-v2/service/schemas v1.33.4 h1:PHjUXL8ySNGYVl6ro54FXwu8BgdNsm/xjwySpqA+I4k= -github.com/aws/aws-sdk-go-v2/service/schemas v1.33.4/go.mod h1:z1T3zem9JVEVUsMtBoFf9CI6UVqO+bZCYAARD3mLWH8= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.5 h1:ssRo1z8FdFaoZc1AWz1R6/amdsxy56akVPql15/AYSs= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.5/go.mod h1:ut4ISJEOb5t2M1DNfx1787tF3UJGlwF3Q97uEulV/lU= -github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.3 h1:6o8+ze30fwnc4V/nhto/0fBYoiws9v78g7M9LbqofrU= -github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.3/go.mod h1:OGz8b7RoqQTdMhzy5fdiaRkOwyOV0yEg/aO9uAnkb+I= -github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.5 h1:JBJfUR1njXvmK9d3ZqC6K3WkttWAkbRf7+9XoIaPy/E= -github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.5/go.mod h1:QOVKb80l0cIaF3MwnX4V8rnHwHdnBJSC8jYGxeP9Bfs= -github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.5 h1:MVnXAF5vPF26AkAe+Fo6z78Oou8E0bZ+ms6hT/u0hoc= -github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.5/go.mod h1:qGotrkSA9OGOZVFQWedkzOzLDGcrUT2EnbCWCivBGX0= -github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.5 h1:ENz/xNI5OSdTobZSyfTxlXZlMS23/tH/sFVTl/Wvwuc= -github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.5/go.mod h1:7W1TBwi28cH8groqlEvrmXU/ezEIGG09HjBBsmGDB+c= -github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.5 h1:zsPa71rrBoG4oc60Nc9jmvNwQnwX5rMZZUzxAR3nIXc= -github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.5/go.mod h1:zQylvlg2uShkf/uj9nrOmdbwBH4+jGfvzDAeH6zQlq8= -github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.8 h1:iu7ZfkC7lZbkLFiiJ3Znl/YXuKNk3XTmwYMHaXXsPUo= -github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.8/go.mod h1:gcmimEFXc7ksrkBtLR2f7JYT9ANpQanofvwP1bq39Sw= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.4 h1:TJYHJY/TEOtWAyaI1p00lGRPQXx6DPLLmna8BjoCwrk= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.4/go.mod h1:gtv4gMhWF+201MWqog46V/fNHgUSddtt9IU6qYgZ4CQ= -github.com/aws/aws-sdk-go-v2/service/ses v1.34.4 h1:0GQy17zYn0U1CHXLh9rEbPZW3zSusSqiGbVBUYDJ2qs= -github.com/aws/aws-sdk-go-v2/service/ses v1.34.4/go.mod h1:NS7mQGFRialwnzHj/bVn8eurbcAGM4xKgPiIk/rwri4= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.4 h1:0T0pWRMBsWSP32FvuCmK/p7ufoEZitS+PODM3+aOTKA= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.4/go.mod h1:yKXc38qs9onyyKCBnH0QFkozi96GqVZGu6//HwpqMP8= -github.com/aws/aws-sdk-go-v2/service/sfn v1.39.5 h1:/HaGWiHdPxAxgwsYY+ZhEz47IOjcQcofFNk7Gd3yLbY= -github.com/aws/aws-sdk-go-v2/service/sfn v1.39.5/go.mod h1:OEmM4ipS3JRTTZxoU8TOLHirsqNHifZUwNciT76xZQ0= -github.com/aws/aws-sdk-go-v2/service/shield v1.34.5 h1:n7OaaYO5Id90TbZStXxd10ZHgzJP/dsmVrUkTvnX7f4= -github.com/aws/aws-sdk-go-v2/service/shield v1.34.5/go.mod h1:5yZs0QTVUBzFVcdmznzUlhvnJFe6ByjGa0L7X71GaRo= -github.com/aws/aws-sdk-go-v2/service/signer v1.31.5 h1:CPMtYBeWQ6SHfp47/6VnA6MoNs4OQDetNqt3/Nf7Z5s= -github.com/aws/aws-sdk-go-v2/service/signer v1.31.5/go.mod h1:wn4LhsujYbBhJyfdeAsLFJmuBGH3Ux6SodfoBjh0r28= -github.com/aws/aws-sdk-go-v2/service/sns v1.38.4 h1:MkaMcZGwW9vt0cW+N2i5JSF/zkxKyDqpGCP1VWip3YM= -github.com/aws/aws-sdk-go-v2/service/sns v1.38.4/go.mod h1:S0rwG+VHP1/jKoT6xJDe8f8Apz9HO42dUI8DmnOzYYU= -github.com/aws/aws-sdk-go-v2/service/sqs v1.42.7 h1:KZldI+77SMG8vHDE55HYSjPcKSeOy2WIRo+HtIz2IY8= -github.com/aws/aws-sdk-go-v2/service/sqs v1.42.7/go.mod h1:wbgNsM9psd+xQtLSDUAICjFCT/HXNZIgx3qyjqQNt88= -github.com/aws/aws-sdk-go-v2/service/ssm v1.65.0 h1:6bPuMpky+qG4L7VQ1RyYVkBrEix1JRC/JPweTRfRDko= -github.com/aws/aws-sdk-go-v2/service/ssm v1.65.0/go.mod h1:mbnkxOJSgkV4YHA5dWSlLolvC1EuxNcaGfn0Gf4e9UU= -github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.7 h1:kz/8Mw8HrNrGlZjh5LIGMNeg/h7wtFMu/zXzbNEJ+z4= -github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.7/go.mod h1:gNXImFj9hXsjX5tgtgH+3GAhzJ1gkwXKVl8cu448dVA= -github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.4 h1:HT2hU7SaHSz7RINT8vRz++MEdDUGvbrrBEOiDtIleQ0= -github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.4/go.mod h1:pdKXsrQEqtzcuFgy/9dbDBCdznCECK0fs826ODHAaD8= -github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.5 h1:joNgSFjCVcqO4ChehYL1g7P8zC3WfjD0lggqFyVbUlE= -github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.5/go.mod h1:H67jYNIX7T7SLe5iZVDMwAtoA8TabGpFW2f/NrPUP0s= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.4 h1:SuE/GiqX4BmG1RJ/SXCuiGX6y4XP4tRkAGSn6wpmgPQ= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.4/go.mod h1:ixryFI/P2+QSLHiT2KLmg1Fl4uZ+SZe9Hj+YdRFMNgg= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.4 h1:FTdEN9dtWPB0EOURNtDPmwGp6GGvMqRJCAihkSl/1No= -github.com/aws/aws-sdk-go-v2/service/sso v1.29.4/go.mod h1:mYubxV9Ff42fZH4kexj43gFPhgc/LyC7KqvUKt1watc= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.0 h1:zW0XCIX3weYJpbbE+8GIWK+ewISjcm9XuItb/+90UDc= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.0/go.mod h1:33Y0SLyIseFE7x9sk4TwQTGZLvKCEoQNMaBIyRc6S8E= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.0 h1:I7ghctfGXrscr7r1Ga/mDqSJKm7Fkpl5Mwq79Z+rZqU= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.0/go.mod h1:Zo9id81XP6jbayIFWNuDpA6lMBWhsVy+3ou2jLa4JnA= -github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.5 h1:66xiSm2c+yKfW89ZCuSUGSpjhlXrnnujYVzMTvlBn9U= -github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.5/go.mod h1:h9W8UyJy3tqo2JUZJKDCzms5P6nAdfctF5AE6wbih8Y= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.5 h1:+LVB0xBqEgjQoqr9bGZbRzvg212B0f17JdflleJRNR4= -github.com/aws/aws-sdk-go-v2/service/sts v1.38.5/go.mod h1:xoaxeqnnUaZjPjaICgIy5B+MHCSb/ZSOn4MvkFNOUA0= -github.com/aws/aws-sdk-go-v2/service/swf v1.32.4 h1:8Vir3v5ofhVSyq+uQsZbhHv5gDmeFB8MOHOBbBTQtic= -github.com/aws/aws-sdk-go-v2/service/swf v1.32.4/go.mod h1:Dn78lVa2sYo1frnLV2Y/VGjPf1cU2AZaXbCskYmRGgM= -github.com/aws/aws-sdk-go-v2/service/synthetics v1.40.5 h1:QFbPjZPYsHIvEfH2IgmmJ5RKLzcxdYAFom2NDtdH9Wg= -github.com/aws/aws-sdk-go-v2/service/synthetics v1.40.5/go.mod h1:UY4GoG7FjIRXEFEy1xI8C2tfq50rwbsmIS3sf5C7pn0= -github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.5 h1:aCsvthnYzQUhclNnOnY6y98GE/5QcSDiJKnZ/O6cM8E= -github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.5/go.mod h1:hEQ9Hci23FipEndGjVf13gKknP1iou0u8v+YZyFwzfE= -github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.5 h1:ULU5NJasc33+18uhZCaxfnENf5S9u8fmLWGtpoR/cng= -github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.5/go.mod h1:UUCLRjt77Mi12nID7LOXKiaHp7tBlS8QSLNNNHv2YVk= -github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.4 h1:jBCvWkHfU0CDXr88Jk2iDP/2w/Ix7N0yoW5JRXHWb4I= -github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.4/go.mod h1:csNEYpo3KmbQvPBGvSvOyRESGHhWn4H2dnuhYTGBH94= -github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.4 h1:lCEmLYq7SKuAovCyT2tVVaRuYvuq/DCOBIiEYhUNiYw= -github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.4/go.mod h1:xzj/HUCYOPwWxjymulevwAu5aEd14h1DbrgD3xcmpE8= -github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.5 h1:+53FqSqWDrlmPr784MGo4uOMS21NJwUJVGtdliCb9tg= -github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.5/go.mod h1:Z72GfN19PJCKpKKQU7/9Rj3dzcK9EScyUj5xd4GwqOc= -github.com/aws/aws-sdk-go-v2/service/transfer v1.65.6 h1:gxMSPqweeuO+f/UswVu13fLU/A5NGilUascqtivEwbU= -github.com/aws/aws-sdk-go-v2/service/transfer v1.65.6/go.mod h1:G3NKnR/n/5iL2FX3ETW10cDnMcs21yaxCgbFoOq8EYU= -github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.3 h1:gArDyF9h3/Ae7cjsaCeb27qrfQ2TTZpXeFQnTOc8rOU= -github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.3/go.mod h1:QhnmLIvllivoSp0DNBF2rJwKrZqSCUhlbF5aHOkTl2c= -github.com/aws/aws-sdk-go-v2/service/vpclattice v1.18.4 h1:rSH+7J2CYam9KjTnP/McEBXGKek3ZKmPIjxzbg9JccY= -github.com/aws/aws-sdk-go-v2/service/vpclattice v1.18.4/go.mod h1:8kiKl6iX78tF/zC2Xre57+tIzyqUgss5EC4XTYbTGsg= -github.com/aws/aws-sdk-go-v2/service/waf v1.30.4 h1:I8iRy0FZaIzvKQbYd+so9dwHjfTH7gJStIto9jVdyGo= -github.com/aws/aws-sdk-go-v2/service/waf v1.30.4/go.mod h1:lX0RUUJZv3o0i7eJpOb5v8U/b1nLXOSrDw+5IDfeQ2k= -github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.5 h1:IsxWqce1g3oinoU7IrhMLHBC9fjU2bsa4a9uB+04ZXk= -github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.5/go.mod h1:cXlfX/JQZm571jLbsJ2KwSkWNL519cIuEGvHRhE00nU= -github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.6 h1:/1GODXDwDC0VajRPSOM7WEB/lt1nHf4EFGq3tek1mfo= -github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.6/go.mod h1:q1Vkk7vOGe+ZOVoAPF40G79KmvIA4PUopJX7MoX02wY= -github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.5 h1:edH2U4T6OVZ3oSF1RQJd5uUkYT5qXsv///5eNbjtctA= -github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.5/go.mod h1:MH8WKWPx4mST1eiSCzfnbM/WnbYAYBjquREGQoXiw1k= -github.com/aws/aws-sdk-go-v2/service/workmail v1.36.3 h1:4fr59LE0V+wHppPzH6KcXnPjYsTnSrOmLfg0fCesPSo= -github.com/aws/aws-sdk-go-v2/service/workmail v1.36.3/go.mod h1:CxGZ2aCZsgLJ5joHnUdydAZnGseF8J+k9Q95dQmslCY= -github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.5 h1:csqxgZrn2tPvnasMPNxIaLCTy6lSXAPMYGks7JkrvzE= -github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.5/go.mod h1:xNd6H5yqIyFcoOwDuJZjR0o6doMVIABzTJ/s6KpVnok= -github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.5 h1:niTF0DKSzYbSwHbqvfgkTGDjCc4KS9AomYar+FtG4Q8= -github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.5/go.mod h1:oOqgO8CM0jBAailzE/c7Y578WoNGZkge1MW/HZ3M0Co= -github.com/aws/aws-sdk-go-v2/service/xray v1.36.3 h1:4EA/KYvUBptDbTt8aWyyasx8ae4ofSkwX4f2EEG3y7k= -github.com/aws/aws-sdk-go-v2/service/xray v1.36.3/go.mod h1:Gb+Fn+VUhd4TJvFpqn7l/+ny0suOK0IZAA+eE7+9oGo= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.9 h1:by3nYZLR9l8bUH7kgaMU4dJgYFjyRdFEfORlDpPILB4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.9/go.mod h1:IWjQYlqw4EX9jw2g3qnEPPWvCE6bS8fKzhMed1OK7c8= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.9 h1:7ILIzhRlYbHmZDdkF15B+RGEO8sGbdSe0RelD0RcV6M= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.9/go.mod h1:6LLPgzztobazqK65Q5qYsFnxwsN0v6cktuIvLC5M7DM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 h1:5r34CgVOD4WZudeEKZ9/iKpiT6cM1JyEROpXjOcdWv8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9/go.mod h1:dB12CEbNWPbzO2uC6QSWHteqOg4JfBVJOojbAoAUb5I= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 h1:wuZ5uW2uhJR63zwNlqWH2W4aL4ZjeJP3o92/W+odDY4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9/go.mod h1:/G58M2fGszCrOzvJUkDdY8O9kycodunH4VdT5oBAqls= +github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.5 h1:1bnvwYxuKCTMiF/MavITDTRnCCOdCbmNWyFbfKMw2wA= +github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.25.5/go.mod h1:Ok83qcqfCvpkKU655IHorvYG0NMPr30P5H8ng9uNaQk= +github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.8 h1:rdiHnyg2/1Wu3/BVCY0o4a5RGs/bF5NTjqscInYWGJ4= +github.com/aws/aws-sdk-go-v2/service/invoicing v1.6.8/go.mod h1:TniL6d9prBubA9ZcfCJo9Q9r2cyh2c4C9csZMUDYuBw= +github.com/aws/aws-sdk-go-v2/service/iot v1.69.5 h1:ufbRtUcNLpfKjE4MXGnqNwF2gXh5s9CUlgfL3nDyd5I= +github.com/aws/aws-sdk-go-v2/service/iot v1.69.5/go.mod h1:xkUGPoYRFoe0i19cUfIMeocCOWG5Ona7MWMeMqqL8eE= +github.com/aws/aws-sdk-go-v2/service/ivs v1.47.6 h1:L4uWqGDzaapkNiPW1LUnHVGkrjynMG5vyGeu+YATgio= +github.com/aws/aws-sdk-go-v2/service/ivs v1.47.6/go.mod h1:i6n4c/4w7kw455UViuMob7/0YoWB24uXkzal1udFz8g= +github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.5 h1:pwetfaLlSr67dBmlJtVNUsBgSdOzk02NfAo1MDqhyQM= +github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.5/go.mod h1:mbBWB0NzEUOjY8FarIsbCWo6DXqylv1mf+B77uT/xlQ= +github.com/aws/aws-sdk-go-v2/service/kafka v1.43.6 h1:gd9n9V4YTRcg5VJfDYBRVJHQBaUMpbKOKWzAhHzyhcA= +github.com/aws/aws-sdk-go-v2/service/kafka v1.43.6/go.mod h1:061TSd3Z7fxrRzFbo8VniS3VErBjATTfC7+HsSUW11g= +github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.5 h1:6lT7GqiBAkuL2bPGUjJDqm4DoPpRom/BhvIokHPLPB4= +github.com/aws/aws-sdk-go-v2/service/kafkaconnect v1.27.5/go.mod h1:Z9w9e4XGxePy+tPjsgNKYiJZXPTFysEbKqpc72dzhO0= +github.com/aws/aws-sdk-go-v2/service/kendra v1.60.6 h1:rGhNWcIhP7DqFve8zlZItzX8UslsM26aSCRTC6M2hGs= +github.com/aws/aws-sdk-go-v2/service/kendra v1.60.6/go.mod h1:3Amyw8Cu+M3VliBNu6PkOvVLLGS9eyzmkwBBYIygr60= +github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.6 h1:VvcHwWDWJs6sbM62LI1UKo3ONVBXSP+sPiYduTOZ5Ug= +github.com/aws/aws-sdk-go-v2/service/keyspaces v1.23.6/go.mod h1:YjFnZVw57O46J972EzA4Ny7HObGqymOoFCymCiLXdDE= +github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.5 h1:GWAVIxhYlkFX76WGG2gus5eyonXaKPv00VpiSqHzXDo= +github.com/aws/aws-sdk-go-v2/service/kinesis v1.40.5/go.mod h1:u/oFMSASsn9QNBRop5lrIpuNwHZwEXjYxNQp7sHFSxc= +github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.6 h1:OL3s9Y927XoMxO4Jod29/eIl1vyS5NDnDesJaLkhjeE= +github.com/aws/aws-sdk-go-v2/service/kinesisanalytics v1.30.6/go.mod h1:1szjTKn1bM+Ce2Pf2g57WqudQXi+YZodbrYMZY2Awzw= +github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.7 h1:lePrOEBRe3FMsApDx6QNfiVsUR0ePYdeE+KkIMM6vp0= +github.com/aws/aws-sdk-go-v2/service/kinesisanalyticsv2 v1.36.7/go.mod h1:AUtvJ7STwd00cd5mT3Vt9WH0LjF56nOWAZzPx+T5wUg= +github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.5 h1:8oO+Su+tqdsF1wll/Zm0eenGi/0lXQljG5sFerZvFXQ= +github.com/aws/aws-sdk-go-v2/service/kinesisvideo v1.32.5/go.mod h1:Mu9FDrPD7xsAZf9KhiL+WFEtnEgO7x6Kf8OJceaiJRU= +github.com/aws/aws-sdk-go-v2/service/kms v1.45.6 h1:Br3kil4j7RPW+7LoLVkYt8SuhIWlg6ylmbmzXJ7PgXY= +github.com/aws/aws-sdk-go-v2/service/kms v1.45.6/go.mod h1:FKXkHzw1fJZtg1P1qoAIiwen5thz/cDRTTDCIu8ljxc= +github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.5 h1:YlhZqR9Ma0x7q83cNpis7YJ1w4u532+ohJ7MSHqZno0= +github.com/aws/aws-sdk-go-v2/service/lakeformation v1.45.5/go.mod h1:e+RSq7q4W1pe3kt1kFBWQLvCsF3LEa6YF695iPjwUqo= +github.com/aws/aws-sdk-go-v2/service/lambda v1.77.6 h1:bU48NwA1e9jFkng1qYUVQjdJFEIv0oxhDO/Zz57M5IU= +github.com/aws/aws-sdk-go-v2/service/lambda v1.77.6/go.mod h1:LFNm6TvaFI2Li7U18hJB++k+qH5nK3TveIFD7x9TFHc= +github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.6 h1:aZ8MXpLB17q6THeWkvpYVheZTf2oOMgaeXYxQLfq8vY= +github.com/aws/aws-sdk-go-v2/service/launchwizard v1.13.6/go.mod h1:5IsG5hZ0YnGeIsZvB88ALqptUB5TmyA68Vh2JtOuolQ= +github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.5 h1:ArkKQMxVIaauILktZS/FMc9u52qGpC3OSAA9AQAnvgU= +github.com/aws/aws-sdk-go-v2/service/lexmodelbuildingservice v1.33.5/go.mod h1:LRYpBu4UZPuBggAl0Q62MaDRDlDYYE/DR/Q3Nr5HnTQ= +github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.6 h1:Ujpm8Qr81ge34jboS6NQu4WK/gpuwjNQI/cW8G2w1+g= +github.com/aws/aws-sdk-go-v2/service/lexmodelsv2 v1.56.6/go.mod h1:xiuNneOma5q5l0VtLAR6MuQ3K5sJlUCz51HB0IdJgvc= +github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.6 h1:jSPCSRdv3Ad2BZtaCO3PWJQmoOe6WXqrG79IoHrTpl4= +github.com/aws/aws-sdk-go-v2/service/licensemanager v1.36.6/go.mod h1:E+dz2RTwFIOG6cKRJiln5khKJmROa6RvP7DKiEEPCFE= +github.com/aws/aws-sdk-go-v2/service/lightsail v1.49.1 h1:J1A0VJlt5HgUX6s11Obe9zrBDECeE2uhQc7Dwhdei9o= +github.com/aws/aws-sdk-go-v2/service/lightsail v1.49.1/go.mod h1:WEOSRNyfIfvgrD9MuSIGrogKyuFahaVMziVq1pHI0NQ= +github.com/aws/aws-sdk-go-v2/service/location v1.49.6 h1:hNRkhRPvAHAqZapl7BPcjls1BAnykokUkF71E0iYgPU= +github.com/aws/aws-sdk-go-v2/service/location v1.49.6/go.mod h1:aRLVKgDTnlsf0moRfee8FTWv9SghW/x3W0W33Y//ZDY= +github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.6 h1:9yP3vAUac8JYDnenwuOuPmpIRBgCVidxWN6hZvab1lE= +github.com/aws/aws-sdk-go-v2/service/lookoutmetrics v1.36.6/go.mod h1:A6750m3A2OebBhSwoXKosN5Vciq/JiY2piPsmZauiwc= +github.com/aws/aws-sdk-go-v2/service/m2 v1.25.6 h1:1pA10Dziy1XrpFNf6aND3Y43imaLL9w6U6lfMBUNR0E= +github.com/aws/aws-sdk-go-v2/service/m2 v1.25.6/go.mod h1:X3NB31GJKffp5h+SnU4aMKMarKd9Bd7jRFs2y/Ihve8= +github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.6 h1:0lg+Mhd61q16NUpxwnNpAhP7sxSOO5H5/l+QxerZuIc= +github.com/aws/aws-sdk-go-v2/service/macie2 v1.49.6/go.mod h1:hAUjN7Dlx1i1Sjbx67uumWB7iwXOA/PM8kNOiw4ygjY= +github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.45.0 h1:4cBXNlo8XYFq/leCpTVuZX2qAp779SIg3wkMPd5FDjo= +github.com/aws/aws-sdk-go-v2/service/mediaconnect v1.45.0/go.mod h1:pyFeP6f26HHtJJeNU4LqcD3R1Zh9RMwZjiluEsgZlYE= +github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.6 h1:gk0yVOnKaRKGyWifpqw3aGeEGB4EO77UYGXnucl93Ek= +github.com/aws/aws-sdk-go-v2/service/mediaconvert v1.82.6/go.mod h1:YZeaUGHZihZA8/pC2hi248p8Y8S4oPMZLXso2RF4hsQ= +github.com/aws/aws-sdk-go-v2/service/medialive v1.84.0 h1:4VnT0CicQgGzIkzbfIz9FcCvl/A25JclsZ/jkkP2sGs= +github.com/aws/aws-sdk-go-v2/service/medialive v1.84.0/go.mod h1:ZWOvuk7slOmdlSnDIY7gr00d/HUEKAYT15oPc2oMprw= +github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.6 h1:xF2FWETQbjkGKK8fcmaJ2bO7i53wwRbsnExg5uTswyI= +github.com/aws/aws-sdk-go-v2/service/mediapackage v1.39.6/go.mod h1:hSlgOOXXYOtXOH8PUE07ZctOeDR9doOvtvpM6oR7z54= +github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.3 h1:Tbh1uS0VAEw75762wftgeXlrpK2AO2tZjObiilryUCQ= +github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.31.3/go.mod h1:5w01h9/Nmf0FUimiQGY9bYPU/of1Nz9oxiGbNxzUYT8= +github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.6 h1:8QUyNYiWzhsbQJITt/v+SNwdA/wH7B8YnDO/9GLeX2g= +github.com/aws/aws-sdk-go-v2/service/mediapackagevod v1.39.6/go.mod h1:QHMKOy8M9YcyxacWIIije66JGOPn0Uv911y3QN5xvOE= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.6 h1:iafXeKlVqhC8/ScR2CzQlWzDm+B3BNcQD7SzZ+gE1LM= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.29.6/go.mod h1:pyztXbSyAGD+TmvQhGva28W3KgwEsjZ39d/tM5E3WLk= +github.com/aws/aws-sdk-go-v2/service/memorydb v1.32.0 h1:R+jvAaitNKrnuBDpAxM/Pi/1JD5cRqwL3cQolngYf+M= +github.com/aws/aws-sdk-go-v2/service/memorydb v1.32.0/go.mod h1:ls5Htz+L0oFjuS/8Md/RLSLCFUpGkvlnZ2GLZ4NZguw= +github.com/aws/aws-sdk-go-v2/service/mgn v1.37.5 h1:BMu425Ntx40waGQ0/g6BeX1F/sYvKdIcO+ABys5Jv9s= +github.com/aws/aws-sdk-go-v2/service/mgn v1.37.5/go.mod h1:F3YMviBP/8gRnYBh8j+6MUw/c3ID0l3IMS37kHAo22Y= +github.com/aws/aws-sdk-go-v2/service/mq v1.34.4 h1:Oo18RmcBezamgeYgLQs0TvQte9qnBsT/h0FXaVR/su0= +github.com/aws/aws-sdk-go-v2/service/mq v1.34.4/go.mod h1:Ix0YBjTUQkaENu7moWEIOuRPvSXCankc9G8+6tCHPFE= +github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.6 h1:E2/4c34w/DlacnWCB00i5vK84Q+R4THQekMFYKEQ6EU= +github.com/aws/aws-sdk-go-v2/service/mwaa v1.39.6/go.mod h1:VGfnBe0/1AmUklInis8fWYCsX1sytShIyJaAskYui8k= +github.com/aws/aws-sdk-go-v2/service/neptune v1.42.5 h1:tfn0wZ5FFDV8USRyR1pbwVuMjc/8lxCXGiXtj4pGP2Y= +github.com/aws/aws-sdk-go-v2/service/neptune v1.42.5/go.mod h1:31tyZ8ZVqFkyO8beZNHcEOQZGn/BkuSpj92xz0DV47M= +github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.5 h1:M6POQvRc86IBNXMGMnigORWW7TuI4DQw6w9/7a22AmE= +github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.21.5/go.mod h1:SDNZtDXmPLQgX3rhJKQilrATByCSvfefeGBzmyHWV9A= +github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.57.1 h1:ft8fBc54sf9RPLzZ9C3R2ICWlsJI7gNXzhe4KM6hcMU= +github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.57.1/go.mod h1:aR3+jhGdmzkcu69LUu3uEfWSz48rSWZpRZ1UiW1brzY= +github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.7 h1:UqDxJzpwgrEi/AuVaXCqN3g0zysr0K/RPY7kxj3kAFs= +github.com/aws/aws-sdk-go-v2/service/networkmanager v1.39.7/go.mod h1:2lpNczbmNGrUPnMa04jr4J2BxQ3jv2pYErTQlELWESg= +github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.6 h1:5MKZrK70vz0m3A/IbE00XgWdX6VARrQMe/lTtlh1VIc= +github.com/aws/aws-sdk-go-v2/service/networkmonitor v1.12.6/go.mod h1:r99VUsxYLupfRyaZ517RoASgRyspKDvj+T3Ec2bsJLg= +github.com/aws/aws-sdk-go-v2/service/notifications v1.7.4 h1:Ur4HSvZrzDevCVcXHLzj/VYKLYznFsIuXXzsqggt0HE= +github.com/aws/aws-sdk-go-v2/service/notifications v1.7.4/go.mod h1:jp/DVjlMmlD2RaRCAYs0IRy2k5XkppwVNc9wo4oYkkQ= +github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.8 h1:SoLCt2Ig7kir4Vv8VtFVqADtaE1iSrC/f2U9vVgCe4M= +github.com/aws/aws-sdk-go-v2/service/notificationscontacts v1.5.8/go.mod h1:TqON/FD1E56TNUpLtwI6m1PbjmuZRhrvbo1ZGOIbzto= +github.com/aws/aws-sdk-go-v2/service/oam v1.22.5 h1:To+7SakfElByzTR10RrFGAXRH2uWBDvMPTFOYQY0Wrw= +github.com/aws/aws-sdk-go-v2/service/oam v1.22.5/go.mod h1:huNDbI1vKiFhIuo8Q4hK09wk1kN+RFdbxrrjSsCZtCQ= +github.com/aws/aws-sdk-go-v2/service/odb v1.4.6 h1:AV9JZ+ErtkFZFJAOao1CSSPdcJzY/onnQU5K5wdiV/8= +github.com/aws/aws-sdk-go-v2/service/odb v1.4.6/go.mod h1:sNgPICtv0QshuEoMhFiRT5rBWnpXMFvLhly/Hu0MqYw= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.5 h1:gkLP1OOn0/gBPD125+Ax+9DKuGGsu9TwvbZJ4bBgcsY= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.5/go.mod h1:c1RKL9jCAUP+7ZtY+99yWcWxRFBsQ3LG5Klkj5PEoJs= +github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.4 h1:46xDV+bDfEaoI4CFYA/SASoD17PhdIfRcnybENoeA68= +github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.26.4/go.mod h1:a+I7XPLBv75d9aI6TvmcMn2osIxiZ8rxjSy/OZQQAlw= +github.com/aws/aws-sdk-go-v2/service/organizations v1.45.3 h1:JcKtlBBVZpu01E+WS5s6MerJezxVNW0arRinXwd8eMg= +github.com/aws/aws-sdk-go-v2/service/organizations v1.45.3/go.mod h1:oiUEFEALhJA54ODqgmRr3o5rZ+SOXARVOj4Gl3d935M= +github.com/aws/aws-sdk-go-v2/service/osis v1.20.2 h1:fmH/ayvn5AcQ2jnFMtbd57CwTtuOKcZLdfl3eGZP7oc= +github.com/aws/aws-sdk-go-v2/service/osis v1.20.2/go.mod h1:t3KwhHJvvtof6DJzL7JtGY4+cxPsQumV1snXgg0+aww= +github.com/aws/aws-sdk-go-v2/service/outposts v1.56.7 h1:q/y5yHOR3CmvBO7G3dQKE8IT2PrfWSorN8iP51qVOHY= +github.com/aws/aws-sdk-go-v2/service/outposts v1.56.7/go.mod h1:AX2swwJXvwgCE0695M12Vw8p/JU2PQNC/5J9ur1Zd9s= +github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.2 h1:jAVEnaD69Jhc3ePMMuKLj7Y6NNRNN4s1X/UT+SMlXag= +github.com/aws/aws-sdk-go-v2/service/paymentcryptography v1.25.2/go.mod h1:LtAy3qbryUglXiyAYdn+OCltWbMMMvYoUK6hAiFc73k= +github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.6 h1:tZK9NedvW1WYWf+eZ437hUNETq4+eofZ9ja32FtFHLQ= +github.com/aws/aws-sdk-go-v2/service/pcaconnectorad v1.15.6/go.mod h1:fRBVcoZiTYjTywau+UcyTXAjtLxz20Jsaz0XXdG2950= +github.com/aws/aws-sdk-go-v2/service/pcs v1.14.0 h1:Dk/dj8EBPQBPawPMR2M9+tijanojSdoxJDSA5clenZo= +github.com/aws/aws-sdk-go-v2/service/pcs v1.14.0/go.mod h1:wyFACwTlB5ZUiOQAqs+5m7gj4xUCbojoUTaZYxa7BjM= +github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.6 h1:6vjEH7AL5aYC49apXto1dHgMBNDdZLh2L3Bve0vkE2o= +github.com/aws/aws-sdk-go-v2/service/pinpoint v1.39.6/go.mod h1:oNyevxM/xQifmv2yk482sM2isWXgloHLrOLoeOrOPHQ= +github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.5 h1:S/QLsL7GTbrtjrALjKWdab+UBUB7LIHnEJtMvdD9khk= +github.com/aws/aws-sdk-go-v2/service/pinpointsmsvoicev2 v1.25.5/go.mod h1:TlvbcCoDxToksnKXX+nmSi70Kn0aMcPo3qr2hgbO+yo= +github.com/aws/aws-sdk-go-v2/service/pipes v1.23.5 h1:QrMb0weKCfbPmFM8Z3tHXGDd8b/g5kkbYSGELgYteOE= +github.com/aws/aws-sdk-go-v2/service/pipes v1.23.5/go.mod h1:OYOBK8E3mCVkk/6bCQk+J0R2JgLYotiBd10P07i6CTk= +github.com/aws/aws-sdk-go-v2/service/polly v1.53.6 h1:ltnQaTs2saOP3REJZlNGbujWoF0/O/uWsKtW5aRs+0o= +github.com/aws/aws-sdk-go-v2/service/polly v1.53.6/go.mod h1:4xoAju2Su1TJ1Q5Y6hxNFLb3kBzYOtgUN05dQj3VTp4= +github.com/aws/aws-sdk-go-v2/service/pricing v1.39.6 h1:SapAI7aLrvLNUCBeBhhR6cU7TFIrRC5KNeaj72hV+fc= +github.com/aws/aws-sdk-go-v2/service/pricing v1.39.6/go.mod h1:TtNWNQGg2WmSIS+j/ZqyJD3xY6zyAuYHBDGxFYQftjU= +github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.6 h1:kLTYFvi4+nsETUZpwqPcVVOfOX/lD7OvQ4aU+TSNGVE= +github.com/aws/aws-sdk-go-v2/service/qbusiness v1.33.6/go.mod h1:XxU8fY4XHMpkvrCDaylvGiaz1PSU1nntX3XasTEomDQ= +github.com/aws/aws-sdk-go-v2/service/qldb v1.30.6 h1:5FBEiFjL83odCokDLGauL1g5Noiapq8jRsqKN2/YaF8= +github.com/aws/aws-sdk-go-v2/service/qldb v1.30.6/go.mod h1:FZR8mKbaQK8xEyQmtZKEPYj6Rxgi3iLKFi7MutHzYNI= +github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.4 h1:NYaNLjesQC14fZR15t25Wws4znd0NsuvZfUWJAtaYA8= +github.com/aws/aws-sdk-go-v2/service/quicksight v1.94.4/go.mod h1:aJPu5hqpBhcV4gXqbAuZhBiIZ+dXHrvJ176qTPADa2A= +github.com/aws/aws-sdk-go-v2/service/ram v1.34.6 h1:S/BivEPJDOKDEaLQuodznRu/9VscK2n24Oi464ySkao= +github.com/aws/aws-sdk-go-v2/service/ram v1.34.6/go.mod h1:IjW9GK9av7d2rdmmi3uze2erokbWAxUtMwDc1YOj+9M= +github.com/aws/aws-sdk-go-v2/service/rbin v1.26.6 h1:wKVcl95mVcHW1rJMsf5SsA9T2zrfOmC5WyDrqpFVnVE= +github.com/aws/aws-sdk-go-v2/service/rbin v1.26.6/go.mod h1:LCbTwbuAosB0UYOB4eMr7CmzwKPaO5ZD+UXEhJ6TPn4= +github.com/aws/aws-sdk-go-v2/service/rds v1.108.1 h1:Felh4W55+rsAjcg+EsRUdCWxXXyy3N9UJz4Ej5tLCC4= +github.com/aws/aws-sdk-go-v2/service/rds v1.108.1/go.mod h1:VOBL5tbhS7AF0m5YpfwLuRBpb5QVp4EWSPizUr/D6iE= +github.com/aws/aws-sdk-go-v2/service/redshift v1.59.0 h1:MtE4oUVeljvF2CWPZwzWERizY5uhZV7os1eJC9oA8BI= +github.com/aws/aws-sdk-go-v2/service/redshift v1.59.0/go.mod h1:ARgrCFhclWArEevJ/GAn+UBBVc9+f9oFurQlyjx262I= +github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.6 h1:PC5iIPcOwMMqAocH4fuiyLKbEOKr9t75zhp7yysK0NY= +github.com/aws/aws-sdk-go-v2/service/redshiftdata v1.37.6/go.mod h1:u8BCO9VvZZqxHaCk4i17Js9WSGR45KPN35k/Gi79hng= +github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.8 h1:YJixVrWNAJYfCXcMVMppPA1RQaPtZ0oXGrLDRf5FHIU= +github.com/aws/aws-sdk-go-v2/service/redshiftserverless v1.31.8/go.mod h1:1T8W8J3Xiwhtikj4yLUXTFwOB6cWvukAzncJUV9A5uw= +github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.5 h1:7XEUHyj3NhDxz8ogR9Zqj8SRA/5J2OJ+u4lpGu+qmJ0= +github.com/aws/aws-sdk-go-v2/service/rekognition v1.51.5/go.mod h1:2lepPReuRVIackBiaSO6c5ch3HXIROzHFxCCpMQgKJc= +github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.6 h1:LvBVCmxDLAp3tNkAXNvedPjNw2DFJ9W0mwOpbkjaSUE= +github.com/aws/aws-sdk-go-v2/service/resiliencehub v1.34.6/go.mod h1:ZBunG0PHHt5TwsVfGyDpPtAeqmCnlo8SjVRsS/me+5Y= +github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.22.0 h1:+vdGkeg7koJ0MtMui392lmmF2gKISzqiUryQuq8HumQ= +github.com/aws/aws-sdk-go-v2/service/resourceexplorer2 v1.22.0/go.mod h1:WeUb0leMU6VjQkjVzmUa/DBuqgaMCgcaWoWNJy4Hg5M= +github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.7 h1:aJEEtqhpU2Vr2zFQ6jJT3z6ryqNSJjQ3UqEUKIsCdU4= +github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.33.7/go.mod h1:RD/9wH7u81Og53+2Vt7qAOA6PstpLcyiud5wCv0R/ds= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.6 h1:c1gIOTNJ6gkocnL33DP1St++uv+f7ClFiUjR5/Pm40o= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.6/go.mod h1:KJZ2lPXqxMULgTX/ldDAa2WeLAR2qz7vGqLEJLCP1RM= +github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.6 h1:1n0OZvoccoCuMn8GYI8/A78sWc0NKc3VTgTyO3fmasY= +github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.21.6/go.mod h1:+X3mqbUeamf2ANy4ppudqH0s6tuH2pFl04Cq8gFAikc= +github.com/aws/aws-sdk-go-v2/service/route53 v1.58.4 h1:KycXrohD5OxAZ5h02YechO2gevvoHfAPAaJM5l8zqb0= +github.com/aws/aws-sdk-go-v2/service/route53 v1.58.4/go.mod h1:xNLZLn4SusktBQ5moqUOgiDKGz3a7vHwF4W0KD+WBPc= +github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.4 h1:mQ7ZPMQ2Dz4dl//dgMOWmApKXGZ9f9cHza7Qh9tnqSM= +github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.4/go.mod h1:7q323bgF8xAtY1+rN/WVtUsbtSPZWWOVsIID9zAI5KA= +github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.6 h1:Tx7z/TsZ+OdtDtUeZFrzAU//NhnFMiGRxeAEEeTIZOI= +github.com/aws/aws-sdk-go-v2/service/route53profiles v1.9.6/go.mod h1:d46EQzstY7ltSyackMoYMJGzq+TrF1RYr3DU15t0mCo= +github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.7 h1:JztKalb2lLUv07Ls1J4ePVmg0RUgyRBx1/k8maIkawE= +github.com/aws/aws-sdk-go-v2/service/route53recoverycontrolconfig v1.31.7/go.mod h1:PJXGu3IjcUbdL8taf9Zl9vB6ZmigpjAq+gFz6hDBmGc= +github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.6 h1:dT53/rvqKgu4MMOzwhv6HVtxgrWp9SgYwkviQIBbmeQ= +github.com/aws/aws-sdk-go-v2/service/route53recoveryreadiness v1.26.6/go.mod h1:6d6uDK4yLgR+5jLqWdYejxBE2yS5NV/4FrOmNZclrm0= +github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.6 h1:lhnQ2Nkm3liKRxl4j3A18DYzGkxaixaSNF0fgXhtZDI= +github.com/aws/aws-sdk-go-v2/service/route53resolver v1.40.6/go.mod h1:hFCmtJyNyNNKxzX43Skr+l4JTpV/w8x470hIJBedcO0= +github.com/aws/aws-sdk-go-v2/service/rum v1.28.7 h1:WD3KNbMhPNIo6NeWIKvH+JyB+nlxA+3FP8T6AeoC8zY= +github.com/aws/aws-sdk-go-v2/service/rum v1.28.7/go.mod h1:d1TetEj0rCx4wEye6LeIjDCgHUkIIS/6cXu8UaI1aP8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.88.3 h1:P18I4ipbk+b/3dZNq5YYh+Hq6XC0vp5RWkLp1tJldDA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.88.3/go.mod h1:Rm3gw2Jov6e6kDuamDvyIlZJDMYk97VeCZ82wz/mVZ0= +github.com/aws/aws-sdk-go-v2/service/s3control v1.66.2 h1:/ZonyP9GF0PKVTCLvnce+muPdS8REakUTHwkP8cyFFU= +github.com/aws/aws-sdk-go-v2/service/s3control v1.66.2/go.mod h1:m5ZEef7/rUTT4ed1B22b+MhYKWnp8Qkj4iIp465G6J0= +github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.6 h1:ISvhq3XY67cCOhHQNuERigQBjUNkr4gjM7f0MFRq9P0= +github.com/aws/aws-sdk-go-v2/service/s3outposts v1.33.6/go.mod h1:rLtMvFVwJRG+in5WrAQxgzDU2KBsenSsNrpLbRa0Xrw= +github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.5 h1:lvhu7h0CC9vsL0kxghR6OeGJwF5VsXDHfeGEAwl6XWE= +github.com/aws/aws-sdk-go-v2/service/s3tables v1.10.5/go.mod h1:ZPE8QxN4+WylqmPew7p7G+J+h1qQo/pbBNLGKr/GJ/o= +github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.8 h1:ERb8DDNjGcCkDHblpHkSNzEs1ONBk+rCITYA6z+Yd1w= +github.com/aws/aws-sdk-go-v2/service/s3vectors v1.4.8/go.mod h1:gSvTmSFxwjt2k+U9eP8LQpR3sDYpwA/desV1WjaEGJ8= +github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.3 h1:7QukmIiqAnEoVfduk36whgv8YGtKjcZc1hilfxZxqYQ= +github.com/aws/aws-sdk-go-v2/service/sagemaker v1.215.3/go.mod h1:BSg+goTRoWiHkPwaU91RjaWtCB4+BAcbj6X6Ihvs8I8= +github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.5 h1:QaBANQbMZMyyZ8UmuOaa533NCkgjtwuKyfJqd6fziUQ= +github.com/aws/aws-sdk-go-v2/service/scheduler v1.17.5/go.mod h1:9ulCU1KqL8XYYCu7Zj15WB2lSlSAb1sDzmwVl9LuMGI= +github.com/aws/aws-sdk-go-v2/service/schemas v1.33.5 h1:f94foSb0xp3flzTDe0qHRl/kwsp5RnUvMGH9jYophXc= +github.com/aws/aws-sdk-go-v2/service/schemas v1.33.5/go.mod h1:StI8kLU7UqwT4GUIyHwd4cmLXxglmNbT+faOZltSlA4= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.6 h1:9PWl450XOG+m5lKv+qg5BXso1eLxpsZLqq7VPug5km0= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.6/go.mod h1:hwt7auGsDcaNQ8pzLgE2kCNyIWouYlAKSjuUu5Dqr7I= +github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.4 h1:56LRTpQSA6dqo2inwUwICUgnlCe3kAddCOhWggdDsYQ= +github.com/aws/aws-sdk-go-v2/service/securityhub v1.64.4/go.mod h1:whhpbyK81XOJWOiCmN4SbYv3X+kgNlMgHOQAnEMRXsM= +github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.6 h1:HDDXTIW91VHxTgu+05f8n5HzJrDAUDqbjX1v3H2KV9Y= +github.com/aws/aws-sdk-go-v2/service/securitylake v1.24.6/go.mod h1:MY0oQdCHOaepsEJoN/WoaCHNoksmhrBrBlDvjUQYJmY= +github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.6 h1:70PEH4oDsU+YER8KUfSedHGlRBVihtcXxah3rokT9S0= +github.com/aws/aws-sdk-go-v2/service/serverlessapplicationrepository v1.29.6/go.mod h1:spm5LxERJz0IOpYf9fH6lBDDGgB3OXSwrV0Oj+fL7xU= +github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.6 h1:ZGvb2y036q8v5bZhuqzmDnqdpo85u/3/B+9NnbYPcXE= +github.com/aws/aws-sdk-go-v2/service/servicecatalog v1.38.6/go.mod h1:eNS1O7ALYB0n1K6UJASh8kgw1KYGg26wHxx35VZgjFs= +github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.6 h1:OFmbZQixBI0tnwxxoiZtdlGZSOqaOHq7wkxJGLcOIsk= +github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.35.6/go.mod h1:zOpRzlMssUTM/YZ/JVuztNnGUMGTvOUHTCtyLEtOUnU= +github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.9 h1:snXikqd2A2wiFwFoEjWVLE1p2hbRaVkSxHCcV/vxibg= +github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.9/go.mod h1:D+QXio/b/Fxee/lnsYvajiEuWcPzCIc2B04YzIHX0/M= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.5 h1:yaKAIVuVWtqDkiGV+gQKYt6gfYxbcnbfL5lv4lEawU4= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.32.5/go.mod h1:OzKW+2JATYOrFN/hai+5/4SezjqbEeLeZrQqNPLPe+s= +github.com/aws/aws-sdk-go-v2/service/ses v1.34.5 h1:NwOeuOFrWoh4xWKINrmaAK4Vh75jmmY0RAuNjQ6W5Es= +github.com/aws/aws-sdk-go-v2/service/ses v1.34.5/go.mod h1:m3BsMJZD0eqjGIniBzwrNUqG9ZUPquC4hY9FyE2qNFo= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.5 h1:ZHBssvFtrtfNCm5APnzFrkdCX4KPDKlSGZ2NbfPmISY= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.53.5/go.mod h1:eJP5lLTdqKwiQB5mKKaSjjJlLB0xcT3pTFF576PbdP0= +github.com/aws/aws-sdk-go-v2/service/sfn v1.39.6 h1:0kpMhSSBrZmYeeKmyM4RftA4XeiC0PDVcbUg3gXNqfk= +github.com/aws/aws-sdk-go-v2/service/sfn v1.39.6/go.mod h1:XyrAUQxv//wWMFyh2mvvTZL9vaYdpjM3Rg5A5QOFOaE= +github.com/aws/aws-sdk-go-v2/service/shield v1.34.6 h1:AWKt4pVqiqzLIT3xoOThd0xT6dY1lSB+7yDcn0N3I48= +github.com/aws/aws-sdk-go-v2/service/shield v1.34.6/go.mod h1:Io5NYTndCqsmL+vdfoQEkInZkbZn8gLloqEjGvng+7M= +github.com/aws/aws-sdk-go-v2/service/signer v1.31.6 h1:TnlG33tsUOBnu7rMicF8YFIC0pxkJdBJwo2R0W5L6Fw= +github.com/aws/aws-sdk-go-v2/service/signer v1.31.6/go.mod h1:a6U0A/LNWknEIS7Fmf4McuUwImMlo6qrKkhbEpSczP8= +github.com/aws/aws-sdk-go-v2/service/sns v1.38.5 h1:c0hINjMfDQvQLJJxfNNcIaLYVLC7E0W2zOQOVVKLnnU= +github.com/aws/aws-sdk-go-v2/service/sns v1.38.5/go.mod h1:E427ZzdOMWh/4KtD48AGfbWLX14iyw9URVOdIwtv80o= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.8 h1:cWiY+//XL5QOYKJyf4Pvt+oE/5wSIi095+bS+ME2lGw= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.8/go.mod h1:sLvnKf0p0sMQ33nkJGP2NpYyWHMojpL0O9neiCGc9lc= +github.com/aws/aws-sdk-go-v2/service/ssm v1.65.1 h1:TFg6XiS7EsHN0/jpV3eVNczZi/sPIVP5jxIs+euIESQ= +github.com/aws/aws-sdk-go-v2/service/ssm v1.65.1/go.mod h1:OIezd9K0sM/64DDP4kXx/i0NdgXu6R5KE6SCsIPJsjc= +github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.8 h1:Nqsc8EhmXUwGCLLxB1cCt/8sDyVUDaS9zpkXyd8zcD0= +github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.30.8/go.mod h1:AGjoKT5weHZ8oo4sFEorNVKsg9noEmEBiXsA5e9veEE= +github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.5 h1:oGUMJl6Wf7vZWiaCRE4MPjtnet6aEjnpF/1WxoKlJ+A= +github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.5/go.mod h1:5TeCNbB10rN3TUR7NWFdRWFLfrjebhMvvE0lQKS30aE= +github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.6 h1:sGhOo5CZV1QV1gsAcrwXJVm2EcVaTCVLhEIr29eaihA= +github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.6/go.mod h1:Y07XpBl1TPJFFfYf4OD1PPmui8rFba8k2u3gAH1H5YM= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.5 h1:D2bijFgTDf26Oizhsj5X6X1B8ibIaZVHgonPeLnNTlQ= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.5/go.mod h1:11+FpRI0DIr3RuA3pRCDwVA22LP4vymQB7MCTMCApKw= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 h1:A1oRkiSQOWstGh61y4Wc/yQ04sqrQZr1Si/oAXj20/s= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.6/go.mod h1:5PfYspyCU5Vw1wNPsxi15LZovOnULudOQuVxphSflQA= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.2 h1:4O5fAx9BpoX5c+5BxUgOLJM7kS0K20JebxzLzfu+JIk= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.2/go.mod h1:7iR/6+xIFUPl0LnAZ0RSBQ4A4R6CyA7WrxKyB9QncWc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 h1:5fm5RTONng73/QA73LhCNR7UT9RpFH3hR6HWL6bIgVY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1/go.mod h1:xBEjWD13h+6nq+z4AkqSfSvqRKFgDIQeaMguAJndOWo= +github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.6 h1:fkyLQiPCNKi7eerHV4m+uM4ljlw6BQjQW2sLh4xVaew= +github.com/aws/aws-sdk-go-v2/service/storagegateway v1.42.6/go.mod h1:e5HFdmxGXdN1LQ/a+twPR3PuQyvI/aPK38MWVU17QHc= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 h1:p3jIvqYwUZgu/XYeI48bJxOhvm47hZb5HUQ0tn6Q9kA= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.6/go.mod h1:WtKK+ppze5yKPkZ0XwqIVWD4beCwv056ZbPQNoeHqM8= +github.com/aws/aws-sdk-go-v2/service/swf v1.32.5 h1:uGf0//B3vB5y2gqeP7qUtyKh8A+MrhWgGXlisdsCCsk= +github.com/aws/aws-sdk-go-v2/service/swf v1.32.5/go.mod h1:jY8XhNSBjSezBEJA5pEM9sW7nqBc6EDmHwIJ1hj5pq4= +github.com/aws/aws-sdk-go-v2/service/synthetics v1.41.0 h1:PhrW72CcuCEhPNItPyE7eO/gE5fx4QJiNQ2Hwo6gqRM= +github.com/aws/aws-sdk-go-v2/service/synthetics v1.41.0/go.mod h1:eCpO7DjOFxysY+P8dEFJMWCTnpMLt7IGbIhSk5yHDMA= +github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.6 h1:RS2HB6ey9KpPETo2pWoPNcedvZY6E6+TETJ+3qHmrVA= +github.com/aws/aws-sdk-go-v2/service/taxsettings v1.16.6/go.mod h1:f2PHOYOjNlFxzDo6eR6Zf89XmUancu6ORaoTVURTY7g= +github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.6 h1:dVOI+vU8QsWJba4VfeZlNObkL76HlZQRjts+HqgfqcI= +github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb v1.16.6/go.mod h1:7ObjtSvjDRJVBRhd9zxh6kgxYMbA9vtBQ24+RNjUdao= +github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.5 h1:ivzKU64lfi9F5VwBLIEcoqQMtXKrn7iUHOmhU8I88pA= +github.com/aws/aws-sdk-go-v2/service/timestreamquery v1.35.5/go.mod h1:cSU9wIi0AjMmlo0ydUD839k1yh7fNnTdCZokIwol5Qg= +github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.5 h1:BjJ8HypXtGM+O5HP2rPfbxq50UuecvoZpRPdTAnILOM= +github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.35.5/go.mod h1:rnOKv/DJpfdiPPOyAdsHSommMuIHW6bmP2rrQJJYPdU= +github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.6 h1:tzRDA4lO/j9nzQiUDxOyshXZ7hrz1bF41+48Sn8rvHo= +github.com/aws/aws-sdk-go-v2/service/transcribe v1.52.6/go.mod h1:ZZN5Hh+s7Cr845LY5cWKJiCplzW/vZwpnpjxifgo4Ko= +github.com/aws/aws-sdk-go-v2/service/transfer v1.66.0 h1:MmwixdCnBGaaOHJHDgkvfB8Z/OmtNdof3pXa6JJjgos= +github.com/aws/aws-sdk-go-v2/service/transfer v1.66.0/go.mod h1:28XXFJKdD8UJP9USN1DMtNNJpSt06CyozE/UaPbgjGA= +github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.5 h1:U7NFjnobEmEFqF9DB4tMLqSIJmciwcGYajpOOJgRdgY= +github.com/aws/aws-sdk-go-v2/service/verifiedpermissions v1.29.5/go.mod h1:BkoBrVIzx/RT4x6XqY1o5iUqq9Hh62PKnBC9YBClDvk= +github.com/aws/aws-sdk-go-v2/service/vpclattice v1.19.0 h1:3OyM+OTHo2c5u3lWQijbwDGF7jmnpZwya+IOAywsQQw= +github.com/aws/aws-sdk-go-v2/service/vpclattice v1.19.0/go.mod h1:DjBHb+rO7d7WLJKX73dO6fULvhHdJrXfv+k3Kkiespc= +github.com/aws/aws-sdk-go-v2/service/waf v1.30.5 h1:JUQsG3CPBtXGGdAril5Fois4wiFE1Z3Z/mkvkjd4TCQ= +github.com/aws/aws-sdk-go-v2/service/waf v1.30.5/go.mod h1:sRusTwVAJQtNy6vsrAHGXtd2WIgBGusW2waE6Kgc/So= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.6 h1:DqojtTvnVwuylF6Ru08okb9UGNrq3qc67mZ8Gpz9sVk= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.30.6/go.mod h1:uo8gzm2uqf+gYYa2blt1ITjIl59iTzOznUGaajPfT+g= +github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.7 h1:inakpEsI7NPyC3VP2EbPA4gFcCnaFNu0JNQ01s0u5nE= +github.com/aws/aws-sdk-go-v2/service/wafv2 v1.67.7/go.mod h1:maJyEaarDIirG/MA0EYIxWc1ctk4sbc4+cEUVCIgorI= +github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.6 h1:0vFMsxhs4763afIR7366ricWl+w1sVOeroRkMOV9BGA= +github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.39.6/go.mod h1:zmHAn01szsTI7D4u2qgUs0CMklmz2af4EU12bDOWZrM= +github.com/aws/aws-sdk-go-v2/service/workmail v1.36.4 h1:hVmkAUyvH4OZkiW0HmNYYeDjVL7jyj3kCN/3r6nPiW4= +github.com/aws/aws-sdk-go-v2/service/workmail v1.36.4/go.mod h1:RlfJYDlvfjkqFAf3Fim2a5ryz6/gOYQJXJLJV5/c/xU= +github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.6 h1:QHAuU6Tfq2k6Okb8cdZ98BkXzmUZflfKG64Fc44CnQQ= +github.com/aws/aws-sdk-go-v2/service/workspaces v1.63.6/go.mod h1:LTdwIWneoBQ7vVoD1gAGXvcNWq1gkgQqbCoKg1iDUZ0= +github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.6 h1:h8PGWVBIctOlbBpupw4CorUI8gCtX7d5o2lSHi12XgM= +github.com/aws/aws-sdk-go-v2/service/workspacesweb v1.32.6/go.mod h1:nUz45LzKA733mQl1wIKcWK87SkJWXo+TiLYC5NUZf3M= +github.com/aws/aws-sdk-go-v2/service/xray v1.36.4 h1:G5VZW+21OPiOGoAFM+gBWPLKyuRaB2dC/RdYgL82ZS8= +github.com/aws/aws-sdk-go-v2/service/xray v1.36.4/go.mod h1:FYhPO/0+3jtQ10m0K1DnBTrJkNgXsrYhSHOt3/mCOnE= github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE= github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= @@ -627,8 +627,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.23.0 h1:l16/Vrl0+x+HjHJWEjcKPwHYoxN9EC78gAFXKlH6m84= github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go v0.23.0/go.mod h1:HAmscHyzSOfB1Dr16KLc177KNbn83wscnZC+N7WyaM8= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66 h1:HA6blfR0h6kGnw4oJ92tZzghubreIkWbQJ4NVNqS688= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.66/go.mod h1:7kTJVbY5+igob9Q5N6KO81EGEKDNI9FpjujB31uI/n0= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67 h1:IS4mjtvkLHXWI5yn/t9ILOUiBqPePMFaO4IRh5pcMk4= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.67/go.mod h1:l81jrdpcZSWUsJs4BGFfdGScefSYEFQRLMQRG3uyvT0= github.com/hashicorp/awspolicyequivalence v1.7.0 h1:HxwPEw2/31BqQa73PinGciTfG2uJ/ATelvDG8X1gScU= github.com/hashicorp/awspolicyequivalence v1.7.0/go.mod h1:+oCTxQEYt+GcRalqrqTCBcJf100SQYiWQ4aENNYxYe0= github.com/hashicorp/cli v1.1.7 h1:/fZJ+hNdwfTSfsxMBa9WWMlfjUZbX8/LnUxgAd7lCVU= @@ -667,8 +667,8 @@ github.com/hashicorp/terraform-exec v0.24.0 h1:mL0xlk9H5g2bn0pPF6JQZk5YlByqSqrO5 github.com/hashicorp/terraform-exec v0.24.0/go.mod h1:lluc/rDYfAhYdslLJQg3J0oDqo88oGQAdHR+wDqFvo4= github.com/hashicorp/terraform-json v0.27.2 h1:BwGuzM6iUPqf9JYM/Z4AF1OJ5VVJEEzoKST/tRDBJKU= github.com/hashicorp/terraform-json v0.27.2/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE= -github.com/hashicorp/terraform-plugin-framework v1.16.0 h1:tP0f+yJg0Z672e7levixDe5EpWwrTrNryPM9kDMYIpE= -github.com/hashicorp/terraform-plugin-framework v1.16.0/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y= +github.com/hashicorp/terraform-plugin-framework v1.16.1 h1:1+zwFm3MEqd/0K3YBB2v9u9DtyYHyEuhVOfeIXbteWA= +github.com/hashicorp/terraform-plugin-framework v1.16.1/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y= github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0 h1:SJXL5FfJJm17554Kpt9jFXngdM6fXbnUnZ6iT2IeiYA= github.com/hashicorp/terraform-plugin-framework-jsontypes v0.2.0/go.mod h1:p0phD0IYhsu9bR4+6OetVvvH59I6LwjXGnTVEr8ox6E= github.com/hashicorp/terraform-plugin-framework-timeouts v0.6.0 h1:Vv16e7EW4nT9668IV0RhdpEmnLl0im7BZx6J+QMlUkg= @@ -789,8 +789,8 @@ github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0 github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.63.0 h1:0W0GZvzQe514c3igO063tR0cFVStoABt1agKqlYToL8= go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.63.0/go.mod h1:wIvTiRUU7Pbfqas/5JVjGZcftBeSAGSYVMOHWzWG0qE= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= diff --git a/version/VERSION b/version/VERSION index f821b19e31c0..4f9a145bbd29 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -6.14.2 \ No newline at end of file +6.15.1 \ No newline at end of file diff --git a/website/docs/actions/codebuild_start_build.html.markdown b/website/docs/actions/codebuild_start_build.html.markdown new file mode 100644 index 000000000000..a8b0c14ef0d2 --- /dev/null +++ b/website/docs/actions/codebuild_start_build.html.markdown @@ -0,0 +1,101 @@ +--- +subcategory: "CodeBuild" +layout: "aws" +page_title: "AWS: aws_codebuild_start_build" +description: |- + Starts a CodeBuild project build. +--- + +# Action: aws_codebuild_start_build + +~> **Note:** `aws_codebuild_start_build` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts a CodeBuild project build. This action will initiate a build and wait for it to complete, providing progress updates during execution. + +For information about AWS CodeBuild, see the [AWS CodeBuild User Guide](https://docs.aws.amazon.com/codebuild/latest/userguide/). For specific information about starting builds, see the [StartBuild](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html) page in the AWS CodeBuild API Reference. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_codebuild_project" "example" { + name = "example-project" + service_role = aws_iam_role.example.arn + + artifacts { + type = "NO_ARTIFACTS" + } + + environment { + compute_type = "BUILD_GENERAL1_SMALL" + image = "aws/codebuild/amazonlinux2-x86_64-standard:3.0" + type = "LINUX_CONTAINER" + } + + source { + type = "NO_SOURCE" + buildspec = "version: 0.2\nphases:\n build:\n commands:\n - echo 'Hello World'" + } +} + +action "aws_codebuild_start_build" "example" { + config { + project_name = aws_codebuild_project.example.name + } +} + +resource "terraform_data" "build_trigger" { + input = "trigger-build" + + lifecycle { + action_trigger { + events = [after_create] + actions = [action.aws_codebuild_start_build.example] + } + } +} +``` + +### Build with Environment Variables + +```terraform +action "aws_codebuild_start_build" "deploy" { + config { + project_name = aws_codebuild_project.deploy.name + source_version = "main" + timeout = 1800 + + environment_variables_override { + name = "ENVIRONMENT" + value = "production" + type = "PLAINTEXT" + } + + environment_variables_override { + name = "API_KEY" + value = "/prod/api-key" + type = "PARAMETER_STORE" + } + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `project_name` - (Required) Name of the CodeBuild project to build. + +The following arguments are optional: + +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `source_version` - (Optional) Version of the build input to be built. For GitHub, this can be a commit SHA, branch name, or tag name. +* `timeout` - (Optional) Timeout in seconds for the build operation. Defaults to 1800 seconds (30 minutes). +* `environment_variables_override` - (Optional) Environment variables to override for this build. See [Environment Variables Override](#environment-variables-override) below. + +### Environment Variables Override + +* `name` - (Required) Environment variable name. +* `value` - (Required) Environment variable value. +* `type` - (Optional) Environment variable type. Valid values are `PLAINTEXT`, `PARAMETER_STORE`, or `SECRETS_MANAGER`. Defaults to `PLAINTEXT`. diff --git a/website/docs/actions/ec2_stop_instance.html.markdown b/website/docs/actions/ec2_stop_instance.html.markdown index 7d627c98ea3c..8220cf22872b 100644 --- a/website/docs/actions/ec2_stop_instance.html.markdown +++ b/website/docs/actions/ec2_stop_instance.html.markdown @@ -10,6 +10,8 @@ description: |- ~> **Note:** `aws_ec2_stop_instance` is in alpha. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. +!> **Warning:** This action may cause unintended consequences. When triggered, the `aws_ec2_stop_instance` action changes the instance state to `stopped`, and Terraform does not reconcile the change. With `aws_instance`, the `instance_state` attribute will be out of sync until the next refresh. With `aws_ec2_instance_state`, this action directly conflicts. With higher-level managers (Auto Scaling Groups, ECS/EKS node groups, EMR, Batch), it may trigger replacement or restart of instances. Use caution—this preview action should be limited to development environments. + Stops an EC2 instance. This action will gracefully stop the instance and wait for it to reach the stopped state. For information about Amazon EC2, see the [Amazon EC2 User Guide](https://docs.aws.amazon.com/ec2/latest/userguide/). For specific information about stopping instances, see the [StopInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StopInstances.html) page in the Amazon EC2 API Reference. @@ -88,4 +90,5 @@ This action supports the following arguments: * `instance_id` - (Required) ID of the EC2 instance to stop. Must be a valid EC2 instance ID (e.g., i-1234567890abcdef0). * `force` - (Optional) Forces the instance to stop. The instance does not have an opportunity to flush file system caches or file system metadata. If you use this option, you must perform file system check and repair procedures. This option is not recommended for Windows instances. Default: `false`. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `timeout` - (Optional) Timeout in seconds to wait for the instance to stop. Must be between 30 and 3600 seconds. Default: `600`. diff --git a/website/docs/actions/events_put_events.html.markdown b/website/docs/actions/events_put_events.html.markdown new file mode 100644 index 000000000000..1dde36fd87dd --- /dev/null +++ b/website/docs/actions/events_put_events.html.markdown @@ -0,0 +1,146 @@ +--- +subcategory: "EventBridge" +layout: "aws" +page_title: "AWS: aws_events_put_events" +description: |- + Sends custom events to Amazon EventBridge so that they can be matched to rules. +--- + +# Action: aws_events_put_events + +~> **Note:** `aws_events_put_events` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Sends custom events to Amazon EventBridge so that they can be matched to rules. This action provides an imperative way to emit events from Terraform plans (e.g., deployment notifications) while still allowing Terraform to manage when the emission occurs through `action_trigger` lifecycle events. + +## Example Usage + +### Basic Event + +```terraform +action "aws_events_put_events" "example" { + config { + entry { + source = "mycompany.myapp" + detail_type = "User Action" + detail = jsonencode({ + user_id = "12345" + action = "login" + }) + } + } +} +``` + +### Multiple Events + +```terraform +action "aws_events_put_events" "batch" { + config { + entry { + source = "mycompany.orders" + detail_type = "Order Created" + detail = jsonencode({ + order_id = "order-123" + amount = 99.99 + }) + } + + entry { + source = "mycompany.orders" + detail_type = "Order Updated" + detail = jsonencode({ + order_id = "order-456" + status = "shipped" + }) + } + } +} +``` + +### Custom Event Bus + +```terraform +resource "aws_cloudwatch_event_bus" "example" { + name = "custom-bus" +} + +action "aws_events_put_events" "custom_bus" { + config { + entry { + source = "mycompany.analytics" + detail_type = "Page View" + event_bus_name = aws_cloudwatch_event_bus.example.name + detail = jsonencode({ + page = "/home" + user = "anonymous" + }) + } + } +} +``` + +### Event with Resources and Timestamp + +```terraform +action "aws_events_put_events" "detailed" { + config { + entry { + source = "aws.ec2" + detail_type = "EC2 Instance State-change Notification" + time = "2023-01-01T12:00:00Z" # RFC3339 + resources = ["arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0"] + detail = jsonencode({ + instance_id = "i-1234567890abcdef0" + state = "running" + }) + } + } +} +``` + +### Triggered by Terraform Data + +```terraform +resource "terraform_data" "deploy" { + input = var.deployment_id + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_events_put_events.deployment] + } + } +} + +action "aws_events_put_events" "deployment" { + config { + entry { + source = "mycompany.deployments" + detail_type = "Deployment Complete" + detail = jsonencode({ + deployment_id = var.deployment_id + environment = var.environment + timestamp = timestamp() + }) + } + } +} +``` + +## Argument Reference + +This action supports the following arguments: + +* `entry` - (Required) One or more `entry` blocks defining events to send. Multiple blocks may be specified. See [below](#entry-block). +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +### `entry` Block + +Each `entry` block supports: + +* `source` - (Required) The source identifier for the event (e.g., `mycompany.myapp`). +* `detail_type` - (Optional) Free-form string used to decide what fields to expect in the event detail. +* `detail` - (Optional) JSON string (use `jsonencode()`) representing the event detail payload. +* `event_bus_name` - (Optional) Name or ARN of the event bus. Defaults to the account's default bus. +* `resources` - (Optional) List of ARNs the event primarily concerns. +* `time` - (Optional) RFC3339 timestamp for the event. If omitted, the receive time is used. diff --git a/website/docs/actions/lambda_invoke.html.markdown b/website/docs/actions/lambda_invoke.html.markdown index 4a048c106e8f..4372d8008799 100644 --- a/website/docs/actions/lambda_invoke.html.markdown +++ b/website/docs/actions/lambda_invoke.html.markdown @@ -218,4 +218,5 @@ This action supports the following arguments: * `invocation_type` - (Optional) Invocation type. Valid values are `RequestResponse` (default) for synchronous invocation that waits for the function to complete and returns the response, `Event` for asynchronous invocation that returns immediately after the request is accepted, and `DryRun` to validate parameters and verify permissions without actually executing the function. * `log_type` - (Optional) Set to `Tail` to include the execution log in the response. Only applies to synchronous invocations (`RequestResponse` invocation type). Defaults to `None`. When set to `Tail`, the last 4 KB of the execution log is included in the response. * `payload` - (Required) JSON payload to send to the Lambda function. This should be a valid JSON string that represents the event data for your function. The payload size limit is 6 MB for synchronous invocations and 256 KB for asynchronous invocations. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `qualifier` - (Optional) Version or alias of the Lambda function to invoke. If not specified, the `$LATEST` version will be invoked. Can be a version number (e.g., `1`) or an alias (e.g., `PROD`). diff --git a/website/docs/actions/ses_send_email.html.markdown b/website/docs/actions/ses_send_email.html.markdown index 4f1bd36adae0..9311d0a810fe 100644 --- a/website/docs/actions/ses_send_email.html.markdown +++ b/website/docs/actions/ses_send_email.html.markdown @@ -169,6 +169,7 @@ This action supports the following arguments: * `cc_addresses` - (Optional) List of email addresses for the CC: field of the message. Recipients in this list will receive the email and their addresses will be visible to all recipients. * `html_body` - (Optional) Message body in HTML format. Either `text_body` or `html_body` (or both) must be specified. HTML content allows for rich formatting including links, images, and styling. * `reply_to_addresses` - (Optional) List of reply-to email addresses for the message. If the recipient replies to the message, each reply-to address will receive the reply. If not specified, replies will go to the source address. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `return_path` - (Optional) Email address that bounces and complaints will be forwarded to when feedback forwarding is enabled. This is useful for handling delivery failures and spam complaints. * `source` - (Required) Email address that is sending the email. This address must be either individually verified with Amazon SES, or from a domain that has been verified with Amazon SES. * `subject` - (Required) Subject of the message: A short summary of the content, which will appear in the recipient's inbox. diff --git a/website/docs/actions/sfn_start_execution.html.markdown b/website/docs/actions/sfn_start_execution.html.markdown new file mode 100644 index 000000000000..37ac7cc2cee4 --- /dev/null +++ b/website/docs/actions/sfn_start_execution.html.markdown @@ -0,0 +1,238 @@ +--- +subcategory: "SFN (Step Functions)" +layout: "aws" +page_title: "AWS: aws_sfn_start_execution" +description: |- + Starts a Step Functions state machine execution with the specified input data. +--- + +# Action: aws_sfn_start_execution + +~> **Note:** `aws_sfn_start_execution` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts a Step Functions state machine execution with the specified input data. This action allows for imperative execution of state machines with full control over execution parameters. + +For information about AWS Step Functions, see the [AWS Step Functions Developer Guide](https://docs.aws.amazon.com/step-functions/latest/dg/). For specific information about starting executions, see the [StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) page in the AWS Step Functions API Reference. + +~> **Note:** For `STANDARD` workflows, executions with the same name and input are idempotent. For `EXPRESS` workflows, each execution is unique regardless of name and input. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_sfn_state_machine" "example" { + name = "example-state-machine" + role_arn = aws_iam_role.sfn.arn + + definition = jsonencode({ + Comment = "A simple minimal example" + StartAt = "Hello" + States = { + Hello = { + Type = "Pass" + Result = "Hello World!" + End = true + } + } + }) +} + +action "aws_sfn_start_execution" "example" { + config { + state_machine_arn = aws_sfn_state_machine.example.arn + input = jsonencode({ + user_id = "12345" + action = "process" + }) + } +} + +resource "terraform_data" "example" { + input = "trigger-execution" + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_sfn_start_execution.example] + } + } +} +``` + +### Named Execution + +```terraform +action "aws_sfn_start_execution" "named" { + config { + state_machine_arn = aws_sfn_state_machine.processor.arn + name = "deployment-${var.deployment_id}" + input = jsonencode({ + deployment_id = var.deployment_id + environment = var.environment + }) + } +} +``` + +### Execution with Version + +```terraform +action "aws_sfn_start_execution" "versioned" { + config { + state_machine_arn = "${aws_sfn_state_machine.example.arn}:${aws_sfn_state_machine.example.version_number}" + input = jsonencode({ + version = "v2" + config = var.processing_config + }) + } +} +``` + +### Execution with Alias + +```terraform +resource "aws_sfn_alias" "prod" { + name = "PROD" + state_machine_arn = aws_sfn_state_machine.example.arn + routing_configuration { + state_machine_version_weight { + state_machine_version_arn = aws_sfn_state_machine.example.arn + weight = 100 + } + } +} + +action "aws_sfn_start_execution" "production" { + config { + state_machine_arn = aws_sfn_alias.prod.arn + input = jsonencode({ + environment = "production" + batch_size = 1000 + }) + } +} +``` + +### X-Ray Tracing + +```terraform +action "aws_sfn_start_execution" "traced" { + config { + state_machine_arn = aws_sfn_state_machine.example.arn + trace_header = "Root=1-${formatdate("YYYYMMDD", timestamp())}-${substr(uuid(), 0, 24)}" + input = jsonencode({ + trace_id = "custom-trace-${timestamp()}" + data = var.processing_data + }) + } +} +``` + +### CI/CD Pipeline Integration + +Use this action in your deployment pipeline to trigger post-deployment workflows: + +```terraform +resource "terraform_data" "deploy_complete" { + input = local.deployment_id + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_sfn_start_execution.post_deploy] + } + } + + depends_on = [aws_lambda_function.processors] +} + +action "aws_sfn_start_execution" "post_deploy" { + config { + state_machine_arn = aws_sfn_state_machine.data_pipeline.arn + name = "post-deploy-${local.deployment_id}" + input = jsonencode({ + deployment_id = local.deployment_id + environment = var.environment + resources = { + lambda_functions = [for f in aws_lambda_function.processors : f.arn] + s3_bucket = aws_s3_bucket.data.bucket + } + }) + } +} +``` + +### Environment-Specific Processing + +```terraform +locals { + execution_config = var.environment == "production" ? { + batch_size = 1000 + max_retries = 3 + timeout_hours = 24 + } : { + batch_size = 100 + max_retries = 1 + timeout_hours = 2 + } +} + +action "aws_sfn_start_execution" "batch_process" { + config { + state_machine_arn = aws_sfn_state_machine.batch_processor.arn + input = jsonencode(merge(local.execution_config, { + data_source = var.data_source + output_path = var.output_path + })) + } +} +``` + +### Complex Workflow Orchestration + +```terraform +action "aws_sfn_start_execution" "orchestrator" { + config { + state_machine_arn = aws_sfn_state_machine.orchestrator.arn + input = jsonencode({ + workflow = { + id = "workflow-${timestamp()}" + type = "data-processing" + steps = var.workflow_steps + } + resources = { + compute = { + lambda_functions = [for f in aws_lambda_function.workers : f.arn] + ecs_cluster = aws_ecs_cluster.processing.arn + } + storage = { + input_bucket = aws_s3_bucket.input.bucket + output_bucket = aws_s3_bucket.output.bucket + temp_bucket = aws_s3_bucket.temp.bucket + } + messaging = { + success_topic = aws_sns_topic.success.arn + error_topic = aws_sns_topic.errors.arn + } + } + metadata = { + created_by = "terraform" + environment = var.environment + version = var.app_version + tags = var.execution_tags + } + }) + } +} +``` + +## Argument Reference + +This action supports the following arguments: + +* `input` - (Optional) JSON input data for the execution. Must be valid JSON. Defaults to `{}` if not specified. The input size limit is 256 KB. +* `name` - (Optional) Name of the execution. Must be unique within the account/region/state machine for 90 days. If not provided, Step Functions automatically generates a UUID. Names must not contain whitespace, brackets, wildcards, or special characters. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `state_machine_arn` - (Required) ARN of the state machine to execute. Can be an unqualified ARN, version-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:version`), or alias-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:alias`). +* `trace_header` - (Optional) AWS X-Ray trace header for distributed tracing. Used to correlate execution traces across services. diff --git a/website/docs/actions/sns_publish.html.markdown b/website/docs/actions/sns_publish.html.markdown index dfc2206e68b2..c238419bf170 100644 --- a/website/docs/actions/sns_publish.html.markdown +++ b/website/docs/actions/sns_publish.html.markdown @@ -138,6 +138,7 @@ This action supports the following arguments: * `message` - (Required) Message to publish. For JSON message structure, this should be a JSON object with protocol-specific messages. Maximum size is 256 KB. * `message_attributes` - (Optional) Message attributes to include with the message. Each attribute consists of a name, data type, and value. Up to 10 attributes are allowed. [See below.](#message-attributes) * `message_structure` - (Optional) Set to `json` if you want to send different messages for each protocol. If not specified, the message will be sent as-is to all protocols. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `subject` - (Optional) Optional subject for the message. Only used for email and email-json protocols. Maximum length is 100 characters. * `topic_arn` - (Required) ARN of the SNS topic to publish the message to. diff --git a/website/docs/actions/transcribe_start_transcription_job.html.markdown b/website/docs/actions/transcribe_start_transcription_job.html.markdown new file mode 100644 index 000000000000..0feb65ab3a99 --- /dev/null +++ b/website/docs/actions/transcribe_start_transcription_job.html.markdown @@ -0,0 +1,124 @@ +--- +subcategory: "Transcribe" +layout: "aws" +page_title: "AWS: aws_transcribe_start_transcription_job" +description: |- + Starts an Amazon Transcribe transcription job. +--- + +# Action: aws_transcribe_start_transcription_job + +~> **Note:** `aws_transcribe_start_transcription_job` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts an Amazon Transcribe transcription job to transcribe audio from a media file. The media file must be uploaded to an Amazon S3 bucket before starting the transcription job. + +For information about Amazon Transcribe, see the [Amazon Transcribe Developer Guide](https://docs.aws.amazon.com/transcribe/latest/dg/). For specific information about starting transcription jobs, see the [StartTranscriptionJob](https://docs.aws.amazon.com/transcribe/latest/APIReference/API_StartTranscriptionJob.html) page in the Amazon Transcribe API Reference. + +~> **Note:** This action starts the transcription job and waits for it to begin processing, but does not wait for the transcription to complete. The job will continue running asynchronously after the action completes. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_s3_bucket" "example" { + bucket = "my-transcription-bucket" +} + +resource "aws_s3_object" "audio" { + bucket = aws_s3_bucket.example.bucket + key = "audio/meeting.mp3" + source = "path/to/meeting.mp3" +} + +action "aws_transcribe_start_transcription_job" "example" { + config { + transcription_job_name = "meeting-transcription-${timestamp()}" + media_file_uri = "s3://${aws_s3_bucket.example.bucket}/${aws_s3_object.audio.key}" + language_code = "en-US" + } +} +``` + +### Automatic Language Detection + +```terraform +action "aws_transcribe_start_transcription_job" "auto_detect" { + config { + transcription_job_name = "auto-detect-transcription" + media_file_uri = "s3://my-bucket/audio/multilingual-meeting.mp3" + identify_language = true + timeout = 600 + } +} +``` + +### Multiple Language Detection + +```terraform +action "aws_transcribe_start_transcription_job" "multilingual" { + config { + transcription_job_name = "multilingual-transcription" + media_file_uri = "s3://my-bucket/audio/conference-call.mp3" + identify_multiple_languages = true + media_format = "mp3" + media_sample_rate_hertz = 44100 + } +} +``` + +### Custom Output Location + +```terraform +action "aws_transcribe_start_transcription_job" "custom_output" { + config { + transcription_job_name = "custom-output-transcription" + media_file_uri = "s3://my-bucket/audio/interview.wav" + language_code = "en-US" + output_bucket_name = aws_s3_bucket.transcripts.bucket + output_key = "transcripts/interview-transcript.json" + } +} +``` + +### CI/CD Pipeline Integration + +```terraform +resource "terraform_data" "process_audio" { + input = var.audio_files + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.batch_process] + } + } + + depends_on = [aws_s3_object.uploaded_audio] +} + +action "aws_transcribe_start_transcription_job" "batch_process" { + config { + transcription_job_name = "batch-${formatdate("YYYY-MM-DD-hhmm", timestamp())}" + media_file_uri = "s3://${aws_s3_bucket.audio.bucket}/${aws_s3_object.uploaded_audio.key}" + language_code = var.audio_language + timeout = 900 + } +} +``` + +## Argument Reference + +This action supports the following arguments: + +* `transcription_job_name` - (Required) Unique name for the transcription job within your AWS account. Must be 1-200 characters and contain only alphanumeric characters, hyphens, periods, and underscores. +* `media_file_uri` - (Required) S3 location of the media file to transcribe (e.g., `s3://bucket-name/file.mp3`). The file must be accessible to Amazon Transcribe. +* `language_code` - (Optional) Language code for the language used in the input media file. Required if `identify_language` and `identify_multiple_languages` are both false. Valid values can be found in the [Amazon Transcribe supported languages documentation](https://docs.aws.amazon.com/transcribe/latest/dg/supported-languages.html). +* `identify_language` - (Optional) Enable automatic language identification for single-language media files. Cannot be used with `identify_multiple_languages`. Default: `false`. +* `identify_multiple_languages` - (Optional) Enable automatic language identification for multi-language media files. Cannot be used with `identify_language`. Default: `false`. +* `media_format` - (Optional) Format of the input media file. If not specified, Amazon Transcribe will attempt to determine the format automatically. Valid values: `mp3`, `mp4`, `wav`, `flac`, `ogg`, `amr`, `webm`, `m4a`. +* `media_sample_rate_hertz` - (Optional) Sample rate of the input media file in Hertz. If not specified, Amazon Transcribe will attempt to determine the sample rate automatically. Valid range: 8000-48000. +* `output_bucket_name` - (Optional) Name of the S3 bucket where you want your transcription output stored. If not specified, output is stored in a service-managed bucket. +* `output_key` - (Optional) S3 object key for your transcription output. If not specified, a default key is generated. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `timeout` - (Optional) Maximum time in seconds to wait for the transcription job to start. Must be between 60 and 3600 seconds. Default: `300`. diff --git a/website/docs/cdktf/python/actions/codebuild_start_build.html.markdown b/website/docs/cdktf/python/actions/codebuild_start_build.html.markdown new file mode 100644 index 000000000000..39d4b8938ddf --- /dev/null +++ b/website/docs/cdktf/python/actions/codebuild_start_build.html.markdown @@ -0,0 +1,93 @@ +--- +subcategory: "CodeBuild" +layout: "aws" +page_title: "AWS: aws_codebuild_start_build" +description: |- + Starts a CodeBuild project build. +--- + + + +# Action: aws_codebuild_start_build + +~> **Note:** `aws_codebuild_start_build` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts a CodeBuild project build. This action will initiate a build and wait for it to complete, providing progress updates during execution. + +For information about AWS CodeBuild, see the [AWS CodeBuild User Guide](https://docs.aws.amazon.com/codebuild/latest/userguide/). For specific information about starting builds, see the [StartBuild](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html) page in the AWS CodeBuild API Reference. + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from cdktf import TerraformResourceLifecycle +from constructs import Construct +from cdktf import Token, DataResource, TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws.codebuild_project import CodebuildProject +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + CodebuildProject(self, "example", + artifacts=CodebuildProjectArtifacts( + type="NO_ARTIFACTS" + ), + environment=CodebuildProjectEnvironment( + compute_type="BUILD_GENERAL1_SMALL", + image="aws/codebuild/amazonlinux2-x86_64-standard:3.0", + type="LINUX_CONTAINER" + ), + name="example-project", + service_role=Token.as_string(aws_iam_role_example.arn), + source=CodebuildProjectSource( + buildspec="version: 0.2\nphases:\n build:\n commands:\n - echo 'Hello World'\n", + type="NO_SOURCE" + ) + ) + DataResource(self, "build_trigger", + input="trigger-build", + lifecycle=TerraformResourceLifecycle( + action_trigger=[{ + "actions": [aws_codebuild_start_build.example], + "events": [after_create] + } + ] + ) + ) +``` + +### Build with Environment Variables + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) +``` + +## Argument Reference + +The following arguments are required: + +* `project_name` - (Required) Name of the CodeBuild project to build. + +The following arguments are optional: + +* `source_version` - (Optional) Version of the build input to be built. For GitHub, this can be a commit SHA, branch name, or tag name. +* `timeout` - (Optional) Timeout in seconds for the build operation. Defaults to 1800 seconds (30 minutes). +* `environment_variables_override` - (Optional) Environment variables to override for this build. See [Environment Variables Override](#environment-variables-override) below. + +### Environment Variables Override + +* `name` - (Required) Environment variable name. +* `value` - (Required) Environment variable value. +* `type` - (Optional) Environment variable type. Valid values are `PLAINTEXT`, `PARAMETER_STORE`, or `SECRETS_MANAGER`. Defaults to `PLAINTEXT`. + + \ No newline at end of file diff --git a/website/docs/cdktf/python/actions/sfn_start_execution.html.markdown b/website/docs/cdktf/python/actions/sfn_start_execution.html.markdown new file mode 100644 index 000000000000..ca0769bd545a --- /dev/null +++ b/website/docs/cdktf/python/actions/sfn_start_execution.html.markdown @@ -0,0 +1,187 @@ +--- +subcategory: "SFN (Step Functions)" +layout: "aws" +page_title: "AWS: aws_sfn_start_execution" +description: |- + Starts a Step Functions state machine execution with the specified input data. +--- + + + +# Action: aws_sfn_start_execution + +~> **Note:** `aws_sfn_start_execution` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts a Step Functions state machine execution with the specified input data. This action allows for imperative execution of state machines with full control over execution parameters. + +For information about AWS Step Functions, see the [AWS Step Functions Developer Guide](https://docs.aws.amazon.com/step-functions/latest/dg/). For specific information about starting executions, see the [StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) page in the AWS Step Functions API Reference. + +~> **Note:** For `STANDARD` workflows, executions with the same name and input are idempotent. For `EXPRESS` workflows, each execution is unique regardless of name and input. + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from cdktf import TerraformResourceLifecycle +from constructs import Construct +from cdktf import Fn, Token, DataResource, TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws.sfn_state_machine import SfnStateMachine +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + SfnStateMachine(self, "example", + definition=Token.as_string( + Fn.jsonencode({ + "Comment": "A simple minimal example", + "StartAt": "Hello", + "States": { + "Hello": { + "End": True, + "Result": "Hello World!", + "Type": "Pass" + } + } + })), + name="example-state-machine", + role_arn=sfn.arn + ) + terraform_data_example = DataResource(self, "example_1", + input="trigger-execution", + lifecycle=TerraformResourceLifecycle( + action_trigger=[{ + "actions": [aws_sfn_start_execution.example], + "events": [before_create, before_update] + } + ] + ) + ) + # This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match. + terraform_data_example.override_logical_id("example") +``` + +### Named Execution + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) +``` + +### Execution with Version + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) +``` + +### Execution with Alias + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws.sfn_alias import SfnAlias +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name, *, stateMachineVersionArn, weight): + super().__init__(scope, name) + SfnAlias(self, "prod", + name="PROD", + routing_configuration=[SfnAliasRoutingConfiguration( + state_machine_version_weight=[{ + "state_machine_version_arn": example.arn, + "weight": 100 + } + ], + state_machine_version_arn=state_machine_version_arn, + weight=weight + ) + ], + state_machine_arn=example.arn + ) +``` + +### X-Ray Tracing + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) +``` + +### CI/CD Pipeline Integration + +Use this action in your deployment pipeline to trigger post-deployment workflows: + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from cdktf import TerraformResourceLifecycle +from constructs import Construct +from cdktf import DataResource, TerraformStack +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + DataResource(self, "deploy_complete", + depends_on=[processors], + input=deployment_id, + lifecycle=TerraformResourceLifecycle( + action_trigger=[{ + "actions": [aws_sfn_start_execution.post_deploy], + "events": [before_create, before_update] + } + ] + ) + ) +``` + +### Environment-Specific Processing + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) +``` + +### Complex Workflow Orchestration + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) +``` + +## Argument Reference + +This action supports the following arguments: + +* `input` - (Optional) JSON input data for the execution. Must be valid JSON. Defaults to `{}` if not specified. The input size limit is 256 KB. +* `name` - (Optional) Name of the execution. Must be unique within the account/region/state machine for 90 days. If not provided, Step Functions automatically generates a UUID. Names must not contain whitespace, brackets, wildcards, or special characters. +* `state_machine_arn` - (Required) ARN of the state machine to execute. Can be an unqualified ARN, version-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:version`), or alias-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:alias`). +* `trace_header` - (Optional) AWS X-Ray trace header for distributed tracing. Used to correlate execution traces across services. + + \ No newline at end of file diff --git a/website/docs/cdktf/python/d/appconfig_application.html.markdown b/website/docs/cdktf/python/d/appconfig_application.html.markdown new file mode 100644 index 000000000000..aafaf8a0fc70 --- /dev/null +++ b/website/docs/cdktf/python/d/appconfig_application.html.markdown @@ -0,0 +1,51 @@ +--- +subcategory: "AppConfig" +layout: "aws" +page_title: "AWS: aws_appconfig_application" +description: |- + Retrieves an AWS AppConfig Application by name. +--- + + + +# Data Source: aws_appconfig_application + +Provides details about an AWS AppConfig Application. + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws. import DataAwsAppconfigApplication +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + DataAwsAppconfigApplication(self, "example", + name="my-appconfig-application" + ) +``` + +## Argument Reference + +This data source supports the following arguments: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `id` - (Optional) ID of the Application. Either `id` or `name` must be specified. +* `name` - (Optional) AWS AppConfig Application name. Either `name` or `id` must be specified. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `arn` - ARN of the Application. +* `description` - Description of the Application. + + \ No newline at end of file diff --git a/website/docs/cdktf/python/d/db_proxy.html.markdown b/website/docs/cdktf/python/d/db_proxy.html.markdown index 7d225219b526..f6d70ebe3ffb 100644 --- a/website/docs/cdktf/python/d/db_proxy.html.markdown +++ b/website/docs/cdktf/python/d/db_proxy.html.markdown @@ -45,6 +45,7 @@ This data source exports the following attributes in addition to the arguments a * `arn` - ARN of the DB Proxy. * `auth` - Configuration(s) with authorization mechanisms to connect to the associated instance or cluster. * `debug_logging` - Whether the proxy includes detailed information about SQL statements in its logs. +* `default_auth_scheme` - Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. * `endpoint` - Endpoint that you can use to connect to the DB proxy. * `engine_family` - Kinds of databases that the proxy can connect to. * `idle_client_timeout` - Number of seconds a connection to the proxy can have no activity before the proxy drops the client connection. @@ -54,4 +55,4 @@ This data source exports the following attributes in addition to the arguments a * `vpc_security_group_ids` - Provides a list of VPC security groups that the proxy belongs to. * `vpc_subnet_ids` - EC2 subnet IDs for the proxy. - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/d/ec2_instance_type_offering.html.markdown b/website/docs/cdktf/python/d/ec2_instance_type_offering.html.markdown index eec452fe94a2..0601531f8292 100644 --- a/website/docs/cdktf/python/d/ec2_instance_type_offering.html.markdown +++ b/website/docs/cdktf/python/d/ec2_instance_type_offering.html.markdown @@ -56,6 +56,7 @@ This data source exports the following attributes in addition to the arguments a * `id` - EC2 Instance Type. * `instance_type` - EC2 Instance Type. +* `location` - Identifier for the location. ## Timeouts @@ -63,4 +64,4 @@ This data source exports the following attributes in addition to the arguments a - `read` - (Default `20m`) - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/d/odb_db_node.html.markdown b/website/docs/cdktf/python/d/odb_db_node.html.markdown new file mode 100644 index 000000000000..fa2a1143f663 --- /dev/null +++ b/website/docs/cdktf/python/d/odb_db_node.html.markdown @@ -0,0 +1,82 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_node" +page_title: "AWS: aws_odb_db_node" +description: |- + Terraform data source for managing db node linked to cloud vm cluster of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_node + +Terraform data source for manging db nodes linked to cloud vm cluster of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws. import DataAwsOdbDbNode +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + DataAwsOdbDbNode(self, "example", + cloud_vm_cluster_id="cloud_vm_cluster_id", + id="db_node_id" + ) +``` + +## Argument Reference + +The following arguments are required: + +* `cloud_vm_cluster_id` - (Required) The unique identifier of the cloud vm cluster. +* `id` - (Required) The unique identifier of db node associated with vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `cloud_vm_cluster_id` - The ID of the cloud VM cluster. +* `status` - The current status of the DB node. +* `status_reason` - Additional information about the status of the DB node. +* `additional_details` - Additional information about the planned maintenance. +* `backup_ip_id` - The Oracle Cloud ID (OCID) of the backup IP address that's associated with the DB node. +* `backup_vnic2_id` - The OCID of the second backup VNIC. +* `backup_vnic_id` - The OCID of the backup VNIC. +* `cpu_core_count` - The number of CPU cores enabled on the DB node. +* `db_storage_size_in_gbs` - The amount of local node storage, in gigabytes (GB), allocated on the DB node. +* `db_server_id` - The unique identifier of the DB server that is associated with the DB node. +* `db_system_id` - The OCID of the DB system. +* `fault_domain` - The name of the fault domain the instance is contained in. +* `host_ip_id` - The OCID of the host IP address that's associated with the DB node. +* `hostname` - The host name for the DB node. +* `ocid` - The OCID of the DB node. +* `oci_resource_anchor_name` - The name of the OCI resource anchor for the DB node. +* `maintenance_type` - The type of database node maintenance. Either VMDB_REBOOT_MIGRATION or EXADBXS_REBOOT_MIGRATION. +* `memory_size_in_gbs` - The allocated memory in GBs on the DB node. +* `software_storage_size_in_gbs` - The size (in GB) of the block storage volume allocation for the DB system. +* `created_at` - The date and time when the DB node was created. +* `time_maintenance_window_end` - The end date and time of the maintenance window. +* `time_maintenance_window_start` - The start date and time of the maintenance window. +* `total_cpu_core_count` - The total number of CPU cores reserved on the DB node. +* `vnic2_id` - The OCID of the second VNIC. +* `vnic_id` - The OCID of the VNIC. +* `private_ip_address` - The private IP address assigned to the DB node. +* `floating_ip_address` - The floating IP address assigned to the DB node. + + \ No newline at end of file diff --git a/website/docs/cdktf/python/d/odb_db_nodes.html.markdown b/website/docs/cdktf/python/d/odb_db_nodes.html.markdown new file mode 100644 index 000000000000..77fb6e420bbd --- /dev/null +++ b/website/docs/cdktf/python/d/odb_db_nodes.html.markdown @@ -0,0 +1,83 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_nodes" +page_title: "AWS: aws_odb_db_nodes" +description: |- + Terraform data source for managing db nodes linked to cloud vm cluster of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_nodes + +Terraform data source for manging db nodes linked to cloud vm cluster of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws. import DataAwsOdbDbNodes +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + DataAwsOdbDbNodes(self, "example", + cloud_vm_cluster_id="example" + ) +``` + +## Argument Reference + +The following arguments are required: + +* `cloud_vm_cluster_id` - (Required) The unique identifier of the cloud vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `db_nodes` - The list of DB nodes along with their properties. + +### db_nodes + +* `additional_details` - Additional information about the planned maintenance. +* `backup_ip_id` - The Oracle Cloud ID (OCID) of the backup IP address that's associated with the DB node. +* `backup_vnic_2_id` - The OCID of the second backup virtual network interface card (VNIC) for the DB node. +* `backup_vnic_id` - The OCID of the backup VNIC for the DB node. +* `cpu_core_count` - The number of CPU cores enabled on the DB node. +* `created_at` - The date and time when the DB node was created. +* `db_node_arn` - The Amazon Resource Name (ARN) of the DB node. +* `db_node_id` - The unique identifier of the DB node. +* `db_node_storage_size_in_gbs` - The amount of local node storage, in gigabytes (GB), that's allocated on the DB node. +* `db_server_id` - The unique identifier of the database server that's associated with the DB node. +* `db_system_id` - The OCID of the DB system. +* `fault_domain` - The name of the fault domain where the DB node is located. +* `host_ip_id` - The OCID of the host IP address that's associated with the DB node. +* `hostname` - The host name for the DB node. +* `maintenance_type` - The type of maintenance the DB node is undergoing. +* `memory_size_in_gbs` - The amount of memory, in gigabytes (GB), that's allocated on the DB node. +* `oci_resource_anchor_name` - The name of the OCI resource anchor for the DB node. +* `ocid` - The OCID of the DB node. +* `software_storage_size_in_gb` - The size of the block storage volume, in gigabytes (GB), that's allocated for the DB system. This attribute applies only for virtual machine DB systems. +* `status` - The current status of the DB node. +* `status_reason` - Additional information about the status of the DB node. +* `time_maintenance_window_end` - The end date and time of the maintenance window. +* `time_maintenance_window_start` - The start date and time of the maintenance window. +* `total_cpu_core_count` - The total number of CPU cores reserved on the DB node. +* `vnic_2_id` - The OCID of the second VNIC. +* `vnic_id` - The OCID of the VNIC. + + \ No newline at end of file diff --git a/website/docs/cdktf/python/d/odb_db_server.html.markdown b/website/docs/cdktf/python/d/odb_db_server.html.markdown new file mode 100644 index 000000000000..57492995e3b3 --- /dev/null +++ b/website/docs/cdktf/python/d/odb_db_server.html.markdown @@ -0,0 +1,74 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_server" +page_title: "AWS: aws_odb_db_server" +description: |- + Terraform data source for managing db server linked to exadata infrastructure of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_server + +Terraform data source for manging db server linked to exadata infrastructure of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws. import DataAwsOdbDbServer +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + DataAwsOdbDbServer(self, "example", + cloud_exadata_infrastructure_id="exadata_infra_id", + id="db_server_id" + ) +``` + +## Argument Reference + +The following arguments are required: + +* `cloud_exadata_infrastructure_id` - (Required) The unique identifier of the cloud vm cluster. +* `id` - (Required) The unique identifier of db node associated with vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `autonomous_virtual_machine_ids` - The list of unique identifiers for the Autonomous VMs associated with this database server. +* `autonomous_vm_cluster_ids` - The OCID of the autonomous VM clusters that are associated with the database server. +* `compute_model` - The compute model of the database server. +* `status` - The status of the database server. +* `status_reason` - Additional information about the current status of the database server. +* `cpu_core_count` - The number of CPU cores enabled on the database server. +* `db_node_storage_size_in_gbs` - The allocated local node storage in GBs on the database server. +* `db_server_patching_details` - The scheduling details for the quarterly maintenance window. Patching and system updates take place during the maintenance window. +* `display_name` - The display name of the database server. +* `exadata_infrastructure_id` - The exadata infrastructure ID of the database server. +* `ocid` - The OCID of the database server to retrieve information about. +* `oci_resource_anchor_name` - The name of the OCI resource anchor. +* `max_cpu_count` - The total number of CPU cores available. +* `max_db_node_storage_in_gbs` - The total local node storage available in GBs. +* `max_memory_in_gbs` - The total memory available in GBs. +* `memory_size_in_gbs` - The allocated memory in GBs on the database server. +* `shape` - The shape of the database server. The shape determines the amount of CPU, storage, and memory resources available. +* `created_at` - The date and time when the database server was created. +* `vm_cluster_ids` - The OCID of the VM clusters that are associated with the database server. + + \ No newline at end of file diff --git a/website/docs/cdktf/python/d/odb_db_servers.html.markdown b/website/docs/cdktf/python/d/odb_db_servers.html.markdown new file mode 100644 index 000000000000..48f7963d30cd --- /dev/null +++ b/website/docs/cdktf/python/d/odb_db_servers.html.markdown @@ -0,0 +1,77 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_servers" +page_title: "AWS: aws_odb_db_servers" +description: |- + Terraform data source for managing db servers linked to exadata infrastructure of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_servers + +Terraform data source for manging db servers linked to exadata infrastructure of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws. import DataAwsOdbDbServers +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + DataAwsOdbDbServers(self, "example", + cloud_exadata_infrastructure_id="exadata_infra_id" + ) +``` + +## Argument Reference + +The following arguments are required: + +* `cloud_exadata_infrastructure_id` - (Required) The unique identifier of the cloud vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `db_servers` - the list of DB servers along with their properties. + +### db_servers + +* `autonomous_virtual_machine_ids` - A list of unique identifiers for the Autonomous VMs. +* `autonomous_vm_cluster_ids` - A list of identifiers for the Autonomous VM clusters. +* `compute_model` - The OCI compute model used when you create or clone an instance: **ECPU** or **OCPU**. ECPUs are based on the number of cores elastically allocated from a pool of compute and storage servers, while OCPUs are based on the physical core of a processor with hyper-threading enabled. +* `cpu_core_count` - The number of CPU cores enabled on the database server. +* `created_at` - The date and time when the database server was created. +* `db_node_storage_size_in_gbs` - The amount of local node storage, in gigabytes (GB), that's allocated on the database server. +* `db_server_id` - The unique identifier of the database server. +* `db_server_patching_details` - The scheduling details for the quarterly maintenance window. Patching and system updates take place during the maintenance window. +* `display_name` - The user-friendly name of the database server. The name doesn't need to be unique. +* `exadata_infrastructure_id` - The ID of the Exadata infrastructure that hosts the database server. +* `max_cpu_count` - The total number of CPU cores available on the database server. +* `max_db_node_storage_in_gbs` - The total amount of local node storage, in gigabytes (GB), that's available on the database server. +* `max_memory_in_gbs` - The total amount of memory, in gigabytes (GB), that's available on the database server. +* `memory_size_in_gbs` - The amount of memory, in gigabytes (GB), that's allocated on the database server. +* `oci_resource_anchor_name` - The name of the OCI resource anchor for the database server. +* `ocid` - The OCID of the database server. +* `shape` - The hardware system model of the Exadata infrastructure that the database server is hosted on. The shape determines the amount of CPU, storage, and memory resources available. +* `status` - The current status of the database server. +* `status_reason` - Additional information about the status of the database server. +* `vm_cluster_ids` - The IDs of the VM clusters that are associated with the database server. + + \ No newline at end of file diff --git a/website/docs/cdktf/python/index.html.markdown b/website/docs/cdktf/python/index.html.markdown index ff4b2b4a0b26..918e9e50b614 100644 --- a/website/docs/cdktf/python/index.html.markdown +++ b/website/docs/cdktf/python/index.html.markdown @@ -11,7 +11,7 @@ description: |- The Amazon Web Services (AWS) provider is Terraform’s most widely-used provider and the industry-standard way to manage AWS infrastructure as code. It is an indispensable part of how leading technology companies, global banks, government agencies, and some of the largest enterprises in the world build and operate in the cloud. Every day, it provisions and orchestrates billions of dollars of AWS infrastructure across thousands of organizations. -With 1,537 resources and 609 data sources, the AWS provider spans the full breadth of AWS services—from foundational capabilities like compute, storage, networking, and identity management to advanced services for AI, analytics, and event-driven architectures, including Lambda, RDS, SageMaker, and Bedrock. Whether automating a single S3 bucket or orchestrating a multi-region, enterprise-scale environment, the provider delivers consistent, reliable workflows that scale with your needs. +With 1,543 resources and 615 data sources, the AWS provider spans the full breadth of AWS services—from foundational capabilities like compute, storage, networking, and identity management to advanced services for AI, analytics, and event-driven architectures, including Lambda, RDS, SageMaker, and Bedrock. Whether automating a single S3 bucket or orchestrating a multi-region, enterprise-scale environment, the provider delivers consistent, reliable workflows that scale with your needs. Configure the provider with your AWS credentials, and you can immediately begin creating and managing infrastructure in a safe, repeatable way. Use the navigation on the left to explore the available resources, or start with our [Get Started tutorials](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/infrastructure-as-code?in=terraform/aws-get-started&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) to learn the fundamentals. For deeper guidance on specific AWS services, visit the [AWS services tutorials](https://developer.hashicorp.com/terraform/tutorials/aws?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS). @@ -897,4 +897,4 @@ Approaches differ per authentication providers: There used to be no better way to get account ID out of the API when using the federated account until `sts:GetCallerIdentity` was introduced. - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/cleanrooms_configured_table.html.markdown b/website/docs/cdktf/python/r/cleanrooms_configured_table.html.markdown index 0adfa3c2f9e7..80bf6a60a0cb 100644 --- a/website/docs/cdktf/python/r/cleanrooms_configured_table.html.markdown +++ b/website/docs/cdktf/python/r/cleanrooms_configured_table.html.markdown @@ -76,6 +76,32 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_cleanrooms_configured_table.example + identity = { + id = "1234abcd-12ab-34cd-56ef-1234567890ab" + } +} + +resource "aws_cleanrooms_configured_table" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +* `id` - (String) ID of the cleanrooms configured table. + +#### Optional + +* `account_id` (String) AWS Account where this resource is managed. +* `region` (String) Region where this resource is managed. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import `aws_cleanrooms_configured_table` using the `id`. For example: ```python @@ -99,4 +125,4 @@ Using `terraform import`, import `aws_cleanrooms_configured_table` using the `id % terraform import aws_cleanrooms_configured_table.table 1234abcd-12ab-34cd-56ef-1234567890ab ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/cloudfront_distribution.html.markdown b/website/docs/cdktf/python/r/cloudfront_distribution.html.markdown index bb27b69311c2..42cb8aaed3b3 100644 --- a/website/docs/cdktf/python/r/cloudfront_distribution.html.markdown +++ b/website/docs/cdktf/python/r/cloudfront_distribution.html.markdown @@ -626,6 +626,7 @@ argument should not be specified. * `http_port` (Required) - HTTP port the custom origin listens on. * `https_port` (Required) - HTTPS port the custom origin listens on. +* `ip_address_type` (Optional) - IP protocol CloudFront uses when connecting to your origin. Valid values: `ipv4`, `ipv6`, `dualstack`. * `origin_protocol_policy` (Required) - Origin protocol policy to apply to your origin. One of `http-only`, `https-only`, or `match-viewer`. * `origin_ssl_protocols` (Required) - List of SSL/TLS protocols that CloudFront can use when connecting to your origin over HTTPS. Valid values: `SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`. For more information, see [Minimum Origin SSL Protocol](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesOriginSSLProtocols) in the Amazon CloudFront Developer Guide. * `origin_keepalive_timeout` - (Optional) The Custom KeepAlive timeout, in seconds. By default, AWS enforces an upper limit of `60`. But you can request an [increase](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#request-custom-request-timeout). Defaults to `5`. @@ -735,4 +736,4 @@ Using `terraform import`, import CloudFront Distributions using the `id`. For ex % terraform import aws_cloudfront_distribution.distribution E74FTE3EXAMPLE ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/connect_instance.html.markdown b/website/docs/cdktf/python/r/connect_instance.html.markdown index 888c4b12d852..21068a1e7fa8 100644 --- a/website/docs/cdktf/python/r/connect_instance.html.markdown +++ b/website/docs/cdktf/python/r/connect_instance.html.markdown @@ -123,6 +123,32 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_connect_instance.example + identity = { + id = "f1288a1f-6193-445a-b47e-af739b2" + } +} + +resource "aws_connect_instance" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +* `id` - (String) ID of the connect instance. + +#### Optional + +- `account_id` (String) AWS Account where this resource is managed. +- `region` (String) Region where this resource is managed. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Connect instances using the `id`. For example: ```python @@ -146,4 +172,4 @@ Using `terraform import`, import Connect instances using the `id`. For example: % terraform import aws_connect_instance.example f1288a1f-6193-445a-b47e-af739b2 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/connect_phone_number.html.markdown b/website/docs/cdktf/python/r/connect_phone_number.html.markdown index 2f0fe5da8240..29b440727303 100644 --- a/website/docs/cdktf/python/r/connect_phone_number.html.markdown +++ b/website/docs/cdktf/python/r/connect_phone_number.html.markdown @@ -122,6 +122,31 @@ The `status` configuration block supports the following attributes: ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_connect_phone_number.example + identity = { + id = "1234abcd-12ab-34cd-56ef-1234567890ab" + } +} +resource "aws_connect_phone_number" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +* `id` - (String) ID of the connect phone number. + +#### Optional + +- `account_id` (String) AWS Account where this resource is managed. +- `region` (String) Region where this resource is managed. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Amazon Connect Phone Numbers using its `id`. For example: ```python @@ -145,4 +170,4 @@ Using `terraform import`, import Amazon Connect Phone Numbers using its `id`. Fo % terraform import aws_connect_phone_number.example 12345678-abcd-1234-efgh-9876543210ab ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/db_proxy.html.markdown b/website/docs/cdktf/python/r/db_proxy.html.markdown index 423d1a16e89e..bd34fb1b1bca 100644 --- a/website/docs/cdktf/python/r/db_proxy.html.markdown +++ b/website/docs/cdktf/python/r/db_proxy.html.markdown @@ -145,8 +145,9 @@ This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `name` - (Required) The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens. -* `auth` - (Required) Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters. Described below. +* `auth` - (Optional) Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters. Required when `default_auth_scheme` is `NONE` or unspecified. Described below. * `debug_logging` - (Optional) Whether the proxy includes detailed information about SQL statements in its logs. This information helps you to debug issues involving SQL behavior or the performance and scalability of the proxy connections. The debug information includes the text of SQL statements that you submit through the proxy. Thus, only enable this setting when needed for debugging, and only when you have security measures in place to safeguard any sensitive information that appears in the logs. +* `default_auth_scheme` - (Optional) Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. Valid values are `NONE` and `IAM_AUTH`. Defaults to `NONE`. * `engine_family` - (Required, Forces new resource) The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. For Aurora MySQL, RDS for MariaDB, and RDS for MySQL databases, specify `MYSQL`. For Aurora PostgreSQL and RDS for PostgreSQL databases, specify `POSTGRESQL`. For RDS for Microsoft SQL Server, specify `SQLSERVER`. Valid values are `MYSQL`, `POSTGRESQL`, and `SQLSERVER`. * `idle_client_timeout` - (Optional) The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it. You can set this value higher or lower than the connection timeout limit for the associated database. * `require_tls` - (Optional) A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy. @@ -206,4 +207,4 @@ Using `terraform import`, import DB proxies using the `name`. For example: % terraform import aws_db_proxy.example example ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/dsql_cluster.html.markdown b/website/docs/cdktf/python/r/dsql_cluster.html.markdown index 4f36ae2ef4e6..97a119c6a0b4 100644 --- a/website/docs/cdktf/python/r/dsql_cluster.html.markdown +++ b/website/docs/cdktf/python/r/dsql_cluster.html.markdown @@ -40,7 +40,10 @@ class MyConvertedCode(TerraformStack): This resource supports the following arguments: -* `deletion_protection_enabled` - (Required) Whether deletion protection is enabled in this cluster. +* `deletion_protection_enabled` - (Optional) Whether deletion protection is enabled in this cluster. + Default value is `false`. +* `force_destroy` - (Optional) Destroys cluster even if `deletion_protection_enabled` is set to `true`. + Default value is `false`. * `kms_encryption_key` - (Optional) The ARN of the AWS KMS key that encrypts data in the DSQL Cluster, or `"AWS_OWNED_KMS_KEY"`. * `multi_region_properties` - (Optional) Multi-region properties of the DSQL Cluster. * `witness_region` - (Required) Witness region for the multi-region clusters. Setting this makes this cluster a multi-region cluster. Changing it recreates the resource. @@ -94,4 +97,4 @@ Using `terraform import`, import DSQL Cluster using the `identifier`. For exampl % terraform import aws_dsql_cluster.example abcde1f234ghijklmnop5qr6st ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/ecs_service.html.markdown b/website/docs/cdktf/python/r/ecs_service.html.markdown index 47b0b57bee57..7456223c7c8f 100644 --- a/website/docs/cdktf/python/r/ecs_service.html.markdown +++ b/website/docs/cdktf/python/r/ecs_service.html.markdown @@ -213,7 +213,7 @@ The following arguments are optional: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `alarms` - (Optional) Information about the CloudWatch alarms. [See below](#alarms). * `availability_zone_rebalancing` - (Optional) ECS automatically redistributes tasks within a service across Availability Zones (AZs) to mitigate the risk of impaired application availability due to underlying infrastructure failures and task lifecycle activities. The valid values are `ENABLED` and `DISABLED`. When creating a new service, if no value is specified, it defaults to `ENABLED` if the service is compatible with AvailabilityZoneRebalancing. When updating an existing service, if no value is specified it defaults to the existing service's AvailabilityZoneRebalancing value. If the service never had an AvailabilityZoneRebalancing value set, Amazon ECS treats this as `DISABLED`. -* `capacity_provider_strategy` - (Optional) Capacity provider strategies to use for the service. Can be one or more. These can be updated without destroying and recreating the service only if `force_new_deployment = true` and not changing from 0 `capacity_provider_strategy` blocks to greater than 0, or vice versa. [See below](#capacity_provider_strategy). Conflicts with `launch_type`. +* `capacity_provider_strategy` - (Optional) Capacity provider strategies to use for the service. Can be one or more. Updating this argument requires `force_new_deployment = true`. [See below](#capacity_provider_strategy). Conflicts with `launch_type`. * `cluster` - (Optional) ARN of an ECS cluster. * `deployment_circuit_breaker` - (Optional) Configuration block for deployment circuit breaker. [See below](#deployment_circuit_breaker). * `deployment_configuration` - (Optional) Configuration block for deployment settings. [See below](#deployment_configuration). @@ -512,4 +512,4 @@ Using `terraform import`, import ECS services using the `name` together with ecs % terraform import aws_ecs_service.imported cluster-name/service-name ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/eks_addon.html.markdown b/website/docs/cdktf/python/r/eks_addon.html.markdown index 151f22ee9529..76d822baebb8 100644 --- a/website/docs/cdktf/python/r/eks_addon.html.markdown +++ b/website/docs/cdktf/python/r/eks_addon.html.markdown @@ -62,13 +62,14 @@ Custom add-on configuration can be passed using `configuration_values` as a sing ~> **Note:** `configuration_values` is a single JSON string should match the valid JSON schema for each add-on with specific version. -To find the correct JSON schema for each add-on can be extracted using [describe-addon-configuration](https://docs.aws.amazon.com/cli/latest/reference/eks/describe-addon-configuration.html) call. -This below is an example for extracting the `configuration_values` schema for `coredns`. +You can use [describe-addon-configuration](https://docs.aws.amazon.com/cli/latest/reference/eks/describe-addon-configuration.html) to extract each add-on's JSON schema. +Here's an example command to extract the `configuration_values` schema for `coredns`. ```bash - aws eks describe-addon-configuration \ - --addon-name coredns \ - --addon-version v1.10.1-eksbuild.1 +aws eks describe-addon-configuration \ + --addon-name coredns \ + --addon-version v1.10.1-eksbuild.1 \ + | jq -r .configurationSchema | jq . ``` Example to create a `coredns` managed addon with custom `configuration_values`. @@ -268,4 +269,4 @@ Using `terraform import`, import EKS add-on using the `cluster_name` and `addon_ % terraform import aws_eks_addon.my_eks_addon my_cluster_name:my_addon_name ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/lakeformation_lf_tag_expression.html.markdown b/website/docs/cdktf/python/r/lakeformation_lf_tag_expression.html.markdown new file mode 100644 index 000000000000..e267fffd1852 --- /dev/null +++ b/website/docs/cdktf/python/r/lakeformation_lf_tag_expression.html.markdown @@ -0,0 +1,95 @@ +--- +subcategory: "Lake Formation" +layout: "aws" +page_title: "AWS: aws_lakeformation_lf_tag_expression" +description: |- + Terraform resource for managing an AWS Lake Formation LF Tag Expression. +--- + + +# Resource: aws_lakeformation_lf_tag_expression + +Terraform resource for managing an AWS Lake Formation LF Tag Expression. + +## Example Usage + +### Basic Usage + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws. import LakeformationLfTagExpression +from imports.aws.lakeformation_lf_tag import LakeformationLfTag +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + example = LakeformationLfTag(self, "example", + key="example", + values=["value"] + ) + aws_lakeformation_lf_tag_expression_example = + LakeformationLfTagExpression(self, "example_1", + expression=[{ + "tag_key": example.key, + "tag_values": example.values + } + ], + name="example" + ) + # This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match. + aws_lakeformation_lf_tag_expression_example.override_logical_id("example") +``` + +## Argument Reference + +The following arguments are required: + +* `name` - (Required) Name of the LF-Tag Expression. +* `expression` - (Required) A list of LF-Tag conditions (key-value pairs). See [expression](#expression) for more details. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `catalog_id` - (Optional) ID of the Data Catalog. Defaults to the account ID if not specified. +* `description` - (Optional) Description of the LF-Tag Expression. + +### expression + +* `tag_key` - (Required) The key-name for the LF-Tag. +* `tag_values` - (Required) A list of possible values for the LF-Tag + +## Attribute Reference + +This resource exports no additional attributes. + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Lake Formation LF Tag Expression using the `name,catalog_id`. For example: + +```python +# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +from constructs import Construct +from cdktf import TerraformStack +# +# Provider bindings are generated by running `cdktf get`. +# See https://cdk.tf/provider-generation for more details. +# +from imports.aws. import LakeformationLfTagExpression +class MyConvertedCode(TerraformStack): + def __init__(self, scope, name): + super().__init__(scope, name) + LakeformationLfTagExpression.generate_config_for_import(self, "example", "example-tag-expression,123456789012") +``` + +Using `terraform import`, import Lake Formation LF Tag Expression using the `name,catalog_id`. For example: + +```console +% terraform import aws_lakeformation_lf_tag_expression.example example-tag-expression,123456789012 +``` + + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/lakeformation_permissions.html.markdown b/website/docs/cdktf/python/r/lakeformation_permissions.html.markdown index 750de3ea90c0..90e9dd374e08 100644 --- a/website/docs/cdktf/python/r/lakeformation_permissions.html.markdown +++ b/website/docs/cdktf/python/r/lakeformation_permissions.html.markdown @@ -120,6 +120,7 @@ The resulting permissions depend on whether the table had `IAMAllowedPrincipals` AllIAMPrincipals is a pseudo-entity group that acts like a Lake Formation principal. The group includes all IAMs in the account that is defined. +```terraform resource "aws_lakeformation_permissions" "example" { permissions = ["SELECT"] principal = "123456789012:IAMPrincipals" @@ -130,6 +131,7 @@ resource "aws_lakeformation_permissions" "example" { column_names = ["event"] } } +``` ## Using Lake Formation Permissions @@ -331,4 +333,4 @@ The following arguments are optional: This resource exports no additional attributes. - \ No newline at end of file + diff --git a/website/docs/cdktf/python/r/macie2_member.html.markdown b/website/docs/cdktf/python/r/macie2_member.html.markdown index 9c028a070092..d507c849e076 100644 --- a/website/docs/cdktf/python/r/macie2_member.html.markdown +++ b/website/docs/cdktf/python/r/macie2_member.html.markdown @@ -47,7 +47,6 @@ This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `account_id` - (Required) The AWS account ID for the account. * `email` - (Required) The email address for the account. -* `tags` - (Optional) A map of key-value pairs that specifies the tags to associate with the account in Amazon Macie. * `status` - (Optional) Specifies the status for the account. To enable Amazon Macie and start all Macie activities for the account, set this value to `ENABLED`. Valid values are `ENABLED` or `PAUSED`. * `invite` - (Optional) Send an invitation to a member * `invitation_message` - (Optional) A custom message to include in the invitation. Amazon Macie adds this message to the standard content that it sends for an invitation. @@ -91,4 +90,4 @@ Using `terraform import`, import `aws_macie2_member` using the account ID of the % terraform import aws_macie2_member.example 123456789012 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/pinpointsmsvoicev2_phone_number.html.markdown b/website/docs/cdktf/python/r/pinpointsmsvoicev2_phone_number.html.markdown index 3b69c0170229..e74a15a2f32a 100644 --- a/website/docs/cdktf/python/r/pinpointsmsvoicev2_phone_number.html.markdown +++ b/website/docs/cdktf/python/r/pinpointsmsvoicev2_phone_number.html.markdown @@ -47,7 +47,7 @@ This resource supports the following arguments: * `opt_out_list_name` - (Optional) The name of the opt-out list to associate with the phone number. * `registration_id` - (Optional) Use this field to attach your phone number for an external registration process. * `self_managed_opt_outs_enabled` - (Optional) When set to `false` an end recipient sends a message that begins with HELP or STOP to one of your dedicated numbers, AWS End User Messaging SMS and Voice automatically replies with a customizable message and adds the end recipient to the opt-out list. When set to true you’re responsible for responding to HELP and STOP requests. You’re also responsible for tracking and honoring opt-out request. -* `two_way_channel_arn` - (Optional) The Amazon Resource Name (ARN) of the two way channel. +* `two_way_channel_arn` - (Optional) Configuration for two-way SMS. Specify an ARN to receive incoming SMS messages, or `connect.[region].amazonaws.com` (with `[region]` replaced by the AWS Region of the Amazon Connect instance) to set Amazon Connect as the inbound destination. * `two_way_channel_enabled` - (Optional) By default this is set to `false`. When set to `true` you can receive incoming text messages from your end recipients. * `two_way_channel_role` - (Optional) IAM Role ARN for a service to assume, to be able to post inbound SMS messages. @@ -86,4 +86,4 @@ Using `terraform import`, import phone numbers using the `id`. For example: % terraform import aws_pinpointsmsvoicev2_phone_number.example phone-abcdef0123456789abcdef0123456789 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/pipes_pipe.html.markdown b/website/docs/cdktf/python/r/pipes_pipe.html.markdown index affbe8d49046..edd03471e50b 100644 --- a/website/docs/cdktf/python/r/pipes_pipe.html.markdown +++ b/website/docs/cdktf/python/r/pipes_pipe.html.markdown @@ -342,7 +342,7 @@ You can find out more about EventBridge Pipes Sources in the [User Guide](https: * `maximum_retry_attempts` - (Optional) Discard records after the specified number of retries. The default value is -1, which sets the maximum number of retries to infinite. When MaximumRetryAttempts is infinite, EventBridge retries failed records until the record expires in the event source. Maximum value of 10,000. * `on_partial_batch_item_failure` - (Optional) Define how to handle item process failures. AUTOMATIC_BISECT halves each batch and retry each half until all the records are processed or there is one failed message left in the batch. Valid values: AUTOMATIC_BISECT. * `parallelization_factor` - (Optional)The number of batches to process concurrently from each shard. The default value is 1. Maximum value of 10. -* `starting_position` - (Optional) The position in a stream from which to start reading. Valid values: TRIM_HORIZON, LATEST. +* `starting_position` - (Required) The position in a stream from which to start reading. Valid values: TRIM_HORIZON, LATEST. ##### source_parameters.dynamodb_stream_parameters.dead_letter_config Configuration Block diff --git a/website/docs/cdktf/python/r/route53_zone.html.markdown b/website/docs/cdktf/python/r/route53_zone.html.markdown index 94948a30fa44..485c41776d21 100644 --- a/website/docs/cdktf/python/r/route53_zone.html.markdown +++ b/website/docs/cdktf/python/r/route53_zone.html.markdown @@ -85,13 +85,26 @@ from cdktf import TerraformStack # See https://cdk.tf/provider-generation for more details. # from imports.aws.route53_zone import Route53Zone +from imports.aws.vpc import Vpc class MyConvertedCode(TerraformStack): def __init__(self, scope, name): super().__init__(scope, name) + primary = Vpc(self, "primary", + cidr_block="10.6.0.0/16", + enable_dns_hostnames=True, + enable_dns_support=True + ) + secondary = Vpc(self, "secondary", + cidr_block="10.7.0.0/16", + enable_dns_hostnames=True, + enable_dns_support=True + ) Route53Zone(self, "private", name="example.com", vpc=[Route53ZoneVpc( - vpc_id=example.id + vpc_id=primary.id + ), Route53ZoneVpc( + vpc_id=secondary.id ) ] ) @@ -157,4 +170,4 @@ Using `terraform import`, import Route53 Zones using the zone `id`. For example: % terraform import aws_route53_zone.myzone Z1D633PJN98FT9 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/route53recoverycontrolconfig_cluster.html.markdown b/website/docs/cdktf/python/r/route53recoverycontrolconfig_cluster.html.markdown index 94a7ab20a5a7..b1995e95c35e 100644 --- a/website/docs/cdktf/python/r/route53recoverycontrolconfig_cluster.html.markdown +++ b/website/docs/cdktf/python/r/route53recoverycontrolconfig_cluster.html.markdown @@ -33,9 +33,10 @@ class MyConvertedCode(TerraformStack): ## Argument Reference -The following arguments are required: +This resource supports the following arguments: * `name` - (Required) Unique name describing the cluster. +* `network_type` - (Optional) Network type of cluster. Valid values are `IPV4` and `DUALSTACK`. Defaults to `IPV4`. ## Attribute Reference @@ -75,4 +76,4 @@ Using `terraform import`, import Route53 Recovery Control Config cluster using t % terraform import aws_route53recoverycontrolconfig_cluster.mycluster arn:aws:route53-recovery-control::313517334327:cluster/f9ae13be-a11e-4ec7-8522-94a70468e6ea ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/s3control_bucket.html.markdown b/website/docs/cdktf/python/r/s3control_bucket.html.markdown index f4dea44747ee..3ca4e5928da0 100644 --- a/website/docs/cdktf/python/r/s3control_bucket.html.markdown +++ b/website/docs/cdktf/python/r/s3control_bucket.html.markdown @@ -55,6 +55,27 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_s3control_bucket.example + identity = { + "arn" = "arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-12345678/bucket/example" + } +} + +resource "aws_s3control_bucket" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +- `arn` (String) ARN of the bucket. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import S3 Control Buckets using Amazon Resource Name (ARN). For example: ```python @@ -78,4 +99,4 @@ Using `terraform import`, import S3 Control Buckets using Amazon Resource Name ( % terraform import aws_s3control_bucket.example arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-12345678/bucket/example ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/sfn_activity.html.markdown b/website/docs/cdktf/python/r/sfn_activity.html.markdown index 4b2fadbb228b..342166622d42 100644 --- a/website/docs/cdktf/python/r/sfn_activity.html.markdown +++ b/website/docs/cdktf/python/r/sfn_activity.html.markdown @@ -78,13 +78,29 @@ This resource supports the following arguments: This resource exports the following attributes in addition to the arguments above: -* `id` - The Amazon Resource Name (ARN) that identifies the created activity. -* `name` - The name of the activity. -* `creation_date` - The date the activity was created. +* `id` - Amazon Resource Name (ARN) of the activity. +* `arn` - Amazon Resource Name (ARN) of the activity. +* `name` - Name of the activity. +* `creation_date` - Date the activity was created. * `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_sfn_activity.example + identity = { + "arn" = "arn:aws:states:eu-west-1:123456789098:activity:bar" + } +} + +resource "aws_sfn_activity" "example" { + ### Configuration omitted for brevity ### +} +``` + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import activities using the `arn`. For example: ```python @@ -99,13 +115,13 @@ from imports.aws.sfn_activity import SfnActivity class MyConvertedCode(TerraformStack): def __init__(self, scope, name): super().__init__(scope, name) - SfnActivity.generate_config_for_import(self, "foo", "arn:aws:states:eu-west-1:123456789098:activity:bar") + SfnActivity.generate_config_for_import(self, "example", "arn:aws:states:eu-west-1:123456789098:activity:bar") ``` Using `terraform import`, import activities using the `arn`. For example: ```console -% terraform import aws_sfn_activity.foo arn:aws:states:eu-west-1:123456789098:activity:bar +% terraform import aws_sfn_activity.example arn:aws:states:eu-west-1:123456789098:activity:bar ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/sfn_alias.html.markdown b/website/docs/cdktf/python/r/sfn_alias.html.markdown index 9c0049885ebf..08bd3407bc7d 100644 --- a/website/docs/cdktf/python/r/sfn_alias.html.markdown +++ b/website/docs/cdktf/python/r/sfn_alias.html.markdown @@ -72,6 +72,21 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_sfn_alias.example + identity = { + "arn" = "arn:aws:states:us-east-1:123456789098:stateMachine:myStateMachine:foo" + } +} + +resource "aws_sfn_alias" "example" { + ### Configuration omitted for brevity ### +} +``` + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SFN (Step Functions) Alias using the `arn`. For example: ```python @@ -95,4 +110,4 @@ Using `terraform import`, import SFN (Step Functions) Alias using the `arn`. For % terraform import aws_sfn_alias.foo arn:aws:states:us-east-1:123456789098:stateMachine:myStateMachine:foo ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/python/r/ssmcontacts_contact_channel.html.markdown b/website/docs/cdktf/python/r/ssmcontacts_contact_channel.html.markdown index a92192cb6878..0f1b19cb7f2b 100644 --- a/website/docs/cdktf/python/r/ssmcontacts_contact_channel.html.markdown +++ b/website/docs/cdktf/python/r/ssmcontacts_contact_channel.html.markdown @@ -92,7 +92,28 @@ This resource exports the following attributes in addition to the arguments abov ## Import -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SSM Contact Channel using the `ARN`. For example: +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_ssmcontacts_contact_channel.example + identity = { + "arn" = "arn:aws:ssm-contacts:us-west-2:123456789012:contact-channel/example" + } +} + +resource "aws_ssmcontacts_contact_channel" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +- `arn` (String) Amazon Resource Name (ARN) of the contact channel. + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SSM Contact Channel using the `arn`. For example: ```python # DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug @@ -109,10 +130,10 @@ class MyConvertedCode(TerraformStack): SsmcontactsContactChannel.generate_config_for_import(self, "example", "arn:aws:ssm-contacts:us-west-2:123456789012:contact-channel/example") ``` -Using `terraform import`, import SSM Contact Channel using the `ARN`. For example: +Using `terraform import`, import SSM Contact Channel using the `arn`. For example: ```console % terraform import aws_ssmcontacts_contact_channel.example arn:aws:ssm-contacts:us-west-2:123456789012:contact-channel/example ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/actions/codebuild_start_build.html.markdown b/website/docs/cdktf/typescript/actions/codebuild_start_build.html.markdown new file mode 100644 index 000000000000..72b75d7ff23c --- /dev/null +++ b/website/docs/cdktf/typescript/actions/codebuild_start_build.html.markdown @@ -0,0 +1,100 @@ +--- +subcategory: "CodeBuild" +layout: "aws" +page_title: "AWS: aws_codebuild_start_build" +description: |- + Starts a CodeBuild project build. +--- + + + +# Action: aws_codebuild_start_build + +~> **Note:** `aws_codebuild_start_build` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts a CodeBuild project build. This action will initiate a build and wait for it to complete, providing progress updates during execution. + +For information about AWS CodeBuild, see the [AWS CodeBuild User Guide](https://docs.aws.amazon.com/codebuild/latest/userguide/). For specific information about starting builds, see the [StartBuild](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html) page in the AWS CodeBuild API Reference. + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { Token, DataResource, TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { CodebuildProject } from "./.gen/providers/aws/codebuild-project"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new CodebuildProject(this, "example", { + artifacts: { + type: "NO_ARTIFACTS", + }, + environment: { + computeType: "BUILD_GENERAL1_SMALL", + image: "aws/codebuild/amazonlinux2-x86_64-standard:3.0", + type: "LINUX_CONTAINER", + }, + name: "example-project", + serviceRole: Token.asString(awsIamRoleExample.arn), + source: { + buildspec: + "version: 0.2\nphases:\n build:\n commands:\n - echo 'Hello World'\n", + type: "NO_SOURCE", + }, + }); + new DataResource(this, "build_trigger", { + input: "trigger-build", + lifecycle: { + actionTrigger: [ + { + actions: [awsCodebuildStartBuild.example], + events: [afterCreate], + }, + ], + }, + }); + } +} + +``` + +### Build with Environment Variables + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + } +} + +``` + +## Argument Reference + +The following arguments are required: + +* `projectName` - (Required) Name of the CodeBuild project to build. + +The following arguments are optional: + +* `sourceVersion` - (Optional) Version of the build input to be built. For GitHub, this can be a commit SHA, branch name, or tag name. +* `timeout` - (Optional) Timeout in seconds for the build operation. Defaults to 1800 seconds (30 minutes). +* `environment_variables_override` - (Optional) Environment variables to override for this build. See [Environment Variables Override](#environment-variables-override) below. + +### Environment Variables Override + +* `name` - (Required) Environment variable name. +* `value` - (Required) Environment variable value. +* `type` - (Optional) Environment variable type. Valid values are `PLAINTEXT`, `PARAMETER_STORE`, or `SECRETS_MANAGER`. Defaults to `PLAINTEXT`. + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/actions/sfn_start_execution.html.markdown b/website/docs/cdktf/typescript/actions/sfn_start_execution.html.markdown new file mode 100644 index 000000000000..4838ae31374c --- /dev/null +++ b/website/docs/cdktf/typescript/actions/sfn_start_execution.html.markdown @@ -0,0 +1,218 @@ +--- +subcategory: "SFN (Step Functions)" +layout: "aws" +page_title: "AWS: aws_sfn_start_execution" +description: |- + Starts a Step Functions state machine execution with the specified input data. +--- + + + +# Action: aws_sfn_start_execution + +~> **Note:** `aws_sfn_start_execution` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts a Step Functions state machine execution with the specified input data. This action allows for imperative execution of state machines with full control over execution parameters. + +For information about AWS Step Functions, see the [AWS Step Functions Developer Guide](https://docs.aws.amazon.com/step-functions/latest/dg/). For specific information about starting executions, see the [StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) page in the AWS Step Functions API Reference. + +~> **Note:** For `STANDARD` workflows, executions with the same name and input are idempotent. For `EXPRESS` workflows, each execution is unique regardless of name and input. + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { Fn, Token, DataResource, TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { SfnStateMachine } from "./.gen/providers/aws/sfn-state-machine"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new SfnStateMachine(this, "example", { + definition: Token.asString( + Fn.jsonencode({ + Comment: "A simple minimal example", + StartAt: "Hello", + States: { + Hello: { + End: true, + Result: "Hello World!", + Type: "Pass", + }, + }, + }) + ), + name: "example-state-machine", + roleArn: sfn.arn, + }); + const terraformDataExample = new DataResource(this, "example_1", { + input: "trigger-execution", + lifecycle: { + actionTrigger: [ + { + actions: [awsSfnStartExecution.example], + events: [beforeCreate, beforeUpdate], + }, + ], + }, + }); + /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ + terraformDataExample.overrideLogicalId("example"); + } +} + +``` + +### Named Execution + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + } +} + +``` + +### Execution with Version + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + } +} + +``` + +### Execution with Alias + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { SfnAlias } from "./.gen/providers/aws/sfn-alias"; +interface MyConfig { + stateMachineVersionArn: any; + weight: any; +} +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string, config: MyConfig) { + super(scope, name); + new SfnAlias(this, "prod", { + name: "PROD", + routingConfiguration: [ + { + state_machine_version_weight: [ + { + state_machine_version_arn: example.arn, + weight: 100, + }, + ], + stateMachineVersionArn: config.stateMachineVersionArn, + weight: config.weight, + }, + ], + state_machine_arn: example.arn, + }); + } +} + +``` + +### X-Ray Tracing + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + } +} + +``` + +### CI/CD Pipeline Integration + +Use this action in your deployment pipeline to trigger post-deployment workflows: + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { DataResource, TerraformStack } from "cdktf"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new DataResource(this, "deploy_complete", { + dependsOn: [processors], + input: deploymentId, + lifecycle: { + actionTrigger: [ + { + actions: [awsSfnStartExecution.postDeploy], + events: [beforeCreate, beforeUpdate], + }, + ], + }, + }); + } +} + +``` + +### Environment-Specific Processing + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + } +} + +``` + +### Complex Workflow Orchestration + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + } +} + +``` + +## Argument Reference + +This action supports the following arguments: + +* `input` - (Optional) JSON input data for the execution. Must be valid JSON. Defaults to `{}` if not specified. The input size limit is 256 KB. +* `name` - (Optional) Name of the execution. Must be unique within the account/region/state machine for 90 days. If not provided, Step Functions automatically generates a UUID. Names must not contain whitespace, brackets, wildcards, or special characters. +* `state_machine_arn` - (Required) ARN of the state machine to execute. Can be an unqualified ARN, version-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:version`), or alias-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:alias`). +* `trace_header` - (Optional) AWS X-Ray trace header for distributed tracing. Used to correlate execution traces across services. + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/d/appconfig_application.html.markdown b/website/docs/cdktf/typescript/d/appconfig_application.html.markdown new file mode 100644 index 000000000000..506beb8616de --- /dev/null +++ b/website/docs/cdktf/typescript/d/appconfig_application.html.markdown @@ -0,0 +1,54 @@ +--- +subcategory: "AppConfig" +layout: "aws" +page_title: "AWS: aws_appconfig_application" +description: |- + Retrieves an AWS AppConfig Application by name. +--- + + + +# Data Source: aws_appconfig_application + +Provides details about an AWS AppConfig Application. + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { DataAwsAppconfigApplication } from "./.gen/providers/aws/"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new DataAwsAppconfigApplication(this, "example", { + name: "my-appconfig-application", + }); + } +} + +``` + +## Argument Reference + +This data source supports the following arguments: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `id` - (Optional) ID of the Application. Either `id` or `name` must be specified. +* `name` - (Optional) AWS AppConfig Application name. Either `name` or `id` must be specified. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `arn` - ARN of the Application. +* `description` - Description of the Application. + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/d/db_proxy.html.markdown b/website/docs/cdktf/typescript/d/db_proxy.html.markdown index e7b9b23d886f..8c1d2d3e8804 100644 --- a/website/docs/cdktf/typescript/d/db_proxy.html.markdown +++ b/website/docs/cdktf/typescript/d/db_proxy.html.markdown @@ -48,6 +48,7 @@ This data source exports the following attributes in addition to the arguments a * `arn` - ARN of the DB Proxy. * `auth` - Configuration(s) with authorization mechanisms to connect to the associated instance or cluster. * `debugLogging` - Whether the proxy includes detailed information about SQL statements in its logs. +* `default_auth_scheme` - Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. * `endpoint` - Endpoint that you can use to connect to the DB proxy. * `engineFamily` - Kinds of databases that the proxy can connect to. * `idleClientTimeout` - Number of seconds a connection to the proxy can have no activity before the proxy drops the client connection. @@ -57,4 +58,4 @@ This data source exports the following attributes in addition to the arguments a * `vpcSecurityGroupIds` - Provides a list of VPC security groups that the proxy belongs to. * `vpcSubnetIds` - EC2 subnet IDs for the proxy. - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/d/ec2_instance_type_offering.html.markdown b/website/docs/cdktf/typescript/d/ec2_instance_type_offering.html.markdown index 7521f1d1aac5..9388727c1c3d 100644 --- a/website/docs/cdktf/typescript/d/ec2_instance_type_offering.html.markdown +++ b/website/docs/cdktf/typescript/d/ec2_instance_type_offering.html.markdown @@ -60,6 +60,7 @@ This data source exports the following attributes in addition to the arguments a * `id` - EC2 Instance Type. * `instanceType` - EC2 Instance Type. +* `location` - Identifier for the location. ## Timeouts @@ -67,4 +68,4 @@ This data source exports the following attributes in addition to the arguments a - `read` - (Default `20m`) - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/d/odb_db_node.html.markdown b/website/docs/cdktf/typescript/d/odb_db_node.html.markdown new file mode 100644 index 000000000000..7cc896a32c10 --- /dev/null +++ b/website/docs/cdktf/typescript/d/odb_db_node.html.markdown @@ -0,0 +1,85 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_node" +page_title: "AWS: aws_odb_db_node" +description: |- + Terraform data source for managing db node linked to cloud vm cluster of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_node + +Terraform data source for manging db nodes linked to cloud vm cluster of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { DataAwsOdbDbNode } from "./.gen/providers/aws/"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new DataAwsOdbDbNode(this, "example", { + cloud_vm_cluster_id: "cloud_vm_cluster_id", + id: "db_node_id", + }); + } +} + +``` + +## Argument Reference + +The following arguments are required: + +* `cloud_vm_cluster_id` - (Required) The unique identifier of the cloud vm cluster. +* `id` - (Required) The unique identifier of db node associated with vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `cloud_vm_cluster_id` - The ID of the cloud VM cluster. +* `status` - The current status of the DB node. +* `statusReason` - Additional information about the status of the DB node. +* `additional_details` - Additional information about the planned maintenance. +* `backup_ip_id` - The Oracle Cloud ID (OCID) of the backup IP address that's associated with the DB node. +* `backup_vnic2_id` - The OCID of the second backup VNIC. +* `backup_vnic_id` - The OCID of the backup VNIC. +* `cpuCoreCount` - The number of CPU cores enabled on the DB node. +* `db_storage_size_in_gbs` - The amount of local node storage, in gigabytes (GB), allocated on the DB node. +* `db_server_id` - The unique identifier of the DB server that is associated with the DB node. +* `dbSystemId` - The OCID of the DB system. +* `fault_domain` - The name of the fault domain the instance is contained in. +* `host_ip_id` - The OCID of the host IP address that's associated with the DB node. +* `hostname` - The host name for the DB node. +* `ocid` - The OCID of the DB node. +* `ociResourceAnchorName` - The name of the OCI resource anchor for the DB node. +* `maintenance_type` - The type of database node maintenance. Either VMDB_REBOOT_MIGRATION or EXADBXS_REBOOT_MIGRATION. +* `memorySizeInGbs` - The allocated memory in GBs on the DB node. +* `software_storage_size_in_gbs` - The size (in GB) of the block storage volume allocation for the DB system. +* `createdAt` - The date and time when the DB node was created. +* `time_maintenance_window_end` - The end date and time of the maintenance window. +* `time_maintenance_window_start` - The start date and time of the maintenance window. +* `total_cpu_core_count` - The total number of CPU cores reserved on the DB node. +* `vnic2_id` - The OCID of the second VNIC. +* `vnic_id` - The OCID of the VNIC. +* `privateIpAddress` - The private IP address assigned to the DB node. +* `floating_ip_address` - The floating IP address assigned to the DB node. + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/d/odb_db_nodes.html.markdown b/website/docs/cdktf/typescript/d/odb_db_nodes.html.markdown new file mode 100644 index 000000000000..d2069b20754a --- /dev/null +++ b/website/docs/cdktf/typescript/d/odb_db_nodes.html.markdown @@ -0,0 +1,86 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_nodes" +page_title: "AWS: aws_odb_db_nodes" +description: |- + Terraform data source for managing db nodes linked to cloud vm cluster of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_nodes + +Terraform data source for manging db nodes linked to cloud vm cluster of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { DataAwsOdbDbNodes } from "./.gen/providers/aws/"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new DataAwsOdbDbNodes(this, "example", { + cloud_vm_cluster_id: "example", + }); + } +} + +``` + +## Argument Reference + +The following arguments are required: + +* `cloud_vm_cluster_id` - (Required) The unique identifier of the cloud vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `db_nodes` - The list of DB nodes along with their properties. + +### db_nodes + +* `additional_details` - Additional information about the planned maintenance. +* `backup_ip_id` - The Oracle Cloud ID (OCID) of the backup IP address that's associated with the DB node. +* `backup_vnic_2_id` - The OCID of the second backup virtual network interface card (VNIC) for the DB node. +* `backup_vnic_id` - The OCID of the backup VNIC for the DB node. +* `cpuCoreCount` - The number of CPU cores enabled on the DB node. +* `createdAt` - The date and time when the DB node was created. +* `db_node_arn` - The Amazon Resource Name (ARN) of the DB node. +* `db_node_id` - The unique identifier of the DB node. +* `dbNodeStorageSizeInGbs` - The amount of local node storage, in gigabytes (GB), that's allocated on the DB node. +* `db_server_id` - The unique identifier of the database server that's associated with the DB node. +* `dbSystemId` - The OCID of the DB system. +* `fault_domain` - The name of the fault domain where the DB node is located. +* `host_ip_id` - The OCID of the host IP address that's associated with the DB node. +* `hostname` - The host name for the DB node. +* `maintenance_type` - The type of maintenance the DB node is undergoing. +* `memorySizeInGbs` - The amount of memory, in gigabytes (GB), that's allocated on the DB node. +* `ociResourceAnchorName` - The name of the OCI resource anchor for the DB node. +* `ocid` - The OCID of the DB node. +* `software_storage_size_in_gb` - The size of the block storage volume, in gigabytes (GB), that's allocated for the DB system. This attribute applies only for virtual machine DB systems. +* `status` - The current status of the DB node. +* `statusReason` - Additional information about the status of the DB node. +* `time_maintenance_window_end` - The end date and time of the maintenance window. +* `time_maintenance_window_start` - The start date and time of the maintenance window. +* `total_cpu_core_count` - The total number of CPU cores reserved on the DB node. +* `vnic_2_id` - The OCID of the second VNIC. +* `vnic_id` - The OCID of the VNIC. + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/d/odb_db_server.html.markdown b/website/docs/cdktf/typescript/d/odb_db_server.html.markdown new file mode 100644 index 000000000000..74a7f0ab543c --- /dev/null +++ b/website/docs/cdktf/typescript/d/odb_db_server.html.markdown @@ -0,0 +1,77 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_server" +page_title: "AWS: aws_odb_db_server" +description: |- + Terraform data source for managing db server linked to exadata infrastructure of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_server + +Terraform data source for manging db server linked to exadata infrastructure of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { DataAwsOdbDbServer } from "./.gen/providers/aws/"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new DataAwsOdbDbServer(this, "example", { + cloud_exadata_infrastructure_id: "exadata_infra_id", + id: "db_server_id", + }); + } +} + +``` + +## Argument Reference + +The following arguments are required: + +* `cloudExadataInfrastructureId` - (Required) The unique identifier of the cloud vm cluster. +* `id` - (Required) The unique identifier of db node associated with vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `autonomous_virtual_machine_ids` - The list of unique identifiers for the Autonomous VMs associated with this database server. +* `autonomous_vm_cluster_ids` - The OCID of the autonomous VM clusters that are associated with the database server. +* `computeModel` - The compute model of the database server. +* `status` - The status of the database server. +* `statusReason` - Additional information about the current status of the database server. +* `cpuCoreCount` - The number of CPU cores enabled on the database server. +* `dbNodeStorageSizeInGbs` - The allocated local node storage in GBs on the database server. +* `db_server_patching_details` - The scheduling details for the quarterly maintenance window. Patching and system updates take place during the maintenance window. +* `displayName` - The display name of the database server. +* `exadata_infrastructure_id` - The exadata infrastructure ID of the database server. +* `ocid` - The OCID of the database server to retrieve information about. +* `ociResourceAnchorName` - The name of the OCI resource anchor. +* `maxCpuCount` - The total number of CPU cores available. +* `max_db_node_storage_in_gbs` - The total local node storage available in GBs. +* `maxMemoryInGbs` - The total memory available in GBs. +* `memorySizeInGbs` - The allocated memory in GBs on the database server. +* `shape` - The shape of the database server. The shape determines the amount of CPU, storage, and memory resources available. +* `createdAt` - The date and time when the database server was created. +* `vm_cluster_ids` - The OCID of the VM clusters that are associated with the database server. + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/d/odb_db_servers.html.markdown b/website/docs/cdktf/typescript/d/odb_db_servers.html.markdown new file mode 100644 index 000000000000..1dc76bdcdf51 --- /dev/null +++ b/website/docs/cdktf/typescript/d/odb_db_servers.html.markdown @@ -0,0 +1,80 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_servers" +page_title: "AWS: aws_odb_db_servers" +description: |- + Terraform data source for managing db servers linked to exadata infrastructure of Oracle Database@AWS. +--- + + + +# Data Source: aws_odb_db_servers + +Terraform data source for manging db servers linked to exadata infrastructure of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { DataAwsOdbDbServers } from "./.gen/providers/aws/"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + new DataAwsOdbDbServers(this, "example", { + cloud_exadata_infrastructure_id: "exadata_infra_id", + }); + } +} + +``` + +## Argument Reference + +The following arguments are required: + +* `cloudExadataInfrastructureId` - (Required) The unique identifier of the cloud vm cluster. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `dbServers` - the list of DB servers along with their properties. + +### db_servers + +* `autonomous_virtual_machine_ids` - A list of unique identifiers for the Autonomous VMs. +* `autonomous_vm_cluster_ids` - A list of identifiers for the Autonomous VM clusters. +* `computeModel` - The OCI compute model used when you create or clone an instance: **ECPU** or **OCPU**. ECPUs are based on the number of cores elastically allocated from a pool of compute and storage servers, while OCPUs are based on the physical core of a processor with hyper-threading enabled. +* `cpuCoreCount` - The number of CPU cores enabled on the database server. +* `createdAt` - The date and time when the database server was created. +* `dbNodeStorageSizeInGbs` - The amount of local node storage, in gigabytes (GB), that's allocated on the database server. +* `db_server_id` - The unique identifier of the database server. +* `db_server_patching_details` - The scheduling details for the quarterly maintenance window. Patching and system updates take place during the maintenance window. +* `displayName` - The user-friendly name of the database server. The name doesn't need to be unique. +* `exadata_infrastructure_id` - The ID of the Exadata infrastructure that hosts the database server. +* `maxCpuCount` - The total number of CPU cores available on the database server. +* `max_db_node_storage_in_gbs` - The total amount of local node storage, in gigabytes (GB), that's available on the database server. +* `maxMemoryInGbs` - The total amount of memory, in gigabytes (GB), that's available on the database server. +* `memorySizeInGbs` - The amount of memory, in gigabytes (GB), that's allocated on the database server. +* `ociResourceAnchorName` - The name of the OCI resource anchor for the database server. +* `ocid` - The OCID of the database server. +* `shape` - The hardware system model of the Exadata infrastructure that the database server is hosted on. The shape determines the amount of CPU, storage, and memory resources available. +* `status` - The current status of the database server. +* `statusReason` - Additional information about the status of the database server. +* `vm_cluster_ids` - The IDs of the VM clusters that are associated with the database server. + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/index.html.markdown b/website/docs/cdktf/typescript/index.html.markdown index 6f305e6c8766..49ab0b6f048f 100644 --- a/website/docs/cdktf/typescript/index.html.markdown +++ b/website/docs/cdktf/typescript/index.html.markdown @@ -11,7 +11,7 @@ description: |- The Amazon Web Services (AWS) provider is Terraform’s most widely-used provider and the industry-standard way to manage AWS infrastructure as code. It is an indispensable part of how leading technology companies, global banks, government agencies, and some of the largest enterprises in the world build and operate in the cloud. Every day, it provisions and orchestrates billions of dollars of AWS infrastructure across thousands of organizations. -With 1,537 resources and 609 data sources, the AWS provider spans the full breadth of AWS services—from foundational capabilities like compute, storage, networking, and identity management to advanced services for AI, analytics, and event-driven architectures, including Lambda, RDS, SageMaker, and Bedrock. Whether automating a single S3 bucket or orchestrating a multi-region, enterprise-scale environment, the provider delivers consistent, reliable workflows that scale with your needs. +With 1,543 resources and 615 data sources, the AWS provider spans the full breadth of AWS services—from foundational capabilities like compute, storage, networking, and identity management to advanced services for AI, analytics, and event-driven architectures, including Lambda, RDS, SageMaker, and Bedrock. Whether automating a single S3 bucket or orchestrating a multi-region, enterprise-scale environment, the provider delivers consistent, reliable workflows that scale with your needs. Configure the provider with your AWS credentials, and you can immediately begin creating and managing infrastructure in a safe, repeatable way. Use the navigation on the left to explore the available resources, or start with our [Get Started tutorials](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/infrastructure-as-code?in=terraform/aws-get-started&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) to learn the fundamentals. For deeper guidance on specific AWS services, visit the [AWS services tutorials](https://developer.hashicorp.com/terraform/tutorials/aws?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS). @@ -948,4 +948,4 @@ Approaches differ per authentication providers: There used to be no better way to get account ID out of the API when using the federated account until `sts:GetCallerIdentity` was introduced. - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/cleanrooms_configured_table.html.markdown b/website/docs/cdktf/typescript/r/cleanrooms_configured_table.html.markdown index 33b82dc203a1..14f2c4687555 100644 --- a/website/docs/cdktf/typescript/r/cleanrooms_configured_table.html.markdown +++ b/website/docs/cdktf/typescript/r/cleanrooms_configured_table.html.markdown @@ -79,6 +79,32 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_cleanrooms_configured_table.example + identity = { + id = "1234abcd-12ab-34cd-56ef-1234567890ab" + } +} + +resource "aws_cleanrooms_configured_table" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +* `id` - (String) ID of the cleanrooms configured table. + +#### Optional + +* `accountId` (String) AWS Account where this resource is managed. +* `region` (String) Region where this resource is managed. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import `aws_cleanrooms_configured_table` using the `id`. For example: ```typescript @@ -109,4 +135,4 @@ Using `terraform import`, import `aws_cleanrooms_configured_table` using the `id % terraform import aws_cleanrooms_configured_table.table 1234abcd-12ab-34cd-56ef-1234567890ab ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/cloudfront_distribution.html.markdown b/website/docs/cdktf/typescript/r/cloudfront_distribution.html.markdown index c1f4c7d36d29..200fcc9a5e65 100644 --- a/website/docs/cdktf/typescript/r/cloudfront_distribution.html.markdown +++ b/website/docs/cdktf/typescript/r/cloudfront_distribution.html.markdown @@ -754,6 +754,7 @@ argument should not be specified. * `httpPort` (Required) - HTTP port the custom origin listens on. * `httpsPort` (Required) - HTTPS port the custom origin listens on. +* `ipAddressType` (Optional) - IP protocol CloudFront uses when connecting to your origin. Valid values: `ipv4`, `ipv6`, `dualstack`. * `originProtocolPolicy` (Required) - Origin protocol policy to apply to your origin. One of `http-only`, `https-only`, or `match-viewer`. * `originSslProtocols` (Required) - List of SSL/TLS protocols that CloudFront can use when connecting to your origin over HTTPS. Valid values: `SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`. For more information, see [Minimum Origin SSL Protocol](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesOriginSSLProtocols) in the Amazon CloudFront Developer Guide. * `originKeepaliveTimeout` - (Optional) The Custom KeepAlive timeout, in seconds. By default, AWS enforces an upper limit of `60`. But you can request an [increase](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#request-custom-request-timeout). Defaults to `5`. @@ -870,4 +871,4 @@ Using `terraform import`, import CloudFront Distributions using the `id`. For ex % terraform import aws_cloudfront_distribution.distribution E74FTE3EXAMPLE ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/connect_instance.html.markdown b/website/docs/cdktf/typescript/r/connect_instance.html.markdown index 331f19c3ba4a..1aca4a905424 100644 --- a/website/docs/cdktf/typescript/r/connect_instance.html.markdown +++ b/website/docs/cdktf/typescript/r/connect_instance.html.markdown @@ -132,6 +132,32 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_connect_instance.example + identity = { + id = "f1288a1f-6193-445a-b47e-af739b2" + } +} + +resource "aws_connect_instance" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +* `id` - (String) ID of the connect instance. + +#### Optional + +- `accountId` (String) AWS Account where this resource is managed. +- `region` (String) Region where this resource is managed. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Connect instances using the `id`. For example: ```typescript @@ -162,4 +188,4 @@ Using `terraform import`, import Connect instances using the `id`. For example: % terraform import aws_connect_instance.example f1288a1f-6193-445a-b47e-af739b2 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/connect_phone_number.html.markdown b/website/docs/cdktf/typescript/r/connect_phone_number.html.markdown index 96726908f818..3b4cf5f21c94 100644 --- a/website/docs/cdktf/typescript/r/connect_phone_number.html.markdown +++ b/website/docs/cdktf/typescript/r/connect_phone_number.html.markdown @@ -131,6 +131,31 @@ The `status` configuration block supports the following attributes: ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_connect_phone_number.example + identity = { + id = "1234abcd-12ab-34cd-56ef-1234567890ab" + } +} +resource "aws_connect_phone_number" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +* `id` - (String) ID of the connect phone number. + +#### Optional + +- `accountId` (String) AWS Account where this resource is managed. +- `region` (String) Region where this resource is managed. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Amazon Connect Phone Numbers using its `id`. For example: ```typescript @@ -161,4 +186,4 @@ Using `terraform import`, import Amazon Connect Phone Numbers using its `id`. Fo % terraform import aws_connect_phone_number.example 12345678-abcd-1234-efgh-9876543210ab ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/db_proxy.html.markdown b/website/docs/cdktf/typescript/r/db_proxy.html.markdown index 4adf52f5251d..99b444c1e3dc 100644 --- a/website/docs/cdktf/typescript/r/db_proxy.html.markdown +++ b/website/docs/cdktf/typescript/r/db_proxy.html.markdown @@ -167,8 +167,9 @@ This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `name` - (Required) The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens. -* `auth` - (Required) Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters. Described below. +* `auth` - (Optional) Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters. Required when `default_auth_scheme` is `NONE` or unspecified. Described below. * `debugLogging` - (Optional) Whether the proxy includes detailed information about SQL statements in its logs. This information helps you to debug issues involving SQL behavior or the performance and scalability of the proxy connections. The debug information includes the text of SQL statements that you submit through the proxy. Thus, only enable this setting when needed for debugging, and only when you have security measures in place to safeguard any sensitive information that appears in the logs. +* `default_auth_scheme` - (Optional) Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. Valid values are `NONE` and `IAM_AUTH`. Defaults to `NONE`. * `engineFamily` - (Required, Forces new resource) The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. For Aurora MySQL, RDS for MariaDB, and RDS for MySQL databases, specify `MYSQL`. For Aurora PostgreSQL and RDS for PostgreSQL databases, specify `POSTGRESQL`. For RDS for Microsoft SQL Server, specify `SQLSERVER`. Valid values are `MYSQL`, `POSTGRESQL`, and `SQLSERVER`. * `idleClientTimeout` - (Optional) The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it. You can set this value higher or lower than the connection timeout limit for the associated database. * `requireTls` - (Optional) A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy. @@ -231,4 +232,4 @@ Using `terraform import`, import DB proxies using the `name`. For example: % terraform import aws_db_proxy.example example ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/dsql_cluster.html.markdown b/website/docs/cdktf/typescript/r/dsql_cluster.html.markdown index 7621e2ee6b97..50c27fba46c7 100644 --- a/website/docs/cdktf/typescript/r/dsql_cluster.html.markdown +++ b/website/docs/cdktf/typescript/r/dsql_cluster.html.markdown @@ -43,7 +43,10 @@ class MyConvertedCode extends TerraformStack { This resource supports the following arguments: -* `deletionProtectionEnabled` - (Required) Whether deletion protection is enabled in this cluster. +* `deletionProtectionEnabled` - (Optional) Whether deletion protection is enabled in this cluster. + Default value is `false`. +* `forceDestroy` - (Optional) Destroys cluster even if `deletionProtectionEnabled` is set to `true`. + Default value is `false`. * `kmsEncryptionKey` - (Optional) The ARN of the AWS KMS key that encrypts data in the DSQL Cluster, or `"AWS_OWNED_KMS_KEY"`. * `multiRegionProperties` - (Optional) Multi-region properties of the DSQL Cluster. * `witnessRegion` - (Required) Witness region for the multi-region clusters. Setting this makes this cluster a multi-region cluster. Changing it recreates the resource. @@ -104,4 +107,4 @@ Using `terraform import`, import DSQL Cluster using the `identifier`. For exampl % terraform import aws_dsql_cluster.example abcde1f234ghijklmnop5qr6st ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/ecs_service.html.markdown b/website/docs/cdktf/typescript/r/ecs_service.html.markdown index f538753c2639..9ddda9798702 100644 --- a/website/docs/cdktf/typescript/r/ecs_service.html.markdown +++ b/website/docs/cdktf/typescript/r/ecs_service.html.markdown @@ -243,7 +243,7 @@ The following arguments are optional: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `alarms` - (Optional) Information about the CloudWatch alarms. [See below](#alarms). * `availabilityZoneRebalancing` - (Optional) ECS automatically redistributes tasks within a service across Availability Zones (AZs) to mitigate the risk of impaired application availability due to underlying infrastructure failures and task lifecycle activities. The valid values are `ENABLED` and `DISABLED`. When creating a new service, if no value is specified, it defaults to `ENABLED` if the service is compatible with AvailabilityZoneRebalancing. When updating an existing service, if no value is specified it defaults to the existing service's AvailabilityZoneRebalancing value. If the service never had an AvailabilityZoneRebalancing value set, Amazon ECS treats this as `DISABLED`. -* `capacityProviderStrategy` - (Optional) Capacity provider strategies to use for the service. Can be one or more. These can be updated without destroying and recreating the service only if `force_new_deployment = true` and not changing from 0 `capacityProviderStrategy` blocks to greater than 0, or vice versa. [See below](#capacity_provider_strategy). Conflicts with `launchType`. +* `capacityProviderStrategy` - (Optional) Capacity provider strategies to use for the service. Can be one or more. Updating this argument requires `force_new_deployment = true`. [See below](#capacity_provider_strategy). Conflicts with `launchType`. * `cluster` - (Optional) ARN of an ECS cluster. * `deploymentCircuitBreaker` - (Optional) Configuration block for deployment circuit breaker. [See below](#deployment_circuit_breaker). * `deploymentConfiguration` - (Optional) Configuration block for deployment settings. [See below](#deployment_configuration). @@ -549,4 +549,4 @@ Using `terraform import`, import ECS services using the `name` together with ecs % terraform import aws_ecs_service.imported cluster-name/service-name ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/eks_addon.html.markdown b/website/docs/cdktf/typescript/r/eks_addon.html.markdown index 61485e584cf0..8f7e4e536815 100644 --- a/website/docs/cdktf/typescript/r/eks_addon.html.markdown +++ b/website/docs/cdktf/typescript/r/eks_addon.html.markdown @@ -68,13 +68,14 @@ Custom add-on configuration can be passed using `configurationValues` as a singl ~> **Note:** `configurationValues` is a single JSON string should match the valid JSON schema for each add-on with specific version. -To find the correct JSON schema for each add-on can be extracted using [describe-addon-configuration](https://docs.aws.amazon.com/cli/latest/reference/eks/describe-addon-configuration.html) call. -This below is an example for extracting the `configurationValues` schema for `coredns`. +You can use [describe-addon-configuration](https://docs.aws.amazon.com/cli/latest/reference/eks/describe-addon-configuration.html) to extract each add-on's JSON schema. +Here's an example command to extract the `configurationValues` schema for `coredns`. ```bash - aws eks describe-addon-configuration \ - --addon-name coredns \ - --addon-version v1.10.1-eksbuild.1 +aws eks describe-addon-configuration \ + --addon-name coredns \ + --addon-version v1.10.1-eksbuild.1 \ + | jq -r .configurationSchema | jq . ``` Example to create a `coredns` managed addon with custom `configurationValues`. @@ -320,4 +321,4 @@ Using `terraform import`, import EKS add-on using the `clusterName` and `addonNa % terraform import aws_eks_addon.my_eks_addon my_cluster_name:my_addon_name ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/lakeformation_lf_tag_expression.html.markdown b/website/docs/cdktf/typescript/r/lakeformation_lf_tag_expression.html.markdown new file mode 100644 index 000000000000..d1f379ee4707 --- /dev/null +++ b/website/docs/cdktf/typescript/r/lakeformation_lf_tag_expression.html.markdown @@ -0,0 +1,106 @@ +--- +subcategory: "Lake Formation" +layout: "aws" +page_title: "AWS: aws_lakeformation_lf_tag_expression" +description: |- + Terraform resource for managing an AWS Lake Formation LF Tag Expression. +--- + + +# Resource: aws_lakeformation_lf_tag_expression + +Terraform resource for managing an AWS Lake Formation LF Tag Expression. + +## Example Usage + +### Basic Usage + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { LakeformationLfTagExpression } from "./.gen/providers/aws/"; +import { LakeformationLfTag } from "./.gen/providers/aws/lakeformation-lf-tag"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + const example = new LakeformationLfTag(this, "example", { + key: "example", + values: ["value"], + }); + const awsLakeformationLfTagExpressionExample = + new LakeformationLfTagExpression(this, "example_1", { + expression: [ + { + tag_key: example.key, + tag_values: example.values, + }, + ], + name: "example", + }); + /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ + awsLakeformationLfTagExpressionExample.overrideLogicalId("example"); + } +} + +``` + +## Argument Reference + +The following arguments are required: + +* `name` - (Required) Name of the LF-Tag Expression. +* `expression` - (Required) A list of LF-Tag conditions (key-value pairs). See [expression](#expression) for more details. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `catalogId` - (Optional) ID of the Data Catalog. Defaults to the account ID if not specified. +* `description` - (Optional) Description of the LF-Tag Expression. + +### expression + +* `tagKey` - (Required) The key-name for the LF-Tag. +* `tagValues` - (Required) A list of possible values for the LF-Tag + +## Attribute Reference + +This resource exports no additional attributes. + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Lake Formation LF Tag Expression using the `name,catalog_id`. For example: + +```typescript +// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug +import { Construct } from "constructs"; +import { TerraformStack } from "cdktf"; +/* + * Provider bindings are generated by running `cdktf get`. + * See https://cdk.tf/provider-generation for more details. + */ +import { LakeformationLfTagExpression } from "./.gen/providers/aws/"; +class MyConvertedCode extends TerraformStack { + constructor(scope: Construct, name: string) { + super(scope, name); + LakeformationLfTagExpression.generateConfigForImport( + this, + "example", + "example-tag-expression,123456789012" + ); + } +} + +``` + +Using `terraform import`, import Lake Formation LF Tag Expression using the `name,catalog_id`. For example: + +```console +% terraform import aws_lakeformation_lf_tag_expression.example example-tag-expression,123456789012 +``` + + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/macie2_member.html.markdown b/website/docs/cdktf/typescript/r/macie2_member.html.markdown index 95f58b7e151d..b52d02c644d3 100644 --- a/website/docs/cdktf/typescript/r/macie2_member.html.markdown +++ b/website/docs/cdktf/typescript/r/macie2_member.html.markdown @@ -50,7 +50,6 @@ This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `accountId` - (Required) The AWS account ID for the account. * `email` - (Required) The email address for the account. -* `tags` - (Optional) A map of key-value pairs that specifies the tags to associate with the account in Amazon Macie. * `status` - (Optional) Specifies the status for the account. To enable Amazon Macie and start all Macie activities for the account, set this value to `ENABLED`. Valid values are `ENABLED` or `PAUSED`. * `invite` - (Optional) Send an invitation to a member * `invitationMessage` - (Optional) A custom message to include in the invitation. Amazon Macie adds this message to the standard content that it sends for an invitation. @@ -97,4 +96,4 @@ Using `terraform import`, import `aws_macie2_member` using the account ID of the % terraform import aws_macie2_member.example 123456789012 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/pinpointsmsvoicev2_phone_number.html.markdown b/website/docs/cdktf/typescript/r/pinpointsmsvoicev2_phone_number.html.markdown index a947e394c9b9..e13413cb6b3c 100644 --- a/website/docs/cdktf/typescript/r/pinpointsmsvoicev2_phone_number.html.markdown +++ b/website/docs/cdktf/typescript/r/pinpointsmsvoicev2_phone_number.html.markdown @@ -50,7 +50,7 @@ This resource supports the following arguments: * `optOutListName` - (Optional) The name of the opt-out list to associate with the phone number. * `registrationId` - (Optional) Use this field to attach your phone number for an external registration process. * `selfManagedOptOutsEnabled` - (Optional) When set to `false` an end recipient sends a message that begins with HELP or STOP to one of your dedicated numbers, AWS End User Messaging SMS and Voice automatically replies with a customizable message and adds the end recipient to the opt-out list. When set to true you’re responsible for responding to HELP and STOP requests. You’re also responsible for tracking and honoring opt-out request. -* `twoWayChannelArn` - (Optional) The Amazon Resource Name (ARN) of the two way channel. +* `twoWayChannelArn` - (Optional) Configuration for two-way SMS. Specify an ARN to receive incoming SMS messages, or `connect.[region].amazonaws.com` (with `[region]` replaced by the AWS Region of the Amazon Connect instance) to set Amazon Connect as the inbound destination. * `twoWayChannelEnabled` - (Optional) By default this is set to `false`. When set to `true` you can receive incoming text messages from your end recipients. * `twoWayChannelRole` - (Optional) IAM Role ARN for a service to assume, to be able to post inbound SMS messages. @@ -96,4 +96,4 @@ Using `terraform import`, import phone numbers using the `id`. For example: % terraform import aws_pinpointsmsvoicev2_phone_number.example phone-abcdef0123456789abcdef0123456789 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/route53_zone.html.markdown b/website/docs/cdktf/typescript/r/route53_zone.html.markdown index 793e6be6ed4f..88480df0509b 100644 --- a/website/docs/cdktf/typescript/r/route53_zone.html.markdown +++ b/website/docs/cdktf/typescript/r/route53_zone.html.markdown @@ -91,14 +91,28 @@ import { TerraformStack } from "cdktf"; * See https://cdk.tf/provider-generation for more details. */ import { Route53Zone } from "./.gen/providers/aws/route53-zone"; +import { Vpc } from "./.gen/providers/aws/vpc"; class MyConvertedCode extends TerraformStack { constructor(scope: Construct, name: string) { super(scope, name); + const primary = new Vpc(this, "primary", { + cidrBlock: "10.6.0.0/16", + enableDnsHostnames: true, + enableDnsSupport: true, + }); + const secondary = new Vpc(this, "secondary", { + cidrBlock: "10.7.0.0/16", + enableDnsHostnames: true, + enableDnsSupport: true, + }); new Route53Zone(this, "private", { name: "example.com", vpc: [ { - vpcId: example.id, + vpcId: primary.id, + }, + { + vpcId: secondary.id, }, ], }); @@ -170,4 +184,4 @@ Using `terraform import`, import Route53 Zones using the zone `id`. For example: % terraform import aws_route53_zone.myzone Z1D633PJN98FT9 ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/route53recoverycontrolconfig_cluster.html.markdown b/website/docs/cdktf/typescript/r/route53recoverycontrolconfig_cluster.html.markdown index 461d37ecaa4d..93ef1dddd247 100644 --- a/website/docs/cdktf/typescript/r/route53recoverycontrolconfig_cluster.html.markdown +++ b/website/docs/cdktf/typescript/r/route53recoverycontrolconfig_cluster.html.markdown @@ -36,9 +36,10 @@ class MyConvertedCode extends TerraformStack { ## Argument Reference -The following arguments are required: +This resource supports the following arguments: * `name` - (Required) Unique name describing the cluster. +* `networkType` - (Optional) Network type of cluster. Valid values are `IPV4` and `DUALSTACK`. Defaults to `IPV4`. ## Attribute Reference @@ -85,4 +86,4 @@ Using `terraform import`, import Route53 Recovery Control Config cluster using t % terraform import aws_route53recoverycontrolconfig_cluster.mycluster arn:aws:route53-recovery-control::313517334327:cluster/f9ae13be-a11e-4ec7-8522-94a70468e6ea ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/s3control_bucket.html.markdown b/website/docs/cdktf/typescript/r/s3control_bucket.html.markdown index ac53bf8a2053..f0be7a847d5b 100644 --- a/website/docs/cdktf/typescript/r/s3control_bucket.html.markdown +++ b/website/docs/cdktf/typescript/r/s3control_bucket.html.markdown @@ -58,6 +58,27 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_s3control_bucket.example + identity = { + "arn" = "arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-12345678/bucket/example" + } +} + +resource "aws_s3control_bucket" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +- `arn` (String) ARN of the bucket. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import S3 Control Buckets using Amazon Resource Name (ARN). For example: ```typescript @@ -88,4 +109,4 @@ Using `terraform import`, import S3 Control Buckets using Amazon Resource Name ( % terraform import aws_s3control_bucket.example arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-12345678/bucket/example ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/sfn_activity.html.markdown b/website/docs/cdktf/typescript/r/sfn_activity.html.markdown index 17c79aef2e59..5f7f43450f1b 100644 --- a/website/docs/cdktf/typescript/r/sfn_activity.html.markdown +++ b/website/docs/cdktf/typescript/r/sfn_activity.html.markdown @@ -84,13 +84,29 @@ This resource supports the following arguments: This resource exports the following attributes in addition to the arguments above: -* `id` - The Amazon Resource Name (ARN) that identifies the created activity. -* `name` - The name of the activity. -* `creationDate` - The date the activity was created. +* `id` - Amazon Resource Name (ARN) of the activity. +* `arn` - Amazon Resource Name (ARN) of the activity. +* `name` - Name of the activity. +* `creationDate` - Date the activity was created. * `tagsAll` - A map of tags assigned to the resource, including those inherited from the provider [`defaultTags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_sfn_activity.example + identity = { + "arn" = "arn:aws:states:eu-west-1:123456789098:activity:bar" + } +} + +resource "aws_sfn_activity" "example" { + ### Configuration omitted for brevity ### +} +``` + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import activities using the `arn`. For example: ```typescript @@ -107,7 +123,7 @@ class MyConvertedCode extends TerraformStack { super(scope, name); SfnActivity.generateConfigForImport( this, - "foo", + "example", "arn:aws:states:eu-west-1:123456789098:activity:bar" ); } @@ -118,7 +134,7 @@ class MyConvertedCode extends TerraformStack { Using `terraform import`, import activities using the `arn`. For example: ```console -% terraform import aws_sfn_activity.foo arn:aws:states:eu-west-1:123456789098:activity:bar +% terraform import aws_sfn_activity.example arn:aws:states:eu-west-1:123456789098:activity:bar ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/sfn_alias.html.markdown b/website/docs/cdktf/typescript/r/sfn_alias.html.markdown index a706d2906673..79ea3700b1f9 100644 --- a/website/docs/cdktf/typescript/r/sfn_alias.html.markdown +++ b/website/docs/cdktf/typescript/r/sfn_alias.html.markdown @@ -80,6 +80,21 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_sfn_alias.example + identity = { + "arn" = "arn:aws:states:us-east-1:123456789098:stateMachine:myStateMachine:foo" + } +} + +resource "aws_sfn_alias" "example" { + ### Configuration omitted for brevity ### +} +``` + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SFN (Step Functions) Alias using the `arn`. For example: ```typescript @@ -110,4 +125,4 @@ Using `terraform import`, import SFN (Step Functions) Alias using the `arn`. For % terraform import aws_sfn_alias.foo arn:aws:states:us-east-1:123456789098:stateMachine:myStateMachine:foo ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/cdktf/typescript/r/ssmcontacts_contact_channel.html.markdown b/website/docs/cdktf/typescript/r/ssmcontacts_contact_channel.html.markdown index ca563d05e208..9f1c4603fce4 100644 --- a/website/docs/cdktf/typescript/r/ssmcontacts_contact_channel.html.markdown +++ b/website/docs/cdktf/typescript/r/ssmcontacts_contact_channel.html.markdown @@ -99,7 +99,28 @@ This resource exports the following attributes in addition to the arguments abov ## Import -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SSM Contact Channel using the `ARN`. For example: +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_ssmcontacts_contact_channel.example + identity = { + "arn" = "arn:aws:ssm-contacts:us-west-2:123456789012:contact-channel/example" + } +} + +resource "aws_ssmcontacts_contact_channel" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +- `arn` (String) Amazon Resource Name (ARN) of the contact channel. + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SSM Contact Channel using the `arn`. For example: ```typescript // DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug @@ -123,10 +144,10 @@ class MyConvertedCode extends TerraformStack { ``` -Using `terraform import`, import SSM Contact Channel using the `ARN`. For example: +Using `terraform import`, import SSM Contact Channel using the `arn`. For example: ```console % terraform import aws_ssmcontacts_contact_channel.example arn:aws:ssm-contacts:us-west-2:123456789012:contact-channel/example ``` - \ No newline at end of file + \ No newline at end of file diff --git a/website/docs/d/db_proxy.html.markdown b/website/docs/d/db_proxy.html.markdown index ff1a895002e9..ae297f065042 100644 --- a/website/docs/d/db_proxy.html.markdown +++ b/website/docs/d/db_proxy.html.markdown @@ -32,6 +32,7 @@ This data source exports the following attributes in addition to the arguments a * `arn` - ARN of the DB Proxy. * `auth` - Configuration(s) with authorization mechanisms to connect to the associated instance or cluster. * `debug_logging` - Whether the proxy includes detailed information about SQL statements in its logs. +* `default_auth_scheme` - Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. * `endpoint` - Endpoint that you can use to connect to the DB proxy. * `engine_family` - Kinds of databases that the proxy can connect to. * `idle_client_timeout` - Number of seconds a connection to the proxy can have no activity before the proxy drops the client connection. diff --git a/website/docs/d/ec2_instance_type_offering.html.markdown b/website/docs/d/ec2_instance_type_offering.html.markdown index 9150643b44b9..b5a4957feb1b 100644 --- a/website/docs/d/ec2_instance_type_offering.html.markdown +++ b/website/docs/d/ec2_instance_type_offering.html.markdown @@ -43,6 +43,7 @@ This data source exports the following attributes in addition to the arguments a * `id` - EC2 Instance Type. * `instance_type` - EC2 Instance Type. +* `location` - Identifier for the location. ## Timeouts diff --git a/website/docs/d/odb_cloud_vm_cluster.html.markdown b/website/docs/d/odb_cloud_vm_cluster.html.markdown index 53d1f8f0be16..55a0b2e77402 100644 --- a/website/docs/d/odb_cloud_vm_cluster.html.markdown +++ b/website/docs/d/odb_cloud_vm_cluster.html.markdown @@ -8,7 +8,7 @@ description: |- # Data Source: aws_odb_cloud_vm_cluster -Terraform data source for Exadata Infrastructure resource in AWS for Oracle Database@AWS. +Terraform data source for cloud vm cluster in AWS for Oracle Database@AWS. You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). @@ -17,8 +17,8 @@ You can find out more about Oracle Database@AWS from [User Guide](https://docs.a ### Basic Usage ```terraform -data "aws_odb_db_servers_list" "example" { - cloud_exadata_infrastructure_id = "example-id" +data "aws_odb_cloud_vm_cluster" "example" { + id = "example-id" } ``` @@ -26,7 +26,7 @@ data "aws_odb_db_servers_list" "example" { The following arguments are required: -* `id` - (Required) The unique identifier of the Exadata infrastructure. +* `id` - (Required) The unique identifier of the cloud vm cluster. The following arguments are optional: diff --git a/website/docs/d/odb_db_system_shapes.html.markdown b/website/docs/d/odb_db_system_shapes.html.markdown new file mode 100644 index 000000000000..39de8e203fd4 --- /dev/null +++ b/website/docs/d/odb_db_system_shapes.html.markdown @@ -0,0 +1,34 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_db_system_shapes" +page_title: "AWS: aws_odb_db_system_shapes" +description: |- + Terraform data source to retrieve available system shapes Oracle Database@AWS. +--- + +# Data Source: aws_odb_db_system_shapes + +Terraform data source to retrieve available system shapes Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```terraform +data "aws_odb_db_system_shapes" "example" {} +``` + +## Argument Reference + +The following arguments are optional: + +* `availability_zone_id` - (Optional) The physical ID of the AZ, for example, use1-az4. This ID persists across accounts. +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `db_system_shapes` - IThe list of shapes and their properties. Information about a hardware system model (shape) that's available for an Exadata infrastructure. The shape determines resources, such as CPU cores, memory, and storage, to allocate to the Exadata infrastructure. diff --git a/website/docs/d/odb_gi_versions.html.markdown b/website/docs/d/odb_gi_versions.html.markdown new file mode 100644 index 000000000000..f3e1be9cfcae --- /dev/null +++ b/website/docs/d/odb_gi_versions.html.markdown @@ -0,0 +1,42 @@ +--- +subcategory: "Oracle Database@AWS" +layout: "AWS: aws_odb_gi_versions_list" +page_title: "AWS: aws_odb_gi_versions" +description: |- + Terraform data source to retrieve available Grid Infrastructure versions of Oracle Database@AWS. +--- + +# Data Source: aws_odb_gi_versions + +Terraform data source to retrieve available Grid Infrastructure versions of Oracle Database@AWS. + +You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). + +## Example Usage + +### Basic Usage + +```terraform +data "aws_odb_gi_versions" "example" {} + +data "aws_odb_gi_versions" "example" { + shape = "Exadata.X11M" +} + +data "aws_odb_gi_versions" "example" { + shape = "Exadata.X9M" +} +``` + +## Argument Reference + +The following arguments are optional: + +* `shape` - (Optional) The system shape. +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `gi_versions` - Information about a specific version of Oracle Grid Infrastructure (GI) software that can be installed on a VM cluster. diff --git a/website/docs/r/bedrock_guardrail.html.markdown b/website/docs/r/bedrock_guardrail.html.markdown index 3956c7bdb47a..8cfe96ca2e59 100644 --- a/website/docs/r/bedrock_guardrail.html.markdown +++ b/website/docs/r/bedrock_guardrail.html.markdown @@ -121,7 +121,7 @@ The `tier_config` configuration block supports the following arguments: ### Contextual Grounding Policy Config -* `filters_config` (Required) List of contextual grounding filter configs. See [Contextual Grounding Filters Config](#contextual-grounding-filters-config) for more information. +* `filters_config` (Required) One or more blocks defining contextual grounding filter configs. See [Contextual Grounding Filters Config](#contextual-grounding-filters-config) for more information. #### Contextual Grounding Filters Config diff --git a/website/docs/r/cleanrooms_configured_table.html.markdown b/website/docs/r/cleanrooms_configured_table.html.markdown index 26c01bae7a8a..b3a63d08993f 100644 --- a/website/docs/r/cleanrooms_configured_table.html.markdown +++ b/website/docs/r/cleanrooms_configured_table.html.markdown @@ -69,6 +69,32 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_cleanrooms_configured_table.example + identity = { + id = "1234abcd-12ab-34cd-56ef-1234567890ab" + } +} + +resource "aws_cleanrooms_configured_table" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +* `id` - (String) ID of the cleanrooms configured table. + +#### Optional + +* `account_id` (String) AWS Account where this resource is managed. +* `region` (String) Region where this resource is managed. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import `aws_cleanrooms_configured_table` using the `id`. For example: ```terraform diff --git a/website/docs/r/cloudfront_distribution.html.markdown b/website/docs/r/cloudfront_distribution.html.markdown index f205bb077500..9503b407d910 100644 --- a/website/docs/r/cloudfront_distribution.html.markdown +++ b/website/docs/r/cloudfront_distribution.html.markdown @@ -549,6 +549,7 @@ argument should not be specified. * `http_port` (Required) - HTTP port the custom origin listens on. * `https_port` (Required) - HTTPS port the custom origin listens on. +* `ip_address_type` (Optional) - IP protocol CloudFront uses when connecting to your origin. Valid values: `ipv4`, `ipv6`, `dualstack`. * `origin_protocol_policy` (Required) - Origin protocol policy to apply to your origin. One of `http-only`, `https-only`, or `match-viewer`. * `origin_ssl_protocols` (Required) - List of SSL/TLS protocols that CloudFront can use when connecting to your origin over HTTPS. Valid values: `SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`. For more information, see [Minimum Origin SSL Protocol](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesOriginSSLProtocols) in the Amazon CloudFront Developer Guide. * `origin_keepalive_timeout` - (Optional) The Custom KeepAlive timeout, in seconds. By default, AWS enforces an upper limit of `60`. But you can request an [increase](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#request-custom-request-timeout). Defaults to `5`. diff --git a/website/docs/r/datazone_environment.html.markdown b/website/docs/r/datazone_environment.html.markdown index 28142e89e308..3edb417362be 100644 --- a/website/docs/r/datazone_environment.html.markdown +++ b/website/docs/r/datazone_environment.html.markdown @@ -17,8 +17,6 @@ Terraform resource for managing an AWS DataZone Environment. ```terraform resource "aws_datazone_environment" "example" { name = "example" - account_identifier = data.aws_caller_identity.test.account_id - account_region = data.aws_region.test.name blueprint_identifier = aws_datazone_environment_blueprint_configuration.test.environment_blueprint_id profile_identifier = aws_datazone_environment_profile.test.id project_identifier = aws_datazone_project.test.id @@ -58,7 +56,9 @@ The following arguments are optional: * `blueprint_identifier` - (Optional) The blueprint with which the environment is created. * `description` - (Optional) The description of the environment. * `glossary_terms` - (Optional) The business glossary terms that can be used in this environment. -* `user_parameters` - (Optional) The user parameters that are used in the environment. See [User Parameters](#user-parameters) for more information. +* `user_parameters` - (Optional) The user parameters that are used in the environment. + See [User Parameters](#user-parameters) for more information. + Changing these values recreates the resource. ### User Parameters diff --git a/website/docs/r/db_proxy.html.markdown b/website/docs/r/db_proxy.html.markdown index 57421f723152..b9ea137b9b2f 100644 --- a/website/docs/r/db_proxy.html.markdown +++ b/website/docs/r/db_proxy.html.markdown @@ -98,8 +98,9 @@ This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `name` - (Required) The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens. -* `auth` - (Required) Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters. Described below. +* `auth` - (Optional) Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters. Required when `default_auth_scheme` is `NONE` or unspecified. Described below. * `debug_logging` - (Optional) Whether the proxy includes detailed information about SQL statements in its logs. This information helps you to debug issues involving SQL behavior or the performance and scalability of the proxy connections. The debug information includes the text of SQL statements that you submit through the proxy. Thus, only enable this setting when needed for debugging, and only when you have security measures in place to safeguard any sensitive information that appears in the logs. +* `default_auth_scheme` - (Optional) Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. Valid values are `NONE` and `IAM_AUTH`. Defaults to `NONE`. * `engine_family` - (Required, Forces new resource) The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. For Aurora MySQL, RDS for MariaDB, and RDS for MySQL databases, specify `MYSQL`. For Aurora PostgreSQL and RDS for PostgreSQL databases, specify `POSTGRESQL`. For RDS for Microsoft SQL Server, specify `SQLSERVER`. Valid values are `MYSQL`, `POSTGRESQL`, and `SQLSERVER`. * `idle_client_timeout` - (Optional) The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it. You can set this value higher or lower than the connection timeout limit for the associated database. * `require_tls` - (Optional) A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy. diff --git a/website/docs/r/dms_endpoint.html.markdown b/website/docs/r/dms_endpoint.html.markdown index b9c4a1b75289..103fadeb7093 100644 --- a/website/docs/r/dms_endpoint.html.markdown +++ b/website/docs/r/dms_endpoint.html.markdown @@ -57,6 +57,7 @@ The following arguments are optional: * `kafka_settings` - (Optional) Configuration block for Kafka settings. See below. * `kinesis_settings` - (Optional) Configuration block for Kinesis settings. See below. * `mongodb_settings` - (Optional) Configuration block for MongoDB settings. See below. +* `mysql_settings` - (Optional) Configuration block for MySQL settings. See below. * `oracle_settings` - (Optional) Configuration block for Oracle settings. See below. * `password` - (Optional) Password to be used to login to the endpoint database. * `postgres_settings` - (Optional) Configuration block for Postgres settings. See below. @@ -134,6 +135,21 @@ The following arguments are optional: * `extract_doc_id` - (Optional) Document ID. Use this setting when `nesting_level` is set to `none`. Default is `false`. * `nesting_level` - (Optional) Specifies either document or table mode. Default is `none`. Valid values are `one` (table mode) and `none` (document mode). +### mysql_settings + +-> Additional information can be found in the [Using MongoDB as a Source for AWS DMS documentation](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MySQL.html). + +* `after_connect_script` - (Optional) Script to run immediately after AWS DMS connects to the endpoint. +* `authentication_method` - (Optional) Authentication method to use. Valid values: `password`, `iam`. +* `clean_source_metadata_on_mismatch` - (Optional) Whether to clean and recreate table metadata information on the replication instance when a mismatch occurs. +* `events_poll_interval` - (Optional) Time interval to check the binary log for new changes/events when the database is idle. Default is `5`. +* `execute_timeout` - (Optional) Client statement timeout (in seconds) for a MySQL source endpoint. +* `max_file_size` - (Optional) Maximum size (in KB) of any .csv file used to transfer data to a MySQL-compatible database. +* `parallel_load_threads` - (Optional) Number of threads to use to load the data into the MySQL-compatible target database. +* `server_timezone` - (Optional) Time zone for the source MySQL database. +* `service_access_role_arn` - (Optional) ARN of the IAM role to authenticate when connecting to the endpoint. +* `target_db_type` - (Optional) Where to migrate source tables on the target. Valid values are `specific-database` and `multiple-databases`. + ### oracle_settings -> Additional information can be found in the [Using Oracle as a Source for AWS DMS documentation](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.Oracle.html). diff --git a/website/docs/r/ecs_capacity_provider.html.markdown b/website/docs/r/ecs_capacity_provider.html.markdown index 9dd2f4a13b2b..13656f8df8a8 100644 --- a/website/docs/r/ecs_capacity_provider.html.markdown +++ b/website/docs/r/ecs_capacity_provider.html.markdown @@ -12,8 +12,12 @@ Provides an ECS cluster capacity provider. More information can be found on the ~> **NOTE:** Associating an ECS Capacity Provider to an Auto Scaling Group will automatically add the `AmazonECSManaged` tag to the Auto Scaling Group. This tag should be included in the `aws_autoscaling_group` resource configuration to prevent Terraform from removing it in subsequent executions as well as ensuring the `AmazonECSManaged` tag is propagated to all EC2 Instances in the Auto Scaling Group if `min_size` is above 0 on creation. Any EC2 Instances in the Auto Scaling Group without this tag must be manually be updated, otherwise they may cause unexpected scaling behavior and metrics. +~> **NOTE:** You must specify exactly one of `auto_scaling_group_provider` or `managed_instances_provider`. When using `managed_instances_provider`, the `cluster` parameter is required. When using `auto_scaling_group_provider`, the `cluster` parameter must not be set. + ## Example Usage +### Auto Scaling Group Provider + ```terraform resource "aws_autoscaling_group" "example" { # ... other configuration, including potentially other tags ... @@ -42,13 +46,58 @@ resource "aws_ecs_capacity_provider" "example" { } ``` +### Managed Instances Provider + +```terraform +resource "aws_ecs_capacity_provider" "example" { + name = "example" + cluster = "my-cluster" + + managed_instances_provider { + infrastructure_role_arn = aws_iam_role.ecs_infrastructure.arn + propagate_tags = "TASK_DEFINITION" + + instance_launch_template { + ec2_instance_profile_arn = aws_iam_instance_profile.ecs_instance.arn + monitoring = "ENABLED" + + network_configuration { + subnets = [aws_subnet.example.id] + security_groups = [aws_security_group.example.id] + } + + storage_configuration { + storage_size_gib = 30 + } + + instance_requirements { + memory_mib { + min = 1024 + max = 8192 + } + + vcpu_count { + min = 1 + max = 4 + } + + instance_generations = ["current"] + cpu_manufacturers = ["intel", "amd"] + } + } + } +} +``` + ## Argument Reference This resource supports the following arguments: -* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). -* `auto_scaling_group_provider` - (Required) Configuration block for the provider for the ECS auto scaling group. Detailed below. +* `auto_scaling_group_provider` - (Optional) Configuration block for the provider for the ECS auto scaling group. Detailed below. Exactly one of `auto_scaling_group_provider` or `managed_instances_provider` must be specified. +* `cluster` - (Optional) Name of the ECS cluster. Required when using `managed_instances_provider`. Must not be set when using `auto_scaling_group_provider`. +* `managed_instances_provider` - (Optional) Configuration block for the managed instances provider. Detailed below. Exactly one of `auto_scaling_group_provider` or `managed_instances_provider` must be specified. * `name` - (Required) Name of the capacity provider. +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ### `auto_scaling_group_provider` @@ -68,6 +117,56 @@ This resource supports the following arguments: * `status` - (Optional) Whether auto scaling is managed by ECS. Valid values are `ENABLED` and `DISABLED`. * `target_capacity` - (Optional) Target utilization for the capacity provider. A number between 1 and 100. +### `managed_instances_provider` + +* `infrastructure_role_arn` - (Required) The Amazon Resource Name (ARN) of the infrastructure role that Amazon ECS uses to manage instances on your behalf. This role must have permissions to launch, terminate, and manage Amazon EC2 instances, as well as access to other AWS services required for Amazon ECS Managed Instances functionality. For more information, see [Amazon ECS infrastructure IAM role](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/infrastructure_IAM_role.html) in the Amazon ECS Developer Guide. +* `instance_launch_template` - (Required) The launch template configuration that specifies how Amazon ECS should launch Amazon EC2 instances. This includes the instance profile, network configuration, storage settings, and instance requirements for attribute-based instance type selection. For more information, see [Store instance launch parameters in Amazon EC2 launch templates](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-templates.html) in the Amazon EC2 User Guide. Detailed below. +* `propagate_tags` - (Optional) Specifies whether to propagate tags from the capacity provider to the Amazon ECS Managed Instances. When enabled, tags applied to the capacity provider are automatically applied to all instances launched by this provider. Valid values are `CAPACITY_PROVIDER` and `NONE`. + +### `instance_launch_template` + +* `ec2_instance_profile_arn` - (Required) The Amazon Resource Name (ARN) of the instance profile that Amazon ECS applies to Amazon ECS Managed Instances. This instance profile must include the necessary permissions for your tasks to access AWS services and resources. For more information, see [Amazon ECS instance profile for Managed Instances](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html) in the Amazon ECS Developer Guide. +* `instance_requirements` - (Optional) The instance requirements. You can specify the instance types and instance requirements such as vCPU count, memory, network performance, and accelerator specifications. Amazon ECS automatically selects the instances that match the specified criteria. Detailed below. +* `monitoring` - (Optional) CloudWatch provides two categories of monitoring: basic monitoring and detailed monitoring. By default, your managed instance is configured for basic monitoring. You can optionally enable detailed monitoring to help you more quickly identify and act on operational issues. You can enable or turn off detailed monitoring at launch or when the managed instance is running or stopped. For more information, see [Detailed monitoring for Amazon ECS Managed Instances](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-metrics.html) in the Amazon ECS Developer Guide. Valid values are `BASIC` and `DETAILED`. +* `network_configuration` - (Required) The network configuration for Amazon ECS Managed Instances. This specifies the subnets and security groups that instances use for network connectivity. Detailed below. +* `storage_configuration` - (Optional) The storage configuration for Amazon ECS Managed Instances. This defines the root volume size and type for the instances. Detailed below. + +### `network_configuration` + +* `security_groups` - (Optional) The list of security group IDs to apply to Amazon ECS Managed Instances. These security groups control the network traffic allowed to and from the instances. +* `subnets` - (Required) The list of subnet IDs where Amazon ECS can launch Amazon ECS Managed Instances. Instances are distributed across the specified subnets for high availability. All subnets must be in the same VPC. + +### `storage_configuration` + +* `storage_size_gib` - (Required) The size of the tasks volume in GiB. Must be at least 1. + +### `instance_requirements` + +* `accelerator_count` - (Optional) The minimum and maximum number of accelerators for the instance types. This is used when you need instances with specific numbers of GPUs or other accelerators. +* `accelerator_manufacturers` - (Optional) The accelerator manufacturers to include. You can specify `nvidia`, `amd`, `amazon-web-services`, `xilinx`, or `habana` depending on your accelerator requirements. Valid values are `amazon-web-services`, `amd`, `nvidia`, `xilinx`, `habana`. +* `accelerator_names` - (Optional) The specific accelerator names to include. For example, you can specify `a100`, `v100`, `k80`, or other specific accelerator models. Valid values are `a100`, `inferentia`, `k520`, `k80`, `m60`, `radeon-pro-v520`, `t4`, `vu9p`, `v100`, `a10g`, `h100`, `t4g`. +* `accelerator_total_memory_mib` - (Optional) The minimum and maximum total accelerator memory in mebibytes (MiB). This is important for GPU workloads that require specific amounts of video memory. +* `accelerator_types` - (Optional) The accelerator types to include. You can specify `gpu` for graphics processing units, `fpga` for field programmable gate arrays, or `inference` for machine learning inference accelerators. Valid values are `gpu`, `fpga`, `inference`. +* `allowed_instance_types` - (Optional) The instance types to include in the selection. When specified, Amazon ECS only considers these instance types, subject to the other requirements specified. Maximum of 400 instance types. You can specify instance type patterns using wildcards (e.g., `m5.*`). +* `bare_metal` - (Optional) Indicates whether to include bare metal instance types. Set to `included` to allow bare metal instances, `excluded` to exclude them, or `required` to use only bare metal instances. Valid values are `included`, `excluded`, `required`. +* `baseline_ebs_bandwidth_mbps` - (Optional) The minimum and maximum baseline Amazon EBS bandwidth in megabits per second (Mbps). This is important for workloads with high storage I/O requirements. +* `burstable_performance` - (Optional) Indicates whether to include burstable performance instance types (T2, T3, T3a, T4g). Set to `included` to allow burstable instances, `excluded` to exclude them, or `required` to use only burstable instances. Valid values are `included`, `excluded`, `required`. +* `cpu_manufacturers` - (Optional) The CPU manufacturers to include or exclude. You can specify `intel`, `amd`, or `amazon-web-services` to control which CPU types are used for your workloads. Valid values are `intel`, `amd`, `amazon-web-services`. +* `excluded_instance_types` - (Optional) The instance types to exclude from selection. Use this to prevent Amazon ECS from selecting specific instance types that may not be suitable for your workloads. Maximum of 400 instance types. +* `instance_generations` - (Optional) The instance generations to include. You can specify `current` to use the latest generation instances, or `previous` to include previous generation instances for cost optimization. Valid values are `current`, `previous`. +* `local_storage` - (Optional) Indicates whether to include instance types with local storage. Set to `included` to allow local storage, `excluded` to exclude it, or `required` to use only instances with local storage. Valid values are `included`, `excluded`, `required`. +* `local_storage_types` - (Optional) The local storage types to include. You can specify `hdd` for hard disk drives, `ssd` for solid state drives, or both. Valid values are `hdd`, `ssd`. +* `max_spot_price_as_percentage_of_optimal_on_demand_price` - (Optional) The maximum price for Spot instances as a percentage of the optimal On-Demand price. This provides more precise cost control for Spot instance selection. +* `memory_gib_per_vcpu` - (Optional) The minimum and maximum amount of memory per vCPU in gibibytes (GiB). This helps ensure that instance types have the appropriate memory-to-CPU ratio for your workloads. +* `memory_mib` - (Required) The minimum and maximum amount of memory in mebibytes (MiB) for the instance types. Amazon ECS selects instance types that have memory within this range. +* `network_bandwidth_gbps` - (Optional) The minimum and maximum network bandwidth in gigabits per second (Gbps). This is crucial for network-intensive workloads that require high throughput. +* `network_interface_count` - (Optional) The minimum and maximum number of network interfaces for the instance types. This is useful for workloads that require multiple network interfaces. +* `on_demand_max_price_percentage_over_lowest_price` - (Optional) The price protection threshold for On-Demand Instances, as a percentage higher than an identified On-Demand price. The identified On-Demand price is the price of the lowest priced current generation C, M, or R instance type with your specified attributes. When Amazon ECS selects instance types with your attributes, it will exclude instance types whose price exceeds your specified threshold. +* `require_hibernate_support` - (Optional) Indicates whether the instance types must support hibernation. When set to `true`, only instance types that support hibernation are selected. +* `spot_max_price_percentage_over_lowest_price` - (Optional) The maximum price for Spot instances as a percentage over the lowest priced On-Demand instance. This helps control Spot instance costs while maintaining access to capacity. +* `total_local_storage_gb` - (Optional) The minimum and maximum total local storage in gigabytes (GB) for instance types with local storage. +* `vcpu_count` - (Required) The minimum and maximum number of vCPUs for the instance types. Amazon ECS selects instance types that have vCPU counts within this range. + ## Attribute Reference This resource exports the following attributes in addition to the arguments above: diff --git a/website/docs/r/elastic_beanstalk_configuration_template.html.markdown b/website/docs/r/elastic_beanstalk_configuration_template.html.markdown index 60ebd52353ba..7751908554b0 100644 --- a/website/docs/r/elastic_beanstalk_configuration_template.html.markdown +++ b/website/docs/r/elastic_beanstalk_configuration_template.html.markdown @@ -15,16 +15,16 @@ application with the same configuration settings. ## Example Usage ```terraform -resource "aws_elastic_beanstalk_application" "tftest" { - name = "tf-test-name" - description = "tf-test-desc" -} - -resource "aws_elastic_beanstalk_configuration_template" "tf_template" { +resource "aws_elastic_beanstalk_configuration_template" "example" { name = "tf-test-template-config" - application = aws_elastic_beanstalk_application.tftest.name + application = aws_elastic_beanstalk_application.example.name solution_stack_name = "64bit Amazon Linux 2015.09 v2.0.8 running Go 1.4" } + +resource "aws_elastic_beanstalk_application" "example" { + name = "tf-test-name" + description = "tf-test-desc" +} ``` ## Argument Reference @@ -46,20 +46,13 @@ off of. Example stacks can be found in the [Amazon API documentation][1] The `setting` field supports the following format: -* `namespace` - unique namespace identifying the option's associated AWS resource -* `name` - name of the configuration option -* `value` - value for the configuration option +* `namespace` - (Required) Unique namespace identifying the option's associated AWS resource +* `name` - (Required) Name of the configuration option +* `value` - (Required) Value for the configuration option * `resource` - (Optional) resource name for [scheduled action](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingscheduledaction) ## Attribute Reference -This resource exports the following attributes in addition to the arguments above: - -* `name` -* `application` -* `description` -* `environment_id` -* `option_settings` -* `solution_stack_name` +This resource exports no additional attributes. [1]: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html diff --git a/website/docs/r/elastic_beanstalk_environment.html.markdown b/website/docs/r/elastic_beanstalk_environment.html.markdown index c0073d489324..24db1962f353 100644 --- a/website/docs/r/elastic_beanstalk_environment.html.markdown +++ b/website/docs/r/elastic_beanstalk_environment.html.markdown @@ -18,16 +18,16 @@ Environments are often things such as `development`, `integration`, or ## Example Usage ```terraform -resource "aws_elastic_beanstalk_application" "tftest" { - name = "tf-test-name" - description = "tf-test-desc" -} - -resource "aws_elastic_beanstalk_environment" "tfenvtest" { +resource "aws_elastic_beanstalk_environment" "example" { name = "tf-test-name" - application = aws_elastic_beanstalk_application.tftest.name + application = aws_elastic_beanstalk_application.example.name solution_stack_name = "64bit Amazon Linux 2015.03 v2.0.3 running Go 1.4" } + +resource "aws_elastic_beanstalk_application" "example" { + name = "tf-test-name" + description = "tf-test-desc" +} ``` ## Argument Reference @@ -72,9 +72,9 @@ for supported options and examples. The `setting` and `all_settings` mappings support the following format: -* `namespace` - unique namespace identifying the option's associated AWS resource -* `name` - name of the configuration option -* `value` - value for the configuration option +* `namespace` - (Required) Unique namespace identifying the option's associated AWS resource +* `name` - (Required) Name of the configuration option +* `value` - (Required) Value for the configuration option * `resource` - (Optional) resource name for [scheduled action](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingscheduledaction) ### Example With Options diff --git a/website/docs/r/iam_service_specific_credential.html.markdown b/website/docs/r/iam_service_specific_credential.html.markdown index f91fb94d227f..48446660ac81 100644 --- a/website/docs/r/iam_service_specific_credential.html.markdown +++ b/website/docs/r/iam_service_specific_credential.html.markdown @@ -12,6 +12,8 @@ Provides an IAM Service Specific Credential. ## Example Usage +### Basic Usage + ```terraform resource "aws_iam_user" "example" { name = "example" @@ -23,22 +25,41 @@ resource "aws_iam_service_specific_credential" "example" { } ``` +### Bedrock API Key with Expiration + +```terraform +resource "aws_iam_user" "example" { + name = "example" +} + +resource "aws_iam_service_specific_credential" "bedrock" { + service_name = "bedrock.amazonaws.com" + user_name = aws_iam_user.example.name + credential_age_days = 30 # API key expires after 30 days +} +``` + ## Argument Reference This resource supports the following arguments: -* `service_name` - (Required) The name of the AWS service that is to be associated with the credentials. The service you specify here is the only service that can be accessed using these credentials. -* `user_name` - (Required) The name of the IAM user that is to be associated with the credentials. The new service-specific credentials have the same permissions as the associated user except that they can be used only to access the specified service. -* `status` - (Optional) The status to be assigned to the service-specific credential. Valid values are `Active` and `Inactive`. Default value is `Active`. +- `service_name` - (Required) The name of the AWS service that is to be associated with the credentials. The service you specify here is the only service that can be accessed using these credentials. Supported services are `codecommit.amazonaws.com`, `bedrock.amazonaws.com`, and `cassandra.amazonaws.com`. +- `user_name` - (Required) The name of the IAM user that is to be associated with the credentials. The new service-specific credentials have the same permissions as the associated user except that they can be used only to access the specified service. +- `status` - (Optional) The status to be assigned to the service-specific credential. Valid values are `Active`, `Inactive`, and `Expired`. Default value is `Active`. Note that `Expired` is only used for read operations and cannot be set manually. +- `credential_age_days` - (Optional, Forces new resource) The number of days until the service specific credential expires. This field is only valid for Bedrock API keys and must be between 1 and 36600 (approximately 100 years). When not specified, the credential will not expire. ## Attribute Reference This resource exports the following attributes in addition to the arguments above: -* `id` - The combination of `service_name` and `user_name` as such: `service_name:user_name:service_specific_credential_id`. -* `service_password` - The generated password for the service-specific credential. -* `service_user_name` - The generated user name for the service-specific credential. This value is generated by combining the IAM user's name combined with the ID number of the AWS account, as in `jane-at-123456789012`, for example. -* `service_specific_credential_id` - The unique identifier for the service-specific credential. +- `id` - The combination of `service_name` and `user_name` as such: `service_name:user_name:service_specific_credential_id`. +- `service_password` - The generated password for the service-specific credential. This value is only available when the credential is created. +- `service_user_name` - The generated user name for the service-specific credential. This value is generated by combining the IAM user's name combined with the ID number of the AWS account, as in `jane-at-123456789012`, for example. +- `service_specific_credential_id` - The unique identifier for the service-specific credential. +- `service_credential_alias` - For Bedrock API keys, this is the public portion of the credential that includes the IAM user name and a suffix containing version and creation information. +- `service_credential_secret` - For Bedrock API keys, this is the secret portion of the credential that should be used to authenticate API calls. This value is only available when the credential is created. +- `create_date` - The date and time, in RFC3339 format, when the service-specific credential was created. +- `expiration_date` - The date and time, in RFC3339 format, when the service specific credential expires. This field is only present for Bedrock API keys that were created with an expiration period. ## Import diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index 4c504fb5f75d..5008a530e4eb 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -91,6 +91,7 @@ The resulting permissions depend on whether the table had `IAMAllowedPrincipals` AllIAMPrincipals is a pseudo-entity group that acts like a Lake Formation principal. The group includes all IAMs in the account that is defined. +```terraform resource "aws_lakeformation_permissions" "example" { permissions = ["SELECT"] principal = "123456789012:IAMPrincipals" @@ -101,6 +102,7 @@ resource "aws_lakeformation_permissions" "example" { column_names = ["event"] } } +``` ## Using Lake Formation Permissions diff --git a/website/docs/r/lambda_alias.html.markdown b/website/docs/r/lambda_alias.html.markdown index 4818adf52372..b062ccf0d489 100644 --- a/website/docs/r/lambda_alias.html.markdown +++ b/website/docs/r/lambda_alias.html.markdown @@ -37,8 +37,7 @@ resource "aws_lambda_alias" "example" { routing_config { additional_version_weights = { "1" = 0.1 # Send 10% of traffic to version 1 - "3" = 0.2 # Send 20% of traffic to version 3 - # Remaining 70% goes to version 2 (the primary version) + # Remaining 90% goes to version 2 (the primary version) } } } diff --git a/website/docs/r/lambda_event_source_mapping.html.markdown b/website/docs/r/lambda_event_source_mapping.html.markdown index e07e63dcf04d..3260f1086d1f 100644 --- a/website/docs/r/lambda_event_source_mapping.html.markdown +++ b/website/docs/r/lambda_event_source_mapping.html.markdown @@ -234,6 +234,7 @@ The following arguments are optional: ### amazon_managed_kafka_event_source_config Configuration Block * `consumer_group_id` - (Optional) Kafka consumer group ID between 1 and 200 characters for use when creating this event source mapping. If one is not specified, this value will be automatically generated. See [AmazonManagedKafkaEventSourceConfig Syntax](https://docs.aws.amazon.com/lambda/latest/dg/API_AmazonManagedKafkaEventSourceConfig.html). +* `schema_registry_config` - (Optional) Block for a Kafka schema registry setting. [See below](#schema_registry_config-configuration-block). ### destination_config Configuration Block @@ -277,12 +278,23 @@ The following arguments are optional: ### self_managed_kafka_event_source_config Configuration Block * `consumer_group_id` - (Optional) Kafka consumer group ID between 1 and 200 characters for use when creating this event source mapping. If one is not specified, this value will be automatically generated. See [SelfManagedKafkaEventSourceConfig Syntax](https://docs.aws.amazon.com/lambda/latest/dg/API_SelfManagedKafkaEventSourceConfig.html). +* `schema_registry_config` - (Optional) Block for a Kafka schema registry setting. [See below](#schema_registry_config-configuration-block). ### source_access_configuration Configuration Block * `type` - (Required) Type of authentication protocol, VPC components, or virtual host for your event source. For valid values, refer to the [AWS documentation](https://docs.aws.amazon.com/lambda/latest/api/API_SourceAccessConfiguration.html). * `uri` - (Required) URI for this configuration. For type `VPC_SUBNET` the value should be `subnet:subnet_id` where `subnet_id` is the value you would find in an aws_subnet resource's id attribute. For type `VPC_SECURITY_GROUP` the value should be `security_group:security_group_id` where `security_group_id` is the value you would find in an aws_security_group resource's id attribute. +### schema_registry_config Configuration Block + +* `access_config` - (Optional) Configuration block for authentication Lambda uses to access the schema registry. + * `type` - (Optional) Authentication type Lambda uses to access the schema registry. + * `uri` - (Optional) URI of the secret (Secrets Manager secret ARN) used to authenticate with the schema registry. +* `event_record_format` - (Optional) Record format that Lambda delivers to the function after schema validation. Valid values: `JSON`, `SOURCE`. +* `schema_registry_uri` - (Optional) URI of the schema registry. For AWS Glue schema registries, use the ARN of the registry. For Confluent schema registries, use the registry URL. +* `schema_validation_config` - (Optional) Repeatable block that defines schema validation settings. These specify the message attributes that Lambda should validate and filter using the schema registry. + * `attribute` - (Optional) Message attribute to validate. Valid values: `KEY`, `VALUE`. + ## Attribute Reference This resource exports the following attributes in addition to the arguments above: diff --git a/website/docs/r/launch_template.html.markdown b/website/docs/r/launch_template.html.markdown index 009d6a8a9ea8..0f9379969907 100644 --- a/website/docs/r/launch_template.html.markdown +++ b/website/docs/r/launch_template.html.markdown @@ -173,7 +173,7 @@ The `ebs` block supports the following: Cannot be used with `snapshot_id`. * `iops` - (Optional) The amount of provisioned [IOPS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-io-characteristics.html). This must be set with a `volume_type` of `"io1/io2/gp3"`. -* `kms_key_id` - (Optional) The ARN of the AWS Key Management Service (AWS KMS) customer master key (CMK) to use when creating the encrypted volume. +* `kms_key_id` - (Optional) Identifier (key ID, key alias, key ARN, or alias ARN) of the customer managed KMS key to use for EBS encryption. `encrypted` must be set to `true` when this is set. * `snapshot_id` - (Optional) The Snapshot ID to mount. * `throughput` - (Optional) The throughput to provision for a `gp3` volume in MiB/s (specified as an integer, e.g., 500), with a maximum of 1,000 MiB/s. diff --git a/website/docs/r/macie2_member.html.markdown b/website/docs/r/macie2_member.html.markdown index f7f047eb0b09..58fb5ba80989 100644 --- a/website/docs/r/macie2_member.html.markdown +++ b/website/docs/r/macie2_member.html.markdown @@ -32,7 +32,6 @@ This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `account_id` - (Required) The AWS account ID for the account. * `email` - (Required) The email address for the account. -* `tags` - (Optional) A map of key-value pairs that specifies the tags to associate with the account in Amazon Macie. * `status` - (Optional) Specifies the status for the account. To enable Amazon Macie and start all Macie activities for the account, set this value to `ENABLED`. Valid values are `ENABLED` or `PAUSED`. * `invite` - (Optional) Send an invitation to a member * `invitation_message` - (Optional) A custom message to include in the invitation. Amazon Macie adds this message to the standard content that it sends for an invitation. diff --git a/website/docs/r/networkfirewall_logging_configuration.html.markdown b/website/docs/r/networkfirewall_logging_configuration.html.markdown index 49d38bc794fb..7e15b5028393 100644 --- a/website/docs/r/networkfirewall_logging_configuration.html.markdown +++ b/website/docs/r/networkfirewall_logging_configuration.html.markdown @@ -70,6 +70,7 @@ This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `firewall_arn` - (Required, Forces new resource) The Amazon Resource Name (ARN) of the Network Firewall firewall. +* `enable_monitoring_dashboard` - (Optional) Whether to enable the detailed firewall monitoring dashboard on the firewall. Defaults to `false`. * `logging_configuration` - (Required) A configuration block describing how AWS Network Firewall performs logging for a firewall. See [Logging Configuration](#logging-configuration) below for details. ### Logging Configuration diff --git a/website/docs/r/odb_cloud_vm_cluster.html.markdown b/website/docs/r/odb_cloud_vm_cluster.html.markdown index bf2b9dde0441..a919c006d589 100644 --- a/website/docs/r/odb_cloud_vm_cluster.html.markdown +++ b/website/docs/r/odb_cloud_vm_cluster.html.markdown @@ -8,7 +8,7 @@ description: |- # Resource: aws_odb_cloud_vm_cluster -Terraform data source for Exadata Infrastructure resource in AWS for Oracle Database@AWS. +Terraform to manage cloud vm cluster resource in AWS for Oracle Database@AWS. You can find out more about Oracle Database@AWS from [User Guide](https://docs.aws.amazon.com/odb/latest/UserGuide/what-is-odb.html). @@ -82,11 +82,11 @@ The following arguments are required: * `odb_network_id` - (Required) The unique identifier of the ODB network for the VM cluster. Changing this will create a new resource. * `ssh_public_keys` - (Required) The public key portion of one or more key pairs used for SSH access to the VM cluster. Changing this will create a new resource. * `data_collection_options` - (Required) The set of preferences for the various diagnostic collection options for the VM cluster. +* `data_storage_size_in_tbs` - (Required) The size of the data disk group, in terabytes (TBs), to allocate for the VM cluster. Changing this will create a new resource. The following arguments are optional: * `cluster_name` - (Optional) The name of the Grid Infrastructure (GI) cluster. Changing this will create a new resource. -* `data_storage_size_in_tbs` - (Optional) The size of the data disk group, in terabytes (TBs), to allocate for the VM cluster. Changing this will create a new resource. * `db_node_storage_size_in_gbs` - (Optional) The amount of local node storage, in gigabytes (GBs), to allocate for the VM cluster. Changing this will create a new resource. * `is_local_backup_enabled` - (Optional) Specifies whether to enable database backups to local Exadata storage for the VM cluster. Changing this will create a new resource. * `is_sparse_diskgroup_enabled` - (Optional) Specifies whether to create a sparse disk group for the VM cluster. Changing this will create a new resource. @@ -123,6 +123,7 @@ This data source exports the following attributes in addition to the arguments a * `system_version` - The operating system version of the image chosen for the VM cluster. * `vip_ids` - The virtual IP (VIP) addresses assigned to the VM cluster. CRS assigns one VIP per node for failover support. * `created_at` - The timestamp when the VM cluster was created. +* `gi_version_computed` - A complete software version of Oracle Grid Infrastructure (GI). * `compute_model` - The compute model used when the instance is created or cloned — either ECPU or OCPU. ECPU is a virtualized compute unit; OCPU is a physical processor core with hyper-threading. * `tags_all` - The combined set of user-defined and provider-defined tags. diff --git a/website/docs/r/pinpointsmsvoicev2_phone_number.html.markdown b/website/docs/r/pinpointsmsvoicev2_phone_number.html.markdown index 83abea4adb4c..00c4e0015ced 100644 --- a/website/docs/r/pinpointsmsvoicev2_phone_number.html.markdown +++ b/website/docs/r/pinpointsmsvoicev2_phone_number.html.markdown @@ -37,7 +37,7 @@ This resource supports the following arguments: * `opt_out_list_name` - (Optional) The name of the opt-out list to associate with the phone number. * `registration_id` - (Optional) Use this field to attach your phone number for an external registration process. * `self_managed_opt_outs_enabled` - (Optional) When set to `false` an end recipient sends a message that begins with HELP or STOP to one of your dedicated numbers, AWS End User Messaging SMS and Voice automatically replies with a customizable message and adds the end recipient to the opt-out list. When set to true you’re responsible for responding to HELP and STOP requests. You’re also responsible for tracking and honoring opt-out request. -* `two_way_channel_arn` - (Optional) The Amazon Resource Name (ARN) of the two way channel. +* `two_way_channel_arn` - (Optional) Configuration for two-way SMS. Specify an ARN to receive incoming SMS messages, or `connect.[region].amazonaws.com` (with `[region]` replaced by the AWS Region of the Amazon Connect instance) to set Amazon Connect as the inbound destination. * `two_way_channel_enabled` - (Optional) By default this is set to `false`. When set to `true` you can receive incoming text messages from your end recipients. * `two_way_channel_role` - (Optional) IAM Role ARN for a service to assume, to be able to post inbound SMS messages. diff --git a/website/docs/r/prometheus_resource_policy.html.markdown b/website/docs/r/prometheus_resource_policy.html.markdown new file mode 100644 index 000000000000..6e7a7f0cc5f9 --- /dev/null +++ b/website/docs/r/prometheus_resource_policy.html.markdown @@ -0,0 +1,166 @@ +--- +subcategory: "AMP (Managed Prometheus)" +layout: "aws" +page_title: "AWS: aws_prometheus_resource_policy" +description: |- + Manages an Amazon Managed Service for Prometheus (AMP) Resource Policy. +--- + +# Resource: aws_prometheus_resource_policy + +Manages an Amazon Managed Service for Prometheus (AMP) Resource Policy. + +Resource-based policies allow you to grant permissions to other AWS accounts or services to access your Prometheus workspace. This enables cross-account access and fine-grained permissions for workspace sharing. + +## Example Usage + +### Basic Resource Policy + +```terraform +resource "aws_prometheus_workspace" "example" { + alias = "example-workspace" +} + +data "aws_caller_identity" "current" {} + +data "aws_iam_policy_document" "example" { + statement { + effect = "Allow" + principals { + type = "AWS" + identifiers = [data.aws_caller_identity.current.account_id] + } + actions = [ + "aps:RemoteWrite", + "aps:QueryMetrics", + "aps:GetSeries", + "aps:GetLabels", + "aps:GetMetricMetadata" + ] + resources = [aws_prometheus_workspace.example.arn] + } +} + +resource "aws_prometheus_resource_policy" "example" { + workspace_id = aws_prometheus_workspace.example.id + policy_document = data.aws_iam_policy_document.example.json +} +``` + +### Cross-Account Access + +```terraform +resource "aws_prometheus_workspace" "example" { + alias = "example-workspace" +} + +data "aws_iam_policy_document" "cross_account" { + statement { + effect = "Allow" + principals { + type = "AWS" + identifiers = ["arn:aws:iam::123456789012:root"] + } + actions = [ + "aps:RemoteWrite", + "aps:QueryMetrics" + ] + resources = [aws_prometheus_workspace.example.arn] + } +} + +resource "aws_prometheus_resource_policy" "cross_account" { + workspace_id = aws_prometheus_workspace.example.id + policy_document = data.aws_iam_policy_document.cross_account.json +} +``` + +### Service-Specific Access + +```terraform +resource "aws_prometheus_workspace" "example" { + alias = "example-workspace" +} + +data "aws_iam_policy_document" "service_access" { + statement { + effect = "Allow" + principals { + type = "Service" + identifiers = ["grafana.amazonaws.com"] + } + actions = [ + "aps:QueryMetrics", + "aps:GetSeries", + "aps:GetLabels", + "aps:GetMetricMetadata" + ] + resources = [aws_prometheus_workspace.example.arn] + } +} + +resource "aws_prometheus_resource_policy" "service_access" { + workspace_id = aws_prometheus_workspace.example.id + policy_document = data.aws_iam_policy_document.service_access.json +} +``` + +## Argument Reference + +This resource supports the following arguments: + +* `workspace_id` - (Required) The ID of the workspace to attach the resource-based policy to. +* `policy_document` - (Required) The JSON policy document to use as the resource-based policy. This policy defines the permissions that other AWS accounts or services have to access your workspace. + +The following arguments are optional: + +* `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `policy_status` - The current status of the resource-based policy. Can be `CREATING`, `ACTIVE`, `UPDATING`, or `DELETING`. +* `revision_id` - The revision ID of the current resource-based policy. + +## Supported Actions + +The following actions are supported in resource policies for Prometheus workspaces: + +* `aps:RemoteWrite` - Allows writing metrics to the workspace +* `aps:QueryMetrics` - Allows querying metrics from the workspace +* `aps:GetSeries` - Allows retrieving time series data +* `aps:GetLabels` - Allows retrieving label names and values +* `aps:GetMetricMetadata` - Allows retrieving metric metadata + +## Notes + +* Only Prometheus-compatible APIs can be used for workspace sharing. Non-Prometheus-compatible APIs added to the policy will be ignored. +* If your workspace uses customer-managed KMS keys for encryption, you must grant the principals in your resource-based policy access to those KMS keys through KMS grants. +* The resource ARN in the policy document must match the workspace ARN that the policy is being attached to. +* Resource policies enable cross-account access and fine-grained permissions for Prometheus workspaces. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +- `create` - (Default `5m`) +- `update` - (Default `5m`) +- `delete` - (Default `5m`) + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import the Resource Policy using the workspace ID. For example: + +```terraform +import { + to = aws_prometheus_resource_policy.example + id = "ws-12345678-90ab-cdef-1234-567890abcdef" +} +``` + +Using `terraform import`, import AMP Resource Policies using the workspace ID. For example: + +```console +% terraform import aws_prometheus_resource_policy.example ws-12345678-90ab-cdef-1234-567890abcdef +``` diff --git a/website/docs/r/route53recoverycontrolconfig_cluster.html.markdown b/website/docs/r/route53recoverycontrolconfig_cluster.html.markdown index 265169b07226..b6259c662d6a 100644 --- a/website/docs/r/route53recoverycontrolconfig_cluster.html.markdown +++ b/website/docs/r/route53recoverycontrolconfig_cluster.html.markdown @@ -25,6 +25,10 @@ This resource supports the following arguments: * `name` - (Required) Unique name describing the cluster. * `network_type` - (Optional) Network type of cluster. Valid values are `IPV4` and `DUALSTACK`. Defaults to `IPV4`. +The following arguments are optional: + +* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + ## Attribute Reference This resource exports the following attributes in addition to the arguments above: @@ -32,6 +36,7 @@ This resource exports the following attributes in addition to the arguments abov * `arn` - ARN of the cluster * `cluster_endpoints` - List of 5 endpoints in 5 regions that can be used to talk to the cluster. See below. * `status` - Status of cluster. `PENDING` when it is being created, `PENDING_DELETION` when it is being deleted and `DEPLOYED` otherwise. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). ### cluster_endpoints diff --git a/website/docs/r/route53recoverycontrolconfig_control_panel.html.markdown b/website/docs/r/route53recoverycontrolconfig_control_panel.html.markdown index c4f7b7f4a35c..acb17354d133 100644 --- a/website/docs/r/route53recoverycontrolconfig_control_panel.html.markdown +++ b/website/docs/r/route53recoverycontrolconfig_control_panel.html.markdown @@ -26,6 +26,10 @@ The following arguments are required: * `cluster_arn` - (Required) ARN of the cluster in which this control panel will reside. * `name` - (Required) Name describing the control panel. +The following arguments are optional: + +* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + ## Attribute Reference This resource exports the following attributes in addition to the arguments above: @@ -34,6 +38,7 @@ This resource exports the following attributes in addition to the arguments abov * `default_control_panel` - Whether a control panel is default. * `routing_control_count` - Number routing controls in a control panel. * `status` - Status of control panel: `PENDING` when it is being created/updated, `PENDING_DELETION` when it is being deleted, and `DEPLOYED` otherwise. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). ## Import diff --git a/website/docs/r/route53recoverycontrolconfig_safety_rule.html.markdown b/website/docs/r/route53recoverycontrolconfig_safety_rule.html.markdown index 0ce22e4340d3..0542e709a980 100644 --- a/website/docs/r/route53recoverycontrolconfig_safety_rule.html.markdown +++ b/website/docs/r/route53recoverycontrolconfig_safety_rule.html.markdown @@ -57,6 +57,7 @@ The following arguments are optional: * `asserted_controls` - (Optional) Routing controls that are part of transactions that are evaluated to determine if a request to change a routing control state is allowed. * `gating_controls` - (Optional) Gating controls for the new gating rule. That is, routing controls that are evaluated by the rule configuration that you specify. * `target_controls` - (Optional) Routing controls that can only be set or unset if the specified `rule_config` evaluates to true for the specified `gating_controls`. +* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ### rule_config @@ -70,6 +71,7 @@ This resource exports the following attributes in addition to the arguments abov * `arn` - ARN of the safety rule. * `status` - Status of the safety rule. `PENDING` when it is being created/updated, `PENDING_DELETION` when it is being deleted, and `DEPLOYED` otherwise. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). ## Import diff --git a/website/docs/r/s3_bucket_lifecycle_configuration.html.markdown b/website/docs/r/s3_bucket_lifecycle_configuration.html.markdown index 49ff6f2af3db..55b1c46f650d 100644 --- a/website/docs/r/s3_bucket_lifecycle_configuration.html.markdown +++ b/website/docs/r/s3_bucket_lifecycle_configuration.html.markdown @@ -28,10 +28,9 @@ See the Amazon S3 User Guide on [setting lifecycle configuration on a bucket](ht ### With neither a filter nor prefix specified -The Lifecycle rule applies to a subset of objects based on the key name prefix (`""`). +When you don't specify a filter or prefix, the lifecycle rule applies to all objects in the bucket. This has the same effect as setting an empty `filter` element. -This configuration is intended to replicate the default behavior of the `lifecycle_rule` -parameter in the Terraform AWS Provider `aws_s3_bucket` resource prior to `v4.0`. +This configuration maintains compatibility with the default behavior of the `lifecycle_rule` parameter from the `aws_s3_bucket` resource in versions prior to v4.0 of the Terraform AWS Provider. ```terraform resource "aws_s3_bucket_lifecycle_configuration" "example" { @@ -384,16 +383,12 @@ The `rule` configuration block supports the following arguments: * `expiration` - (Optional) Configuration block that specifies the expiration for the lifecycle of the object in the form of date, days and, whether the object has a delete marker. [See below](#expiration). * `filter` - (Optional) Configuration block used to identify objects that a Lifecycle Rule applies to. [See below](#filter). - If not specified, the `rule` will default to using `prefix`. - One of `filter` or `prefix` should be specified. * `id` - (Required) Unique identifier for the rule. The value cannot be longer than 255 characters. * `noncurrent_version_expiration` - (Optional) Configuration block that specifies when noncurrent object versions expire. [See below](#noncurrent_version_expiration). * `noncurrent_version_transition` - (Optional) Set of configuration blocks that specify the transition rule for the lifecycle rule that describes when noncurrent objects transition to a specific storage class. [See below](#noncurrent_version_transition). * `prefix` - (Optional) **DEPRECATED** Use `filter` instead. This has been deprecated by Amazon S3. Prefix identifying one or more objects to which the rule applies. - Defaults to an empty string (`""`) if `filter` is not specified. - One of `prefix` or `filter` should be specified. * `status` - (Required) Whether the rule is currently being applied. Valid values: `Enabled` or `Disabled`. * `transition` - (Optional) Set of configuration blocks that specify when an Amazon S3 object transitions to a specified storage class. [See below](#transition). diff --git a/website/docs/r/service_discovery_service.html.markdown b/website/docs/r/service_discovery_service.html.markdown index 401b5482ee5f..b5650937aa3b 100644 --- a/website/docs/r/service_discovery_service.html.markdown +++ b/website/docs/r/service_discovery_service.html.markdown @@ -39,7 +39,7 @@ resource "aws_service_discovery_service" "example" { routing_policy = "MULTIVALUE" } - health_check_custom_config { + health_check_config { failure_threshold = 1 } } @@ -79,9 +79,9 @@ This resource supports the following arguments: * `name` - (Required, Forces new resource) The name of the service. * `description` - (Optional) The description of the service. * `dns_config` - (Optional) A complex type that contains information about the resource record sets that you want Amazon Route 53 to create when you register an instance. See [`dns_config` Block](#dns_config-block) for details. -* `health_check_config` - (Optional) A complex type that contains settings for an optional health check. Only for Public DNS namespaces. See [`health_check_config` Block](#health_check_config-block) for details. * `force_destroy` - (Optional) A boolean that indicates all instances should be deleted from the service so that the service can be destroyed without error. These instances are not recoverable. Defaults to `false`. -* `health_check_custom_config` - (Optional, Forces new resource) A complex type that contains settings for ECS managed health checks. See [`health_check_custom_config` Block](#health_check_custom_config-block) for details. +* `health_check_config` - (Optional) A complex type that contains settings for an optional health check. Only for Public DNS namespaces. See [`health_check_config` Block](#health_check_config-block) for details. +* `health_check_custom_config` - (Optional, **Deprecated**, Forces new resource) Please use `health_check_config` instead. See [`health_check_custom_config` Block](#health_check_custom_config-block) for details. * `namespace_id` - (Optional) The ID of the namespace that you want to use to create the service. * `type` - (Optional) If present, specifies that the service instances are only discoverable using the `DiscoverInstances` API operation. No DNS records is registered for the service instances. The only valid value is `HTTP`. * `tags` - (Optional) A map of tags to assign to the service. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. @@ -111,6 +111,8 @@ The `health_check_config` configuration block supports the following arguments: ### `health_check_custom_config` Block +~> The `health_check_custom_config` argument is deprecated. Use [`health_check_config`](#health_check_config-block) instead, which supports additional attributes. + The `health_check_custom_config` configuration block supports the following arguments: * `failure_threshold` - (Optional, **Deprecated** Forces new resource) The number of 30-second intervals that you want service discovery to wait before it changes the health status of a service instance. Value is always set to 1. diff --git a/website/docs/r/ssmcontacts_contact.html.markdown b/website/docs/r/ssmcontacts_contact.html.markdown index e6c5c59c4ae4..6504aa4ba133 100644 --- a/website/docs/r/ssmcontacts_contact.html.markdown +++ b/website/docs/r/ssmcontacts_contact.html.markdown @@ -64,6 +64,27 @@ This resource exports the following attributes in addition to the arguments abov ## Import +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_ssmcontacts_contact.example + identity = { + "arn" = "arn:aws:ssm-contacts:us-west-2:123456789012:contact/example" + } +} + +resource "aws_ssmcontacts_contact" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +- `arn` (String) Amazon Resource Name (ARN) of the contact. + In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SSM Contact using the `ARN`. For example: ```terraform diff --git a/website/docs/r/ssmcontacts_contact_channel.html.markdown b/website/docs/r/ssmcontacts_contact_channel.html.markdown index 8f9099aa36dc..1092434b7ed1 100644 --- a/website/docs/r/ssmcontacts_contact_channel.html.markdown +++ b/website/docs/r/ssmcontacts_contact_channel.html.markdown @@ -72,7 +72,28 @@ This resource exports the following attributes in addition to the arguments abov ## Import -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SSM Contact Channel using the `ARN`. For example: +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: + +```terraform +import { + to = aws_ssmcontacts_contact_channel.example + identity = { + "arn" = "arn:aws:ssm-contacts:us-west-2:123456789012:contact-channel/example" + } +} + +resource "aws_ssmcontacts_contact_channel" "example" { + ### Configuration omitted for brevity ### +} +``` + +### Identity Schema + +#### Required + +- `arn` (String) Amazon Resource Name (ARN) of the contact channel. + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import SSM Contact Channel using the `arn`. For example: ```terraform import { @@ -81,7 +102,7 @@ import { } ``` -Using `terraform import`, import SSM Contact Channel using the `ARN`. For example: +Using `terraform import`, import SSM Contact Channel using the `arn`. For example: ```console % terraform import aws_ssmcontacts_contact_channel.example arn:aws:ssm-contacts:us-west-2:123456789012:contact-channel/example diff --git a/website/docs/r/transfer_host_key.html.markdown b/website/docs/r/transfer_host_key.html.markdown new file mode 100644 index 000000000000..6c59d588a3f1 --- /dev/null +++ b/website/docs/r/transfer_host_key.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Transfer Family" +layout: "aws" +page_title: "AWS: aws_transfer_host_key" +description: |- + Manages a host key for a server. +--- + +# Resource: aws_transfer_host_key + +Manages a host key for a server. This is an [_additional server host key_](https://docs.aws.amazon.com/transfer/latest/userguide/server-host-key-add.html). + +## Example Usage + +```terraform +resource "aws_transfer_host_key" "example" { + server_id = aws_transfer_server.example.id + description = "example additional host key" + + host_key_body_wo = <