diff --git a/moto/ec2/exceptions.py b/moto/ec2/exceptions.py index e7328ff1d..677d2f939 100644 --- a/moto/ec2/exceptions.py +++ b/moto/ec2/exceptions.py @@ -481,6 +481,14 @@ class CidrLimitExceeded(EC2ClientError): ) +class UnsupportedTenancy(EC2ClientError): + def __init__(self, tenancy): + super(UnsupportedTenancy, self).__init__( + "UnsupportedTenancy", + "The tenancy value {0} is not supported.".format(tenancy), + ) + + class OperationNotPermitted(EC2ClientError): def __init__(self, association_id): super(OperationNotPermitted, self).__init__( diff --git a/moto/ec2/models.py b/moto/ec2/models.py index 72232b9eb..88be042d9 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -38,6 +38,7 @@ from os import listdir from .exceptions import ( CidrLimitExceeded, + UnsupportedTenancy, DependencyViolationError, EC2ClientError, FilterNotImplementedError, @@ -2941,6 +2942,10 @@ class VPC(TaggedEC2Resource, CloudFormationModel): amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block, ) + @property + def owner_id(self): + return ACCOUNT_ID + @staticmethod def cloudformation_name_type(): return None @@ -3011,11 +3016,25 @@ class VPC(TaggedEC2Resource, CloudFormationModel): else: return super(VPC, self).get_filter_value(filter_name, "DescribeVpcs") + def modify_vpc_tenancy(self, tenancy): + if tenancy != "default": + raise UnsupportedTenancy(tenancy) + self.instance_tenancy = tenancy + return True + def associate_vpc_cidr_block( self, cidr_block, amazon_provided_ipv6_cidr_block=False ): max_associations = 5 if not amazon_provided_ipv6_cidr_block else 1 + for cidr in self.cidr_block_association_set.copy(): + if ( + self.cidr_block_association_set.get(cidr) + .get("cidr_block_state") + .get("state") + == "disassociated" + ): + self.cidr_block_association_set.pop(cidr) if ( len(self.get_cidr_block_association_set(amazon_provided_ipv6_cidr_block)) >= max_associations @@ -3199,6 +3218,10 @@ class VPCBackend(object): else: raise InvalidParameterValueError(attr_name) + def modify_vpc_tenancy(self, vpc_id, tenancy): + vpc = self.get_vpc(vpc_id) + return vpc.modify_vpc_tenancy(tenancy) + def enable_vpc_classic_link(self, vpc_id): vpc = self.get_vpc(vpc_id) return vpc.enable_vpc_classic_link() diff --git a/moto/ec2/responses/vpcs.py b/moto/ec2/responses/vpcs.py index cc553fd3b..06ebce63f 100644 --- a/moto/ec2/responses/vpcs.py +++ b/moto/ec2/responses/vpcs.py @@ -51,6 +51,13 @@ class VPCs(BaseResponse): template = self.response_template(DESCRIBE_VPCS_RESPONSE) return template.render(vpcs=vpcs, doc_date=doc_date) + def modify_vpc_tenancy(self): + vpc_id = self._get_param("VpcId") + tenancy = self._get_param("InstanceTenancy") + value = self.ec2_backend.modify_vpc_tenancy(vpc_id, tenancy) + template = self.response_template(MODIFY_VPC_TENANCY_RESPONSE) + return template.render(value=value) + def describe_vpc_attribute(self): vpc_id = self._get_param("VpcId") attribute = self._get_param("Attribute") @@ -245,6 +252,7 @@ CREATE_VPC_RESPONSE = """ {% endif %} {% if vpc.dhcp_options %}{{ vpc.dhcp_options.id }}{% else %}dopt-1a2b3c4d2{% endif %} {{ vpc.instance_tenancy }} + {{ vpc.owner_id }} {% for tag in vpc.get_tags() %} @@ -344,6 +352,7 @@ DESCRIBE_VPCS_RESPONSE = """ {% if vpc.dhcp_options %}{{ vpc.dhcp_options.id }}{% else %}dopt-7a8b9c2d{% endif %} {{ vpc.instance_tenancy }} {{ vpc.is_default }} + {{ vpc.owner_id }} {% for tag in vpc.get_tags() %} @@ -366,6 +375,13 @@ DELETE_VPC_RESPONSE = """ """ +MODIFY_VPC_TENANCY_RESPONSE = """ + + 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE + true + +""" + DESCRIBE_VPC_ATTRIBUTE_RESPONSE = """ 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE diff --git a/tests/terraform-tests.success.txt b/tests/terraform-tests.success.txt index 2b1fad552..f32629ca2 100644 --- a/tests/terraform-tests.success.txt +++ b/tests/terraform-tests.success.txt @@ -61,3 +61,4 @@ TestAccAWSSsmParameterDataSource TestAccAWSUserGroupMembership TestAccAWSUserPolicyAttachment TestAccAWSUserSSHKey +TestAccAWSVpc_ \ No newline at end of file