Added new functionality for EC2 (#4701)

This commit is contained in:
Simon Toftegaard Petersen 2021-12-19 15:27:23 +01:00 committed by GitHub
parent 82588b2638
commit cd0f0ee83c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 142 additions and 33 deletions

View File

@ -1185,7 +1185,7 @@
## ec2 ## ec2
<details> <details>
<summary>33% implemented</summary> <summary>34% implemented</summary>
- [ ] accept_reserved_instances_exchange_quote - [ ] accept_reserved_instances_exchange_quote
- [ ] accept_transit_gateway_multicast_domain_associations - [ ] accept_transit_gateway_multicast_domain_associations
@ -1510,7 +1510,7 @@
- [X] detach_network_interface - [X] detach_network_interface
- [X] detach_volume - [X] detach_volume
- [X] detach_vpn_gateway - [X] detach_vpn_gateway
- [ ] disable_ebs_encryption_by_default - [X] disable_ebs_encryption_by_default
- [ ] disable_fast_snapshot_restores - [ ] disable_fast_snapshot_restores
- [ ] disable_image_deprecation - [ ] disable_image_deprecation
- [ ] disable_ipam_organization_admin_account - [ ] disable_ipam_organization_admin_account
@ -1530,7 +1530,7 @@
- [X] disassociate_transit_gateway_route_table - [X] disassociate_transit_gateway_route_table
- [ ] disassociate_trunk_interface - [ ] disassociate_trunk_interface
- [X] disassociate_vpc_cidr_block - [X] disassociate_vpc_cidr_block
- [ ] enable_ebs_encryption_by_default - [X] enable_ebs_encryption_by_default
- [ ] enable_fast_snapshot_restores - [ ] enable_fast_snapshot_restores
- [ ] enable_image_deprecation - [ ] enable_image_deprecation
- [ ] enable_ipam_organization_admin_account - [ ] enable_ipam_organization_admin_account
@ -1552,7 +1552,7 @@
- [ ] get_console_screenshot - [ ] get_console_screenshot
- [ ] get_default_credit_specification - [ ] get_default_credit_specification
- [ ] get_ebs_default_kms_key_id - [ ] get_ebs_default_kms_key_id
- [ ] get_ebs_encryption_by_default - [X] get_ebs_encryption_by_default
- [ ] get_flow_logs_integration_template - [ ] get_flow_logs_integration_template
- [ ] get_groups_for_capacity_reservation - [ ] get_groups_for_capacity_reservation
- [ ] get_host_reservation_purchase_preview - [ ] get_host_reservation_purchase_preview

View File

@ -359,7 +359,7 @@ ec2
- [X] detach_network_interface - [X] detach_network_interface
- [X] detach_volume - [X] detach_volume
- [X] detach_vpn_gateway - [X] detach_vpn_gateway
- [ ] disable_ebs_encryption_by_default - [X] disable_ebs_encryption_by_default
- [ ] disable_fast_snapshot_restores - [ ] disable_fast_snapshot_restores
- [ ] disable_image_deprecation - [ ] disable_image_deprecation
- [ ] disable_ipam_organization_admin_account - [ ] disable_ipam_organization_admin_account
@ -379,7 +379,7 @@ ec2
- [X] disassociate_transit_gateway_route_table - [X] disassociate_transit_gateway_route_table
- [ ] disassociate_trunk_interface - [ ] disassociate_trunk_interface
- [X] disassociate_vpc_cidr_block - [X] disassociate_vpc_cidr_block
- [ ] enable_ebs_encryption_by_default - [X] enable_ebs_encryption_by_default
- [ ] enable_fast_snapshot_restores - [ ] enable_fast_snapshot_restores
- [ ] enable_image_deprecation - [ ] enable_image_deprecation
- [ ] enable_ipam_organization_admin_account - [ ] enable_ipam_organization_admin_account
@ -401,7 +401,7 @@ ec2
- [ ] get_console_screenshot - [ ] get_console_screenshot
- [ ] get_default_credit_specification - [ ] get_default_credit_specification
- [ ] get_ebs_default_kms_key_id - [ ] get_ebs_default_kms_key_id
- [ ] get_ebs_encryption_by_default - [X] get_ebs_encryption_by_default
- [ ] get_flow_logs_integration_template - [ ] get_flow_logs_integration_template
- [ ] get_groups_for_capacity_reservation - [ ] get_groups_for_capacity_reservation
- [ ] get_host_reservation_purchase_preview - [ ] get_host_reservation_purchase_preview

View File

@ -1,31 +1,21 @@
import copy import copy
from datetime import datetime
import itertools
import ipaddress import ipaddress
import itertools
import json import json
from operator import itemgetter
from os import listdir
from os import environ
import pathlib import pathlib
import re import re
import warnings import warnings
import weakref import weakref
from collections import defaultdict
from collections import OrderedDict from collections import OrderedDict
from collections import defaultdict
from datetime import datetime
from operator import itemgetter
from os import environ
from os import listdir
from boto3 import Session from boto3 import Session
from moto.packages.boto.ec2.instance import Instance as BotoInstance, Reservation from moto.core import ACCOUNT_ID
from moto.packages.boto.ec2.blockdevicemapping import (
BlockDeviceMapping,
BlockDeviceType,
)
from moto.packages.boto.ec2.spotinstancerequest import (
SpotInstanceRequest as BotoSpotRequest,
)
from moto.packages.boto.ec2.launchspecification import LaunchSpecification
from moto.core import BaseBackend from moto.core import BaseBackend
from moto.core.models import Model, BaseModel, CloudFormationModel from moto.core.models import Model, BaseModel, CloudFormationModel
from moto.core.utils import ( from moto.core.utils import (
@ -33,10 +23,17 @@ from moto.core.utils import (
camelcase_to_underscores, camelcase_to_underscores,
aws_api_matches, aws_api_matches,
) )
from moto.core import ACCOUNT_ID
from moto.kms import kms_backends from moto.kms import kms_backends
from moto.packages.boto.ec2.blockdevicemapping import (
BlockDeviceMapping,
BlockDeviceType,
)
from moto.packages.boto.ec2.instance import Instance as BotoInstance, Reservation
from moto.packages.boto.ec2.launchspecification import LaunchSpecification
from moto.packages.boto.ec2.spotinstancerequest import (
SpotInstanceRequest as BotoSpotRequest,
)
from moto.utilities.utils import load_resource, merge_multiple_dicts, filter_resources from moto.utilities.utils import load_resource, merge_multiple_dicts, filter_resources
from .exceptions import ( from .exceptions import (
CidrLimitExceeded, CidrLimitExceeded,
GenericInvalidParameterValueError, GenericInvalidParameterValueError,
@ -204,7 +201,6 @@ for location_type in listdir(root / offerings_path):
instance["LocationType"] = location_type instance["LocationType"] = location_type
INSTANCE_TYPE_OFFERINGS[location_type][_region.replace(".json", "")] = res INSTANCE_TYPE_OFFERINGS[location_type][_region.replace(".json", "")] = res
if "MOTO_AMIS_PATH" in environ: if "MOTO_AMIS_PATH" in environ:
with open(environ.get("MOTO_AMIS_PATH"), "r", encoding="utf-8") as f: with open(environ.get("MOTO_AMIS_PATH"), "r", encoding="utf-8") as f:
AMIS = json.load(f) AMIS = json.load(f)
@ -1485,6 +1481,24 @@ class KeyPairBackend(object):
return keypair return keypair
class SettingsBackend(object):
def __init__(self):
self.ebs_encryption_by_default = False
super().__init__()
def disable_ebs_encryption_by_default(self):
ec2_backend = ec2_backends[self.region_name]
ec2_backend.ebs_encryption_by_default = False
def enable_ebs_encryption_by_default(self):
ec2_backend = ec2_backends[self.region_name]
ec2_backend.ebs_encryption_by_default = True
def get_ebs_encryption_by_default(self):
ec2_backend = ec2_backends[self.region_name]
return ec2_backend.ebs_encryption_by_default
class TagBackend(object): class TagBackend(object):
VALID_TAG_FILTERS = ["key", "resource-id", "resource-type", "value"] VALID_TAG_FILTERS = ["key", "resource-id", "resource-type", "value"]
@ -7371,7 +7385,6 @@ class VpnGatewayBackend(object):
vpn_gateway = self.get_vpn_gateway(vpn_gateway_id) vpn_gateway = self.get_vpn_gateway(vpn_gateway_id)
detached = vpn_gateway.attachments.get(vpc_id, None) detached = vpn_gateway.attachments.get(vpc_id, None)
if not detached: if not detached:
raise InvalidVpnGatewayAttachmentError(vpn_gateway.id, vpc_id) raise InvalidVpnGatewayAttachmentError(vpn_gateway.id, vpc_id)
detached.state = "detached" detached.state = "detached"
return detached return detached
@ -7461,7 +7474,6 @@ class CustomerGatewayBackend(object):
class TransitGateway(TaggedEC2Resource, CloudFormationModel): class TransitGateway(TaggedEC2Resource, CloudFormationModel):
DEFAULT_OPTIONS = { DEFAULT_OPTIONS = {
"AmazonSideAsn": "64512", "AmazonSideAsn": "64512",
"AssociationDefaultRouteTableId": "tgw-rtb-0d571391e50cf8514", "AssociationDefaultRouteTableId": "tgw-rtb-0d571391e50cf8514",
@ -7833,7 +7845,6 @@ class TransitGatewayAttachment(TaggedEC2Resource):
def __init__( def __init__(
self, backend, resource_id, resource_type, transit_gateway_id, tags=None self, backend, resource_id, resource_type, transit_gateway_id, tags=None
): ):
self.ec2_backend = backend self.ec2_backend = backend
self.association = {} self.association = {}
self.propagation = {} self.propagation = {}
@ -7863,7 +7874,6 @@ class TransitGatewayAttachment(TaggedEC2Resource):
class TransitGatewayVpcAttachment(TransitGatewayAttachment): class TransitGatewayVpcAttachment(TransitGatewayAttachment):
DEFAULT_OPTIONS = { DEFAULT_OPTIONS = {
"ApplianceModeSupport": "disable", "ApplianceModeSupport": "disable",
"DnsSupport": "enable", "DnsSupport": "enable",
@ -7873,7 +7883,6 @@ class TransitGatewayVpcAttachment(TransitGatewayAttachment):
def __init__( def __init__(
self, backend, transit_gateway_id, vpc_id, subnet_ids, tags=None, options=None self, backend, transit_gateway_id, vpc_id, subnet_ids, tags=None, options=None
): ):
super().__init__( super().__init__(
backend=backend, backend=backend,
transit_gateway_id=transit_gateway_id, transit_gateway_id=transit_gateway_id,
@ -7898,7 +7907,6 @@ class TransitGatewayPeeringAttachment(TransitGatewayAttachment):
tags=None, tags=None,
region_name=None, region_name=None,
): ):
super().__init__( super().__init__(
backend=backend, backend=backend,
transit_gateway_id=transit_gateway_id, transit_gateway_id=transit_gateway_id,
@ -8626,6 +8634,7 @@ class EC2Backend(
SpotPriceBackend, SpotPriceBackend,
ElasticAddressBackend, ElasticAddressBackend,
KeyPairBackend, KeyPairBackend,
SettingsBackend,
DHCPOptionsSetBackend, DHCPOptionsSetBackend,
NetworkAclBackend, NetworkAclBackend,
VpnGatewayBackend, VpnGatewayBackend,

View File

@ -20,6 +20,7 @@ from .placement_groups import PlacementGroups
from .reserved_instances import ReservedInstances from .reserved_instances import ReservedInstances
from .route_tables import RouteTables from .route_tables import RouteTables
from .security_groups import SecurityGroups from .security_groups import SecurityGroups
from .settings import Settings
from .spot_fleets import SpotFleets from .spot_fleets import SpotFleets
from .spot_instances import SpotInstances from .spot_instances import SpotInstances
from .subnets import Subnets from .subnets import Subnets
@ -63,6 +64,7 @@ class EC2Response(
ReservedInstances, ReservedInstances,
RouteTables, RouteTables,
SecurityGroups, SecurityGroups,
Settings,
SpotFleets, SpotFleets,
SpotInstances, SpotInstances,
Subnets, Subnets,

View File

@ -0,0 +1,47 @@
from moto.core.responses import BaseResponse
class Settings(BaseResponse):
def disable_ebs_encryption_by_default(self):
if self.is_not_dryrun("DisableEbsEncryptionByDefault"):
self.ec2_backend.disable_ebs_encryption_by_default()
template = self.response_template(
DISABLE_EBS_ENCRYPTION_BY_DEFAULT_RESPONSE
)
return template.render(ebsEncryptionByDefault=False).replace(
"False", "false"
)
def enable_ebs_encryption_by_default(self):
if self.is_not_dryrun("EnableEbsEncryptionByDefault"):
self.ec2_backend.enable_ebs_encryption_by_default()
template = self.response_template(
ENABLED_EBS_ENCRYPTION_BY_DEFAULT_RESPONSE
)
return template.render(ebsEncryptionByDefault=True).replace("True", "true")
def get_ebs_encryption_by_default(self):
if self.is_not_dryrun("GetEbsEncryptionByDefault"):
result = self.ec2_backend.get_ebs_encryption_by_default()
template = self.response_template(GET_EBS_ENCRYPTION_BY_DEFAULT_RESPONSE)
return (
template.render(ebsEncryptionByDefault=result)
.replace("False", "false")
.replace("True", "true")
)
DISABLE_EBS_ENCRYPTION_BY_DEFAULT_RESPONSE = """<DisableEbsEncryptionByDefaultResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>418c3f8f-3a1c-45c8-b59e-3722797a6449Example</requestId>
<ebsEncryptionByDefault>{{ ebsEncryptionByDefault }}</ebsEncryptionByDefault>
</DisableEbsEncryptionByDefaultResponse>"""
ENABLED_EBS_ENCRYPTION_BY_DEFAULT_RESPONSE = """<EnableEbsEncryptionByDefaultResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>418c3f8f-3a1c-45c8-b59e-3722797a6449Example</requestId>
<ebsEncryptionByDefault>{{ ebsEncryptionByDefault }}</ebsEncryptionByDefault>
</EnableEbsEncryptionByDefaultResponse>"""
GET_EBS_ENCRYPTION_BY_DEFAULT_RESPONSE = """<GetEbsEncryptionByDefaultResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>418c3f8f-3a1c-45c8-b59e-3722797a6449Example</requestId>
<ebsEncryptionByDefault>{{ ebsEncryptionByDefault }}</ebsEncryptionByDefault>
</GetEbsEncryptionByDefaultResponse>"""

View File

@ -0,0 +1,51 @@
import logging
import boto3
import sure # noqa # pylint: disable=unused-import
from moto import mock_ec2
logger = logging.getLogger(__name__)
@mock_ec2
def test_disable_ebs_encryption_by_default():
ec2 = boto3.client("ec2", "eu-central-1")
ec2.enable_ebs_encryption_by_default()
response = ec2.get_ebs_encryption_by_default()
response.should.have.key("EbsEncryptionByDefault").equal(True)
ec2.disable_ebs_encryption_by_default()
after_disable_response = ec2.get_ebs_encryption_by_default()
after_disable_response.should.have.key("EbsEncryptionByDefault").equal(False)
@mock_ec2
def test_enable_ebs_encryption_by_default():
ec2 = boto3.client("ec2", region_name="eu-central-1")
response = ec2.enable_ebs_encryption_by_default()
ec2.get_ebs_encryption_by_default()
response.should.have.key("EbsEncryptionByDefault").equal(True)
@mock_ec2
def test_get_ebs_encryption_by_default():
ec2 = boto3.client("ec2", region_name="eu-west-1")
response = ec2.get_ebs_encryption_by_default()
response.should.have.key("EbsEncryptionByDefault").equal(False)
@mock_ec2
def test_enable_ebs_encryption_by_default_region():
ec2_eu = boto3.client("ec2", region_name="eu-central-1")
ec2_eu.enable_ebs_encryption_by_default()
response = ec2_eu.get_ebs_encryption_by_default()
response.should.have.key("EbsEncryptionByDefault").equal(True)
ec2_us = boto3.client("ec2", region_name="us-east-1")
response = ec2_us.get_ebs_encryption_by_default()
response.should.have.key("EbsEncryptionByDefault").equal(False)