diff --git a/CHANGELOG.md b/CHANGELOG.md index 4049f65ac..a242f2ce8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,41 @@ Moto Changelog Unreleased ----- +2.2.5 +----- + General: + * Python 3.9 is now officially supported + + New Methods: + * DynamoDB (API v20111205, now deprecated) + * UpdateItem + * EC2: + * modify_vpc_peering_connection_options() + * Glue: + * create_crawler() + * delete_crawler() + * get_crawler() + * get_crawlers() + * SSM: + * describe_document_permission() + * modify_document_permission() + + Miscellaneous: + * CloudFormation:create_stack() now has validation for an empty Outputs-parameter + * EC2 now returns errors in the correct format, fixing various bugs with `terraform destroy` + * EC2:authorize_security_group_egress() now returns the securityGroupRuleSet-attribute + * EC2:authorize_security_group_ingress() now returns the securityGroupRuleSet-attribute + * EC2:create_route() now supports the EgressOnlyInternetGatewayId-parameter + * EC2:create_route_table() now adds an IPv6-route when enabled + * EC2:describe_security_groups() now returns the ipv6Ranges-attribute + * EC2:describe_vpc_peering_connection() now supports the VpcPeeringConnectionIds-parameter + * Organisations:detach_policy() now actually detaches a policy - before it was essentially a no-op + * Route53:create_health_check() now supports the CallerReference-parameter + * Route53:create_health_check() now support default values for integer-parameters such as Port/RequestInterval/FailureThreshold + * Route53:create_health_check() now supports several additional parameters such as MeasureLatency/Inverted/Disabled/EnableSNI/ChildHealthChecks + * SQS:create_queue() now supports the queue-attributes FifoThroughputLimit and DeduplicationScope + + 2.2.4 ----- New Methods: diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md index c9ae8b4af..11eb6375e 100644 --- a/IMPLEMENTATION_COVERAGE.md +++ b/IMPLEMENTATION_COVERAGE.md @@ -975,19 +975,26 @@ - [ ] create_backup_plan - [ ] create_backup_selection - [ ] create_backup_vault +- [ ] create_framework +- [ ] create_report_plan - [ ] delete_backup_plan - [ ] delete_backup_selection - [ ] delete_backup_vault - [ ] delete_backup_vault_access_policy - [ ] delete_backup_vault_notifications +- [ ] delete_framework - [ ] delete_recovery_point +- [ ] delete_report_plan - [ ] describe_backup_job - [ ] describe_backup_vault - [ ] describe_copy_job +- [ ] describe_framework - [ ] describe_global_settings - [ ] describe_protected_resource - [ ] describe_recovery_point - [ ] describe_region_settings +- [ ] describe_report_job +- [ ] describe_report_plan - [ ] describe_restore_job - [ ] disassociate_recovery_point - [ ] export_backup_plan_template @@ -1006,23 +1013,29 @@ - [ ] list_backup_selections - [ ] list_backup_vaults - [ ] list_copy_jobs +- [ ] list_frameworks - [ ] list_protected_resources - [ ] list_recovery_points_by_backup_vault - [ ] list_recovery_points_by_resource +- [ ] list_report_jobs +- [ ] list_report_plans - [ ] list_restore_jobs - [ ] list_tags - [ ] put_backup_vault_access_policy - [ ] put_backup_vault_notifications - [ ] start_backup_job - [ ] start_copy_job +- [ ] start_report_job - [ ] start_restore_job - [ ] stop_backup_job - [ ] tag_resource - [ ] untag_resource - [ ] update_backup_plan +- [ ] update_framework - [ ] update_global_settings - [ ] update_recovery_point_lifecycle - [ ] update_region_settings +- [ ] update_report_plan ## batch @@ -2438,6 +2451,7 @@ - [ ] get_ec2_instance_recommendations - [ ] get_ec2_recommendation_projected_metrics - [ ] get_enrollment_status +- [ ] get_enrollment_statuses_for_organization - [ ] get_lambda_function_recommendations - [ ] get_recommendation_summaries - [ ] update_enrollment_status @@ -3393,7 +3407,7 @@ ## ec2
-32% implemented +34% implemented - [ ] accept_reserved_instances_exchange_quote - [ ] accept_transit_gateway_multicast_domain_associations @@ -3609,15 +3623,15 @@ - [X] describe_instance_credit_specifications - [ ] describe_instance_event_notification_attributes - [ ] describe_instance_event_windows -- [ ] describe_instance_status +- [X] describe_instance_status - [X] describe_instance_type_offerings - [X] describe_instance_types -- [ ] describe_instances +- [X] describe_instances - [X] describe_internet_gateways - [ ] describe_ipv6_pools - [X] describe_key_pairs - [ ] describe_launch_template_versions -- [ ] describe_launch_templates +- [X] describe_launch_templates - [ ] describe_local_gateway_route_table_virtual_interface_group_associations - [ ] describe_local_gateway_route_table_vpc_associations - [ ] describe_local_gateway_route_tables @@ -3626,7 +3640,7 @@ - [ ] describe_local_gateways - [X] describe_managed_prefix_lists - [ ] describe_moving_addresses -- [ ] describe_nat_gateways +- [X] describe_nat_gateways - [X] describe_network_acls - [ ] describe_network_insights_analyses - [ ] describe_network_insights_paths @@ -3643,7 +3657,7 @@ - [ ] describe_reserved_instances_listings - [ ] describe_reserved_instances_modifications - [ ] describe_reserved_instances_offerings -- [ ] describe_route_tables +- [X] describe_route_tables - [ ] describe_scheduled_instance_availability - [ ] describe_scheduled_instances - [ ] describe_security_group_references @@ -3671,7 +3685,7 @@ - [X] describe_transit_gateway_peering_attachments - [ ] describe_transit_gateway_route_tables - [X] describe_transit_gateway_vpc_attachments -- [ ] describe_transit_gateways +- [X] describe_transit_gateways - [ ] describe_trunk_interface_associations - [ ] describe_volume_attribute - [ ] describe_volume_status @@ -3685,11 +3699,11 @@ - [ ] describe_vpc_endpoint_service_configurations - [ ] describe_vpc_endpoint_service_permissions - [ ] describe_vpc_endpoint_services -- [ ] describe_vpc_endpoints -- [ ] describe_vpc_peering_connections -- [ ] describe_vpcs +- [X] describe_vpc_endpoints +- [X] describe_vpc_peering_connections +- [X] describe_vpcs - [X] describe_vpn_connections -- [ ] describe_vpn_gateways +- [X] describe_vpn_gateways - [ ] detach_classic_link_vpc - [X] detach_internet_gateway - [X] detach_network_interface @@ -4904,13 +4918,14 @@ ## glue
-7% implemented +6% implemented - [ ] batch_create_partition - [ ] batch_delete_connection - [ ] batch_delete_partition - [ ] batch_delete_table - [ ] batch_delete_table_version +- [ ] batch_get_blueprints - [ ] batch_get_crawlers - [ ] batch_get_dev_endpoints - [ ] batch_get_jobs @@ -4921,6 +4936,7 @@ - [ ] batch_update_partition - [ ] cancel_ml_task_run - [ ] check_schema_version_validity +- [ ] create_blueprint - [ ] create_classifier - [ ] create_connection - [X] create_crawler @@ -4938,6 +4954,7 @@ - [ ] create_trigger - [ ] create_user_defined_function - [ ] create_workflow +- [ ] delete_blueprint - [ ] delete_classifier - [ ] delete_column_statistics_for_partition - [ ] delete_column_statistics_for_table @@ -4959,6 +4976,9 @@ - [ ] delete_trigger - [ ] delete_user_defined_function - [ ] delete_workflow +- [ ] get_blueprint +- [ ] get_blueprint_run +- [ ] get_blueprint_runs - [ ] get_catalog_import_status - [ ] get_classifier - [ ] get_classifiers @@ -5012,6 +5032,7 @@ - [ ] get_workflow_run_properties - [ ] get_workflow_runs - [ ] import_catalog_to_glue +- [ ] list_blueprints - [ ] list_crawlers - [ ] list_dev_endpoints - [ ] list_jobs @@ -5031,6 +5052,7 @@ - [ ] reset_job_bookmark - [ ] resume_workflow_run - [ ] search_tables +- [ ] start_blueprint_run - [ ] start_crawler - [ ] start_crawler_schedule - [ ] start_export_labels_task_run @@ -5046,6 +5068,7 @@ - [ ] stop_workflow_run - [ ] tag_resource - [ ] untag_resource +- [ ] update_blueprint - [ ] update_classifier - [ ] update_column_statistics_for_partition - [ ] update_column_statistics_for_table @@ -5862,11 +5885,13 @@ ## iot-data
-80% implemented +57% implemented - [X] delete_thing_shadow +- [ ] get_retained_message - [X] get_thing_shadow - [ ] list_named_shadows_for_thing +- [ ] list_retained_messages - [X] publish - [X] update_thing_shadow
@@ -11117,7 +11142,7 @@ ## transcribe
-22% implemented +20% implemented - [ ] create_call_analytics_category - [ ] create_language_model @@ -11145,12 +11170,15 @@ - [ ] list_language_models - [X] list_medical_transcription_jobs - [X] list_medical_vocabularies +- [ ] list_tags_for_resource - [ ] list_transcription_jobs - [ ] list_vocabularies - [ ] list_vocabulary_filters - [ ] start_call_analytics_job - [X] start_medical_transcription_job - [ ] start_transcription_job +- [ ] tag_resource +- [ ] untag_resource - [ ] update_call_analytics_category - [ ] update_medical_vocabulary - [ ] update_vocabulary diff --git a/README.md b/README.md index 65699cf5a..305290306 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ It gets even better! Moto isn't just for Python code and it isn't just for S3. L | Config | @mock_config | basic + core endpoints done | | | Data Pipeline | @mock_datapipeline | basic endpoints done | | | DynamoDB | @mock_dynamodb | core endpoints done | API 20111205. Deprecated. | -| DynamoDB2 | @mock_dynamodb2 | all endpoints + partial indexes | API 20120810 (Latest) | +| DynamoDB2 | @mock_dynamodb2 | core endpoints done | API 20120810 (Latest) | | EC2 | @mock_ec2 | core endpoints done | | | - AMI | | core endpoints done | | | - EBS | | core endpoints done | | diff --git a/moto/ec2/models.py b/moto/ec2/models.py index e23801f3c..509c2ad7c 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -1147,6 +1147,17 @@ class InstanceBackend(object): reservations = filter_reservations(reservations, filters) return reservations + def describe_instances(self, filters=None): + return self.all_reservations(filters) + + def describe_instance_status(self, instance_ids, include_all_instances, filters): + if instance_ids: + return self.get_multi_instances_by_id(instance_ids, filters) + elif include_all_instances: + return self.all_instances(filters) + else: + return self.all_running_instances(filters) + def all_reservations(self, filters=None): reservations = [ copy.copy(reservation) for reservation in self.reservations.values() @@ -3265,7 +3276,7 @@ class VPCBackend(object): match_vpc = vpcs.get_vpc(vpc_id) return match_vpc - def get_all_vpcs(self, vpc_ids=None, filters=None): + def describe_vpcs(self, vpc_ids=None, filters=None): matches = self.vpcs.values() if vpc_ids: matches = [vpc for vpc in matches if vpc.id in vpc_ids] @@ -3278,7 +3289,7 @@ class VPCBackend(object): def delete_vpc(self, vpc_id): # Delete route table if only main route table remains. - route_tables = self.get_all_route_tables(filters={"vpc-id": vpc_id}) + route_tables = self.describe_route_tables(filters={"vpc-id": vpc_id}) if len(route_tables) > 1: raise DependencyViolationError( "The vpc {0} has dependencies and cannot be deleted.".format(vpc_id) @@ -3429,7 +3440,7 @@ class VPCBackend(object): vpc_endpoint.state = "deleted" return True - def get_vpc_end_point(self, vpc_end_point_ids, filters=None): + def describe_vpc_endpoints(self, vpc_end_point_ids, filters=None): vpc_end_points = self.vpc_end_points.values() if vpc_end_point_ids: @@ -3563,7 +3574,7 @@ class VPCPeeringConnectionBackend(object): vpc_pcx_cx.vpc_pcxs[vpc_pcx_id] = vpc_pcx return vpc_pcx - def get_all_vpc_peering_connections(self, vpc_peering_ids=None): + def describe_vpc_peering_connections(self, vpc_peering_ids=None): if vpc_peering_ids: return [pcx for pcx in self.vpc_pcxs.values() if pcx.id in vpc_peering_ids] return self.vpc_pcxs.values() @@ -4355,7 +4366,7 @@ class RouteTableBackend(object): raise InvalidRouteTableIdError(route_table_id) return route_table - def get_all_route_tables(self, route_table_ids=None, filters=None): + def describe_route_tables(self, route_table_ids=None, filters=None): route_tables = self.route_tables.values() if route_table_ids: @@ -4387,7 +4398,7 @@ class RouteTableBackend(object): def associate_route_table(self, route_table_id, gateway_id=None, subnet_id=None): # Idempotent if association already exists. - route_tables_by_subnet = self.get_all_route_tables( + route_tables_by_subnet = self.describe_route_tables( filters={"association.subnet-id": [subnet_id]} ) if route_tables_by_subnet: @@ -4422,7 +4433,7 @@ class RouteTableBackend(object): return association_id # Find route table which currently has the association, error if none. - route_tables_by_association_id = self.get_all_route_tables( + route_tables_by_association_id = self.describe_route_tables( filters={"association.route-table-association-id": [association_id]} ) if not route_tables_by_association_id: @@ -6246,7 +6257,7 @@ class VpnGatewayBackend(object): self.vpn_gateways[vpn_gateway_id] = vpn_gateway return vpn_gateway - def get_all_vpn_gateways(self, filters=None): + def describe_vpn_gateways(self, filters=None): vpn_gateways = self.vpn_gateways.values() return generic_filter(filters, vpn_gateways) @@ -6438,7 +6449,7 @@ class TransitGatewayBackend(object): self.transit_gateways[transit_gateway.id] = transit_gateway return transit_gateway - def get_all_transit_gateways(self, filters): + def describe_transit_gateways(self, filters): transit_gateways = list(self.transit_gateways.values()) attr_pairs = ( @@ -7209,7 +7220,7 @@ class NatGatewayBackend(object): self.nat_gateways = {} super(NatGatewayBackend, self).__init__() - def get_all_nat_gateways(self, filters): + def describe_nat_gateways(self, filters): nat_gateways = self.nat_gateways.values() if filters is not None: @@ -7342,7 +7353,7 @@ class LaunchTemplateBackend(object): def get_launch_template_by_name(self, name): return self.get_launch_template(self.launch_template_name_to_ids[name]) - def get_launch_templates( + def describe_launch_templates( self, template_names=None, template_ids=None, filters=None ): if template_names and not template_ids: diff --git a/moto/ec2/responses/instances.py b/moto/ec2/responses/instances.py index d85cef099..ca17e8bfd 100644 --- a/moto/ec2/responses/instances.py +++ b/moto/ec2/responses/instances.py @@ -24,7 +24,7 @@ class InstanceResponse(BaseResponse): instance_ids, filters=filter_dict ) else: - reservations = self.ec2_backend.all_reservations(filters=filter_dict) + reservations = self.ec2_backend.describe_instances(filters=filter_dict) reservation_ids = [reservation.id for reservation in reservations] if token: @@ -129,14 +129,9 @@ class InstanceResponse(BaseResponse): for f in filters ] - if instance_ids: - instances = self.ec2_backend.get_multi_instances_by_id( - instance_ids, filters - ) - elif include_all_instances: - instances = self.ec2_backend.all_instances(filters) - else: - instances = self.ec2_backend.all_running_instances(filters) + instances = self.ec2_backend.describe_instance_status( + instance_ids, include_all_instances, filters + ) template = self.response_template(EC2_INSTANCE_STATUS) return template.render(instances=instances) diff --git a/moto/ec2/responses/launch_templates.py b/moto/ec2/responses/launch_templates.py index 0d803f164..874c84a13 100644 --- a/moto/ec2/responses/launch_templates.py +++ b/moto/ec2/responses/launch_templates.py @@ -261,7 +261,7 @@ class LaunchTemplates(BaseResponse): tree = ElementTree.Element("DescribeLaunchTemplatesResponse") templates_node = ElementTree.SubElement(tree, "launchTemplates") - templates = self.ec2_backend.get_launch_templates( + templates = self.ec2_backend.describe_launch_templates( template_names=template_names, template_ids=template_ids, filters=filters, diff --git a/moto/ec2/responses/nat_gateways.py b/moto/ec2/responses/nat_gateways.py index 7c77bbb44..e61a726a5 100644 --- a/moto/ec2/responses/nat_gateways.py +++ b/moto/ec2/responses/nat_gateways.py @@ -28,7 +28,7 @@ class NatGateways(BaseResponse): def describe_nat_gateways(self): filters = filters_from_querystring(self.querystring) - nat_gateways = self.ec2_backend.get_all_nat_gateways(filters) + nat_gateways = self.ec2_backend.describe_nat_gateways(filters) template = self.response_template(DESCRIBE_NAT_GATEWAYS_RESPONSE) return template.render(nat_gateways=nat_gateways) diff --git a/moto/ec2/responses/route_tables.py b/moto/ec2/responses/route_tables.py index cea1c5043..14c733445 100644 --- a/moto/ec2/responses/route_tables.py +++ b/moto/ec2/responses/route_tables.py @@ -70,7 +70,7 @@ class RouteTables(BaseResponse): def describe_route_tables(self): route_table_ids = self._get_multi_param("RouteTableId") filters = filters_from_querystring(self.querystring) - route_tables = self.ec2_backend.get_all_route_tables(route_table_ids, filters) + route_tables = self.ec2_backend.describe_route_tables(route_table_ids, filters) template = self.response_template(DESCRIBE_ROUTE_TABLES_RESPONSE) return template.render(route_tables=route_tables) diff --git a/moto/ec2/responses/transit_gateways.py b/moto/ec2/responses/transit_gateways.py index 0de9ef586..fa3449bd5 100644 --- a/moto/ec2/responses/transit_gateways.py +++ b/moto/ec2/responses/transit_gateways.py @@ -40,7 +40,7 @@ class TransitGateways(BaseResponse): def describe_transit_gateways(self): filters = filters_from_querystring(self.querystring) - transit_gateways = self.ec2_backend.get_all_transit_gateways(filters) + transit_gateways = self.ec2_backend.describe_transit_gateways(filters) template = self.response_template(DESCRIBE_TRANSIT_GATEWAY_RESPONSE) return template.render(transit_gateways=transit_gateways) diff --git a/moto/ec2/responses/virtual_private_gateways.py b/moto/ec2/responses/virtual_private_gateways.py index 1686134b1..71960f27e 100644 --- a/moto/ec2/responses/virtual_private_gateways.py +++ b/moto/ec2/responses/virtual_private_gateways.py @@ -36,7 +36,7 @@ class VirtualPrivateGateways(BaseResponse): def describe_vpn_gateways(self): filters = filters_from_querystring(self.querystring) - vpn_gateways = self.ec2_backend.get_all_vpn_gateways(filters) + vpn_gateways = self.ec2_backend.describe_vpn_gateways(filters) template = self.response_template(DESCRIBE_VPN_GATEWAYS_RESPONSE) return template.render(vpn_gateways=vpn_gateways) diff --git a/moto/ec2/responses/vpc_peering_connections.py b/moto/ec2/responses/vpc_peering_connections.py index f645415e5..89d5035ce 100644 --- a/moto/ec2/responses/vpc_peering_connections.py +++ b/moto/ec2/responses/vpc_peering_connections.py @@ -30,7 +30,9 @@ class VPCPeeringConnections(BaseResponse): def describe_vpc_peering_connections(self): ids = self._get_multi_param("VpcPeeringConnectionId") - vpc_pcxs = self.ec2_backend.get_all_vpc_peering_connections(vpc_peering_ids=ids) + vpc_pcxs = self.ec2_backend.describe_vpc_peering_connections( + vpc_peering_ids=ids + ) template = self.response_template(DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE) return template.render(vpc_pcxs=vpc_pcxs) diff --git a/moto/ec2/responses/vpcs.py b/moto/ec2/responses/vpcs.py index 224f6d850..ca9985b47 100644 --- a/moto/ec2/responses/vpcs.py +++ b/moto/ec2/responses/vpcs.py @@ -42,7 +42,7 @@ class VPCs(BaseResponse): def describe_vpcs(self): vpc_ids = self._get_multi_param("VpcId") filters = filters_from_querystring(self.querystring) - vpcs = self.ec2_backend.get_all_vpcs(vpc_ids=vpc_ids, filters=filters) + vpcs = self.ec2_backend.describe_vpcs(vpc_ids=vpc_ids, filters=filters) doc_date = ( "2013-10-15" if "Boto/" in self.headers.get("user-agent", "") @@ -69,7 +69,7 @@ class VPCs(BaseResponse): def describe_vpc_classic_link_dns_support(self): vpc_ids = self._get_multi_param("VpcIds") filters = filters_from_querystring(self.querystring) - vpcs = self.ec2_backend.get_all_vpcs(vpc_ids=vpc_ids, filters=filters) + vpcs = self.ec2_backend.describe_vpcs(vpc_ids=vpc_ids, filters=filters) doc_date = self._get_doc_date() template = self.response_template( DESCRIBE_VPC_CLASSIC_LINK_DNS_SUPPORT_RESPONSE @@ -101,7 +101,7 @@ class VPCs(BaseResponse): def describe_vpc_classic_link(self): vpc_ids = self._get_multi_param("VpcId") filters = filters_from_querystring(self.querystring) - vpcs = self.ec2_backend.get_all_vpcs(vpc_ids=vpc_ids, filters=filters) + vpcs = self.ec2_backend.describe_vpcs(vpc_ids=vpc_ids, filters=filters) doc_date = self._get_doc_date() template = self.response_template(DESCRIBE_VPC_CLASSIC_LINK_RESPONSE) return template.render(vpcs=vpcs, doc_date=doc_date) @@ -212,7 +212,7 @@ class VPCs(BaseResponse): def describe_vpc_endpoints(self): vpc_end_points_ids = self._get_multi_param("VpcEndpointId") filters = filters_from_querystring(self.querystring) - vpc_end_points = self.ec2_backend.get_vpc_end_point( + vpc_end_points = self.ec2_backend.describe_vpc_endpoints( vpc_end_point_ids=vpc_end_points_ids, filters=filters ) template = self.response_template(DESCRIBE_VPC_ENDPOINT_RESPONSE)