Repository: getmoto/moto
Pull request #8259 (2024-10-24 18:14:26)

WAFv2 Rules Implementation
- Implement WAFv2 Rules APIs
- Create a model class for Rules
- Implement LockTokens and some other missing fields for WACLs

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/8259?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
Attention: Patch coverage is `96.01770%` with `9 lines` in your changes missing coverage. Please review.
> Project coverage is 94.55%. Comparing base [(`035586c`)](https://app.codecov.io/gh/getmoto/moto/commit/035586c69c0cf144fd12ba27c4acbb92fb2e04cb?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`298a683`)](https://app.codecov.io/gh/getmoto/moto/commit/298a683ea2e75ddaffa302c71cfc70aca8d13626?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).
> Report is 15 commits behind head on master.

| [Files with missing lines](https://app.codecov.io/gh/getmoto/moto/pull/8259?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Patch % | Lines |
|---|---|---|
| [moto/wafv2/models.py](https://app.codecov.io/gh/getmoto/moto/pull/8259?src=pr&el=tree&filepath=moto%2Fwafv2%2Fmodels.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by93YWZ2Mi9tb2RlbHMucHk=) | 95.86% | [6 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/8259?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |
| [moto/utilities/utils.py](https://app.codecov.io/gh/getmoto/moto/pull/8259?src=pr&el=tree&filepath=moto%2Futilities%2Futils.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by91dGlsaXRpZXMvdXRpbHMucHk=) | 71.42% | [2 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/8259?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |
| [moto/wafv2/responses.py](https://app.codecov.io/gh/getmoto/moto/pull/8259?src=pr&el=tree&filepath=moto%2Fwafv2%2Fresponses.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by93YWZ2Mi9yZXNwb25zZXMucHk=) | 98.43% | [1 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/8259?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #8259      +/-   ##
==========================================
+ Coverage   94.54%   94.55%   +0.01%     
==========================================
  Files        1158     1158              
  Lines      100111   100482     +371     
==========================================
+ Hits        94654    95015     +361     
- Misses       5457     5467      +10     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/8259/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/8259/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `28.87% <19.02%> (-0.01%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/8259/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `94.53% <96.01%> (+0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/8259?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).


Patch:
diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md
index 9a028d6bd..216a6488c 100644
--- a/IMPLEMENTATION_COVERAGE.md
+++ b/IMPLEMENTATION_COVERAGE.md
@@ -296,7 +296,7 @@
 
 ## appconfig
 <details>
-<summary>33% implemented</summary>
+<summary>34% implemented</summary>
 
 - [X] create_application
 - [X] create_configuration_profile
@@ -312,7 +312,6 @@
 - [ ] delete_extension
 - [ ] delete_extension_association
 - [X] delete_hosted_configuration_version
-- [ ] get_account_settings
 - [X] get_application
 - [ ] get_configuration
 - [X] get_configuration_profile
@@ -335,7 +334,6 @@
 - [ ] stop_deployment
 - [X] tag_resource
 - [X] untag_resource
-- [ ] update_account_settings
 - [X] update_application
 - [X] update_configuration_profile
 - [ ] update_deployment_strategy
@@ -722,7 +720,7 @@
 
 ## batch
 <details>
-<summary>96% implemented</summary>
+<summary>100% implemented</summary>
 
 - [X] cancel_job
 - [X] create_compute_environment
@@ -737,7 +735,6 @@
 - [X] describe_job_queues
 - [X] describe_jobs
 - [X] describe_scheduling_policies
-- [ ] get_job_queue_snapshot
 - [X] list_jobs
 - [X] list_scheduling_policies
 - [X] list_tags_for_resource
@@ -753,50 +750,34 @@
 
 ## bedrock
 <details>
-<summary>28% implemented</summary>
+<summary>43% implemented</summary>
 
-- [ ] batch_delete_evaluation_job
 - [ ] create_evaluation_job
 - [ ] create_guardrail
 - [ ] create_guardrail_version
-- [ ] create_model_copy_job
 - [X] create_model_customization_job
-- [ ] create_model_import_job
-- [ ] create_model_invocation_job
 - [ ] create_provisioned_model_throughput
 - [X] delete_custom_model
 - [ ] delete_guardrail
-- [ ] delete_imported_model
 - [X] delete_model_invocation_logging_configuration
 - [ ] delete_provisioned_model_throughput
 - [X] get_custom_model
 - [ ] get_evaluation_job
 - [ ] get_foundation_model
 - [ ] get_guardrail
-- [ ] get_imported_model
-- [ ] get_inference_profile
-- [ ] get_model_copy_job
 - [X] get_model_customization_job
-- [ ] get_model_import_job
-- [ ] get_model_invocation_job
 - [X] get_model_invocation_logging_configuration
 - [ ] get_provisioned_model_throughput
 - [X] list_custom_models
 - [ ] list_evaluation_jobs
 - [ ] list_foundation_models
 - [ ] list_guardrails
-- [ ] list_imported_models
-- [ ] list_inference_profiles
-- [ ] list_model_copy_jobs
 - [X] list_model_customization_jobs
-- [ ] list_model_import_jobs
-- [ ] list_model_invocation_jobs
 - [ ] list_provisioned_model_throughputs
 - [X] list_tags_for_resource
 - [X] put_model_invocation_logging_configuration
 - [ ] stop_evaluation_job
 - [X] stop_model_customization_job
-- [ ] stop_model_invocation_job
 - [X] tag_resource
 - [X] untag_resource
 - [ ] update_guardrail
@@ -805,29 +786,20 @@
 
 ## bedrock-agent
 <details>
-<summary>17% implemented</summary>
+<summary>27% implemented</summary>
 
 - [ ] associate_agent_knowledge_base
 - [X] create_agent
 - [ ] create_agent_action_group
 - [ ] create_agent_alias
 - [ ] create_data_source
-- [ ] create_flow
-- [ ] create_flow_alias
-- [ ] create_flow_version
 - [X] create_knowledge_base
-- [ ] create_prompt
-- [ ] create_prompt_version
 - [X] delete_agent
 - [ ] delete_agent_action_group
 - [ ] delete_agent_alias
 - [ ] delete_agent_version
 - [ ] delete_data_source
-- [ ] delete_flow
-- [ ] delete_flow_alias
-- [ ] delete_flow_version
 - [X] delete_knowledge_base
-- [ ] delete_prompt
 - [ ] disassociate_agent_knowledge_base
 - [X] get_agent
 - [ ] get_agent_action_group
@@ -835,29 +807,19 @@
 - [ ] get_agent_knowledge_base
 - [ ] get_agent_version
 - [ ] get_data_source
-- [ ] get_flow
-- [ ] get_flow_alias
-- [ ] get_flow_version
 - [ ] get_ingestion_job
 - [X] get_knowledge_base
-- [ ] get_prompt
 - [ ] list_agent_action_groups
 - [ ] list_agent_aliases
 - [ ] list_agent_knowledge_bases
 - [ ] list_agent_versions
 - [X] list_agents
 - [ ] list_data_sources
-- [ ] list_flow_aliases
-- [ ] list_flow_versions
-- [ ] list_flows
 - [ ] list_ingestion_jobs
 - [X] list_knowledge_bases
-- [ ] list_prompts
 - [X] list_tags_for_resource
 - [ ] prepare_agent
-- [ ] prepare_flow
 - [ ] start_ingestion_job
-- [ ] stop_ingestion_job
 - [X] tag_resource
 - [X] untag_resource
 - [ ] update_agent
@@ -865,15 +827,12 @@
 - [ ] update_agent_alias
 - [ ] update_agent_knowledge_base
 - [ ] update_data_source
-- [ ] update_flow
-- [ ] update_flow_alias
 - [ ] update_knowledge_base
-- [ ] update_prompt
 </details>
 
 ## budgets
 <details>
-<summary>26% implemented</summary>
+<summary>30% implemented</summary>
 
 - [X] create_budget
 - [ ] create_budget_action
@@ -894,9 +853,6 @@
 - [X] describe_notifications_for_budget
 - [ ] describe_subscribers_for_notification
 - [ ] execute_budget_action
-- [ ] list_tags_for_resource
-- [ ] tag_resource
-- [ ] untag_resource
 - [ ] update_budget
 - [ ] update_budget_action
 - [ ] update_notification
@@ -1397,7 +1353,7 @@
 
 ## codepipeline
 <details>
-<summary>18% implemented</summary>
+<summary>20% implemented</summary>
 
 - [ ] acknowledge_job
 - [ ] acknowledge_third_party_job
@@ -1419,11 +1375,8 @@
 - [ ] list_action_types
 - [ ] list_pipeline_executions
 - [X] list_pipelines
-- [ ] list_rule_executions
-- [ ] list_rule_types
 - [X] list_tags_for_resource
 - [ ] list_webhooks
-- [ ] override_stage_condition
 - [ ] poll_for_jobs
 - [ ] poll_for_third_party_jobs
 - [ ] put_action_revision
@@ -1435,7 +1388,6 @@
 - [ ] put_webhook
 - [ ] register_webhook_with_third_party
 - [ ] retry_stage_execution
-- [ ] rollback_stage
 - [ ] start_pipeline_execution
 - [ ] stop_pipeline_execution
 - [X] tag_resource
@@ -2016,7 +1968,6 @@
 - [ ] apply_pending_maintenance_action
 - [ ] batch_start_recommendations
 - [ ] cancel_replication_task_assessment_run
-- [ ] create_data_migration
 - [ ] create_data_provider
 - [ ] create_endpoint
 - [ ] create_event_subscription
@@ -2029,7 +1980,6 @@
 - [X] create_replication_task
 - [ ] delete_certificate
 - [ ] delete_connection
-- [ ] delete_data_migration
 - [ ] delete_data_provider
 - [ ] delete_endpoint
 - [ ] delete_event_subscription
@@ -2047,7 +1997,6 @@
 - [ ] describe_certificates
 - [ ] describe_connections
 - [ ] describe_conversion_configuration
-- [ ] describe_data_migrations
 - [ ] describe_data_providers
 - [ ] describe_endpoint_settings
 - [ ] describe_endpoint_types
@@ -2090,7 +2039,6 @@
 - [ ] import_certificate
 - [ ] list_tags_for_resource
 - [ ] modify_conversion_configuration
-- [ ] modify_data_migration
 - [ ] modify_data_provider
 - [ ] modify_endpoint
 - [ ] modify_event_subscription
@@ -2107,7 +2055,6 @@
 - [ ] reload_tables
 - [ ] remove_tags_from_resource
 - [ ] run_fleet_advisor_lsa_analysis
-- [ ] start_data_migration
 - [ ] start_extension_pack_association
 - [ ] start_metadata_model_assessment
 - [ ] start_metadata_model_conversion
@@ -2119,7 +2066,6 @@
 - [X] start_replication_task
 - [ ] start_replication_task_assessment
 - [ ] start_replication_task_assessment_run
-- [ ] stop_data_migration
 - [ ] stop_replication
 - [X] stop_replication_task
 - [ ] test_connection
@@ -2128,7 +2074,7 @@
 
 ## ds
 <details>
-<summary>25% implemented</summary>
+<summary>26% implemented</summary>
 
 - [ ] accept_shared_directory
 - [ ] add_ip_routes
@@ -2155,7 +2101,6 @@
 - [ ] describe_client_authentication_settings
 - [ ] describe_conditional_forwarders
 - [X] describe_directories
-- [ ] describe_directory_data_access
 - [ ] describe_domain_controllers
 - [ ] describe_event_topics
 - [X] describe_ldaps_settings
@@ -2166,12 +2111,10 @@
 - [X] describe_trusts
 - [ ] describe_update_directory
 - [ ] disable_client_authentication
-- [ ] disable_directory_data_access
 - [X] disable_ldaps
 - [ ] disable_radius
 - [X] disable_sso
 - [ ] enable_client_authentication
-- [ ] enable_directory_data_access
 - [X] enable_ldaps
 - [ ] enable_radius
 - [X] enable_sso
@@ -2292,7 +2235,6 @@
 <summary>33% implemented</summary>
 
 - [ ] accept_address_transfer
-- [ ] accept_capacity_reservation_billing_ownership
 - [ ] accept_reserved_instances_exchange_quote
 - [ ] accept_transit_gateway_multicast_domain_associations
 - [X] accept_transit_gateway_peering_attachment
@@ -2308,7 +2250,6 @@
 - [X] assign_private_ip_addresses
 - [ ] assign_private_nat_gateway_address
 - [X] associate_address
-- [ ] associate_capacity_reservation_billing_owner
 - [ ] associate_client_vpn_target_network
 - [X] associate_dhcp_options
 - [ ] associate_enclave_certificate_iam_role
@@ -2349,7 +2290,6 @@
 - [X] copy_image
 - [X] copy_snapshot
 - [ ] create_capacity_reservation
-- [ ] create_capacity_reservation_by_splitting
 - [ ] create_capacity_reservation_fleet
 - [X] create_carrier_gateway
 - [ ] create_client_vpn_endpoint
@@ -2370,7 +2310,6 @@
 - [ ] create_instance_export_task
 - [X] create_internet_gateway
 - [ ] create_ipam
-- [ ] create_ipam_external_resource_verification_token
 - [ ] create_ipam_pool
 - [ ] create_ipam_resource_discovery
 - [ ] create_ipam_scope
@@ -2447,7 +2386,6 @@
 - [ ] delete_instance_event_window
 - [X] delete_internet_gateway
 - [ ] delete_ipam
-- [ ] delete_ipam_external_resource_verification_token
 - [ ] delete_ipam_pool
 - [ ] delete_ipam_resource_discovery
 - [ ] delete_ipam_scope
@@ -2525,7 +2463,6 @@
 - [ ] describe_bundle_tasks
 - [ ] describe_byoip_cidrs
 - [ ] describe_capacity_block_offerings
-- [ ] describe_capacity_reservation_billing_requests
 - [ ] describe_capacity_reservation_fleets
 - [ ] describe_capacity_reservations
 - [X] describe_carrier_gateways
@@ -2573,7 +2510,6 @@
 - [X] describe_instances
 - [X] describe_internet_gateways
 - [ ] describe_ipam_byoasn
-- [ ] describe_ipam_external_resource_verification_tokens
 - [ ] describe_ipam_pools
 - [ ] describe_ipam_resource_discoveries
 - [ ] describe_ipam_resource_discovery_associations
@@ -2631,7 +2567,6 @@
 - [ ] describe_store_image_tasks
 - [X] describe_subnets
 - [X] describe_tags
-- [ ] describe_traffic_mirror_filter_rules
 - [ ] describe_traffic_mirror_filters
 - [ ] describe_traffic_mirror_sessions
 - [ ] describe_traffic_mirror_targets
@@ -2691,7 +2626,6 @@
 - [X] disable_vpc_classic_link
 - [X] disable_vpc_classic_link_dns_support
 - [X] disassociate_address
-- [ ] disassociate_capacity_reservation_billing_owner
 - [ ] disassociate_client_vpn_target_network
 - [ ] disassociate_enclave_certificate_iam_role
 - [X] disassociate_iam_instance_profile
@@ -2743,7 +2677,6 @@
 - [ ] get_host_reservation_purchase_preview
 - [ ] get_image_block_public_access_state
 - [ ] get_instance_metadata_defaults
-- [ ] get_instance_tpm_ek_pub
 - [ ] get_instance_types_from_instance_requirements
 - [ ] get_instance_uefi_data
 - [ ] get_ipam_address_history
@@ -2801,7 +2734,6 @@
 - [X] modify_image_attribute
 - [X] modify_instance_attribute
 - [ ] modify_instance_capacity_reservation_attributes
-- [ ] modify_instance_cpu_options
 - [ ] modify_instance_credit_specification
 - [ ] modify_instance_event_start_time
 - [ ] modify_instance_event_window
@@ -2855,7 +2787,6 @@
 - [ ] monitor_instances
 - [ ] move_address_to_vpc
 - [ ] move_byoip_cidr_to_ipam
-- [ ] move_capacity_reservation_instances
 - [ ] provision_byoip_cidr
 - [ ] provision_ipam_byoasn
 - [ ] provision_ipam_pool_cidr
@@ -2869,7 +2800,6 @@
 - [ ] register_instance_event_notification_attributes
 - [ ] register_transit_gateway_multicast_group_members
 - [ ] register_transit_gateway_multicast_group_sources
-- [ ] reject_capacity_reservation_billing_ownership
 - [ ] reject_transit_gateway_multicast_domain_associations
 - [X] reject_transit_gateway_peering_attachment
 - [ ] reject_transit_gateway_vpc_attachment
@@ -2936,7 +2866,7 @@
 
 ## ecr
 <details>
-<summary>59% implemented</summary>
+<summary>67% implemented</summary>
 
 - [ ] batch_check_layer_availability
 - [X] batch_delete_image
@@ -2945,12 +2875,10 @@
 - [ ] complete_layer_upload
 - [ ] create_pull_through_cache_rule
 - [X] create_repository
-- [ ] create_repository_creation_template
 - [X] delete_lifecycle_policy
 - [ ] delete_pull_through_cache_rule
 - [X] delete_registry_policy
 - [X] delete_repository
-- [ ] delete_repository_creation_template
 - [X] delete_repository_policy
 - [ ] describe_image_replication_status
 - [X] describe_image_scan_findings
@@ -2958,8 +2886,6 @@
 - [ ] describe_pull_through_cache_rules
 - [X] describe_registry
 - [X] describe_repositories
-- [ ] describe_repository_creation_templates
-- [ ] get_account_setting
 - [ ] get_authorization_token
 - [ ] get_download_url_for_layer
 - [X] get_lifecycle_policy
@@ -2970,7 +2896,6 @@
 - [ ] initiate_layer_upload
 - [X] list_images
 - [X] list_tags_for_resource
-- [ ] put_account_setting
 - [X] put_image
 - [X] put_image_scanning_configuration
 - [X] put_image_tag_mutability
@@ -2984,7 +2909,6 @@
 - [X] tag_resource
 - [X] untag_resource
 - [ ] update_pull_through_cache_rule
-- [ ] update_repository_creation_template
 - [ ] upload_layer_part
 - [ ] validate_pull_through_cache_rule
 </details>
@@ -3344,7 +3268,7 @@
 
 ## elbv2
 <details>
-<summary>64% implemented</summary>
+<summary>70% implemented</summary>
 
 - [X] add_listener_certificates
 - [X] add_tags
@@ -3357,12 +3281,10 @@
 - [X] delete_listener
 - [X] delete_load_balancer
 - [X] delete_rule
-- [ ] delete_shared_trust_store_association
 - [X] delete_target_group
 - [ ] delete_trust_store
 - [X] deregister_targets
 - [ ] describe_account_limits
-- [ ] describe_listener_attributes
 - [X] describe_listener_certificates
 - [X] describe_listeners
 - [X] describe_load_balancer_attributes
@@ -3376,11 +3298,9 @@
 - [ ] describe_trust_store_associations
 - [ ] describe_trust_store_revocations
 - [ ] describe_trust_stores
-- [ ] get_resource_policy
 - [ ] get_trust_store_ca_certificates_bundle
 - [ ] get_trust_store_revocation_content
 - [X] modify_listener
-- [ ] modify_listener_attributes
 - [X] modify_load_balancer_attributes
 - [X] modify_rule
 - [X] modify_target_group
@@ -3460,12 +3380,11 @@
 
 ## emr-containers
 <details>
-<summary>34% implemented</summary>
+<summary>40% implemented</summary>
 
 - [X] cancel_job_run
 - [ ] create_job_template
 - [ ] create_managed_endpoint
-- [ ] create_security_configuration
 - [X] create_virtual_cluster
 - [ ] delete_job_template
 - [ ] delete_managed_endpoint
@@ -3473,13 +3392,11 @@
 - [X] describe_job_run
 - [ ] describe_job_template
 - [ ] describe_managed_endpoint
-- [ ] describe_security_configuration
 - [X] describe_virtual_cluster
 - [ ] get_managed_endpoint_session_credentials
 - [X] list_job_runs
 - [ ] list_job_templates
 - [ ] list_managed_endpoints
-- [ ] list_security_configurations
 - [ ] list_tags_for_resource
 - [X] list_virtual_clusters
 - [X] start_job_run
@@ -3489,7 +3406,7 @@
 
 ## emr-serverless
 <details>
-<summary>68% implemented</summary>
+<summary>73% implemented</summary>
 
 - [X] cancel_job_run
 - [X] create_application
@@ -3498,7 +3415,6 @@
 - [ ] get_dashboard_for_job_run
 - [X] get_job_run
 - [X] list_applications
-- [ ] list_job_run_attempts
 - [X] list_job_runs
 - [ ] list_tags_for_resource
 - [X] start_application
@@ -3568,7 +3484,7 @@
 
 ## events
 <details>
-<summary>78% implemented</summary>
+<summary>80% implemented</summary>
 
 - [ ] activate_event_source
 - [X] cancel_replay
@@ -3626,7 +3542,6 @@
 - [X] update_archive
 - [X] update_connection
 - [ ] update_endpoint
-- [ ] update_event_bus
 </details>
 
 ## firehose
@@ -3808,7 +3723,7 @@
 
 ## glue
 <details>
-<summary>29% implemented</summary>
+<summary>31% implemented</summary>
 
 - [X] batch_create_partition
 - [ ] batch_delete_connection
@@ -3825,7 +3740,6 @@
 - [ ] batch_get_table_optimizer
 - [X] batch_get_triggers
 - [ ] batch_get_workflows
-- [ ] batch_put_data_quality_statistic_annotation
 - [ ] batch_stop_job_run
 - [X] batch_update_partition
 - [ ] cancel_data_quality_rule_recommendation_run
@@ -3853,7 +3767,6 @@
 - [X] create_table
 - [ ] create_table_optimizer
 - [X] create_trigger
-- [ ] create_usage_profile
 - [ ] create_user_defined_function
 - [ ] create_workflow
 - [ ] delete_blueprint
@@ -3880,7 +3793,6 @@
 - [ ] delete_table_optimizer
 - [X] delete_table_version
 - [X] delete_trigger
-- [ ] delete_usage_profile
 - [ ] delete_user_defined_function
 - [ ] delete_workflow
 - [ ] get_blueprint
@@ -3900,8 +3812,6 @@
 - [X] get_crawlers
 - [ ] get_custom_entity_type
 - [ ] get_data_catalog_encryption_settings
-- [ ] get_data_quality_model
-- [ ] get_data_quality_model_result
 - [ ] get_data_quality_result
 - [ ] get_data_quality_rule_recommendation_run
 - [ ] get_data_quality_ruleset
@@ -3947,7 +3857,6 @@
 - [ ] get_unfiltered_partition_metadata
 - [ ] get_unfiltered_partitions_metadata
 - [ ] get_unfiltered_table_metadata
-- [ ] get_usage_profile
 - [ ] get_user_defined_function
 - [ ] get_user_defined_functions
 - [ ] get_workflow
@@ -3964,8 +3873,6 @@
 - [ ] list_data_quality_rule_recommendation_runs
 - [ ] list_data_quality_ruleset_evaluation_runs
 - [ ] list_data_quality_rulesets
-- [ ] list_data_quality_statistic_annotations
-- [ ] list_data_quality_statistics
 - [ ] list_dev_endpoints
 - [X] list_jobs
 - [ ] list_ml_transforms
@@ -3976,10 +3883,8 @@
 - [ ] list_statements
 - [ ] list_table_optimizer_runs
 - [X] list_triggers
-- [ ] list_usage_profiles
 - [ ] list_workflows
 - [ ] put_data_catalog_encryption_settings
-- [ ] put_data_quality_profile_annotation
 - [ ] put_resource_policy
 - [X] put_schema_version_metadata
 - [ ] put_workflow_run_properties
@@ -4010,7 +3915,6 @@
 - [X] stop_trigger
 - [ ] stop_workflow_run
 - [X] tag_resource
-- [ ] test_connection
 - [X] untag_resource
 - [ ] update_blueprint
 - [ ] update_classifier
@@ -4032,7 +3936,6 @@
 - [X] update_table
 - [ ] update_table_optimizer
 - [ ] update_trigger
-- [ ] update_usage_profile
 - [ ] update_user_defined_function
 - [ ] update_workflow
 </details>
@@ -4137,7 +4040,7 @@
 
 ## guardduty
 <details>
-<summary>14% implemented</summary>
+<summary>15% implemented</summary>
 
 - [ ] accept_administrator_invitation
 - [ ] accept_invitation
@@ -4145,7 +4048,6 @@
 - [X] create_detector
 - [X] create_filter
 - [ ] create_ip_set
-- [ ] create_malware_protection_plan
 - [ ] create_members
 - [ ] create_publishing_destination
 - [ ] create_sample_findings
@@ -4155,7 +4057,6 @@
 - [X] delete_filter
 - [ ] delete_invitations
 - [ ] delete_ip_set
-- [ ] delete_malware_protection_plan
 - [ ] delete_members
 - [ ] delete_publishing_destination
 - [ ] delete_threat_intel_set
@@ -4175,7 +4076,6 @@
 - [ ] get_findings_statistics
 - [ ] get_invitations_count
 - [ ] get_ip_set
-- [ ] get_malware_protection_plan
 - [ ] get_malware_scan_settings
 - [ ] get_master_account
 - [ ] get_member_detectors
@@ -4191,7 +4091,6 @@
 - [ ] list_findings
 - [ ] list_invitations
 - [ ] list_ip_sets
-- [ ] list_malware_protection_plans
 - [ ] list_members
 - [X] list_organization_admin_accounts
 - [ ] list_publishing_destinations
@@ -4207,7 +4106,6 @@
 - [X] update_filter
 - [ ] update_findings_feedback
 - [ ] update_ip_set
-- [ ] update_malware_protection_plan
 - [ ] update_malware_scan_settings
 - [ ] update_member_detectors
 - [ ] update_organization_configuration
@@ -4477,7 +4375,6 @@
 - [ ] accept_certificate_transfer
 - [ ] add_thing_to_billing_group
 - [X] add_thing_to_thing_group
-- [ ] associate_sbom_with_package_version
 - [ ] associate_targets_with_job
 - [X] attach_policy
 - [X] attach_principal_policy
@@ -4596,7 +4493,6 @@
 - [ ] detach_security_profile
 - [X] detach_thing_principal
 - [X] disable_topic_rule
-- [ ] disassociate_sbom_from_package_version
 - [X] enable_topic_rule
 - [ ] get_behavior_model_training_summaries
 - [ ] get_buckets_aggregation
@@ -4657,7 +4553,6 @@
 - [ ] list_provisioning_templates
 - [ ] list_related_resources_for_audit_finding
 - [ ] list_role_aliases
-- [ ] list_sbom_validation_results
 - [ ] list_scheduled_audits
 - [ ] list_security_profiles
 - [ ] list_security_profiles_for_target
@@ -4876,7 +4771,7 @@
 
 ## kms
 <details>
-<summary>64% implemented</summary>
+<summary>65% implemented</summary>
 
 - [X] cancel_key_deletion
 - [ ] connect_custom_key_store
@@ -4888,7 +4783,6 @@
 - [X] delete_alias
 - [ ] delete_custom_key_store
 - [ ] delete_imported_key_material
-- [ ] derive_shared_secret
 - [ ] describe_custom_key_stores
 - [X] describe_key
 - [X] disable_key
@@ -4935,7 +4829,7 @@
 
 ## lakeformation
 <details>
-<summary>36% implemented</summary>
+<summary>37% implemented</summary>
 
 - [X] add_lf_tags_to_resource
 - [ ] assume_decorated_role_with_saml
@@ -4958,7 +4852,6 @@
 - [ ] describe_transaction
 - [ ] extend_transaction
 - [ ] get_data_cells_filter
-- [ ] get_data_lake_principal
 - [X] get_data_lake_settings
 - [ ] get_effective_permissions_for_path
 - [X] get_lf_tag
@@ -4996,7 +4889,7 @@
 
 ## lambda
 <details>
-<summary>63% implemented</summary>
+<summary>65% implemented</summary>
 
 - [ ] add_layer_version_permission
 - [X] add_permission
@@ -5024,7 +4917,6 @@
 - [X] get_function_concurrency
 - [ ] get_function_configuration
 - [X] get_function_event_invoke_config
-- [ ] get_function_recursion_config
 - [X] get_function_url_config
 - [X] get_layer_version
 - [ ] get_layer_version_by_arn
@@ -5052,7 +4944,6 @@
 - [ ] put_function_code_signing_config
 - [X] put_function_concurrency
 - [X] put_function_event_invoke_config
-- [ ] put_function_recursion_config
 - [ ] put_provisioned_concurrency_config
 - [ ] put_runtime_management_config
 - [ ] remove_layer_version_permission
@@ -5070,7 +4961,7 @@
 
 ## logs
 <details>
-<summary>47% implemented</summary>
+<summary>48% implemented</summary>
 
 - [ ] associate_kms_key
 - [X] cancel_export_task
@@ -5095,7 +4986,6 @@
 - [X] delete_retention_policy
 - [X] delete_subscription_filter
 - [ ] describe_account_policies
-- [ ] describe_configuration_templates
 - [ ] describe_deliveries
 - [ ] describe_delivery_destinations
 - [ ] describe_delivery_sources
@@ -5146,7 +5036,6 @@
 - [X] untag_log_group
 - [X] untag_resource
 - [ ] update_anomaly
-- [ ] update_delivery_configuration
 - [ ] update_log_anomaly_detector
 </details>
 
@@ -5185,7 +5074,7 @@
 
 ## mediaconnect
 <details>
-<summary>34% implemented</summary>
+<summary>35% implemented</summary>
 
 - [ ] add_bridge_outputs
 - [ ] add_bridge_sources
@@ -5203,7 +5092,6 @@
 - [ ] describe_bridge
 - [X] describe_flow
 - [ ] describe_flow_source_metadata
-- [ ] describe_flow_source_thumbnail
 - [ ] describe_gateway
 - [ ] describe_gateway_instance
 - [ ] describe_offering
@@ -5243,7 +5131,7 @@
 
 ## medialive
 <details>
-<summary>10% implemented</summary>
+<summary>13% implemented</summary>
 
 - [ ] accept_input_device_transfer
 - [ ] batch_delete
@@ -5253,51 +5141,38 @@
 - [ ] cancel_input_device_transfer
 - [ ] claim_device
 - [X] create_channel
-- [ ] create_channel_placement_group
 - [ ] create_cloud_watch_alarm_template
 - [ ] create_cloud_watch_alarm_template_group
-- [ ] create_cluster
 - [ ] create_event_bridge_rule_template
 - [ ] create_event_bridge_rule_template_group
 - [X] create_input
 - [ ] create_input_security_group
 - [ ] create_multiplex
 - [ ] create_multiplex_program
-- [ ] create_network
-- [ ] create_node
-- [ ] create_node_registration_script
 - [ ] create_partner_input
 - [ ] create_signal_map
 - [ ] create_tags
 - [X] delete_channel
-- [ ] delete_channel_placement_group
 - [ ] delete_cloud_watch_alarm_template
 - [ ] delete_cloud_watch_alarm_template_group
-- [ ] delete_cluster
 - [ ] delete_event_bridge_rule_template
 - [ ] delete_event_bridge_rule_template_group
 - [X] delete_input
 - [ ] delete_input_security_group
 - [ ] delete_multiplex
 - [ ] delete_multiplex_program
-- [ ] delete_network
-- [ ] delete_node
 - [ ] delete_reservation
 - [ ] delete_schedule
 - [ ] delete_signal_map
 - [ ] delete_tags
 - [ ] describe_account_configuration
 - [X] describe_channel
-- [ ] describe_channel_placement_group
-- [ ] describe_cluster
 - [X] describe_input
 - [ ] describe_input_device
 - [ ] describe_input_device_thumbnail
 - [ ] describe_input_security_group
 - [ ] describe_multiplex
 - [ ] describe_multiplex_program
-- [ ] describe_network
-- [ ] describe_node
 - [ ] describe_offering
 - [ ] describe_reservation
 - [ ] describe_schedule
@@ -5307,11 +5182,9 @@
 - [ ] get_event_bridge_rule_template
 - [ ] get_event_bridge_rule_template_group
 - [ ] get_signal_map
-- [ ] list_channel_placement_groups
 - [X] list_channels
 - [ ] list_cloud_watch_alarm_template_groups
 - [ ] list_cloud_watch_alarm_templates
-- [ ] list_clusters
 - [ ] list_event_bridge_rule_template_groups
 - [ ] list_event_bridge_rule_templates
 - [ ] list_input_device_transfers
@@ -5320,8 +5193,6 @@
 - [X] list_inputs
 - [ ] list_multiplex_programs
 - [ ] list_multiplexes
-- [ ] list_networks
-- [ ] list_nodes
 - [ ] list_offerings
 - [ ] list_reservations
 - [ ] list_signal_maps
@@ -5344,10 +5215,8 @@
 - [ ] update_account_configuration
 - [X] update_channel
 - [ ] update_channel_class
-- [ ] update_channel_placement_group
 - [ ] update_cloud_watch_alarm_template
 - [ ] update_cloud_watch_alarm_template_group
-- [ ] update_cluster
 - [ ] update_event_bridge_rule_template
 - [ ] update_event_bridge_rule_template_group
 - [X] update_input
@@ -5355,9 +5224,6 @@
 - [ ] update_input_security_group
 - [ ] update_multiplex
 - [ ] update_multiplex_program
-- [ ] update_network
-- [ ] update_node
-- [ ] update_node_state
 - [ ] update_reservation
 </details>
 
@@ -5948,9 +5814,9 @@
 
 ## panorama
 <details>
-<summary>23% implemented</summary>
+<summary>32% implemented</summary>
 
-- [ ] create_application_instance
+- [X] create_application_instance
 - [ ] create_job_for_devices
 - [X] create_node_from_template_job
 - [ ] create_package
@@ -5958,7 +5824,7 @@
 - [X] delete_device
 - [ ] delete_package
 - [ ] deregister_package_version
-- [ ] describe_application_instance
+- [X] describe_application_instance
 - [ ] describe_application_instance_details
 - [X] describe_device
 - [ ] describe_device_job
@@ -5969,7 +5835,7 @@
 - [ ] describe_package_version
 - [ ] list_application_instance_dependencies
 - [ ] list_application_instance_node_instances
-- [ ] list_application_instances
+- [X] list_application_instances
 - [X] list_devices
 - [ ] list_devices_jobs
 - [ ] list_node_from_template_jobs
@@ -5993,7 +5859,6 @@
 - [ ] create_batch_inference_job
 - [ ] create_batch_segment_job
 - [ ] create_campaign
-- [ ] create_data_deletion_job
 - [ ] create_dataset
 - [ ] create_dataset_export_job
 - [ ] create_dataset_group
@@ -6018,7 +5883,6 @@
 - [ ] describe_batch_inference_job
 - [ ] describe_batch_segment_job
 - [ ] describe_campaign
-- [ ] describe_data_deletion_job
 - [ ] describe_dataset
 - [ ] describe_dataset_export_job
 - [ ] describe_dataset_group
@@ -6036,7 +5900,6 @@
 - [ ] list_batch_inference_jobs
 - [ ] list_batch_segment_jobs
 - [ ] list_campaigns
-- [ ] list_data_deletion_jobs
 - [ ] list_dataset_export_jobs
 - [ ] list_dataset_groups
 - [ ] list_dataset_import_jobs
@@ -6060,7 +5923,6 @@
 - [ ] update_dataset
 - [ ] update_metric_attribution
 - [ ] update_recommender
-- [ ] update_solution
 </details>
 
 ## pinpoint
@@ -6236,8 +6098,6 @@
 <details>
 <summary>9% implemented</summary>
 
-- [ ] batch_create_topic_reviewed_answer
-- [ ] batch_delete_topic_reviewed_answer
 - [ ] cancel_ingestion
 - [ ] create_account_customization
 - [ ] create_account_subscription
@@ -6313,9 +6173,7 @@
 - [ ] describe_iam_policy_assignment
 - [ ] describe_ingestion
 - [ ] describe_ip_restriction
-- [ ] describe_key_registration
 - [ ] describe_namespace
-- [ ] describe_q_personalization_configuration
 - [ ] describe_refresh_schedule
 - [ ] describe_role_custom_permission
 - [ ] describe_template
@@ -6344,7 +6202,6 @@
 - [ ] list_data_sources
 - [ ] list_folder_members
 - [ ] list_folders
-- [ ] list_folders_for_resource
 - [X] list_group_memberships
 - [X] list_groups
 - [ ] list_iam_policy_assignments
@@ -6362,7 +6219,6 @@
 - [ ] list_theme_versions
 - [ ] list_themes
 - [ ] list_topic_refresh_schedules
-- [ ] list_topic_reviewed_answers
 - [ ] list_topics
 - [X] list_user_groups
 - [X] list_users
@@ -6379,7 +6235,6 @@
 - [ ] start_asset_bundle_export_job
 - [ ] start_asset_bundle_import_job
 - [ ] start_dashboard_snapshot_job
-- [ ] start_dashboard_snapshot_job_schedule
 - [ ] tag_resource
 - [ ] untag_resource
 - [ ] update_account_customization
@@ -6400,12 +6255,9 @@
 - [ ] update_iam_policy_assignment
 - [ ] update_identity_propagation_config
 - [ ] update_ip_restriction
-- [ ] update_key_registration
 - [ ] update_public_sharing_settings
-- [ ] update_q_personalization_configuration
 - [ ] update_refresh_schedule
 - [ ] update_role_custom_permission
-- [ ] update_spice_capacity_configuration
 - [ ] update_template
 - [ ] update_template_alias
 - [ ] update_template_permissions
@@ -6641,7 +6493,7 @@
 
 ## redshift
 <details>
-<summary>21% implemented</summary>
+<summary>22% implemented</summary>
 
 - [ ] accept_reserved_node_exchange
 - [ ] add_partner
@@ -6665,7 +6517,6 @@
 - [ ] create_event_subscription
 - [ ] create_hsm_client_certificate
 - [ ] create_hsm_configuration
-- [ ] create_integration
 - [ ] create_redshift_idc_application
 - [ ] create_scheduled_action
 - [X] create_snapshot_copy_grant
@@ -6684,7 +6535,6 @@
 - [ ] delete_event_subscription
 - [ ] delete_hsm_client_certificate
 - [ ] delete_hsm_configuration
-- [ ] delete_integration
 - [ ] delete_partner
 - [ ] delete_redshift_idc_application
 - [ ] delete_resource_policy
@@ -6717,7 +6567,6 @@
 - [ ] describe_hsm_client_certificates
 - [ ] describe_hsm_configurations
 - [ ] describe_inbound_integrations
-- [ ] describe_integrations
 - [ ] describe_logging_status
 - [ ] describe_node_configuration_options
 - [ ] describe_orderable_cluster_options
@@ -6759,7 +6608,6 @@
 - [ ] modify_custom_domain_association
 - [ ] modify_endpoint_access
 - [ ] modify_event_subscription
-- [ ] modify_integration
 - [ ] modify_redshift_idc_application
 - [ ] modify_scheduled_action
 - [X] modify_snapshot_copy_retention_period
@@ -6881,9 +6729,8 @@
 
 ## resiliencehub
 <details>
-<summary>28% implemented</summary>
+<summary>31% implemented</summary>
 
-- [ ] accept_resource_grouping_recommendations
 - [ ] add_draft_app_version_resource_mappings
 - [ ] batch_update_recommendation_status
 - [X] create_app
@@ -6907,11 +6754,9 @@
 - [ ] describe_app_version_template
 - [ ] describe_draft_app_version_resources_import_status
 - [X] describe_resiliency_policy
-- [ ] describe_resource_grouping_recommendation_task
 - [X] import_resources_to_draft_app_version
 - [ ] list_alarm_recommendations
 - [ ] list_app_assessment_compliance_drifts
-- [ ] list_app_assessment_resource_drifts
 - [X] list_app_assessments
 - [ ] list_app_component_compliances
 - [ ] list_app_component_recommendations
@@ -6923,7 +6768,6 @@
 - [X] list_apps
 - [ ] list_recommendation_templates
 - [X] list_resiliency_policies
-- [ ] list_resource_grouping_recommendations
 - [ ] list_sop_recommendations
 - [ ] list_suggested_resiliency_policies
 - [X] list_tags_for_resource
@@ -6931,11 +6775,9 @@
 - [ ] list_unsupported_app_version_resources
 - [X] publish_app_version
 - [ ] put_draft_app_version_template
-- [ ] reject_resource_grouping_recommendations
 - [ ] remove_draft_app_version_resource_mappings
 - [ ] resolve_app_version_resources
 - [ ] start_app_assessment
-- [ ] start_resource_grouping_recommendation_task
 - [X] tag_resource
 - [X] untag_resource
 - [ ] update_app
@@ -6947,25 +6789,20 @@
 
 ## resource-groups
 <details>
-<summary>47% implemented</summary>
+<summary>61% implemented</summary>
 
-- [ ] cancel_tag_sync_task
 - [X] create_group
 - [X] delete_group
 - [ ] get_account_settings
 - [X] get_group
 - [X] get_group_configuration
 - [ ] get_group_query
-- [ ] get_tag_sync_task
 - [X] get_tags
 - [ ] group_resources
 - [ ] list_group_resources
-- [ ] list_grouping_statuses
 - [X] list_groups
-- [ ] list_tag_sync_tasks
 - [X] put_group_configuration
 - [ ] search_resources
-- [ ] start_tag_sync_task
 - [X] tag
 - [ ] ungroup_resources
 - [X] untag
@@ -7417,7 +7254,6 @@
 - [ ] list_access_grants_locations
 - [ ] list_access_points
 - [ ] list_access_points_for_object_lambda
-- [ ] list_caller_access_grants
 - [ ] list_jobs
 - [ ] list_multi_region_access_points
 - [ ] list_regional_buckets
@@ -7449,7 +7285,7 @@
 
 ## sagemaker
 <details>
-<summary>33% implemented</summary>
+<summary>35% implemented</summary>
 
 - [ ] add_association
 - [X] add_tags
@@ -7478,7 +7314,6 @@
 - [X] create_feature_group
 - [ ] create_flow_definition
 - [ ] create_hub
-- [ ] create_hub_content_reference
 - [ ] create_human_task_ui
 - [X] create_hyper_parameter_tuning_job
 - [ ] create_image
@@ -7487,7 +7322,6 @@
 - [ ] create_inference_experiment
 - [ ] create_inference_recommendations_job
 - [ ] create_labeling_job
-- [ ] create_mlflow_tracking_server
 - [X] create_model
 - [X] create_model_bias_job_definition
 - [X] create_model_card
@@ -7499,10 +7333,8 @@
 - [ ] create_monitoring_schedule
 - [X] create_notebook_instance
 - [X] create_notebook_instance_lifecycle_config
-- [ ] create_optimization_job
 - [X] create_pipeline
 - [ ] create_presigned_domain_url
-- [ ] create_presigned_mlflow_tracking_server_url
 - [ ] create_presigned_notebook_instance_url
 - [X] create_processing_job
 - [ ] create_project
@@ -7537,14 +7369,12 @@
 - [ ] delete_flow_definition
 - [ ] delete_hub
 - [ ] delete_hub_content
-- [ ] delete_hub_content_reference
 - [ ] delete_human_task_ui
 - [X] delete_hyper_parameter_tuning_job
 - [ ] delete_image
 - [ ] delete_image_version
 - [ ] delete_inference_component
 - [ ] delete_inference_experiment
-- [ ] delete_mlflow_tracking_server
 - [X] delete_model
 - [X] delete_model_bias_job_definition
 - [X] delete_model_card
@@ -7556,7 +7386,6 @@
 - [ ] delete_monitoring_schedule
 - [X] delete_notebook_instance
 - [X] delete_notebook_instance_lifecycle_config
-- [ ] delete_optimization_job
 - [X] delete_pipeline
 - [ ] delete_project
 - [ ] delete_space
@@ -7603,7 +7432,6 @@
 - [ ] describe_inference_recommendations_job
 - [ ] describe_labeling_job
 - [ ] describe_lineage_group
-- [ ] describe_mlflow_tracking_server
 - [X] describe_model
 - [X] describe_model_bias_job_definition
 - [X] describe_model_card
@@ -7615,7 +7443,6 @@
 - [ ] describe_monitoring_schedule
 - [ ] describe_notebook_instance
 - [X] describe_notebook_instance_lifecycle_config
-- [ ] describe_optimization_job
 - [X] describe_pipeline
 - [X] describe_pipeline_definition_for_execution
 - [X] describe_pipeline_execution
@@ -7680,7 +7507,6 @@
 - [ ] list_labeling_jobs
 - [ ] list_labeling_jobs_for_workteam
 - [ ] list_lineage_groups
-- [ ] list_mlflow_tracking_servers
 - [X] list_model_bias_job_definitions
 - [ ] list_model_card_export_jobs
 - [X] list_model_card_versions
@@ -7697,7 +7523,6 @@
 - [ ] list_monitoring_schedules
 - [ ] list_notebook_instance_lifecycle_configs
 - [X] list_notebook_instances
-- [ ] list_optimization_jobs
 - [ ] list_pipeline_execution_steps
 - [X] list_pipeline_executions
 - [X] list_pipeline_parameters_for_execution
@@ -7728,7 +7553,6 @@
 - [ ] send_pipeline_execution_step_success
 - [ ] start_edge_deployment_stage
 - [ ] start_inference_experiment
-- [ ] start_mlflow_tracking_server
 - [ ] start_monitoring_schedule
 - [X] start_notebook_instance
 - [X] start_pipeline_execution
@@ -7740,10 +7564,8 @@
 - [ ] stop_inference_experiment
 - [ ] stop_inference_recommendations_job
 - [ ] stop_labeling_job
-- [ ] stop_mlflow_tracking_server
 - [ ] stop_monitoring_schedule
 - [X] stop_notebook_instance
-- [ ] stop_optimization_job
 - [ ] stop_pipeline_execution
 - [ ] stop_processing_job
 - [ ] stop_training_job
@@ -7769,7 +7591,6 @@
 - [ ] update_inference_component
 - [ ] update_inference_component_runtime_config
 - [ ] update_inference_experiment
-- [ ] update_mlflow_tracking_server
 - [X] update_model_card
 - [X] update_model_package
 - [ ] update_monitoring_alert
@@ -7790,9 +7611,8 @@
 
 ## sagemaker-metrics
 <details>
-<summary>50% implemented</summary>
+<summary>100% implemented</summary>
 
-- [ ] batch_get_metrics
 - [X] batch_put_metrics
 </details>
 
@@ -8294,7 +8114,6 @@
 - [ ] describe_instance_patch_states
 - [ ] describe_instance_patch_states_for_patch_group
 - [ ] describe_instance_patches
-- [ ] describe_instance_properties
 - [ ] describe_inventory_deletions
 - [ ] describe_maintenance_window_execution_task_invocations
 - [ ] describe_maintenance_window_execution_tasks
@@ -8472,7 +8291,7 @@
 
 ## stepfunctions
 <details>
-<summary>54% implemented</summary>
+<summary>55% implemented</summary>
 
 - [ ] create_activity
 - [X] create_state_machine
@@ -8510,7 +8329,6 @@
 - [X] update_map_run
 - [X] update_state_machine
 - [ ] update_state_machine_alias
-- [ ] validate_state_machine_definition
 </details>
 
 ## sts
@@ -8551,14 +8369,12 @@
 
 ## swf
 <details>
-<summary>48% implemented</summary>
+<summary>51% implemented</summary>
 
 - [ ] count_closed_workflow_executions
 - [ ] count_open_workflow_executions
 - [X] count_pending_activity_tasks
 - [X] count_pending_decision_tasks
-- [ ] delete_activity_type
-- [ ] delete_workflow_type
 - [ ] deprecate_activity_type
 - [X] deprecate_domain
 - [ ] deprecate_workflow_type
@@ -8627,12 +8443,11 @@
 
 ## timestream-query
 <details>
-<summary>40% implemented</summary>
+<summary>46% implemented</summary>
 
 - [ ] cancel_query
 - [X] create_scheduled_query
 - [X] delete_scheduled_query
-- [ ] describe_account_settings
 - [X] describe_endpoints
 - [X] describe_scheduled_query
 - [ ] execute_scheduled_query
@@ -8642,7 +8457,6 @@
 - [X] query
 - [ ] tag_resource
 - [ ] untag_resource
-- [ ] update_account_settings
 - [X] update_scheduled_query
 </details>
 
@@ -8760,7 +8574,6 @@
 - [ ] list_certificates
 - [ ] list_connectors
 - [ ] list_executions
-- [ ] list_file_transfer_results
 - [ ] list_host_keys
 - [ ] list_profiles
 - [ ] list_security_policies
@@ -8849,7 +8662,7 @@
 
 ## workspaces
 <details>
-<summary>17% implemented</summary>
+<summary>18% implemented</summary>
 
 - [ ] accept_account_link_invitation
 - [ ] associate_connection_alias
@@ -8867,7 +8680,6 @@
 - [ ] create_workspace_bundle
 - [X] create_workspace_image
 - [X] create_workspaces
-- [ ] create_workspaces_pool
 - [ ] delete_account_link_invitation
 - [ ] delete_client_branding
 - [ ] delete_connect_client_add_in
@@ -8899,8 +8711,6 @@
 - [ ] describe_workspace_snapshots
 - [X] describe_workspaces
 - [ ] describe_workspaces_connection_status
-- [ ] describe_workspaces_pool_sessions
-- [ ] describe_workspaces_pools
 - [ ] disassociate_connection_alias
 - [ ] disassociate_ip_groups
 - [ ] disassociate_workspace_application
@@ -8915,7 +8725,6 @@
 - [X] modify_client_properties
 - [ ] modify_saml_properties
 - [X] modify_selfservice_permissions
-- [ ] modify_streaming_properties
 - [ ] modify_workspace_access_properties
 - [X] modify_workspace_creation_properties
 - [ ] modify_workspace_properties
@@ -8927,23 +8736,18 @@
 - [ ] restore_workspace
 - [ ] revoke_ip_rules
 - [ ] start_workspaces
-- [ ] start_workspaces_pool
 - [ ] stop_workspaces
-- [ ] stop_workspaces_pool
 - [ ] terminate_workspaces
-- [ ] terminate_workspaces_pool
-- [ ] terminate_workspaces_pool_session
 - [ ] update_connect_client_add_in
 - [ ] update_connection_alias_permission
 - [ ] update_rules_of_ip_group
 - [ ] update_workspace_bundle
 - [X] update_workspace_image_permission
-- [ ] update_workspaces_pool
 </details>
 
 ## workspaces-web
 <details>
-<summary>44% implemented</summary>
+<summary>46% implemented</summary>
 
 - [X] associate_browser_settings
 - [ ] associate_ip_access_settings
@@ -8973,14 +8777,12 @@
 - [ ] disassociate_trust_store
 - [ ] disassociate_user_access_logging_settings
 - [ ] disassociate_user_settings
-- [ ] expire_session
 - [X] get_browser_settings
 - [ ] get_identity_provider
 - [ ] get_ip_access_settings
 - [X] get_network_settings
 - [X] get_portal
 - [ ] get_portal_service_provider_metadata
-- [ ] get_session
 - [ ] get_trust_store
 - [ ] get_trust_store_certificate
 - [X] get_user_access_logging_settings
@@ -8990,7 +8792,6 @@
 - [ ] list_ip_access_settings
 - [X] list_network_settings
 - [X] list_portals
-- [ ] list_sessions
 - [X] list_tags_for_resource
 - [ ] list_trust_store_certificates
 - [ ] list_trust_stores
@@ -9013,6 +8814,7 @@
 
 - accessanalyzer
 - account
+- alexaforbusiness
 - amplify
 - amplifybackend
 - amplifyuibuilder
@@ -9021,17 +8823,16 @@
 - appflow
 - appintegrations
 - application-insights
-- application-signals
 - applicationcostprofiler
 - apprunner
 - appstream
-- apptest
 - arc-zonal-shift
 - artifact
 - auditmanager
 - autoscaling-plans
 - b2bi
 - backup-gateway
+- backupstorage
 - bcm-data-exports
 - bedrock-agent-runtime
 - bedrock-runtime
@@ -9062,6 +8863,7 @@
 - codeguru-reviewer
 - codeguru-security
 - codeguruprofiler
+- codestar
 - codestar-connections
 - codestar-notifications
 - cognito-sync
@@ -9088,7 +8890,6 @@
 - docdb
 - docdb-elastic
 - drs
-- ds-data
 - ecr-public
 - eks-auth
 - elastic-inference
@@ -9108,6 +8909,7 @@
 - groundstation
 - health
 - healthlake
+- honeycode
 - imagebuilder
 - importexport
 - inspector
@@ -9155,13 +8957,11 @@
 - m2
 - machinelearning
 - macie2
-- mailmanager
 - managedblockchain-query
 - marketplace-agreement
 - marketplace-catalog
 - marketplace-deployment
 - marketplace-entitlement
-- marketplace-reporting
 - marketplacecommerceanalytics
 - mediaconvert
 - mediapackage-vod
@@ -9174,6 +8974,7 @@
 - migrationhub-config
 - migrationhuborchestrator
 - migrationhubstrategy
+- mobile
 - mturk
 - mwaa
 - neptune-graph
@@ -9188,8 +8989,6 @@
 - payment-cryptography
 - payment-cryptography-data
 - pca-connector-ad
-- pca-connector-scep
-- pcs
 - personalize-events
 - personalize-runtime
 - pi
@@ -9200,7 +8999,6 @@
 - pricing
 - privatenetworks
 - proton
-- qapps
 - qbusiness
 - qconnect
 - qldb-session
@@ -9231,10 +9029,8 @@
 - sms-voice
 - snow-device-management
 - snowball
-- socialmessaging
 - ssm-contacts
 - ssm-incidents
-- ssm-quicksetup
 - ssm-sap
 - sso
 - sso-oidc
@@ -9242,7 +9038,6 @@
 - supplychain
 - support-app
 - synthetics
-- taxsettings
 - timestream-influxdb
 - tnb
 - translate
@@ -9255,6 +9050,7 @@
 - wellarchitected
 - wisdom
 - workdocs
+- worklink
 - workmail
 - workmailmessageflow
 - workspaces-thin-client
diff --git a/docs/docs/services/budgets.rst b/docs/docs/services/budgets.rst
index 236b80b6b..56d8721b5 100644
--- a/docs/docs/services/budgets.rst
+++ b/docs/docs/services/budgets.rst
@@ -43,9 +43,6 @@ budgets
 
 - [ ] describe_subscribers_for_notification
 - [ ] execute_budget_action
-- [ ] list_tags_for_resource
-- [ ] tag_resource
-- [ ] untag_resource
 - [ ] update_budget
 - [ ] update_budget_action
 - [ ] update_notification
diff --git a/docs/docs/services/codepipeline.rst b/docs/docs/services/codepipeline.rst
index acc67b9e0..c9a3a4c9f 100644
--- a/docs/docs/services/codepipeline.rst
+++ b/docs/docs/services/codepipeline.rst
@@ -50,7 +50,6 @@ codepipeline
 - [ ] put_webhook
 - [ ] register_webhook_with_third_party
 - [ ] retry_stage_execution
-- [ ] rollback_stage
 - [ ] start_pipeline_execution
 - [ ] stop_pipeline_execution
 - [X] tag_resource
diff --git a/docs/docs/services/ec2.rst b/docs/docs/services/ec2.rst
index fd17becf9..41c92b4d0 100644
--- a/docs/docs/services/ec2.rst
+++ b/docs/docs/services/ec2.rst
@@ -504,7 +504,6 @@ ec2
 - [ ] get_host_reservation_purchase_preview
 - [ ] get_image_block_public_access_state
 - [ ] get_instance_metadata_defaults
-- [ ] get_instance_tpm_ek_pub
 - [ ] get_instance_types_from_instance_requirements
 - [ ] get_instance_uefi_data
 - [ ] get_ipam_address_history
diff --git a/docs/docs/services/emr-containers.rst b/docs/docs/services/emr-containers.rst
index 888b7cc84..779f0d27f 100644
--- a/docs/docs/services/emr-containers.rst
+++ b/docs/docs/services/emr-containers.rst
@@ -19,7 +19,6 @@ emr-containers
 - [X] cancel_job_run
 - [ ] create_job_template
 - [ ] create_managed_endpoint
-- [ ] create_security_configuration
 - [X] create_virtual_cluster
 - [ ] delete_job_template
 - [ ] delete_managed_endpoint
@@ -27,13 +26,11 @@ emr-containers
 - [X] describe_job_run
 - [ ] describe_job_template
 - [ ] describe_managed_endpoint
-- [ ] describe_security_configuration
 - [X] describe_virtual_cluster
 - [ ] get_managed_endpoint_session_credentials
 - [X] list_job_runs
 - [ ] list_job_templates
 - [ ] list_managed_endpoints
-- [ ] list_security_configurations
 - [ ] list_tags_for_resource
 - [X] list_virtual_clusters
 - [X] start_job_run
diff --git a/docs/docs/services/panorama.rst b/docs/docs/services/panorama.rst
index 807e05d10..0faea429a 100644
--- a/docs/docs/services/panorama.rst
+++ b/docs/docs/services/panorama.rst
@@ -14,7 +14,7 @@ panorama
 
 |start-h3| Implemented features for this service |end-h3|
 
-- [ ] create_application_instance
+- [X] create_application_instance
 - [ ] create_job_for_devices
 - [X] create_node_from_template_job
 - [ ] create_package
@@ -22,7 +22,7 @@ panorama
 - [X] delete_device
 - [ ] delete_package
 - [ ] deregister_package_version
-- [ ] describe_application_instance
+- [X] describe_application_instance
 - [ ] describe_application_instance_details
 - [X] describe_device
 - [ ] describe_device_job
@@ -33,7 +33,7 @@ panorama
 - [ ] describe_package_version
 - [ ] list_application_instance_dependencies
 - [ ] list_application_instance_node_instances
-- [ ] list_application_instances
+- [X] list_application_instances
 - [X] list_devices
 - [ ] list_devices_jobs
 - [ ] list_node_from_template_jobs
diff --git a/docs/docs/services/personalize.rst b/docs/docs/services/personalize.rst
index cdb3abd11..0a305161c 100644
--- a/docs/docs/services/personalize.rst
+++ b/docs/docs/services/personalize.rst
@@ -19,7 +19,6 @@ personalize
 - [ ] create_batch_inference_job
 - [ ] create_batch_segment_job
 - [ ] create_campaign
-- [ ] create_data_deletion_job
 - [ ] create_dataset
 - [ ] create_dataset_export_job
 - [ ] create_dataset_group
@@ -44,7 +43,6 @@ personalize
 - [ ] describe_batch_inference_job
 - [ ] describe_batch_segment_job
 - [ ] describe_campaign
-- [ ] describe_data_deletion_job
 - [ ] describe_dataset
 - [ ] describe_dataset_export_job
 - [ ] describe_dataset_group
@@ -62,7 +60,6 @@ personalize
 - [ ] list_batch_inference_jobs
 - [ ] list_batch_segment_jobs
 - [ ] list_campaigns
-- [ ] list_data_deletion_jobs
 - [ ] list_dataset_export_jobs
 - [ ] list_dataset_groups
 - [ ] list_dataset_import_jobs
diff --git a/docs/docs/services/quicksight.rst b/docs/docs/services/quicksight.rst
index f97f959b3..ce905596f 100644
--- a/docs/docs/services/quicksight.rst
+++ b/docs/docs/services/quicksight.rst
@@ -190,7 +190,6 @@ quicksight
 - [ ] update_q_personalization_configuration
 - [ ] update_refresh_schedule
 - [ ] update_role_custom_permission
-- [ ] update_spice_capacity_configuration
 - [ ] update_template
 - [ ] update_template_alias
 - [ ] update_template_permissions
diff --git a/docs/docs/services/resiliencehub.rst b/docs/docs/services/resiliencehub.rst
index 570998eee..cd75f41d9 100644
--- a/docs/docs/services/resiliencehub.rst
+++ b/docs/docs/services/resiliencehub.rst
@@ -50,7 +50,6 @@ resiliencehub
 - [X] import_resources_to_draft_app_version
 - [ ] list_alarm_recommendations
 - [ ] list_app_assessment_compliance_drifts
-- [ ] list_app_assessment_resource_drifts
 - [X] list_app_assessments
   
         Moto will not actually execute any assessments, so this operation will return an empty list by default.
diff --git a/docs/docs/services/ssm.rst b/docs/docs/services/ssm.rst
index b084e2ea0..f5ebad48c 100644
--- a/docs/docs/services/ssm.rst
+++ b/docs/docs/services/ssm.rst
@@ -85,7 +85,6 @@ ssm
 - [ ] describe_instance_patch_states
 - [ ] describe_instance_patch_states_for_patch_group
 - [ ] describe_instance_patches
-- [ ] describe_instance_properties
 - [ ] describe_inventory_deletions
 - [ ] describe_maintenance_window_execution_task_invocations
 - [ ] describe_maintenance_window_execution_tasks
diff --git a/docs/docs/services/stepfunctions.rst b/docs/docs/services/stepfunctions.rst
index 5c01dc0fd..067ddedee 100644
--- a/docs/docs/services/stepfunctions.rst
+++ b/docs/docs/services/stepfunctions.rst
@@ -52,5 +52,4 @@ stepfunctions
 - [X] update_map_run
 - [X] update_state_machine
 - [ ] update_state_machine_alias
-- [ ] validate_state_machine_definition
 
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-east-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-east-1.json
index d5be43b10..926ba6ebd 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-east-1.json
@@ -895,6 +895,42 @@
   "InstanceType": "r7g.xlarge",
   "Location": "ape1-az1"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ape1-az1"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ape1-az1"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "ape1-az1"
@@ -1831,6 +1867,42 @@
   "InstanceType": "r7g.xlarge",
   "Location": "ape1-az2"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ape1-az2"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ape1-az2"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "ape1-az2"
@@ -2811,6 +2883,42 @@
   "InstanceType": "r7g.xlarge",
   "Location": "ape1-az3"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ape1-az3"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ape1-az3"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "ape1-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-3.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-3.json
index 66ed5ce7f..64e8cfb96 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-3.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/ap-southeast-3.json
@@ -723,6 +723,42 @@
   "InstanceType": "r6gd.xlarge",
   "Location": "apse3-az1"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "apse3-az1"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "apse3-az1"
+ },
  {
   "InstanceType": "r7i.12xlarge",
   "Location": "apse3-az1"
@@ -1571,6 +1607,42 @@
   "InstanceType": "r6gd.xlarge",
   "Location": "apse3-az2"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "apse3-az2"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "apse3-az2"
+ },
  {
   "InstanceType": "r7i.12xlarge",
   "Location": "apse3-az2"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-2.json
index 1ff7e1c67..b17b6d474 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/eu-central-2.json
@@ -1715,6 +1715,42 @@
   "InstanceType": "c6g.xlarge",
   "Location": "euc2-az3"
  },
+ {
+  "InstanceType": "c6gd.12xlarge",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.16xlarge",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.2xlarge",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.4xlarge",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.8xlarge",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.large",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.medium",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.metal",
+  "Location": "euc2-az3"
+ },
+ {
+  "InstanceType": "c6gd.xlarge",
+  "Location": "euc2-az3"
+ },
  {
   "InstanceType": "c6in.12xlarge",
   "Location": "euc2-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/me-central-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/me-central-1.json
index ed70ce266..09a28a396 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/me-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/me-central-1.json
@@ -607,6 +607,42 @@
   "InstanceType": "r6i.xlarge",
   "Location": "mec1-az1"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "mec1-az1"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "mec1-az1"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "mec1-az1"
@@ -1287,6 +1323,42 @@
   "InstanceType": "r6i.xlarge",
   "Location": "mec1-az2"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "mec1-az2"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "mec1-az2"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "mec1-az2"
@@ -1935,6 +2007,42 @@
   "InstanceType": "r6i.xlarge",
   "Location": "mec1-az3"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "mec1-az3"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "mec1-az3"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "mec1-az3"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json
index d4b5ebcbd..2934b97a1 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone-id/us-east-1.json
@@ -13467,6 +13467,38 @@
   "InstanceType": "g6.xlarge",
   "Location": "use1-az6"
  },
+ {
+  "InstanceType": "g6e.12xlarge",
+  "Location": "use1-az6"
+ },
+ {
+  "InstanceType": "g6e.16xlarge",
+  "Location": "use1-az6"
+ },
+ {
+  "InstanceType": "g6e.24xlarge",
+  "Location": "use1-az6"
+ },
+ {
+  "InstanceType": "g6e.2xlarge",
+  "Location": "use1-az6"
+ },
+ {
+  "InstanceType": "g6e.48xlarge",
+  "Location": "use1-az6"
+ },
+ {
+  "InstanceType": "g6e.4xlarge",
+  "Location": "use1-az6"
+ },
+ {
+  "InstanceType": "g6e.8xlarge",
+  "Location": "use1-az6"
+ },
+ {
+  "InstanceType": "g6e.xlarge",
+  "Location": "use1-az6"
+ },
  {
   "InstanceType": "gr6.4xlarge",
   "Location": "use1-az6"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-east-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-east-1.json
index 629d3d9ec..7b9bd7df0 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-east-1.json
@@ -895,6 +895,42 @@
   "InstanceType": "r7g.xlarge",
   "Location": "ap-east-1a"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ap-east-1a"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ap-east-1a"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "ap-east-1a"
@@ -1831,6 +1867,42 @@
   "InstanceType": "r7g.xlarge",
   "Location": "ap-east-1b"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ap-east-1b"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ap-east-1b"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "ap-east-1b"
@@ -2811,6 +2883,42 @@
   "InstanceType": "r7g.xlarge",
   "Location": "ap-east-1c"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ap-east-1c"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ap-east-1c"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "ap-east-1c"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-3.json b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-3.json
index 2f92444e9..6a61dcdde 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-3.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/ap-southeast-3.json
@@ -723,6 +723,42 @@
   "InstanceType": "r6gd.xlarge",
   "Location": "ap-southeast-3a"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ap-southeast-3a"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ap-southeast-3a"
+ },
  {
   "InstanceType": "r7i.12xlarge",
   "Location": "ap-southeast-3a"
@@ -1571,6 +1607,42 @@
   "InstanceType": "r6gd.xlarge",
   "Location": "ap-southeast-3b"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ap-southeast-3b"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ap-southeast-3b"
+ },
  {
   "InstanceType": "r7i.12xlarge",
   "Location": "ap-southeast-3b"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-2.json b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-2.json
index eb71f2a91..955b2ef80 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-2.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/eu-central-2.json
@@ -1715,6 +1715,42 @@
   "InstanceType": "c6g.xlarge",
   "Location": "eu-central-2c"
  },
+ {
+  "InstanceType": "c6gd.12xlarge",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.16xlarge",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.2xlarge",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.4xlarge",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.8xlarge",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.large",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.medium",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.metal",
+  "Location": "eu-central-2c"
+ },
+ {
+  "InstanceType": "c6gd.xlarge",
+  "Location": "eu-central-2c"
+ },
  {
   "InstanceType": "c6in.12xlarge",
   "Location": "eu-central-2c"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/me-central-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/me-central-1.json
index 348207dc1..d6cd20dd0 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/me-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/me-central-1.json
@@ -607,6 +607,42 @@
   "InstanceType": "r6i.xlarge",
   "Location": "me-central-1a"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "me-central-1a"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "me-central-1a"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "me-central-1a"
@@ -1287,6 +1323,42 @@
   "InstanceType": "r6i.xlarge",
   "Location": "me-central-1b"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "me-central-1b"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "me-central-1b"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "me-central-1b"
@@ -1935,6 +2007,42 @@
   "InstanceType": "r6i.xlarge",
   "Location": "me-central-1c"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "me-central-1c"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "me-central-1c"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "me-central-1c"
diff --git a/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json b/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json
index 4f466a771..e9b86bc49 100644
--- a/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/availability-zone/us-east-1.json
@@ -7455,6 +7455,38 @@
   "InstanceType": "g6.xlarge",
   "Location": "us-east-1c"
  },
+ {
+  "InstanceType": "g6e.12xlarge",
+  "Location": "us-east-1c"
+ },
+ {
+  "InstanceType": "g6e.16xlarge",
+  "Location": "us-east-1c"
+ },
+ {
+  "InstanceType": "g6e.24xlarge",
+  "Location": "us-east-1c"
+ },
+ {
+  "InstanceType": "g6e.2xlarge",
+  "Location": "us-east-1c"
+ },
+ {
+  "InstanceType": "g6e.48xlarge",
+  "Location": "us-east-1c"
+ },
+ {
+  "InstanceType": "g6e.4xlarge",
+  "Location": "us-east-1c"
+ },
+ {
+  "InstanceType": "g6e.8xlarge",
+  "Location": "us-east-1c"
+ },
+ {
+  "InstanceType": "g6e.xlarge",
+  "Location": "us-east-1c"
+ },
  {
   "InstanceType": "gr6.4xlarge",
   "Location": "us-east-1c"
diff --git a/moto/ec2/resources/instance_type_offerings/region/ap-east-1.json b/moto/ec2/resources/instance_type_offerings/region/ap-east-1.json
index 3acfe738b..35833d3cc 100644
--- a/moto/ec2/resources/instance_type_offerings/region/ap-east-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/ap-east-1.json
@@ -911,6 +911,42 @@
   "InstanceType": "r7g.xlarge",
   "Location": "ap-east-1"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ap-east-1"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ap-east-1"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "ap-east-1"
diff --git a/moto/ec2/resources/instance_type_offerings/region/ap-southeast-3.json b/moto/ec2/resources/instance_type_offerings/region/ap-southeast-3.json
index 24081d606..83b4ebca6 100644
--- a/moto/ec2/resources/instance_type_offerings/region/ap-southeast-3.json
+++ b/moto/ec2/resources/instance_type_offerings/region/ap-southeast-3.json
@@ -723,6 +723,42 @@
   "InstanceType": "r6gd.xlarge",
   "Location": "ap-southeast-3"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "ap-southeast-3"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "ap-southeast-3"
+ },
  {
   "InstanceType": "r7i.12xlarge",
   "Location": "ap-southeast-3"
diff --git a/moto/ec2/resources/instance_type_offerings/region/me-central-1.json b/moto/ec2/resources/instance_type_offerings/region/me-central-1.json
index 5f9ecb962..974bed129 100644
--- a/moto/ec2/resources/instance_type_offerings/region/me-central-1.json
+++ b/moto/ec2/resources/instance_type_offerings/region/me-central-1.json
@@ -607,6 +607,42 @@
   "InstanceType": "r6i.xlarge",
   "Location": "me-central-1"
  },
+ {
+  "InstanceType": "r7gd.12xlarge",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.16xlarge",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.2xlarge",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.4xlarge",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.8xlarge",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.large",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.medium",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.metal",
+  "Location": "me-central-1"
+ },
+ {
+  "InstanceType": "r7gd.xlarge",
+  "Location": "me-central-1"
+ },
  {
   "InstanceType": "t3.2xlarge",
   "Location": "me-central-1"
diff --git a/moto/ec2/resources/instance_types.json b/moto/ec2/resources/instance_types.json
index 5b7cbd9cc..33259191a 100644
--- a/moto/ec2/resources/instance_types.json
+++ b/moto/ec2/resources/instance_types.json
@@ -28371,7 +28371,7 @@
     "MaximumEfaInterfaces": 1
    },
    "EfaSupported": true,
-   "EnaSrdSupported": false,
+   "EnaSrdSupported": true,
    "EnaSupport": "required",
    "EncryptionInTransitSupported": true,
    "Ipv4AddressesPerInterface": 30,
@@ -28637,7 +28637,7 @@
     "MaximumEfaInterfaces": 2
    },
    "EfaSupported": true,
-   "EnaSrdSupported": false,
+   "EnaSrdSupported": true,
    "EnaSupport": "required",
    "EncryptionInTransitSupported": true,
    "Ipv4AddressesPerInterface": 50,
@@ -28903,7 +28903,7 @@
     "MaximumEfaInterfaces": 4
    },
    "EfaSupported": true,
-   "EnaSrdSupported": false,
+   "EnaSrdSupported": true,
    "EnaSupport": "required",
    "EncryptionInTransitSupported": true,
    "Ipv4AddressesPerInterface": 50,
diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py
index f0b2e772c..5bea4b221 100644
--- a/moto/elbv2/models.py
+++ b/moto/elbv2/models.py
@@ -635,6 +635,7 @@ class FakeLoadBalancer(CloudFormationModel):
         "routing.http.xff_header_processing.mode",
         "routing.http2.enabled",
         "waf.fail_open.enabled",
+        "zonal_shift.config.enabled",
     }
 
     def __init__(
diff --git a/moto/organizations/exceptions.py b/moto/organizations/exceptions.py
index 4a08438f9..10fb8ecbe 100644
--- a/moto/organizations/exceptions.py
+++ b/moto/organizations/exceptions.py
@@ -11,6 +11,16 @@ class AccountAlreadyRegisteredException(JsonRESTError):
         )
 
 
+class AccountAlreadyClosedException(JsonRESTError):
+    code = 400
+
+    def __init__(self) -> None:
+        super().__init__(
+            "AccountAlreadyClosedException",
+            "The provided account is already closed.",
+        )
+
+
 class AccountNotRegisteredException(JsonRESTError):
     code = 400
 
diff --git a/moto/organizations/models.py b/moto/organizations/models.py
index 2f0f03b18..d84f0ca2e 100644
--- a/moto/organizations/models.py
+++ b/moto/organizations/models.py
@@ -1,6 +1,6 @@
 import json
 import re
-from typing import Any, Dict, List, Optional
+from typing import Any, Dict, List, Optional, Tuple
 
 from moto.core.base_backend import BackendDict, BaseBackend
 from moto.core.common_models import BaseModel
@@ -8,6 +8,7 @@ from moto.core.exceptions import RESTError
 from moto.core.utils import unix_time, utcnow
 from moto.organizations import utils
 from moto.organizations.exceptions import (
+    AccountAlreadyClosedException,
     AccountAlreadyRegisteredException,
     AccountNotFoundException,
     AccountNotRegisteredException,
@@ -149,6 +150,8 @@ class FakeAccount(BaseModel):
         }
 
     def close(self) -> None:
+        if self.status == "SUSPENDED":
+            raise AccountAlreadyClosedException
         # TODO: The CloseAccount spec allows the account to pass through a
         # "PENDING_CLOSURE" state before reaching the SUSPENDED state.
         self.status = "SUSPENDED"
@@ -451,9 +454,18 @@ class OrganizationsBackend(BaseBackend):
         return self.org.describe()
 
     def describe_organization(self) -> Dict[str, Any]:
-        if not self.org:
-            raise AWSOrganizationsNotInUseException
-        return self.org.describe()
+        if self.org:
+            # This is a master account
+            return self.org.describe()
+
+        if self.account_id in organizations_backends.master_accounts:
+            # This is a member account
+            master_account_id, partition = organizations_backends.master_accounts[
+                self.account_id
+            ]
+            return organizations_backends[master_account_id][partition].org.describe()  # type: ignore[union-attr]
+
+        raise AWSOrganizationsNotInUseException
 
     def delete_organization(self) -> None:
         if [account for account in self.accounts if account.name != "master"]:
@@ -523,6 +535,10 @@ class OrganizationsBackend(BaseBackend):
         new_account = FakeAccount(self.org, **kwargs)  # type: ignore
         self.accounts.append(new_account)
         self.attach_policy(PolicyId=utils.DEFAULT_POLICY_ID, TargetId=new_account.id)
+        organizations_backends.master_accounts[new_account.id] = (
+            self.account_id,
+            self.partition,
+        )
         return new_account.create_account_status
 
     def close_account(self, **kwargs: Any) -> None:
@@ -530,6 +546,7 @@ class OrganizationsBackend(BaseBackend):
             if account.id == kwargs["AccountId"]:
                 account.close()
                 return
+        organizations_backends.master_accounts.pop(kwargs["AccountId"], None)
         raise AccountNotFoundException
 
     def get_account_by_id(self, account_id: str) -> FakeAccount:
@@ -977,13 +994,35 @@ class OrganizationsBackend(BaseBackend):
             raise InvalidInputException("You specified an invalid value.")
 
     def remove_account_from_organization(self, **kwargs: str) -> None:
-        account = self.get_account_by_id(kwargs["AccountId"])
+        account_id = kwargs["AccountId"]
+        if account_id not in organizations_backends.master_accounts:
+            raise AWSOrganizationsNotInUseException
+        organizations_backends.master_accounts.pop(account_id, None)
+        account = self.get_account_by_id(account_id)
         for policy in account.attached_policies:
             policy.attachments.remove(account)
         self.accounts.remove(account)
 
 
-organizations_backends = BackendDict(
+class OrganizationsBackendDict(BackendDict[OrganizationsBackend]):
+    """
+    Specialised to keep track of master accounts.
+    """
+
+    def __init__(
+        self,
+        backend: Any,
+        service_name: str,
+        use_boto3_regions: bool = True,
+        additional_regions: Optional[List[str]] = None,
+    ):
+        super().__init__(backend, service_name, use_boto3_regions, additional_regions)
+
+        # Maps member account IDs to the (master account ID, partition) which owns the organisation
+        self.master_accounts: Dict[str, Tuple[str, str]] = {}
+
+
+organizations_backends = OrganizationsBackendDict(
     OrganizationsBackend,
     "organizations",
     use_boto3_regions=False,
diff --git a/moto/panorama/models.py b/moto/panorama/models.py
index c32589ebc..4b17eeb7f 100644
--- a/moto/panorama/models.py
+++ b/moto/panorama/models.py
@@ -13,7 +13,7 @@ from moto.panorama.utils import (
     arn_formatter,
     deep_convert_datetime_to_isoformat,
     generate_package_id,
-    hash_device_name,
+    hash_name,
 )
 from moto.utilities.paginator import paginate
 
@@ -34,6 +34,12 @@ PAGINATION_MODEL = {
         "limit_default": 123,
         "unique_attribute": "package_id",
     },
+    "list_application_instances": {
+        "input_token": "next_token",
+        "limit_key": "max_results",
+        "limit_default": 123,
+        "unique_attribute": "application_instance_id",
+    },
 }
 
 
@@ -104,7 +110,7 @@ class Device(BaseObject):
             "utf-8"
         )
         self.arn = arn_formatter("device", self.name, self.account_id, self.region_name)
-        self.device_id = f"device-{hash_device_name(name)}"
+        self.device_id = f"device-{hash_name(name)}"
         self.iot_thing_name = ""
 
         self.alternate_softwares = [
@@ -253,7 +259,7 @@ class Package(BaseObject):
         self.package_version = package_version
         self.output_package_name = f"{self.package_name}-{self.package_version}-{self.patch_version[:8]}-{self.name}"
         self.owner_account = account_id
-        self.package_id = f"package-{hash_device_name(package_name)}"
+        self.package_id = f"package-{hash_name(package_name)}"
         self.package_arn = arn_formatter(
             "package", self.package_id, account_id, region_name
         )
@@ -268,6 +274,81 @@ class Package(BaseObject):
         return package_response
 
 
+class ApplicationInstance(BaseObject):
+    def __init__(
+        self,
+        account_id: str,
+        region_name: str,
+        default_runtime_context_device: str,
+        default_runtime_context_device_name: str,
+        description: str,
+        manifest_overrides_payload: Dict[str, str],
+        manifest_payload: Dict[str, str],
+        name: str,
+        runtime_role_arn: str,
+        tags: Dict[str, str],
+    ) -> None:
+        self.default_runtime_context_device = default_runtime_context_device
+        self.default_runtime_context_device_name = default_runtime_context_device_name
+        self.description = description
+        self.manifest_overrides_payload = manifest_overrides_payload
+        self.manifest_payload = manifest_payload
+        self.name = name
+        self.runtime_role_arn = runtime_role_arn
+        self.tags = tags
+        now = datetime.now(tzutc())
+        self.created_time = now
+        self.last_updated_time = now
+        name = f"{self.name}-{self.created_time}"
+        self.application_instance_id = f"applicationInstance-{hash_name(name).lower()}"
+        self.arn = arn_formatter(
+            "application-instance",
+            self.application_instance_id,
+            account_id=account_id,
+            region_name=region_name,
+        )
+        self.health_status = "RUNNING"
+        self.status = "DEPLOYMENT_SUCCEEDED"
+        self.status_description = "string"
+        self.runtime_context_states = [
+            {
+                "DesiredState": "RUNNING",
+                "DeviceReportedStatus": "RUNNING",
+                "DeviceReportedTime": now,
+                "RuntimeContextName": "string",
+            },
+        ]
+
+    def add_new_runtime_context_states(
+        self, desired_state: str, device_reported_status: str
+    ) -> None:
+        now = datetime.now(tzutc())
+        self.runtime_context_states.append(
+            {
+                "DesiredState": desired_state,
+                "DeviceReportedStatus": device_reported_status,
+                "DeviceReportedTime": now,
+                "RuntimeContextName": "string",
+            }
+        )
+
+    def response_object(self) -> Dict[str, Any]:
+        response_object = super().gen_response_object()
+        response_object = deep_convert_datetime_to_isoformat(response_object)
+        return response_object
+
+    def response_listed(self) -> Dict[str, Any]:
+        package_response = self.response_object()
+        return package_response
+
+    def response_created(self) -> Dict[str, str]:
+        return {"ApplicationInstanceId": self.application_instance_id}
+
+    def response_describe(self) -> Dict[str, str]:
+        response_object = self.response_object()
+        return response_object
+
+
 class Node(BaseObject):
     def __init__(
         self,
@@ -320,6 +401,7 @@ class PanoramaBackend(BaseBackend):
         self.devices_memory: Dict[str, Device] = {}
         self.node_from_template_memory: Dict[str, Node] = {}
         self.nodes_memory: Dict[str, Package] = {}
+        self.application_instances_memory: Dict[str, ApplicationInstance] = {}
 
     def provision_device(
         self,
@@ -434,6 +516,74 @@ class PanoramaBackend(BaseBackend):
         )
         return category_nodes
 
+    def create_application_instance(
+        self,
+        application_instance_id_to_replace: Optional[str],
+        default_runtime_context_device: str,
+        description: str,
+        manifest_overrides_payload: Dict[str, str],
+        manifest_payload: Dict[str, str],
+        name: str,
+        runtime_role_arn: str,
+        tags: Dict[str, str],
+    ) -> ApplicationInstance:
+        device = self.devices_memory.get(default_runtime_context_device)
+        if device is None:
+            raise ValidationError(f"Device {default_runtime_context_device} not found")
+        if (
+            application_instance_id_to_replace
+            and application_instance_id_to_replace in self.application_instances_memory
+        ):
+            removed_application_instance = self.application_instances_memory[
+                application_instance_id_to_replace
+            ]
+            removed_application_instance.status = "REMOVAL_SUCCEEDED"
+            removed_application_instance.add_new_runtime_context_states(
+                desired_state="REMOVED", device_reported_status="REMOVAL_IN_PROGRESS"
+            )
+
+        application_instance = ApplicationInstance(
+            account_id=self.account_id,
+            region_name=self.region_name,
+            default_runtime_context_device=default_runtime_context_device,
+            default_runtime_context_device_name=device.name,
+            description=description,
+            manifest_overrides_payload=manifest_overrides_payload,
+            manifest_payload=manifest_payload,
+            name=name,
+            runtime_role_arn=runtime_role_arn,
+            tags=tags,
+        )
+        self.application_instances_memory[
+            application_instance.application_instance_id
+        ] = application_instance
+        return application_instance
+
+    def describe_application_instance(
+        self, application_instance_id: str
+    ) -> ApplicationInstance:
+        application_instance = self.application_instances_memory[
+            application_instance_id
+        ]
+        return application_instance
+
+    @paginate(pagination_model=PAGINATION_MODEL)
+    def list_application_instances(
+        self,
+        device_id: Optional[str],
+        status_filter: Optional[str],
+    ) -> List[ApplicationInstance]:
+        filtered_application_instances = filter(
+            lambda x: x.status == status_filter if status_filter else True,
+            filter(
+                lambda x: x.default_runtime_context_device == device_id
+                if device_id
+                else True,
+                self.application_instances_memory.values(),
+            ),
+        )
+        return list(filtered_application_instances)
+
 
 panorama_backends = BackendDict(
     PanoramaBackend,
diff --git a/moto/panorama/responses.py b/moto/panorama/responses.py
index a7cd19d88..40ad46488 100644
--- a/moto/panorama/responses.py
+++ b/moto/panorama/responses.py
@@ -108,3 +108,59 @@ class PanoramaResponse(BaseResponse):
                 "NextToken": next_token,
             }
         )
+
+    def create_application_instance(self) -> str:
+        application_instance_id_to_replace = self._get_param(
+            "ApplicationInstanceIdToReplace"
+        )
+        default_runtime_context_device = self._get_param("DefaultRuntimeContextDevice")
+        description = self._get_param("Description")
+        manifest_overrides_payload = self._get_param("ManifestOverridesPayload")
+        manifest_payload = self._get_param("ManifestPayload")
+        name = self._get_param("Name")
+        runtime_role_arn = self._get_param("RuntimeRoleArn")
+        tags = self._get_param("Tags")
+        application_instance = self.panorama_backend.create_application_instance(
+            application_instance_id_to_replace=application_instance_id_to_replace,
+            default_runtime_context_device=default_runtime_context_device,
+            description=description,
+            manifest_overrides_payload=manifest_overrides_payload,
+            manifest_payload=manifest_payload,
+            name=name,
+            runtime_role_arn=runtime_role_arn,
+            tags=tags,
+        )
+        return json.dumps(application_instance.response_created())
+
+    def describe_application_instance(self) -> str:
+        application_instance_id = self._get_param("ApplicationInstanceId")
+        application_instance = self.panorama_backend.describe_application_instance(
+            application_instance_id=application_instance_id
+        )
+        return json.dumps(application_instance.response_describe())
+
+    def describe_application_instance_details(self) -> str:
+        return self.describe_application_instance()
+
+    def list_application_instances(self) -> str:
+        device_id = self._get_param("deviceId")
+        max_results = self._get_int_param("maxResults")
+        status_filter = self._get_param("statusFilter")
+        next_token = self._get_param("nextToken")
+        list_application_instances, next_token = (
+            self.panorama_backend.list_application_instances(
+                device_id=device_id,
+                max_results=max_results,
+                status_filter=status_filter,
+                next_token=next_token,
+            )
+        )
+        return json.dumps(
+            {
+                "ApplicationInstances": [
+                    application_instance.response_describe()
+                    for application_instance in list_application_instances
+                ],
+                "NextToken": next_token,
+            }
+        )
diff --git a/moto/panorama/urls.py b/moto/panorama/urls.py
index cddfa4f42..90b8ef565 100644
--- a/moto/panorama/urls.py
+++ b/moto/panorama/urls.py
@@ -11,4 +11,7 @@ url_paths = {
     "{0}/packages/template-job$": PanoramaResponse.dispatch,
     "{0}/packages/template-job/(?P<JobId>[^/]+)$": PanoramaResponse.dispatch,
     "{0}/nodes$": PanoramaResponse.dispatch,
+    "{0}/application-instances$": PanoramaResponse.dispatch,
+    "{0}/application-instances/(?P<ApplicationInstanceId>[^/]+)$": PanoramaResponse.dispatch,
+    "{0}/application-instances/(?P<ApplicationInstanceId>[^/]+)/details$": PanoramaResponse.dispatch,
 }
diff --git a/moto/panorama/utils.py b/moto/panorama/utils.py
index 8118a4a24..d9b4f4641 100644
--- a/moto/panorama/utils.py
+++ b/moto/panorama/utils.py
@@ -17,10 +17,10 @@ def deep_convert_datetime_to_isoformat(obj: Any) -> Any:
         return obj
 
 
-def hash_device_name(name: str) -> str:
+def hash_name(name: str) -> str:
     digest = hashlib.md5(name.encode("utf-8")).digest()
-    token = base64.b64encode(digest)
-    return token.decode("utf-8")
+    token = base64.urlsafe_b64encode(digest)
+    return token.decode("utf-8").rstrip("=")
 
 
 def generate_package_id(name: str) -> str:
diff --git a/moto/ssm/resources/regions.json b/moto/ssm/resources/regions.json
index bb3aa740a..c6a1784af 100644
--- a/moto/ssm/resources/regions.json
+++ b/moto/ssm/resources/regions.json
@@ -2075,6 +2075,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "cognito-idp": {
+                "Value": "cognito-idp",
+                "endpoint": {
+                  "Value": "cognito-idp.ap-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "compute-optimizer": {
                 "Value": "compute-optimizer",
                 "endpoint": {
@@ -12371,6 +12380,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.ap-south-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -13422,6 +13440,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "mediapackage-vod": {
+                "Value": "mediapackage-vod",
+                "endpoint": {
+                  "Value": "mediapackage-vod.ap-south-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "mediapackagev2": {
                 "Value": "mediapackagev2",
                 "endpoint": {
@@ -16329,6 +16356,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.ap-southeast-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -22419,6 +22455,15 @@
                   "Value": "controlcatalog.ap-southeast-5.amazonaws.com"
                 }
               },
+              "controltower": {
+                "Value": "controltower",
+                "endpoint": {
+                  "Value": "controltower.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "datasync": {
                 "Value": "datasync",
                 "endpoint": {
@@ -22872,6 +22917,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "storagegateway": {
+                "Value": "storagegateway",
+                "endpoint": {
+                  "Value": "storagegateway.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sts": {
                 "Value": "sts",
                 "endpoint": {
@@ -25591,6 +25645,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "cognito-idp": {
+                "Value": "cognito-idp",
+                "endpoint": {
+                  "Value": "cognito-idp.ca-west-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "config": {
                 "Value": "config",
                 "endpoint": {
@@ -33408,6 +33471,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "wickr": {
+                "Value": "wickr",
+                "endpoint": {
+                  "Value": "api.messaging.wickr.eu-central-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "xray": {
                 "Value": "xray",
                 "endpoint": {
@@ -33676,6 +33748,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "braket": {
+                "Value": "braket",
+                "endpoint": {
+                  "Value": "braket.eu-north-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "chatbot": {
                 "Value": "chatbot"
               },
@@ -41065,6 +41146,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.eu-west-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -43667,6 +43757,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.eu-west-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -48268,6 +48367,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "mediapackage-vod": {
+                "Value": "mediapackage-vod",
+                "endpoint": {
+                  "Value": "mediapackage-vod.me-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "mediapackagev2": {
                 "Value": "mediapackagev2",
                 "endpoint": {
@@ -55533,6 +55641,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.us-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -58239,6 +58356,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.us-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
@@ -59596,6 +59722,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "redshift-serverless": {
+                "Value": "redshift-serverless",
+                "endpoint": {
+                  "Value": "redshift-serverless.us-gov-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "resiliencehub": {
                 "Value": "resiliencehub",
                 "endpoint": {
@@ -61316,6 +61451,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "redshift-serverless": {
+                "Value": "redshift-serverless",
+                "endpoint": {
+                  "Value": "redshift-serverless.us-gov-west-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "rekognition": {
                 "Value": "rekognition",
                 "endpoint": {
@@ -66555,6 +66699,15 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "socialmessaging": {
+                "Value": "socialmessaging",
+                "endpoint": {
+                  "Value": "social-messaging.us-west-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sqs": {
                 "Value": "sqs",
                 "endpoint": {
diff --git a/moto/ssm/resources/services.json b/moto/ssm/resources/services.json
index fbb75690d..aea17d34f 100644
--- a/moto/ssm/resources/services.json
+++ b/moto/ssm/resources/services.json
@@ -8172,6 +8172,15 @@
               "Value": "https://aws.amazon.com/braket/"
             },
             "regions": {
+              "eu-north-1": {
+                "Value": "eu-north-1",
+                "endpoint": {
+                  "Value": "braket.eu-north-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "eu-west-2": {
                 "Value": "eu-west-2",
                 "endpoint": {
@@ -14210,6 +14219,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-1": {
+                "Value": "ap-east-1",
+                "endpoint": {
+                  "Value": "cognito-idp.ap-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -14300,6 +14318,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ca-west-1": {
+                "Value": "ca-west-1",
+                "endpoint": {
+                  "Value": "cognito-idp.ca-west-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "eu-central-1": {
                 "Value": "eu-central-1",
                 "endpoint": {
@@ -15959,6 +15986,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-southeast-5": {
+                "Value": "ap-southeast-5",
+                "endpoint": {
+                  "Value": "controltower.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ca-central-1": {
                 "Value": "ca-central-1",
                 "endpoint": {
@@ -41593,6 +41629,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-south-2": {
+                "Value": "ap-south-2",
+                "endpoint": {
+                  "Value": "mediapackage-vod.ap-south-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-southeast-1": {
                 "Value": "ap-southeast-1",
                 "endpoint": {
@@ -41674,6 +41719,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "me-central-1": {
+                "Value": "me-central-1",
+                "endpoint": {
+                  "Value": "mediapackage-vod.me-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sa-east-1": {
                 "Value": "sa-east-1",
                 "endpoint": {
@@ -51537,6 +51591,24 @@
                   "Value": "HTTPS"
                 }
               },
+              "us-gov-east-1": {
+                "Value": "us-gov-east-1",
+                "endpoint": {
+                  "Value": "redshift-serverless.us-gov-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "us-gov-west-1": {
+                "Value": "us-gov-west-1",
+                "endpoint": {
+                  "Value": "redshift-serverless.us-gov-west-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "us-west-1": {
                 "Value": "us-west-1",
                 "endpoint": {
@@ -61222,6 +61294,73 @@
               }
             }
           },
+          "socialmessaging": {
+            "regions": {
+              "ap-south-1": {
+                "Value": "ap-south-1",
+                "endpoint": {
+                  "Value": "social-messaging.ap-south-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "ap-southeast-1": {
+                "Value": "ap-southeast-1",
+                "endpoint": {
+                  "Value": "social-messaging.ap-southeast-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "eu-west-1": {
+                "Value": "eu-west-1",
+                "endpoint": {
+                  "Value": "social-messaging.eu-west-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "eu-west-2": {
+                "Value": "eu-west-2",
+                "endpoint": {
+                  "Value": "social-messaging.eu-west-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "us-east-1": {
+                "Value": "us-east-1",
+                "endpoint": {
+                  "Value": "social-messaging.us-east-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "us-east-2": {
+                "Value": "us-east-2",
+                "endpoint": {
+                  "Value": "social-messaging.us-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "us-west-2": {
+                "Value": "us-west-2",
+                "endpoint": {
+                  "Value": "social-messaging.us-west-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              }
+            }
+          },
           "sqs": {
             "Value": "sqs",
             "longName": {
@@ -63302,6 +63441,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-southeast-5": {
+                "Value": "ap-southeast-5",
+                "endpoint": {
+                  "Value": "storagegateway.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ca-central-1": {
                 "Value": "ca-central-1",
                 "endpoint": {
@@ -68594,6 +68742,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "eu-central-2": {
+                "Value": "eu-central-2",
+                "endpoint": {
+                  "Value": "api.messaging.wickr.eu-central-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "eu-west-2": {
                 "Value": "eu-west-2",
                 "endpoint": {
diff --git a/moto/utilities/utils.py b/moto/utilities/utils.py
index d0ad79d65..1b4ccb53f 100644
--- a/moto/utilities/utils.py
+++ b/moto/utilities/utils.py
@@ -3,6 +3,7 @@ import hashlib
 import json
 import pkgutil
 from typing import Any, Dict, Iterator, List, MutableMapping, Optional, Tuple, TypeVar
+from uuid import UUID
 
 DEFAULT_PARTITION = "aws"
 REGION_PREFIX_TO_PARTITION = {
@@ -67,6 +68,14 @@ def merge_multiple_dicts(*args: Any) -> Dict[str, Any]:
     return result
 
 
+def is_valid_uuid(uuid: str, version: int = 4) -> bool:
+    try:
+        UUID(uuid, version=version)
+        return True
+    except ValueError:
+        return False
+
+
 RESOURCE_TYPE = TypeVar("RESOURCE_TYPE")
 
 
diff --git a/moto/wafv2/exceptions.py b/moto/wafv2/exceptions.py
index 6a9810eeb..76d69f44a 100644
--- a/moto/wafv2/exceptions.py
+++ b/moto/wafv2/exceptions.py
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from moto.core.exceptions import JsonRESTError
 
 
@@ -13,6 +15,26 @@ class WAFV2DuplicateItemException(WAFv2ClientError):
         )
 
 
+class WAFV2InsufficientInformationException(WAFv2ClientError):
+    def __init__(
+        self,
+        name: Optional[str],
+        scope: Optional[str],
+        id: Optional[str],
+        arn: Optional[str],
+    ) -> None:
+        super().__init__(
+            "AcessDeniedException",
+            (
+                "Critical information is missing in your request: "
+                f"GetRuleGroupRequest(name={name if name else 'null'}, "
+                f"scope={scope if scope else 'null'}, "
+                f"id={id if id else 'null'}, "
+                f"aRN={arn if arn is not None else 'null'})."
+            ),
+        )
+
+
 class WAFNonexistentItemException(WAFv2ClientError):
     def __init__(self) -> None:
         super().__init__(
diff --git a/moto/wafv2/models.py b/moto/wafv2/models.py
index 5623e8138..4c0e1b87b 100644
--- a/moto/wafv2/models.py
+++ b/moto/wafv2/models.py
@@ -1,10 +1,13 @@
 import re
 from collections import OrderedDict
-from typing import TYPE_CHECKING, Any, Dict, List, Optional
+from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
 
 from moto.core.base_backend import BackendDict, BaseBackend
 from moto.core.common_models import BaseModel
-from moto.core.utils import iso_8601_datetime_with_milliseconds
+from moto.core.utils import (
+    camelcase_to_underscores,
+    iso_8601_datetime_with_milliseconds,
+)
 from moto.moto_api._internal import mock_random
 from moto.utilities.tagging_service import TaggingService
 from moto.utilities.utils import ARN_PARTITION_REGEX, PARTITION_NAMES
@@ -13,8 +16,9 @@ from .exceptions import (
     WAFNonexistentItemException,
     WAFOptimisticLockException,
     WAFV2DuplicateItemException,
+    WAFV2InsufficientInformationException,
 )
-from .utils import make_arn_for_ip_set, make_arn_for_wacl
+from .utils import make_arn_for_ip_set, make_arn_for_rule_group, make_arn_for_wacl
 
 if TYPE_CHECKING:
     from moto.apigateway.models import Stage
@@ -28,7 +32,49 @@ APIGATEWAY_REGEX = (
 )
 
 
-# TODO: Add remaining properties
+class FakeRule(BaseModel):
+    def __init__(
+        self,
+        name: str,
+        priority: int,
+        statement: Dict[str, Any],
+        visibility_config: Dict[str, Union[str, bool]],
+        action: Optional[Dict[str, Any]] = None,
+        captcha_config: Optional[Dict[str, Dict[str, int]]] = None,
+        challenge_config: Optional[Dict[str, Dict[str, int]]] = None,
+        override_action: Optional[Dict[str, Any]] = None,
+        rule_labels: Optional[List[Dict[str, str]]] = None,
+    ):
+        self.name = name
+        self.priority = priority
+        self.statement = statement
+        self.visibility_config = visibility_config
+        self.action = action
+        self.captcha_config = captcha_config
+        self.challenge_config = challenge_config
+        self.override_action = override_action
+        self.rule_labels = rule_labels
+
+    def get_consumed_label(self) -> Optional[str]:
+        return self.statement.get("LabelMatchStatement", {}).get("Key")
+
+    def get_available_labels(self) -> Optional[List[str]]:
+        return [r["Name"] for r in self.rule_labels] if self.rule_labels else None
+
+    def to_dict(self) -> Dict[str, Any]:
+        return {
+            "Name": self.name,
+            "Action": self.action,
+            "Priority": self.priority,
+            "Statement": self.statement,
+            "VisibilityConfig": self.visibility_config,
+            "CaptchaConfig": self.captcha_config,
+            "ChallengeConfig": self.challenge_config,
+            "OverrideAction": self.override_action,
+            "RuleLabels": self.rule_labels,
+        }
+
+
 class FakeWebACL(BaseModel):
     """
     https://docs.aws.amazon.com/waf/latest/APIReference/API_WebACL.html
@@ -37,31 +83,55 @@ class FakeWebACL(BaseModel):
     def __init__(
         self,
         name: str,
+        account: str,
         arn: str,
         wacl_id: str,
         visibility_config: Dict[str, Any],
         default_action: Dict[str, Any],
         description: Optional[str],
-        rules: List[Dict[str, Any]],
+        rules: Optional[List[FakeRule]],
+        association_config: Optional[Dict[str, Any]] = None,
+        captcha_config: Optional[Dict[str, Any]] = None,
+        challenge_config: Optional[Dict[str, Any]] = None,
+        custom_response_bodies: Optional[Dict[str, Any]] = None,
+        token_domains: Optional[List[str]] = None,
     ):
         self.name = name
+        self.account = account
         self.created_time = iso_8601_datetime_with_milliseconds()
         self.id = wacl_id
         self.arn = arn
         self.description = description or ""
         self.capacity = 3
-        self.rules = rules
+        self.rules = rules or []
         self.visibility_config = visibility_config
         self.default_action = default_action
-        self.lock_token = str(mock_random.uuid4())[0:6]
+        self.lock_token = self._generate_lock_token()
         self.associated_resources: List[str] = []
+        self.association_config = association_config
+        self.captcha_config = captcha_config
+        self.challenge_config = challenge_config
+        self.custom_response_bodies = custom_response_bodies
+        self.token_domains = token_domains
+        self.label_namespace = self._get_label_namespace()
+
+    def _generate_lock_token(self) -> str:
+        return str(mock_random.uuid4())
+
+    def _get_label_namespace(self) -> str:
+        return f"awswaf:{self.account}:webacl:{self.name}:"
 
     def update(
         self,
         default_action: Optional[Dict[str, Any]],
-        rules: Optional[List[Dict[str, Any]]],
+        rules: Optional[List[FakeRule]],
         description: Optional[str],
         visibility_config: Optional[Dict[str, Any]],
+        custom_response_bodies: Optional[Dict[str, Any]],
+        captcha_config: Optional[Dict[str, Any]],
+        challenge_config: Optional[Dict[str, Any]],
+        token_domains: Optional[List[str]],
+        association_config: Optional[Dict[str, Any]],
     ) -> None:
         if default_action is not None:
             self.default_action = default_action
@@ -71,18 +141,45 @@ class FakeWebACL(BaseModel):
             self.description = description
         if visibility_config is not None:
             self.visibility_config = visibility_config
-        self.lock_token = str(mock_random.uuid4())[0:6]
-
-    def to_dict(self) -> Dict[str, Any]:
+        if custom_response_bodies is not None:
+            self.custom_response_bodies = custom_response_bodies
+        if captcha_config is not None:
+            self.captcha_config = captcha_config
+        if challenge_config is not None:
+            self.challenge_config = challenge_config
+        if token_domains is not None:
+            self.token_domains = token_domains
+        if association_config is not None:
+            self.association_config = association_config
+        self.lock_token = self._generate_lock_token()
+
+    def to_short_dict(self) -> Dict[str, Any]:
         # Format for summary https://docs.aws.amazon.com/waf/latest/APIReference/API_CreateWebACL.html (response syntax section)
         return {
             "ARN": self.arn,
             "Description": self.description,
             "Id": self.id,
             "Name": self.name,
-            "Rules": self.rules,
+            "LockToken": self.lock_token,
+        }
+
+    def to_dict(self) -> Dict[str, Any]:
+        return {
+            "Name": self.name,
+            "Id": self.id,
+            "ARN": self.arn,
+            "Description": self.description,
+            "Rules": [r.to_dict() for r in self.rules],
             "DefaultAction": self.default_action,
             "VisibilityConfig": self.visibility_config,
+            "Capacity": self.capacity,
+            "LockToken": self.lock_token,
+            "AssociationConfig": self.association_config,
+            "CaptchaConfig": self.captcha_config,
+            "ChallengeConfig": self.challenge_config,
+            "CustomResponseBodies": self.custom_response_bodies,
+            "TokenDomains": self.token_domains,
+            "LabelNamespace": self.label_namespace,
         }
 
 
@@ -130,7 +227,7 @@ class FakeIPSet(BaseModel):
         }
 
 
-class FakeLoggingConfiguration:
+class FakeLoggingConfiguration(BaseModel):
     def __init__(
         self,
         arn: str,
@@ -155,6 +252,108 @@ class FakeLoggingConfiguration:
         }
 
 
+class FakeRuleGroup(BaseModel):
+    def __init__(
+        self,
+        account: str,
+        name: str,
+        id: str,
+        arn: str,
+        scope: str,
+        capacity: int,
+        visibility_config: Dict[str, Any],
+        description: Optional[str],
+        rules: Optional[List[FakeRule]],
+        custom_response_bodies: Optional[Dict[str, Any]] = None,
+    ):
+        self.account = account
+        self.name = name
+        self.id = id
+        self.arn = arn
+        self.lock_token = self._generate_lock_token()
+        self.scope = scope
+        self.capacity = capacity
+        self.description = description or ""
+        self.rules = rules or []
+        self.visibility_config = visibility_config
+        self.custom_response_bodies = custom_response_bodies
+        self.label_namespace = self._get_label_namespace()
+        self.available_labels = self._get_available_labels()
+        self.consumed_labels = self._get_consumed_labels()
+
+    def _generate_lock_token(self) -> str:
+        return str(mock_random.uuid4())
+
+    def _get_available_labels(self) -> Optional[List[Dict[str, str]]]:
+        return (
+            [
+                {"Name": f"{self.label_namespace}{label}"}
+                for rule in self.rules
+                for label in (rule.get_available_labels() or [])
+            ]
+            if self.rules
+            else None
+        )
+
+    def _get_consumed_labels(self) -> Optional[List[Dict[str, str]]]:
+        return (
+            [
+                {"Name": f"{self.label_namespace}{label}"}
+                for rule in self.rules
+                if (label := rule.get_consumed_label())
+            ]
+            if self.rules
+            else None
+        )
+
+    def _get_label_namespace(self) -> str:
+        return f"awswaf:{self.account}:rulegroup:{self.name}:"
+
+    def update(
+        self,
+        description: Optional[str],
+        rules: Optional[List[FakeRule]],
+        visibility_config: Optional[Dict[str, Any]],
+        custom_response_bodies: Optional[Dict[str, Any]],
+    ) -> str:
+        if description is not None:
+            self.description = description
+        if rules is not None:
+            self.rules = rules
+        if visibility_config is not None:
+            self.visibility_config = visibility_config
+        if custom_response_bodies is not None:
+            self.custom_response_bodies = custom_response_bodies
+
+        self.lock_token = self._generate_lock_token()
+        return self.lock_token
+
+    def to_short_dict(self) -> Dict[str, Any]:
+        return {
+            "Name": self.name,
+            "Id": self.id,
+            "Description": self.description,
+            "LockToken": self.lock_token,
+            "ARN": self.arn,
+        }
+
+    def to_dict(self) -> Dict[str, Any]:
+        return {
+            "Name": self.name,
+            "Id": self.id,
+            "Capacity": self.capacity,
+            "ARN": self.arn,
+            "Description": self.description,
+            "Rules": [r.to_dict() for r in self.rules],
+            "VisibilityConfig": self.visibility_config,
+            "LabelNamespace": self.label_namespace,
+            "AvailableLabels": self.available_labels,
+            "ConsumedLabels": self.consumed_labels,
+            "CustomResponseBodies": self.custom_response_bodies,
+            "LockToken": self.lock_token,
+        }
+
+
 class WAFV2Backend(BaseBackend):
     """
     https://docs.aws.amazon.com/waf/latest/APIReference/API_Operations_AWS_WAFV2.html
@@ -165,6 +364,7 @@ class WAFV2Backend(BaseBackend):
         self.wacls: Dict[str, FakeWebACL] = OrderedDict()
         self.ip_sets: Dict[str, FakeIPSet] = OrderedDict()
         self.logging_configurations: Dict[str, FakeLoggingConfiguration] = OrderedDict()
+        self.rule_groups: Dict[str, FakeRuleGroup] = OrderedDict()
         self.tagging_service = TaggingService()
         # TODO: self.load_balancers = OrderedDict()
 
@@ -207,6 +407,9 @@ class WAFV2Backend(BaseBackend):
         except:  # noqa: E722 Do not use bare except
             return None
 
+    def _generate_id(self) -> str:
+        return str(mock_random.uuid4())
+
     def create_web_acl(
         self,
         name: str,
@@ -216,36 +419,59 @@ class WAFV2Backend(BaseBackend):
         description: str,
         tags: List[Dict[str, str]],
         rules: List[Dict[str, Any]],
+        association_config: Optional[Dict[str, Any]],
+        captcha_config: Optional[Dict[str, Any]],
+        challenge_config: Optional[Dict[str, Any]],
+        custom_response_bodies: Optional[Dict[str, Any]],
+        token_domains: Optional[List[str]],
     ) -> FakeWebACL:
-        """
-        The following parameters are not yet implemented: CustomResponseBodies, CaptchaConfig
-        """
-        wacl_id = str(mock_random.uuid4())
+        wacl_id = self._generate_id()
         arn = make_arn_for_wacl(
             name=name,
             account_id=self.account_id,
             region_name=self.region_name,
-            wacl_id=wacl_id,
+            _id=wacl_id,
             scope=scope,
         )
         if arn in self.wacls or self._is_duplicate_name(name):
             raise WAFV2DuplicateItemException()
+        rule_objs = [
+            FakeRule(**{camelcase_to_underscores(k): v for k, v in rule.items()})
+            for rule in rules
+        ]
         new_wacl = FakeWebACL(
-            name, arn, wacl_id, visibility_config, default_action, description, rules
+            name=name,
+            account=self.account_id,
+            arn=arn,
+            wacl_id=wacl_id,
+            visibility_config=visibility_config,
+            default_action=default_action,
+            description=description,
+            rules=rule_objs,
+            association_config=association_config,
+            captcha_config=captcha_config,
+            challenge_config=challenge_config,
+            custom_response_bodies=custom_response_bodies,
+            token_domains=token_domains,
         )
         self.wacls[arn] = new_wacl
         self.tag_resource(arn, tags)
         return new_wacl
 
-    def delete_web_acl(self, name: str, _id: str) -> None:
-        """
-        The LockToken-parameter is not yet implemented
-        """
-        self.wacls = {
-            arn: wacl
-            for arn, wacl in self.wacls.items()
-            if wacl.name != name and wacl.id != _id
-        }
+    def delete_web_acl(self, name: str, scope: str, _id: str, lock_token: str) -> None:
+        arn = make_arn_for_wacl(
+            name=name,
+            account_id=self.account_id,
+            region_name=self.region_name,
+            _id=_id,
+            scope=scope,
+        )
+        if arn not in self.wacls:
+            raise WAFNonexistentItemException
+        wacl = self.wacls[arn]
+        if wacl.lock_token != lock_token:
+            raise WAFOptimisticLockException()
+        self.wacls.pop(arn)
 
     def get_web_acl(self, name: str, _id: str) -> FakeWebACL:
         for wacl in self.wacls.values():
@@ -254,14 +480,17 @@ class WAFV2Backend(BaseBackend):
         raise WAFNonexistentItemException
 
     def list_web_acls(self) -> List[Dict[str, Any]]:
-        return [wacl.to_dict() for wacl in self.wacls.values()]
+        return [wacl.to_short_dict() for wacl in self.wacls.values()]
 
     def _is_duplicate_name(self, name: str) -> bool:
-        allWaclNames = set(wacl.name for wacl in self.wacls.values())
-        return name in allWaclNames
+        all_wacl_names = set(wacl.name for wacl in self.wacls.values())
+        return name in all_wacl_names
 
-    def list_rule_groups(self) -> List[Any]:
-        return []
+    def list_rule_groups(self, scope: str) -> List[Any]:
+        rule_groups = [
+            group for group in self.rule_groups.values() if group.scope == scope
+        ]
+        return rule_groups
 
     def list_tags_for_resource(self, arn: str) -> List[Dict[str, str]]:
         """
@@ -283,12 +512,35 @@ class WAFV2Backend(BaseBackend):
         rules: Optional[List[Dict[str, Any]]],
         description: Optional[str],
         visibility_config: Optional[Dict[str, Any]],
+        lock_token: str,
+        custom_response_bodies: Optional[Dict[str, Any]],
+        captcha_config: Optional[Dict[str, Any]],
+        challenge_config: Optional[Dict[str, Any]],
+        token_domains: Optional[List[str]],
+        association_config: Optional[Dict[str, Any]],
     ) -> str:
-        """
-        The following parameters are not yet implemented: LockToken, CustomResponseBodies, CaptchaConfig
-        """
         acl = self.get_web_acl(name, _id)
-        acl.update(default_action, rules, description, visibility_config)
+        if acl.lock_token != lock_token:
+            raise WAFOptimisticLockException()
+        rule_objs = (
+            [
+                FakeRule(**{camelcase_to_underscores(k): v for k, v in rule.items()})
+                for rule in rules
+            ]
+            if rules
+            else None
+        )
+        acl.update(
+            default_action,
+            rule_objs,
+            description,
+            visibility_config,
+            custom_response_bodies,
+            captcha_config,
+            challenge_config,
+            token_domains,
+            association_config,
+        )
         return acl.lock_token
 
     def create_ip_set(
@@ -300,7 +552,7 @@ class WAFV2Backend(BaseBackend):
         addresses: List[str],
         tags: List[Dict[str, str]],
     ) -> FakeIPSet:
-        ip_set_id = str(mock_random.uuid4())
+        ip_set_id = self._generate_id()
         arn = make_arn_for_ip_set(
             name=name,
             account_id=self.account_id,
@@ -425,5 +677,110 @@ class WAFV2Backend(BaseBackend):
             if f":{scope}:" in arn
         ]
 
+    def create_rule_group(
+        self,
+        name: str,
+        scope: str,
+        capacity: int,
+        description: Optional[str],
+        rules: Optional[List[Dict[str, Any]]],
+        visibility_config: Dict[str, Union[bool, str]],
+        tags: Optional[List[Dict[str, str]]],
+        custom_response_bodies: Optional[Dict[str, str]],
+    ) -> FakeRuleGroup:
+        id = self._generate_id()
+        arn = make_arn_for_rule_group(
+            name, self.account_id, self.region_name, id, scope
+        )
+        if name in set(group.name for group in self.rule_groups.values()):
+            raise WAFV2DuplicateItemException()
+        rules_objs = (
+            [
+                FakeRule(**{camelcase_to_underscores(k): v for k, v in rule.items()})
+                for rule in rules
+            ]
+            if rules
+            else None
+        )
+        rule_group = FakeRuleGroup(
+            name=name,
+            account=self.account_id,
+            id=id,
+            arn=arn,
+            scope=scope,
+            capacity=capacity,
+            visibility_config=visibility_config,
+            description=description,
+            rules=rules_objs,
+            custom_response_bodies=custom_response_bodies,
+        )
+        self.rule_groups[arn] = rule_group
+        self.tagging_service.tag_resource(arn, tags)
+        return rule_group
+
+    def update_rule_group(
+        self,
+        name: str,
+        scope: str,
+        id: str,
+        description: Optional[str],
+        rules: Optional[List[Dict[str, Any]]],
+        visibility_config: Dict[str, Any],
+        lock_token: str,
+        custom_response_bodies: Optional[Dict[str, Any]],
+    ) -> FakeRuleGroup:
+        arn = make_arn_for_rule_group(
+            name, self.account_id, self.region_name, id, scope
+        )
+        if not (group := self.rule_groups.get(arn)):
+            raise WAFNonexistentItemException()
+        if group.lock_token != lock_token:
+            raise WAFOptimisticLockException()
+        rules_objs = (
+            [
+                FakeRule(**{camelcase_to_underscores(k): v for k, v in rule.items()})
+                for rule in rules
+            ]
+            if rules
+            else None
+        )
+        group.update(description, rules_objs, visibility_config, custom_response_bodies)
+
+        return group
+
+    def delete_rule_group(
+        self, name: str, scope: str, id: str, lock_token: str
+    ) -> None:
+        arn = make_arn_for_rule_group(
+            name, self.account_id, self.region_name, id, scope
+        )
+        if not (group := self.rule_groups.get(arn)):
+            raise WAFNonexistentItemException()
+        if group.lock_token != lock_token:
+            raise WAFOptimisticLockException()
+        self.rule_groups.pop(arn)
+        return
+
+    def get_rule_group(
+        self,
+        name: Optional[str],
+        scope: Optional[str],
+        id: Optional[str],
+        arn: Optional[str],
+    ) -> FakeRuleGroup:
+        if not arn and not (name and scope and id):
+            raise WAFV2InsufficientInformationException(name, scope, id, arn)
+        else:
+            arn = arn or make_arn_for_rule_group(
+                name,  # type: ignore[arg-type]
+                self.account_id,
+                self.region_name,
+                id,  # type: ignore[arg-type]
+                scope,  # type: ignore[arg-type]
+            )
+        if not (group := self.rule_groups.get(arn)):
+            raise WAFNonexistentItemException()
+        return group
+
 
 wafv2_backends = BackendDict(WAFV2Backend, "wafv2", additional_regions=PARTITION_NAMES)
diff --git a/moto/wafv2/responses.py b/moto/wafv2/responses.py
index 68b496059..b8b03c22e 100644
--- a/moto/wafv2/responses.py
+++ b/moto/wafv2/responses.py
@@ -47,6 +47,11 @@ class WAFV2Response(BaseResponse):
         description = body.get("Description")
         tags = body.get("Tags", [])
         rules = body.get("Rules", [])
+        association_config = body.get("AssociationConfig")
+        captcha_config = body.get("CaptchaConfig")
+        challenge_config = body.get("ChallengeConfig")
+        custom_response_bodies = body.get("CustomResponseBodies")
+        token_domains = body.get("TokenDomains")
         web_acl = self.wafv2_backend.create_web_acl(
             name,
             body["VisibilityConfig"],
@@ -55,8 +60,13 @@ class WAFV2Response(BaseResponse):
             description,
             tags,
             rules,
+            association_config,
+            captcha_config,
+            challenge_config,
+            custom_response_bodies,
+            token_domains,
         )
-        response = {"Summary": web_acl.to_dict()}
+        response = {"Summary": web_acl.to_short_dict()}
         response_headers = {"Content-Type": "application/json"}
         return 200, response_headers, json.dumps(response)
 
@@ -66,7 +76,8 @@ class WAFV2Response(BaseResponse):
             self.region = GLOBAL_REGION
         name = self._get_param("Name")
         _id = self._get_param("Id")
-        self.wafv2_backend.delete_web_acl(name, _id)
+        lock_token = self._get_param("LockToken")
+        self.wafv2_backend.delete_web_acl(name, scope, _id, lock_token)
         response_headers = {"Content-Type": "application/json"}
         return 200, response_headers, "{}"
 
@@ -96,8 +107,8 @@ class WAFV2Response(BaseResponse):
         scope = self._get_param("Scope")
         if scope == "CLOUDFRONT":
             self.region = GLOBAL_REGION
-        rule_groups = self.wafv2_backend.list_rule_groups()
-        response = {"RuleGroups": [rg.to_dict() for rg in rule_groups]}
+        rule_groups = self.wafv2_backend.list_rule_groups(scope)
+        response = {"RuleGroups": [rg.to_short_dict() for rg in rule_groups]}
         response_headers = {"Content-Type": "application/json"}
         return 200, response_headers, json.dumps(response)
 
@@ -136,10 +147,27 @@ class WAFV2Response(BaseResponse):
         rules = body.get("Rules")
         description = body.get("Description")
         visibility_config = body.get("VisibilityConfig")
-        lock_token = self.wafv2_backend.update_web_acl(
-            name, _id, default_action, rules, description, visibility_config
+        lock_token = body.get("LockToken")
+        custom_response_bodies = body.get("CustomResponseBodies")
+        captcha_config = body.get("CaptchaConfig")
+        challenge_config = body.get("ChallengeConfig")
+        token_domains = body.get("TokenDomains")
+        association_config = body.get("AssociationConfig")
+        new_lock_token = self.wafv2_backend.update_web_acl(
+            name,
+            _id,
+            default_action,
+            rules,
+            description,
+            visibility_config,
+            lock_token,
+            custom_response_bodies,
+            captcha_config,
+            challenge_config,
+            token_domains,
+            association_config,
         )
-        return 200, {}, json.dumps({"NextLockToken": lock_token})
+        return 200, {}, json.dumps({"NextLockToken": new_lock_token})
 
     def create_ip_set(self) -> TYPE_RESPONSE:
         body = json.loads(self.body)
@@ -316,6 +344,86 @@ class WAFV2Response(BaseResponse):
         self.wafv2_backend.delete_logging_configuration(resource_arn)
         return 200, {}, "{}"
 
+    def create_rule_group(self) -> TYPE_RESPONSE:
+        name = self._get_param("Name")
+        scope = self._get_param("Scope")
+        capacity = self._get_param("Capacity")
+        description = self._get_param("Description")
+        rules = self._get_param("Rules", [])
+        visibility_config = self._get_param("VisibilityConfig")
+        tags = self._get_param("Tags")
+        custom_response_bodies = self._get_param("CustomResponseBodies")
+        if scope == "CLOUDFRONT":
+            self.region = GLOBAL_REGION
+        group = self.wafv2_backend.create_rule_group(
+            name=name,
+            scope=scope,
+            capacity=capacity,
+            description=description,
+            rules=rules,
+            visibility_config=visibility_config,
+            tags=tags,
+            custom_response_bodies=custom_response_bodies,
+        )
+        return 200, {}, json.dumps(dict(Summary=group.to_short_dict()))
+
+    def update_rule_group(self) -> TYPE_RESPONSE:
+        name = self._get_param("Name")
+        scope = self._get_param("Scope")
+        id = self._get_param("Id")
+        description = self._get_param("Description")
+        rules = self._get_param("Rules")
+        visibility_config = self._get_param("VisibilityConfig")
+        lock_token = self._get_param("LockToken")
+        custom_response_bodies = self._get_param("CustomResponseBodies")
+        if scope == "CLOUDFRONT":
+            self.region = GLOBAL_REGION
+        updated_group = self.wafv2_backend.update_rule_group(
+            name=name,
+            scope=scope,
+            id=id,
+            description=description,
+            rules=rules,
+            visibility_config=visibility_config,
+            lock_token=lock_token,
+            custom_response_bodies=custom_response_bodies,
+        )
+        return 200, {}, json.dumps(dict(NextLockToken=updated_group.lock_token))
+
+    def delete_rule_group(self) -> TYPE_RESPONSE:
+        name = self._get_param("Name")
+        scope = self._get_param("Scope")
+        id = self._get_param("Id")
+        lock_token = self._get_param("LockToken")
+        if scope == "CLOUDFRONT":
+            self.region = GLOBAL_REGION
+        self.wafv2_backend.delete_rule_group(
+            name=name,
+            scope=scope,
+            id=id,
+            lock_token=lock_token,
+        )
+        return 200, {}, json.dumps(dict())
+
+    def get_rule_group(self) -> TYPE_RESPONSE:
+        name = self._get_param("Name")
+        scope = self._get_param("Scope")
+        id = self._get_param("Id")
+        arn = self._get_param("ARN")
+        if scope == "CLOUDFRONT" or (
+            isinstance(arn, str) and arn.split(":")[3] == GLOBAL_REGION
+        ):
+            self.region = GLOBAL_REGION
+        rule_group = self.wafv2_backend.get_rule_group(
+            name=name,
+            scope=scope,
+            id=id,
+            arn=arn,
+        )
+        group_dict = rule_group.to_dict()
+        lock_token = group_dict.pop("LockToken")
+        return 200, {}, json.dumps(dict(RuleGroup=group_dict, LockToken=lock_token))
+
 
 # notes about region and scope
 # --scope = CLOUDFRONT is ALWAYS us-east-1 (but we use "global" instead to differentiate between REGIONAL us-east-1)
diff --git a/moto/wafv2/urls.py b/moto/wafv2/urls.py
index 86725f2b2..e3908a1df 100644
--- a/moto/wafv2/urls.py
+++ b/moto/wafv2/urls.py
@@ -6,4 +6,5 @@ url_bases = [
 
 url_paths = {
     "{0}/": WAFV2Response.dispatch,
+    "{0}/$": WAFV2Response.dispatch,
 }
diff --git a/moto/wafv2/utils.py b/moto/wafv2/utils.py
index 9bb7b4753..0be4a57dc 100644
--- a/moto/wafv2/utils.py
+++ b/moto/wafv2/utils.py
@@ -1,23 +1,6 @@
-from moto.utilities.utils import PARTITION_NAMES, get_partition
-
-
-def make_arn_for_wacl(
-    name: str, account_id: str, region_name: str, wacl_id: str, scope: str
-) -> str:
-    """https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works.html - explains --scope (cloudfront vs regional)"""
-    return make_arn(name, account_id, region_name, wacl_id, scope, "webacl")
-
-
-def make_arn_for_ip_set(
-    name: str, account_id: str, region_name: str, _id: str, scope: str
-) -> str:
-    return make_arn(name, account_id, region_name, _id, scope, "ipset")
-
+from functools import partial
 
-def make_arn_for_logging_configuration(
-    name: str, account_id: str, region_name: str, _id: str, scope: str
-) -> str:
-    return make_arn(name, account_id, region_name, _id, scope, "logingconfiguration")
+from moto.utilities.utils import PARTITION_NAMES, get_partition
 
 
 def make_arn(
@@ -35,3 +18,9 @@ def make_arn(
     )
 
     return f"arn:{partition}:wafv2:{region_name}:{account_id}:{scope}/{resource}/{name}/{_id}"
+
+
+make_arn_for_wacl = partial(make_arn, resource="webacl")
+make_arn_for_ip_set = partial(make_arn, resource="ipset")
+make_arn_for_logging_configuration = partial(make_arn, resource="loggingconfiguration")
+make_arn_for_rule_group = partial(make_arn, resource="rulegroup")


Test patch:
diff --git a/tests/test_organizations/test_organizations_boto3.py b/tests/test_organizations/test_organizations_boto3.py
index 5c1ee7d18..81d833297 100644
--- a/tests/test_organizations/test_organizations_boto3.py
+++ b/tests/test_organizations/test_organizations_boto3.py
@@ -31,6 +31,11 @@ from .organizations_test_utils import (
     validate_service_control_policy,
 )
 
+# Accounts
+mockname = "mock-account"
+mockdomain = "moto-example.org"
+mockemail = "@".join([mockname, mockdomain])
+
 
 @mock_aws
 @pytest.mark.parametrize(
@@ -112,11 +117,26 @@ def test_create_account_creates_custom_role():
 
 @mock_aws
 def test_describe_organization():
+    if not settings.TEST_DECORATOR_MODE:
+        raise SkipTest("Involves changing account using env variable")
+
     client = boto3.client("organizations", region_name="us-east-1")
     client.create_organization(FeatureSet="ALL")
     response = client.describe_organization()
     validate_organization(response)
 
+    # Ensure member accounts can also describe the organisation from any region
+    account_id = client.create_account(AccountName=mockname, Email=mockemail)[
+        "CreateAccountStatus"
+    ]["AccountId"]
+
+    for region_name in ["ap-south-1", "eu-west-1"]:
+        with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account_id}):
+            response = boto3.client(
+                "organizations", region_name=region_name
+            ).describe_organization()
+            validate_organization(response)
+
 
 @mock_aws
 def test_describe_organization_exception():
@@ -250,12 +270,6 @@ def test_list_organizational_units_for_parent_exception():
     assert "ParentNotFoundException" in ex.response["Error"]["Message"]
 
 
-# Accounts
-mockname = "mock-account"
-mockdomain = "moto-example.org"
-mockemail = "@".join([mockname, mockdomain])
-
-
 @mock_aws
 def test_create_account():
     client = boto3.client("organizations", region_name="us-east-1")
@@ -297,6 +311,14 @@ def test_close_account_puts_account_in_suspended_status():
     account = client.describe_account(AccountId=created_account_id)["Account"]
     assert account["Status"] == "SUSPENDED"
 
+    with pytest.raises(ClientError) as exc:
+        client.close_account(AccountId=created_account_id)
+    assert exc.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
+    assert "AccountAlreadyClosedException" in exc.value.response["Error"]["Code"]
+    assert exc.value.response["Error"]["Message"] == (
+        "The provided account is already closed."
+    )
+
 
 @mock_aws
 def test_close_account_id_not_in_org_raises_exception():
@@ -607,6 +629,9 @@ def test_get_paginated_list_create_account_status():
 
 @mock_aws
 def test_remove_account_from_organization():
+    if not settings.TEST_DECORATOR_MODE:
+        raise SkipTest("Involves changing account using env variable")
+
     client = boto3.client("organizations", region_name="us-east-1")
     _ = client.create_organization(FeatureSet="ALL")["Organization"]
     create_account_status = client.create_account(
@@ -629,6 +654,20 @@ def test_remove_account_from_organization():
     assert len(accounts) == 1
     assert not created_account_exists(accounts)
 
+    # After the account is removed from an organisation, calling DescribeOrganization from the removed account should raise
+    with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account_id}):
+        with pytest.raises(ClientError) as exc:
+            client.describe_organization()
+    assert exc.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
+    assert "AWSOrganizationsNotInUse" in exc.value.response["Error"]["Code"]
+
+    # Attempting to remove invalid account must raise
+    bad_account_id = "010101010101"
+    with pytest.raises(ClientError) as exc:
+        client.remove_account_from_organization(AccountId=bad_account_id)
+    assert exc.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
+    assert "AWSOrganizationsNotInUse" in exc.value.response["Error"]["Code"]
+
 
 @mock_aws
 def test_delete_organization_with_existing_account():
diff --git a/tests/test_panorama/test_application_instance.py b/tests/test_panorama/test_application_instance.py
new file mode 100644
index 000000000..a76cf8e59
--- /dev/null
+++ b/tests/test_panorama/test_application_instance.py
@@ -0,0 +1,394 @@
+import datetime
+from unittest import SkipTest
+from unittest.mock import ANY
+
+import boto3
+from dateutil.tz import tzutc
+from freezegun import freeze_time
+
+from moto import mock_aws, settings
+
+GIVEN_DEVICE_NAME = "not-a-device-name"
+PROVISION_DEVICE_PARAMS = {
+    "Description": "not a device description",
+    "Name": GIVEN_DEVICE_NAME,
+    "NetworkingConfiguration": {
+        "Ethernet0": {
+            "ConnectionType": "STATIC_IP",
+            "StaticIpConnectionInfo": {
+                "DefaultGateway": "192.168.1.1",
+                "Dns": [
+                    "8.8.8.8",
+                ],
+                "IpAddress": "192.168.1.10",
+                "Mask": "255.255.255.0",
+            },
+        },
+        "Ethernet1": {
+            "ConnectionType": "dhcp",
+        },
+        "Ntp": {
+            "NtpServers": [
+                "0.pool.ntp.org",
+                "1.pool.ntp.org",
+                "0.fr.pool.ntp.org",
+            ]
+        },
+    },
+    "Tags": {"Key": "test-key", "Value": "test-value"},
+}
+
+
+@mock_aws
+def test_create_application_instance() -> None:
+    # Given
+    panorama_client = boto3.client("panorama", "eu-west-1")
+    response_device_creation = panorama_client.provision_device(
+        **PROVISION_DEVICE_PARAMS
+    )
+
+    # When
+    response = panorama_client.create_application_instance(
+        DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+        Description="not a description",
+        ManifestOverridesPayload={
+            "PayloadData": "dumped_payload_data",
+        },
+        ManifestPayload={
+            "PayloadData": "dumped_manifest_payload_data",
+        },
+        Name="not-a-name",
+        RuntimeRoleArn="not-an-arn",
+        Tags={
+            "Key": "value",
+        },
+    )
+    # Then
+    assert isinstance(response["ApplicationInstanceId"], str)
+    assert response["ApplicationInstanceId"].startswith("applicationInstance-")
+    assert len(response["ApplicationInstanceId"]) == 42
+
+
+@mock_aws
+def test_describe_application_instance() -> None:
+    # Given
+    panorama_client = boto3.client("panorama", "eu-west-1")
+    response_device_creation = panorama_client.provision_device(
+        **PROVISION_DEVICE_PARAMS
+    )
+    given_application_instance_name = "not-a-name"
+    given_application_instance_arn = "not-an-arn"
+    response_created = panorama_client.create_application_instance(
+        DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+        Description="not a description",
+        ManifestOverridesPayload={
+            "PayloadData": "dumped_payload_data",
+        },
+        ManifestPayload={
+            "PayloadData": "dumped_manifest_payload_data",
+        },
+        Name=given_application_instance_name,
+        RuntimeRoleArn=given_application_instance_arn,
+        Tags={
+            "Key": "value",
+        },
+    )
+
+    # When
+    response = panorama_client.describe_application_instance(
+        ApplicationInstanceId=response_created["ApplicationInstanceId"]
+    )
+
+    # Then
+    assert (
+        response["ApplicationInstanceId"] == response_created["ApplicationInstanceId"]
+    )
+    assert response.get("ApplicationInstanceIdToReplace") is None
+    assert response["Arn"].startswith(
+        "arn:aws:panorama:eu-west-1:123456789012:application-instance/"
+    )
+    assert response["Arn"].endswith(response_created["ApplicationInstanceId"])
+    assert isinstance(response["CreatedTime"], datetime.datetime)
+    assert (
+        response["DefaultRuntimeContextDevice"] == response_device_creation["DeviceId"]
+    )
+    assert response["DefaultRuntimeContextDeviceName"] == "not-a-device-name"
+    assert response["Description"] == "not a description"
+    assert response["HealthStatus"] == "RUNNING"
+    assert isinstance(response["LastUpdatedTime"], datetime.datetime)
+    assert response["Name"] == given_application_instance_name
+    assert response["RuntimeRoleArn"] == given_application_instance_arn
+    assert response["Status"] == "DEPLOYMENT_SUCCEEDED"
+
+
+@mock_aws
+def test_create_application_instance_should_set_created_time() -> None:
+    # Given
+    if settings.TEST_SERVER_MODE:
+        raise SkipTest("Can't use ManagedState in ServerMode")
+    panorama_client = boto3.client("panorama", "eu-west-1")
+    response_device_creation = panorama_client.provision_device(
+        **PROVISION_DEVICE_PARAMS
+    )
+    given_application_instance_name = "not-a-name"
+    given_application_instance_arn = "not-an-arn"
+    with freeze_time("2020-01-01 12:00:00"):
+        response_created = panorama_client.create_application_instance(
+            DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+            Description="not a description",
+            ManifestOverridesPayload={
+                "PayloadData": "dumped_payload_data",
+            },
+            ManifestPayload={
+                "PayloadData": "dumped_manifest_payload_data",
+            },
+            Name=given_application_instance_name,
+            RuntimeRoleArn=given_application_instance_arn,
+            Tags={
+                "Key": "value",
+            },
+        )
+
+    # When
+    response = panorama_client.describe_application_instance(
+        ApplicationInstanceId=response_created["ApplicationInstanceId"]
+    )
+
+    # Then
+    assert response["CreatedTime"] == datetime.datetime(
+        2020, 1, 1, 12, 0, 0, tzinfo=tzutc()
+    )
+    assert response["LastUpdatedTime"] == datetime.datetime(
+        2020, 1, 1, 12, 0, 0, tzinfo=tzutc()
+    )
+
+
+@mock_aws
+def test_describe_application_instance_details() -> None:
+    # Given
+    panorama_client = boto3.client("panorama", "eu-west-1")
+    given_application_instance_name = "not-a-name"
+    given_application_instance_arn = "not-an-arn"
+    response_device_creation = panorama_client.provision_device(
+        **PROVISION_DEVICE_PARAMS
+    )
+    given_manifest_payload = {
+        "PayloadData": "dumped_manifest_payload_data",
+    }
+    given_manifest_overrides_payload = {
+        "PayloadData": "dumped_payload_data",
+    }
+    response_created = panorama_client.create_application_instance(
+        DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+        Description="not a description",
+        ManifestOverridesPayload=given_manifest_overrides_payload,
+        ManifestPayload=given_manifest_payload,
+        Name=given_application_instance_name,
+        RuntimeRoleArn=given_application_instance_arn,
+        Tags={
+            "Key": "value",
+        },
+    )
+
+    # When
+    response = panorama_client.describe_application_instance_details(
+        ApplicationInstanceId=response_created["ApplicationInstanceId"]
+    )
+
+    # Then
+    assert (
+        response["ApplicationInstanceId"] == response_created["ApplicationInstanceId"]
+    )
+    assert response.get("ApplicationInstanceIdToReplace") is None
+    assert isinstance(response["CreatedTime"], datetime.datetime)
+    assert (
+        response["DefaultRuntimeContextDevice"] == response_device_creation["DeviceId"]
+    )
+    assert response["Description"] == "not a description"
+    assert response["Name"] == given_application_instance_name
+    assert response["ManifestPayload"] == given_manifest_payload
+    assert response["ManifestOverridesPayload"] == given_manifest_overrides_payload
+
+
+@mock_aws
+def test_list_application_instances() -> None:
+    # Given
+    panorama_client = boto3.client("panorama", "eu-west-1")
+    given_application_instance_name = "not-a-name"
+    given_application_instance_arn = "not-an-arn"
+    given_device_name = "not-a-device-name"
+    response_device_creation = panorama_client.provision_device(
+        **PROVISION_DEVICE_PARAMS
+    )
+    response_created_1 = panorama_client.create_application_instance(
+        DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+        Description="not a description",
+        ManifestOverridesPayload={
+            "PayloadData": "dumped_payload_data",
+        },
+        ManifestPayload={
+            "PayloadData": "dumped_manifest_payload_data",
+        },
+        Name=given_application_instance_name,
+        RuntimeRoleArn=given_application_instance_arn,
+        Tags={
+            "Key": "value",
+        },
+    )
+    response_created_2 = panorama_client.create_application_instance(
+        ApplicationInstanceIdToReplace=response_created_1["ApplicationInstanceId"],
+        DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+        Description="not a description",
+        ManifestOverridesPayload={
+            "PayloadData": "dumped_payload_data",
+        },
+        ManifestPayload={
+            "PayloadData": "dumped_manifest_payload_data",
+        },
+        Name=given_application_instance_name,
+        RuntimeRoleArn=given_application_instance_arn,
+        Tags={
+            "Key": "value",
+        },
+    )
+
+    # When
+    response_1 = panorama_client.list_application_instances(
+        DeviceId=response_device_creation["DeviceId"],
+        MaxResults=1,
+    )
+    response_2 = panorama_client.list_application_instances(
+        DeviceId=response_device_creation["DeviceId"],
+        MaxResults=1,
+        NextToken=response_1["NextToken"],
+    )
+
+    # Then
+    assert len(response_1["ApplicationInstances"]) == 1
+    assert (
+        response_1["ApplicationInstances"][0]["ApplicationInstanceId"]
+        == response_created_1["ApplicationInstanceId"]
+    )
+    assert response_1["ApplicationInstances"][0]["Arn"].startswith(
+        "arn:aws:panorama:eu-west-1:123456789012:application-instance/"
+    )
+    assert response_1["ApplicationInstances"][0]["Arn"].endswith(
+        response_created_1["ApplicationInstanceId"]
+    )
+    assert isinstance(
+        response_1["ApplicationInstances"][0]["CreatedTime"], datetime.datetime
+    )
+    assert (
+        response_1["ApplicationInstances"][0]["DefaultRuntimeContextDevice"]
+        == response_device_creation["DeviceId"]
+    )
+    assert (
+        response_1["ApplicationInstances"][0]["DefaultRuntimeContextDeviceName"]
+        == given_device_name
+    )
+    assert response_1["ApplicationInstances"][0]["Description"] == "not a description"
+    assert response_1["ApplicationInstances"][0]["HealthStatus"] == "RUNNING"
+    assert response_1["ApplicationInstances"][0]["Name"], response_created_1["Name"]
+    assert response_1["ApplicationInstances"][0]["RuntimeContextStates"] == [
+        {
+            "DesiredState": "RUNNING",
+            "DeviceReportedStatus": "RUNNING",
+            "DeviceReportedTime": ANY,
+            "RuntimeContextName": "string",
+        },
+        {
+            "DesiredState": "REMOVED",
+            "DeviceReportedStatus": "REMOVAL_IN_PROGRESS",
+            "DeviceReportedTime": ANY,
+            "RuntimeContextName": "string",
+        },
+    ]
+    assert response_1["ApplicationInstances"][0]["Status"] == "REMOVAL_SUCCEEDED"
+    assert response_1["ApplicationInstances"][0]["StatusDescription"] == "string"
+    assert response_1["ApplicationInstances"][0]["Tags"] == {"Key": "value"}
+    assert response_1["NextToken"] is not None
+
+    assert len(response_2["ApplicationInstances"]) == 1
+    assert (
+        response_2["ApplicationInstances"][0]["ApplicationInstanceId"]
+        == response_created_2["ApplicationInstanceId"]
+    )
+    assert "NextToken" not in response_2
+    assert response_2["ApplicationInstances"][0]["RuntimeContextStates"] == [
+        {
+            "DesiredState": "RUNNING",
+            "DeviceReportedStatus": "RUNNING",
+            "DeviceReportedTime": ANY,
+            "RuntimeContextName": "string",
+        }
+    ]
+
+
+@mock_aws
+def test_list_application_should_return_only_filtered_results_if_status_filter_used() -> (
+    None
+):
+    # Given
+    panorama_client = boto3.client("panorama", "eu-west-1")
+    given_application_instance_name = "not-a-name"
+    given_application_instance_name_2 = "not-a-name-2"
+    given_application_instance_arn = "not-an-arn"
+    response_device_creation = panorama_client.provision_device(
+        **PROVISION_DEVICE_PARAMS
+    )
+    response_created_1 = panorama_client.create_application_instance(
+        DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+        Description="not a description",
+        ManifestOverridesPayload={
+            "PayloadData": "dumped_payload_data",
+        },
+        ManifestPayload={
+            "PayloadData": "dumped_manifest_payload_data",
+        },
+        Name=given_application_instance_name,
+        RuntimeRoleArn=given_application_instance_arn,
+        Tags={
+            "Key": "value",
+        },
+    )
+    response_created_2 = panorama_client.create_application_instance(
+        ApplicationInstanceIdToReplace=response_created_1["ApplicationInstanceId"],
+        DefaultRuntimeContextDevice=response_device_creation["DeviceId"],
+        Description="not a description",
+        ManifestOverridesPayload={
+            "PayloadData": "dumped_payload_data",
+        },
+        ManifestPayload={
+            "PayloadData": "dumped_manifest_payload_data",
+        },
+        Name=given_application_instance_name_2,
+        RuntimeRoleArn=given_application_instance_arn,
+        Tags={
+            "Key": "value",
+        },
+    )
+
+    # When
+    response_deployed = panorama_client.list_application_instances(
+        DeviceId=response_device_creation["DeviceId"],
+        MaxResults=123,
+        StatusFilter="DEPLOYMENT_SUCCEEDED",
+    )
+
+    response_removed = panorama_client.list_application_instances(
+        DeviceId=response_device_creation["DeviceId"],
+        MaxResults=123,
+        StatusFilter="REMOVAL_SUCCEEDED",
+    )
+
+    # Then
+    assert len(response_removed["ApplicationInstances"]) == 1
+    assert (
+        response_removed["ApplicationInstances"][0]["ApplicationInstanceId"]
+        == response_created_1["ApplicationInstanceId"]
+    )
+    assert len(response_deployed["ApplicationInstances"]) == 1
+    assert (
+        response_deployed["ApplicationInstances"][0]["ApplicationInstanceId"]
+        == response_created_2["ApplicationInstanceId"]
+    )
diff --git a/tests/test_panorama/test_nodes.py b/tests/test_panorama/test_nodes.py
index cc1bf637b..bdaaf02ff 100644
--- a/tests/test_panorama/test_nodes.py
+++ b/tests/test_panorama/test_nodes.py
@@ -139,9 +139,9 @@ def test_list_nodes() -> None:
     assert node["OwnerAccount"] == "123456789012"
     assert (
         node["PackageArn"]
-        == "arn:aws:panorama:us-east-1:123456789012:package/package-+Y6+ycqU+ogoBTHuibMzGg=="
+        == "arn:aws:panorama:us-east-1:123456789012:package/package--Y6-ycqU-ogoBTHuibMzGg"
     )
-    assert node["PackageId"] == "package-+Y6+ycqU+ogoBTHuibMzGg=="
+    assert node["PackageId"] == "package--Y6-ycqU-ogoBTHuibMzGg"
     assert node["PackageName"] == "not-an-output-package-name"
     assert node["PackageVersion"] == "1.0"
     assert (
@@ -154,9 +154,3 @@ def test_list_nodes() -> None:
     assert isinstance(response_page_2["Nodes"], list)
     assert len(response_page_2["Nodes"]) == 1
     assert "NextToken" not in response_page_2
-
-
-"""
-botocore.errorfactory.ValidationException: An error occurred (ValidationException) when calling the CreateNodeFromTemplateJob operation: {"reason":"FIELD_VALIDATION_FAILED","message":"The input fails to satisfy the constraints specified by an AWS service.","fields":[{"name":"TemplateParameters","message":"Unsupported template parameters: [param]"}]}
-botocore.errorfactory.ValidationException: An error occurred (ValidationException) when calling the CreateNodeFromTemplateJob operation: {"Message":[ECMA 262 regex \"^([0-9]+)\\.([0-9]+)$\" does not match input string \"not-an-output-package-version\"]}
-"""
diff --git a/tests/test_panorama/test_panorama_device.py b/tests/test_panorama/test_panorama_device.py
index 72b966fa1..443b654ac 100644
--- a/tests/test_panorama/test_panorama_device.py
+++ b/tests/test_panorama/test_panorama_device.py
@@ -54,7 +54,7 @@ def test_provision_device() -> None:
         resp["Arn"] == "arn:aws:panorama:eu-west-1:123456789012:device/test-device-name"
     )
     assert resp["Certificates"] == b"certificate"
-    assert resp["DeviceId"] == "device-RsozEWjZpeNe3SXHidX3mg=="
+    assert resp["DeviceId"] == "device-RsozEWjZpeNe3SXHidX3mg"
     assert resp["IotThingName"] == ""
     assert resp["Status"] == "AWAITING_PROVISIONING"
 
@@ -129,7 +129,7 @@ def test_describe_device() -> None:
     assert resp["Description"] == "test device description"
     assert resp["DeviceAggregatedStatus"] == "ONLINE"
     assert resp["DeviceConnectionStatus"] == "ONLINE"
-    assert resp["DeviceId"] == "device-RsozEWjZpeNe3SXHidX3mg=="
+    assert resp["DeviceId"] == "device-RsozEWjZpeNe3SXHidX3mg"
     assert resp["LatestDeviceJob"] == {"JobType": "REBOOT", "Status": "COMPLETED"}
     assert resp["LatestSoftware"] == "6.2.1"
     assert resp["LeaseExpirationTime"] == datetime(2020, 1, 6, 12, 0, tzinfo=tzutc())
diff --git a/tests/test_wafv2/test_wafv2.py b/tests/test_wafv2/test_wafv2.py
index 0646d2fe1..5c8af466f 100644
--- a/tests/test_wafv2/test_wafv2.py
+++ b/tests/test_wafv2/test_wafv2.py
@@ -41,6 +41,38 @@ def test_create_web_acl(region, partition):
 @mock_aws
 def test_create_web_acl_with_all_arguments():
     client = boto3.client("wafv2", region_name="us-east-2")
+    rule_1 = {
+        "Action": {"Allow": {}},
+        "Name": "tf-acc-test-8205974093017792151-2",
+        "Priority": 10,
+        "Statement": {"GeoMatchStatement": {"CountryCodes": ["US", "NL"]}},
+        "VisibilityConfig": {
+            "CloudWatchMetricsEnabled": False,
+            "MetricName": "tf-acc-test-8205974093017792151-2",
+            "SampledRequestsEnabled": False,
+        },
+    }
+    rule_2 = {
+        "Action": {"Count": {}},
+        "Name": "tf-acc-test-8205974093017792151-1",
+        "Priority": 5,
+        "Statement": {
+            "SizeConstraintStatement": {
+                "ComparisonOperator": "LT",
+                "FieldToMatch": {"QueryString": {}},
+                "Size": 50,
+                "TextTransformations": [
+                    {"Priority": 2, "Type": "CMD_LINE"},
+                    {"Priority": 5, "Type": "NONE"},
+                ],
+            }
+        },
+        "VisibilityConfig": {
+            "CloudWatchMetricsEnabled": False,
+            "MetricName": "tf-acc-test-8205974093017792151-1",
+            "SampledRequestsEnabled": False,
+        },
+    }
     web_acl_id = client.create_web_acl(
         Name="test",
         Scope="CLOUDFRONT",
@@ -51,39 +83,35 @@ def test_create_web_acl_with_all_arguments():
             "CloudWatchMetricsEnabled": False,
             "MetricName": "idk",
         },
-        Rules=[
-            {
-                "Action": {"Allow": {}},
-                "Name": "tf-acc-test-8205974093017792151-2",
-                "Priority": 10,
-                "Statement": {"GeoMatchStatement": {"CountryCodes": ["US", "NL"]}},
-                "VisibilityConfig": {
-                    "CloudWatchMetricsEnabled": False,
-                    "MetricName": "tf-acc-test-8205974093017792151-2",
-                    "SampledRequestsEnabled": False,
+        AssociationConfig={
+            "RequestBody": {
+                "Test": {
+                    "DefaultSizeInspectionLimit": "KB_64",
                 },
             },
-            {
-                "Action": {"Count": {}},
-                "Name": "tf-acc-test-8205974093017792151-1",
-                "Priority": 5,
-                "Statement": {
-                    "SizeConstraintStatement": {
-                        "ComparisonOperator": "LT",
-                        "FieldToMatch": {"QueryString": {}},
-                        "Size": 50,
-                        "TextTransformations": [
-                            {"Priority": 2, "Type": "CMD_LINE"},
-                            {"Priority": 5, "Type": "NONE"},
-                        ],
-                    }
-                },
-                "VisibilityConfig": {
-                    "CloudWatchMetricsEnabled": False,
-                    "MetricName": "tf-acc-test-8205974093017792151-1",
-                    "SampledRequestsEnabled": False,
-                },
+        },
+        CustomResponseBodies={
+            "Test": {
+                "Content": "test",
+                "ContentType": "TEXT_PLAIN",
             },
+        },
+        CaptchaConfig={
+            "ImmunityTimeProperty": {"ImmunityTime": 60},
+        },
+        ChallengeConfig={
+            "ImmunityTimeProperty": {"ImmunityTime": 60},
+        },
+        TokenDomains=[
+            "test1.com",
+            "test2.com",
+        ],
+        Tags=[
+            {"Key": "TestKey", "Value": "TestValue"},
+        ],
+        Rules=[
+            rule_1,
+            rule_2,
         ],
     )["Summary"]["Id"]
 
@@ -96,6 +124,27 @@ def test_create_web_acl_with_all_arguments():
         "MetricName": "idk",
     }
     assert len(wacl["Rules"]) == 2
+    assert rule_1 in wacl["Rules"] and rule_2 in wacl["Rules"]
+    assert wacl["AssociationConfig"] == {
+        "RequestBody": {
+            "Test": {
+                "DefaultSizeInspectionLimit": "KB_64",
+            },
+        },
+    }
+    assert wacl["CustomResponseBodies"] == {
+        "Test": {
+            "Content": "test",
+            "ContentType": "TEXT_PLAIN",
+        },
+    }
+    assert wacl["CaptchaConfig"] == {
+        "ImmunityTimeProperty": {"ImmunityTime": 60},
+    }
+    assert wacl["ChallengeConfig"] == {
+        "ImmunityTimeProperty": {"ImmunityTime": 60},
+    }
+    assert wacl["TokenDomains"] == ["test1.com", "test2.com"]
 
 
 @mock_aws
@@ -106,6 +155,7 @@ def test_get_web_acl():
     wacl = conn.get_web_acl(Name="John", Scope="REGIONAL", Id=web_acl_id)["WebACL"]
     assert wacl["Name"] == "John"
     assert wacl["Id"] == web_acl_id
+    assert wacl["LabelNamespace"] == f"awswaf:{ACCOUNT_ID}:webacl:John:"
 
 
 @mock_aws
@@ -129,17 +179,23 @@ def test_list_web_acl():
 @mock_aws
 def test_delete_web_acl():
     conn = boto3.client("wafv2", region_name="us-east-1")
-    wacl_id = conn.create_web_acl(**CREATE_WEB_ACL_BODY("Daphne", "REGIONAL"))[
-        "Summary"
-    ]["Id"]
+    wacl = conn.create_web_acl(**CREATE_WEB_ACL_BODY("Daphne", "REGIONAL"))["Summary"]
 
-    conn.delete_web_acl(Name="Daphne", Id=wacl_id, Scope="REGIONAL", LockToken="n/a")
+    with pytest.raises(ClientError) as e:
+        conn.delete_web_acl(
+            Name="Daphne", Id=wacl["Id"], Scope="REGIONAL", LockToken="123"
+        )
+    assert e.value.response["Error"]["Code"] == "WAFOptimisticLockException"
+
+    conn.delete_web_acl(
+        Name="Daphne", Id=wacl["Id"], Scope="REGIONAL", LockToken=wacl["LockToken"]
+    )
 
     res = conn.list_web_acls(**LIST_WEB_ACL_BODY("REGIONAL"))
     assert len(res["WebACLs"]) == 0
 
     with pytest.raises(ClientError) as exc:
-        conn.get_web_acl(Name="Daphne", Scope="REGIONAL", Id=wacl_id)
+        conn.get_web_acl(Name="Daphne", Scope="REGIONAL", Id=wacl["Id"])
     err = exc.value.response["Error"]
     assert err["Code"] == "WAFNonexistentItemException"
     assert err["Message"] == (
@@ -150,14 +206,12 @@ def test_delete_web_acl():
 @mock_aws
 def test_update_web_acl():
     conn = boto3.client("wafv2", region_name="us-east-1")
-    wacl_id = conn.create_web_acl(**CREATE_WEB_ACL_BODY("Daphne", "REGIONAL"))[
-        "Summary"
-    ]["Id"]
+    wacl = conn.create_web_acl(**CREATE_WEB_ACL_BODY("Daphne", "REGIONAL"))["Summary"]
 
     resp = conn.update_web_acl(
         Name="Daphne",
         Scope="REGIONAL",
-        Id=wacl_id,
+        Id=wacl["Id"],
         DefaultAction={"Block": {"CustomResponse": {"ResponseCode": 412}}},
         Description="updated_desc",
         Rules=[
@@ -172,7 +226,7 @@ def test_update_web_acl():
                 },
             }
         ],
-        LockToken="n/a",
+        LockToken=wacl["LockToken"],
         VisibilityConfig={
             "SampledRequestsEnabled": True,
             "CloudWatchMetricsEnabled": True,
@@ -181,7 +235,22 @@ def test_update_web_acl():
     )
     assert "NextLockToken" in resp
 
-    acl = conn.get_web_acl(Name="Daphne", Scope="REGIONAL", Id=wacl_id)["WebACL"]
+    with pytest.raises(ClientError) as e:
+        conn.update_web_acl(
+            Name="Daphne",
+            Scope="REGIONAL",
+            Id=wacl["Id"],
+            DefaultAction={"Block": {"CustomResponse": {"ResponseCode": 412}}},
+            LockToken="123",
+            VisibilityConfig={
+                "SampledRequestsEnabled": True,
+                "CloudWatchMetricsEnabled": True,
+                "MetricName": "updated",
+            },
+        )
+    assert e.value.response["Error"]["Code"] == "WAFOptimisticLockException"
+
+    acl = conn.get_web_acl(Name="Daphne", Scope="REGIONAL", Id=wacl["Id"])["WebACL"]
     assert acl["Description"] == "updated_desc"
     assert acl["DefaultAction"] == {"Block": {"CustomResponse": {"ResponseCode": 412}}}
     assert acl["Rules"] == [
@@ -347,4 +416,4 @@ def test_logging_configuration_crud():
         wafv2_client.get_logging_configuration(
             ResourceArn=logging_configuration["ResourceArn"]
         )
-    e.value.response["Error"]["Code"] == "WAFNonexistentItemException"
+    assert e.value.response["Error"]["Code"] == "WAFNonexistentItemException"
diff --git a/tests/test_wafv2/test_wafv2_rules.py b/tests/test_wafv2/test_wafv2_rules.py
index 43e764d78..1d4f7fba2 100644
--- a/tests/test_wafv2/test_wafv2_rules.py
+++ b/tests/test_wafv2/test_wafv2_rules.py
@@ -1,10 +1,358 @@
 import boto3
+import pytest
+from botocore.exceptions import ClientError
 
 from moto import mock_aws
+from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
+from moto.utilities.utils import is_valid_uuid
+
+
+@mock_aws
+def test_create_rule_group():
+    client = boto3.client("wafv2", region_name="ap-southeast-1")
+    resp = client.create_rule_group(
+        Capacity=100,
+        Name="test-group",
+        Scope="REGIONAL",
+        VisibilityConfig={
+            "SampledRequestsEnabled": False,
+            "CloudWatchMetricsEnabled": False,
+            "MetricName": "test-group",
+        },
+    )["Summary"]
+    assert resp["ARN"].startswith(
+        f"arn:aws:wafv2:ap-southeast-1:{ACCOUNT_ID}:regional/rulegroup/test-group/"
+    )
+    assert resp["Name"] == "test-group"
+    assert resp["Description"] == ""
+    assert is_valid_uuid(resp["Id"])
+    assert is_valid_uuid(resp["LockToken"])
+    assert "VisibilityConfig" not in resp
+    assert "Rules" not in resp
+
+    with pytest.raises(ClientError) as e:
+        client.create_rule_group(
+            Capacity=100,
+            Name="test-group",
+            Scope="REGIONAL",
+            VisibilityConfig={
+                "SampledRequestsEnabled": False,
+                "CloudWatchMetricsEnabled": False,
+                "MetricName": "test-group",
+            },
+        )
+    assert e.value.response["Error"]["Code"] == "WafV2DuplicateItem"
+
+
+@mock_aws
+def test_update_rule_group():
+    client = boto3.client("wafv2", region_name="ap-southeast-1")
+    group = client.create_rule_group(
+        Capacity=100,
+        Name="test-group",
+        Scope="REGIONAL",
+        VisibilityConfig={
+            "SampledRequestsEnabled": False,
+            "CloudWatchMetricsEnabled": False,
+            "MetricName": "test-group",
+        },
+    )["Summary"]
+
+    test_rule = {
+        "Name": "test-rule",
+        "Priority": 0,
+        "Statement": {
+            "LabelMatchStatement": {
+                "Scope": "LABEL",
+                "Key": "testlabelmatch",
+            }
+        },
+        "Action": {
+            "Allow": {},
+        },
+        "VisibilityConfig": {
+            "SampledRequestsEnabled": True,
+            "CloudWatchMetricsEnabled": True,
+            "MetricName": "test-rule",
+        },
+        "CaptchaConfig": {
+            "ImmunityTimeProperty": {
+                "ImmunityTime": 60,
+            }
+        },
+        "ChallengeConfig": {
+            "ImmunityTimeProperty": {
+                "ImmunityTime": 60,
+            }
+        },
+        "OverrideAction": {
+            "Count": {},
+            "None": {},
+        },
+        "RuleLabels": [
+            {
+                "Name": "testlabel",
+            },
+        ],
+    }
+
+    resp = client.update_rule_group(
+        Name="test-group",
+        Scope="REGIONAL",
+        Id=group["Id"],
+        Rules=[
+            test_rule,
+        ],
+        LockToken=group["LockToken"],
+        VisibilityConfig={
+            "SampledRequestsEnabled": True,
+            "CloudWatchMetricsEnabled": True,
+            "MetricName": "new-metric",
+        },
+        Description="test",
+        CustomResponseBodies={
+            "Test": {
+                "Content": "ohmylookatthiscontent",
+                "ContentType": "TEXT_PLAIN",
+            },
+        },
+    )
+    assert (
+        is_valid_uuid(resp["NextLockToken"])
+        and resp["NextLockToken"] != group["LockToken"]
+    )
+    updated_group = client.get_rule_group(ARN=group["ARN"])["RuleGroup"]
+    assert updated_group["VisibilityConfig"] == {
+        "SampledRequestsEnabled": True,
+        "CloudWatchMetricsEnabled": True,
+        "MetricName": "new-metric",
+    }
+    assert updated_group["Description"] == "test"
+    assert updated_group["CustomResponseBodies"] == {
+        "Test": {
+            "Content": "ohmylookatthiscontent",
+            "ContentType": "TEXT_PLAIN",
+        },
+    }
+    assert updated_group["Rules"][0] == test_rule
+
+    with pytest.raises(ClientError) as e:
+        client.update_rule_group(
+            Name="test-group",
+            Scope="REGIONAL",
+            Id=group["Id"],
+            LockToken="123",
+            VisibilityConfig={
+                "SampledRequestsEnabled": False,
+                "CloudWatchMetricsEnabled": False,
+                "MetricName": "new-metric",
+            },
+        )
+    assert e.value.response["Error"]["Code"] == "WAFOptimisticLockException"
+
+    with pytest.raises(ClientError) as e:
+        client.update_rule_group(
+            Name="bad-group",
+            Scope="REGIONAL",
+            Id=group["Id"],
+            LockToken=group["LockToken"],
+            VisibilityConfig={
+                "SampledRequestsEnabled": False,
+                "CloudWatchMetricsEnabled": False,
+                "MetricName": "new-metric",
+            },
+        )
+    assert e.value.response["Error"]["Code"] == "WAFNonexistentItemException"
+
+
+@mock_aws
+def test_delete_rule_group():
+    client = boto3.client("wafv2", region_name="eu-west-1")
+    group = client.create_rule_group(
+        Capacity=100,
+        Name="test-group-1",
+        Scope="REGIONAL",
+        VisibilityConfig={
+            "SampledRequestsEnabled": False,
+            "CloudWatchMetricsEnabled": False,
+            "MetricName": "test-group-1",
+        },
+    )["Summary"]
+    with pytest.raises(ClientError) as e:
+        client.delete_rule_group(
+            Name="test-group-1",
+            Scope="CLOUDFRONT",
+            Id=group["Id"],
+            LockToken=group["LockToken"],
+        )
+    assert e.value.response["Error"]["Code"] == "WAFNonexistentItemException"
+
+    with pytest.raises(ClientError) as e:
+        client.delete_rule_group(
+            Name="test-group-1",
+            Scope="REGIONAL",
+            Id=group["Id"],
+            LockToken="1234567890",
+        )
+    assert e.value.response["Error"]["Code"] == "WAFOptimisticLockException"
+
+    assert len(client.list_rule_groups(Scope="REGIONAL")["RuleGroups"]) == 1
+    client.delete_rule_group(
+        Name="test-group-1",
+        Scope="REGIONAL",
+        Id=group["Id"],
+        LockToken=group["LockToken"],
+    )
+    assert len(client.list_rule_groups(Scope="REGIONAL")["RuleGroups"]) == 0
+
+
+@mock_aws
+def test_get_rule_group():
+    client = boto3.client("wafv2", region_name="us-east-2")
+    test_rule = {
+        "Name": "test-rule",
+        "Priority": 0,
+        "Statement": {
+            "LabelMatchStatement": {
+                "Scope": "LABEL",
+                "Key": "testlabelmatch",
+            }
+        },
+        "Action": {
+            "Allow": {},
+        },
+        "VisibilityConfig": {
+            "SampledRequestsEnabled": True,
+            "CloudWatchMetricsEnabled": True,
+            "MetricName": "test-rule",
+        },
+        "CaptchaConfig": {
+            "ImmunityTimeProperty": {
+                "ImmunityTime": 60,
+            }
+        },
+        "ChallengeConfig": {
+            "ImmunityTimeProperty": {
+                "ImmunityTime": 60,
+            }
+        },
+        "OverrideAction": {
+            "Count": {},
+            "None": {},
+        },
+        "RuleLabels": [
+            {
+                "Name": "testlabel",
+            },
+        ],
+    }
+
+    new_group = client.create_rule_group(
+        Capacity=100,
+        Name="test-group-all-params",
+        Description="test",
+        Scope="CLOUDFRONT",
+        VisibilityConfig={
+            "SampledRequestsEnabled": True,
+            "CloudWatchMetricsEnabled": True,
+            "MetricName": "test-group",
+        },
+        Rules=[
+            test_rule,
+        ],
+        CustomResponseBodies={
+            "Test": {
+                "Content": "ohmylookatthiscontent",
+                "ContentType": "TEXT_PLAIN",
+            },
+        },
+        Tags=[
+            {
+                "Key": "test-key",
+                "Value": "test-value",
+            },
+        ],
+    )["Summary"]
+    resp = client.get_rule_group(
+        Id=new_group["Id"], Scope="CLOUDFRONT", Name="test-group-all-params"
+    )
+    group = resp["RuleGroup"]
+    assert is_valid_uuid(resp["LockToken"])
+    assert is_valid_uuid(group["Id"])
+    assert group["ARN"] == new_group["ARN"]
+    assert group["Capacity"] == 100
+    assert group["CustomResponseBodies"] == {
+        "Test": {
+            "Content": "ohmylookatthiscontent",
+            "ContentType": "TEXT_PLAIN",
+        },
+    }
+    assert group["Description"] == "test"
+    assert group["Id"] == new_group["Id"]
+    assert group["Name"] == "test-group-all-params"
+    assert (
+        group["LabelNamespace"] == f"awswaf:{ACCOUNT_ID}:rulegroup:{new_group['Name']}:"
+    )
+    assert group["AvailableLabels"] == [{"Name": f"{group['LabelNamespace']}testlabel"}]
+    assert group["ConsumedLabels"] == [
+        {"Name": f"{group['LabelNamespace']}testlabelmatch"}
+    ]
+    assert group["Name"] == "test-group-all-params"
+    assert group["Rules"][0] == test_rule
+    assert group["VisibilityConfig"] == {
+        "SampledRequestsEnabled": True,
+        "CloudWatchMetricsEnabled": True,
+        "MetricName": "test-group",
+    }
+
+    with pytest.raises(ClientError) as e:
+        client.get_rule_group(
+            ARN=f"arn:aws:wafv2:ap-southeast-1:{ACCOUNT_ID}:regional/rulegroup/test-group/1234567890)"
+        )
+    assert e.value.response["Error"]["Code"] == "WAFNonexistentItemException"
+
+    with pytest.raises(ClientError) as e:
+        client.get_rule_group(Name="test-group")
+    assert e.value.response["Error"]["Code"] == "AcessDeniedException"
+    assert (
+        e.value.response["Error"]["Message"]
+        == "Critical information is missing in your request: GetRuleGroupRequest(name=test-group, scope=null, id=null, aRN=null)."
+    )
 
 
 @mock_aws
 def test_list_rule_groups():
     client = boto3.client("wafv2", region_name="us-east-2")
-    resp = client.list_rule_groups(Scope="CLOUDFRONT")
-    assert resp["RuleGroups"] == []
+    assert len(client.list_rule_groups(Scope="REGIONAL")["RuleGroups"]) == 0
+    regional_group = client.create_rule_group(
+        Capacity=100,
+        Name="test-group-1",
+        Scope="REGIONAL",
+        VisibilityConfig={
+            "SampledRequestsEnabled": False,
+            "CloudWatchMetricsEnabled": False,
+            "MetricName": "test-group-1",
+        },
+    )["Summary"]
+    cf_group = client.create_rule_group(
+        Capacity=100,
+        Name="test-group-2",
+        Scope="CLOUDFRONT",
+        VisibilityConfig={
+            "SampledRequestsEnabled": True,
+            "CloudWatchMetricsEnabled": True,
+            "MetricName": "test-group-2",
+        },
+    )["Summary"]
+
+    reg_groups = client.list_rule_groups(Scope="REGIONAL")["RuleGroups"]
+    cf_groups = client.list_rule_groups(Scope="CLOUDFRONT")["RuleGroups"]
+    assert len(reg_groups) == len(cf_groups) == 1
+    regional = reg_groups[0]
+    assert regional["ARN"] == regional_group["ARN"]
+    assert cf_groups[0]["ARN"] == cf_group["ARN"]
+    assert regional["Name"] == "test-group-1"
+    assert "Scope" not in regional
+    assert is_valid_uuid(regional["LockToken"])
+    assert is_valid_uuid(regional["Id"]) and regional["Id"] == regional_group["Id"]
+    assert "VisibilityConfig" not in regional