Decentralize cloudformation naming responsibilities (#3201)

* #3127 - Decentralize CF naming responsibilities

* Decentralize CloudFormation naming responsibilities

* Update URLs in cloudformation_resource_type functions

* Fix flake8 errors

* Black formatting

* Add a bunch of imports to populate CloudFormationModel.__subclasses__

* Add noqa to s3 models import statement in cloudformation/parsing.py

* Black formatting

* Remove debugging print statement

Co-authored-by: Bert Blommers <info@bertblommers.nl>
This commit is contained in:
Adam Richie-Halford 2020-08-01 07:23:36 -07:00 committed by GitHub
commit 9a9a1d8413
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 717 additions and 208 deletions

View file

@ -22,7 +22,7 @@ from boto.ec2.launchspecification import LaunchSpecification
from moto.compat import OrderedDict
from moto.core import BaseBackend
from moto.core.models import Model, BaseModel
from moto.core.models import Model, BaseModel, CloudFormationModel
from moto.core.utils import (
iso_8601_datetime_with_milliseconds,
camelcase_to_underscores,
@ -219,7 +219,7 @@ class TaggedEC2Resource(BaseModel):
raise FilterNotImplementedError(filter_name, method_name)
class NetworkInterface(TaggedEC2Resource):
class NetworkInterface(TaggedEC2Resource, CloudFormationModel):
def __init__(
self,
ec2_backend,
@ -268,6 +268,15 @@ class NetworkInterface(TaggedEC2Resource):
if group:
self._group_set.append(group)
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinterface.html
return "AWS::EC2::NetworkInterface"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -454,7 +463,7 @@ class NetworkInterfaceBackend(object):
return generic_filter(filters, enis)
class Instance(TaggedEC2Resource, BotoInstance):
class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
VALID_ATTRIBUTES = {
"instanceType",
"kernel",
@ -621,6 +630,15 @@ class Instance(TaggedEC2Resource, BotoInstance):
formatted_ip, self.region_name
)
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-instance.html
return "AWS::EC2::Instance"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -1843,7 +1861,7 @@ class SecurityRule(object):
return True
class SecurityGroup(TaggedEC2Resource):
class SecurityGroup(TaggedEC2Resource, CloudFormationModel):
def __init__(self, ec2_backend, group_id, name, description, vpc_id=None):
self.ec2_backend = ec2_backend
self.id = group_id
@ -1861,6 +1879,15 @@ class SecurityGroup(TaggedEC2Resource):
if vpc and len(vpc.get_cidr_block_association_set(ipv6=True)) > 0:
self.egress_rules.append(SecurityRule("-1", None, None, [], []))
@staticmethod
def cloudformation_name_type():
return "GroupName"
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-securitygroup.html
return "AWS::EC2::SecurityGroup"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -2260,11 +2287,20 @@ class SecurityGroupBackend(object):
raise RulesPerSecurityGroupLimitExceededError
class SecurityGroupIngress(object):
class SecurityGroupIngress(CloudFormationModel):
def __init__(self, security_group, properties):
self.security_group = security_group
self.properties = properties
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-securitygroupingress.html
return "AWS::EC2::SecurityGroupIngress"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -2328,7 +2364,7 @@ class SecurityGroupIngress(object):
return cls(security_group, properties)
class VolumeAttachment(object):
class VolumeAttachment(CloudFormationModel):
def __init__(self, volume, instance, device, status):
self.volume = volume
self.attach_time = utc_date_and_time()
@ -2336,6 +2372,15 @@ class VolumeAttachment(object):
self.device = device
self.status = status
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volumeattachment.html
return "AWS::EC2::VolumeAttachment"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -2354,7 +2399,7 @@ class VolumeAttachment(object):
return attachment
class Volume(TaggedEC2Resource):
class Volume(TaggedEC2Resource, CloudFormationModel):
def __init__(
self, ec2_backend, volume_id, size, zone, snapshot_id=None, encrypted=False
):
@ -2367,6 +2412,15 @@ class Volume(TaggedEC2Resource):
self.ec2_backend = ec2_backend
self.encrypted = encrypted
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-volume.html
return "AWS::EC2::Volume"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -2623,7 +2677,7 @@ class EBSBackend(object):
return True
class VPC(TaggedEC2Resource):
class VPC(TaggedEC2Resource, CloudFormationModel):
def __init__(
self,
ec2_backend,
@ -2656,6 +2710,15 @@ class VPC(TaggedEC2Resource):
amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block,
)
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
return "AWS::EC2::VPC"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -3022,13 +3085,22 @@ class VPCPeeringConnectionStatus(object):
self.message = "Inactive"
class VPCPeeringConnection(TaggedEC2Resource):
class VPCPeeringConnection(TaggedEC2Resource, CloudFormationModel):
def __init__(self, vpc_pcx_id, vpc, peer_vpc):
self.id = vpc_pcx_id
self.vpc = vpc
self.peer_vpc = peer_vpc
self._status = VPCPeeringConnectionStatus()
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcpeeringconnection.html
return "AWS::EC2::VPCPeeringConnection"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -3114,7 +3186,7 @@ class VPCPeeringConnectionBackend(object):
return vpc_pcx
class Subnet(TaggedEC2Resource):
class Subnet(TaggedEC2Resource, CloudFormationModel):
def __init__(
self,
ec2_backend,
@ -3150,6 +3222,15 @@ class Subnet(TaggedEC2Resource):
self._unused_ips = set() # if instance is destroyed hold IP here for reuse
self._subnet_ips = {} # has IP: instance
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html
return "AWS::EC2::Subnet"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -3377,11 +3458,20 @@ class SubnetBackend(object):
raise InvalidParameterValueError(attr_name)
class SubnetRouteTableAssociation(object):
class SubnetRouteTableAssociation(CloudFormationModel):
def __init__(self, route_table_id, subnet_id):
self.route_table_id = route_table_id
self.subnet_id = subnet_id
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnetroutetableassociation.html
return "AWS::EC2::SubnetRouteTableAssociation"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -3411,7 +3501,7 @@ class SubnetRouteTableAssociationBackend(object):
return subnet_association
class RouteTable(TaggedEC2Resource):
class RouteTable(TaggedEC2Resource, CloudFormationModel):
def __init__(self, ec2_backend, route_table_id, vpc_id, main=False):
self.ec2_backend = ec2_backend
self.id = route_table_id
@ -3420,6 +3510,15 @@ class RouteTable(TaggedEC2Resource):
self.associations = {}
self.routes = {}
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html
return "AWS::EC2::RouteTable"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -3555,7 +3654,7 @@ class RouteTableBackend(object):
return self.associate_route_table(route_table_id, subnet_id)
class Route(object):
class Route(CloudFormationModel):
def __init__(
self,
route_table,
@ -3581,6 +3680,15 @@ class Route(object):
self.interface = interface
self.vpc_pcx = vpc_pcx
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html
return "AWS::EC2::Route"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -3748,12 +3856,21 @@ class RouteBackend(object):
return deleted
class InternetGateway(TaggedEC2Resource):
class InternetGateway(TaggedEC2Resource, CloudFormationModel):
def __init__(self, ec2_backend):
self.ec2_backend = ec2_backend
self.id = random_internet_gateway_id()
self.vpc = None
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html
return "AWS::EC2::InternetGateway"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -3826,11 +3943,20 @@ class InternetGatewayBackend(object):
return self.describe_internet_gateways(internet_gateway_ids=igw_ids)[0]
class VPCGatewayAttachment(BaseModel):
class VPCGatewayAttachment(CloudFormationModel):
def __init__(self, gateway_id, vpc_id):
self.gateway_id = gateway_id
self.vpc_id = vpc_id
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcgatewayattachment.html
return "AWS::EC2::VPCGatewayAttachment"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -4051,7 +4177,7 @@ class SpotFleetLaunchSpec(object):
self.weighted_capacity = float(weighted_capacity)
class SpotFleetRequest(TaggedEC2Resource):
class SpotFleetRequest(TaggedEC2Resource, CloudFormationModel):
def __init__(
self,
ec2_backend,
@ -4100,6 +4226,15 @@ class SpotFleetRequest(TaggedEC2Resource):
def physical_resource_id(self):
return self.id
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-spotfleet.html
return "AWS::EC2::SpotFleet"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -4323,7 +4458,7 @@ class SpotFleetBackend(object):
return True
class ElasticAddress(object):
class ElasticAddress(CloudFormationModel):
def __init__(self, domain, address=None):
if address:
self.public_ip = address
@ -4335,6 +4470,15 @@ class ElasticAddress(object):
self.eni = None
self.association_id = None
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-eip.html
return "AWS::EC2::EIP"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name
@ -5095,7 +5239,7 @@ class CustomerGatewayBackend(object):
return deleted
class NatGateway(object):
class NatGateway(CloudFormationModel):
def __init__(self, backend, subnet_id, allocation_id):
# public properties
self.id = random_nat_gateway_id()
@ -5133,6 +5277,15 @@ class NatGateway(object):
eips = self._backend.address_by_allocation([self.allocation_id])
return eips[0].public_ip
@staticmethod
def cloudformation_name_type():
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html
return "AWS::EC2::NatGateway"
@classmethod
def create_from_cloudformation_json(
cls, resource_name, cloudformation_json, region_name