Add tagging to all applicable EC2 objects. Closes #66.
This commit is contained in:
parent
06481ebe7e
commit
955b4c6c4a
@ -36,7 +36,13 @@ class InstanceState(object):
|
|||||||
self.code = code
|
self.code = code
|
||||||
|
|
||||||
|
|
||||||
class Instance(BotoInstance):
|
class TaggedEC2Instance(object):
|
||||||
|
def get_tags(self, *args, **kwargs):
|
||||||
|
tags = ec2_backend.describe_tags(self.id)
|
||||||
|
return tags
|
||||||
|
|
||||||
|
|
||||||
|
class Instance(BotoInstance, TaggedEC2Instance):
|
||||||
def __init__(self, image_id, user_data, security_groups, **kwargs):
|
def __init__(self, image_id, user_data, security_groups, **kwargs):
|
||||||
super(Instance, self).__init__()
|
super(Instance, self).__init__()
|
||||||
self.id = random_instance_id()
|
self.id = random_instance_id()
|
||||||
@ -86,10 +92,6 @@ class Instance(BotoInstance):
|
|||||||
self._state.name = "running"
|
self._state.name = "running"
|
||||||
self._state.code = 16
|
self._state.code = 16
|
||||||
|
|
||||||
def get_tags(self, *args, **kwargs):
|
|
||||||
tags = ec2_backend.describe_tags(self.id)
|
|
||||||
return tags
|
|
||||||
|
|
||||||
|
|
||||||
class InstanceBackend(object):
|
class InstanceBackend(object):
|
||||||
|
|
||||||
@ -267,7 +269,7 @@ class TagBackend(object):
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
class Ami(object):
|
class Ami(TaggedEC2Instance):
|
||||||
def __init__(self, ami_id, instance, name, description):
|
def __init__(self, ami_id, instance, name, description):
|
||||||
self.id = ami_id
|
self.id = ami_id
|
||||||
self.instance = instance
|
self.instance = instance
|
||||||
@ -657,7 +659,7 @@ class EBSBackend(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class VPC(object):
|
class VPC(TaggedEC2Instance):
|
||||||
def __init__(self, vpc_id, cidr_block):
|
def __init__(self, vpc_id, cidr_block):
|
||||||
self.id = vpc_id
|
self.id = vpc_id
|
||||||
self.cidr_block = cidr_block
|
self.cidr_block = cidr_block
|
||||||
@ -703,7 +705,7 @@ class VPCBackend(object):
|
|||||||
return vpc
|
return vpc
|
||||||
|
|
||||||
|
|
||||||
class Subnet(object):
|
class Subnet(TaggedEC2Instance):
|
||||||
def __init__(self, subnet_id, vpc_id, cidr_block):
|
def __init__(self, subnet_id, vpc_id, cidr_block):
|
||||||
self.id = subnet_id
|
self.id = subnet_id
|
||||||
self.vpc_id = vpc_id
|
self.vpc_id = vpc_id
|
||||||
@ -1061,7 +1063,7 @@ class ElasticAddressBackend(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class DHCPOptionsSet(object):
|
class DHCPOptionsSet(TaggedEC2Instance):
|
||||||
def __init__(self, domain_name_servers=None, domain_name=None,
|
def __init__(self, domain_name_servers=None, domain_name=None,
|
||||||
ntp_servers=None, netbios_name_servers=None,
|
ntp_servers=None, netbios_name_servers=None,
|
||||||
netbios_node_type=None):
|
netbios_node_type=None):
|
||||||
@ -1071,7 +1073,7 @@ class DHCPOptionsSet(object):
|
|||||||
"ntp-servers": ntp_servers,
|
"ntp-servers": ntp_servers,
|
||||||
"netbios-name-servers": netbios_name_servers,
|
"netbios-name-servers": netbios_name_servers,
|
||||||
"netbios-node-type": netbios_node_type,
|
"netbios-node-type": netbios_node_type,
|
||||||
}
|
}
|
||||||
self.id = random_dhcp_option_id()
|
self.id = random_dhcp_option_id()
|
||||||
self.vpc = None
|
self.vpc = None
|
||||||
|
|
||||||
@ -1113,7 +1115,7 @@ class DHCPOptionsSetBackend(object):
|
|||||||
if options_id in self.dhcp_options_sets:
|
if options_id in self.dhcp_options_sets:
|
||||||
if self.dhcp_options_sets[options_id].vpc:
|
if self.dhcp_options_sets[options_id].vpc:
|
||||||
raise DependencyViolationError("Cannot delete assigned DHCP options.")
|
raise DependencyViolationError("Cannot delete assigned DHCP options.")
|
||||||
dhcp_opt = self.dhcp_options_sets.pop(options_id)
|
self.dhcp_options_sets.pop(options_id)
|
||||||
else:
|
else:
|
||||||
raise InvalidDHCPOptionsIdError(options_id)
|
raise InvalidDHCPOptionsIdError(options_id)
|
||||||
return True
|
return True
|
||||||
|
@ -92,7 +92,16 @@ DESCRIBE_IMAGES_RESPONSE = """<DescribeImagesResponse xmlns="http://ec2.amazonaw
|
|||||||
</item>
|
</item>
|
||||||
</blockDeviceMapping>
|
</blockDeviceMapping>
|
||||||
<virtualizationType>{{ image.virtualization_type }}</virtualizationType>
|
<virtualizationType>{{ image.virtualization_type }}</virtualizationType>
|
||||||
<tagSet/>
|
<tagSet>
|
||||||
|
{% for tag in image.get_tags() %}
|
||||||
|
<item>
|
||||||
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
<hypervisor>xen</hypervisor>
|
<hypervisor>xen</hypervisor>
|
||||||
</item>
|
</item>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -6,8 +6,8 @@ from moto.ec2.utils import (
|
|||||||
from moto.ec2.models import ec2_backend
|
from moto.ec2.models import ec2_backend
|
||||||
from moto.ec2.exceptions import(
|
from moto.ec2.exceptions import(
|
||||||
InvalidVPCIdError,
|
InvalidVPCIdError,
|
||||||
InvalidParameterValueError
|
InvalidParameterValueError,
|
||||||
)
|
)
|
||||||
|
|
||||||
NETBIOS_NODE_TYPES = [1, 2, 4, 8]
|
NETBIOS_NODE_TYPES = [1, 2, 4, 8]
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class DHCPOptions(BaseResponse):
|
|||||||
ntp_servers=ntp_servers,
|
ntp_servers=ntp_servers,
|
||||||
netbios_name_servers=netbios_name_servers,
|
netbios_name_servers=netbios_name_servers,
|
||||||
netbios_node_type=netbios_node_type
|
netbios_node_type=netbios_node_type
|
||||||
)
|
)
|
||||||
|
|
||||||
template = Template(CREATE_DHCP_OPTIONS_RESPONSE)
|
template = Template(CREATE_DHCP_OPTIONS_RESPONSE)
|
||||||
return template.render(dhcp_options_set=dhcp_options_set)
|
return template.render(dhcp_options_set=dhcp_options_set)
|
||||||
@ -105,7 +105,16 @@ CREATE_DHCP_OPTIONS_RESPONSE = u"""
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</dhcpConfigurationSet>
|
</dhcpConfigurationSet>
|
||||||
<tagSet/>
|
<tagSet>
|
||||||
|
{% for tag in dhcp_options_set.get_tags() %}
|
||||||
|
<item>
|
||||||
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
</dhcpOptions>
|
</dhcpOptions>
|
||||||
</CreateDhcpOptionsResponse>
|
</CreateDhcpOptionsResponse>
|
||||||
"""
|
"""
|
||||||
@ -141,7 +150,16 @@ DESCRIBE_DHCP_OPTIONS_RESPONSE = u"""
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</dhcpConfigurationSet>
|
</dhcpConfigurationSet>
|
||||||
<tagSet/>
|
<tagSet>
|
||||||
|
{% for tag in dhcp_options_set.get_tags() %}
|
||||||
|
<item>
|
||||||
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
</dhcpOptions>
|
</dhcpOptions>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</item>
|
</item>
|
||||||
|
@ -37,7 +37,16 @@ CREATE_SUBNET_RESPONSE = """
|
|||||||
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
||||||
<availableIpAddressCount>251</availableIpAddressCount>
|
<availableIpAddressCount>251</availableIpAddressCount>
|
||||||
<availabilityZone>us-east-1a</availabilityZone>
|
<availabilityZone>us-east-1a</availabilityZone>
|
||||||
<tagSet/>
|
<tagSet>
|
||||||
|
{% for tag in subnet.get_tags() %}
|
||||||
|
<item>
|
||||||
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
</subnet>
|
</subnet>
|
||||||
</CreateSubnetResponse>"""
|
</CreateSubnetResponse>"""
|
||||||
|
|
||||||
@ -59,7 +68,16 @@ DESCRIBE_SUBNETS_RESPONSE = """
|
|||||||
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
||||||
<availableIpAddressCount>251</availableIpAddressCount>
|
<availableIpAddressCount>251</availableIpAddressCount>
|
||||||
<availabilityZone>us-east-1a</availabilityZone>
|
<availabilityZone>us-east-1a</availabilityZone>
|
||||||
<tagSet/>
|
<tagSet>
|
||||||
|
{% for tag in subnet.get_tags() %}
|
||||||
|
<item>
|
||||||
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
</item>
|
</item>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</subnetSet>
|
</subnetSet>
|
||||||
|
@ -35,7 +35,16 @@ CREATE_VPC_RESPONSE = """
|
|||||||
<cidrBlock>{{ vpc.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ vpc.cidr_block }}</cidrBlock>
|
||||||
<dhcpOptionsId>dopt-1a2b3c4d2</dhcpOptionsId>
|
<dhcpOptionsId>dopt-1a2b3c4d2</dhcpOptionsId>
|
||||||
<instanceTenancy>default</instanceTenancy>
|
<instanceTenancy>default</instanceTenancy>
|
||||||
<tagSet/>
|
<tagSet>
|
||||||
|
{% for tag in vpc.get_tags() %}
|
||||||
|
<item>
|
||||||
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
</vpc>
|
</vpc>
|
||||||
</CreateVpcResponse>"""
|
</CreateVpcResponse>"""
|
||||||
|
|
||||||
@ -50,7 +59,16 @@ DESCRIBE_VPCS_RESPONSE = """
|
|||||||
<cidrBlock>{{ vpc.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ vpc.cidr_block }}</cidrBlock>
|
||||||
<dhcpOptionsId>dopt-7a8b9c2d</dhcpOptionsId>
|
<dhcpOptionsId>dopt-7a8b9c2d</dhcpOptionsId>
|
||||||
<instanceTenancy>default</instanceTenancy>
|
<instanceTenancy>default</instanceTenancy>
|
||||||
<tagSet/>
|
<tagSet>
|
||||||
|
{% for tag in vpc.get_tags() %}
|
||||||
|
<item>
|
||||||
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
</item>
|
</item>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</vpcSet>
|
</vpcSet>
|
||||||
|
@ -22,6 +22,26 @@ def test_ami_create_and_delete():
|
|||||||
success = conn.deregister_image.when.called_with(image).should.throw(EC2ResponseError)
|
success = conn.deregister_image.when.called_with(image).should.throw(EC2ResponseError)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_ami_tagging():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
|
instance = reservation.instances[0]
|
||||||
|
conn.create_image(instance.id, "test-ami", "this is a test ami")
|
||||||
|
image = conn.get_all_images()[0]
|
||||||
|
|
||||||
|
image.add_tag("a key", "some value")
|
||||||
|
|
||||||
|
tag = conn.get_all_tags()[0]
|
||||||
|
tag.name.should.equal("a key")
|
||||||
|
tag.value.should.equal("some value")
|
||||||
|
|
||||||
|
# Refresh the DHCP options
|
||||||
|
image = conn.get_all_images()[0]
|
||||||
|
image.tags.should.have.length_of(1)
|
||||||
|
image.tags["a key"].should.equal("some value")
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_ami_create_from_missing_instance():
|
def test_ami_create_from_missing_instance():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
@ -114,5 +114,22 @@ def test_delete_dhcp_options():
|
|||||||
def test_delete_dhcp_options_invalid_id():
|
def test_delete_dhcp_options_invalid_id():
|
||||||
conn = boto.connect_vpc('the_key', 'the_secret')
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
|
||||||
dhcp_option = conn.create_dhcp_options()
|
conn.create_dhcp_options()
|
||||||
conn.delete_dhcp_options.when.called_with("1").should.throw(EC2ResponseError)
|
conn.delete_dhcp_options.when.called_with("1").should.throw(EC2ResponseError)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_dhcp_tagging():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
dhcp_option = conn.create_dhcp_options()
|
||||||
|
|
||||||
|
dhcp_option.add_tag("a key", "some value")
|
||||||
|
|
||||||
|
tag = conn.get_all_tags()[0]
|
||||||
|
tag.name.should.equal("a key")
|
||||||
|
tag.value.should.equal("some value")
|
||||||
|
|
||||||
|
# Refresh the DHCP options
|
||||||
|
dhcp_option = conn.get_all_dhcp_options()[0]
|
||||||
|
dhcp_option.tags.should.have.length_of(1)
|
||||||
|
dhcp_option.tags["a key"].should.equal("some value")
|
||||||
|
@ -21,3 +21,21 @@ def test_subnets():
|
|||||||
|
|
||||||
conn.delete_subnet.when.called_with(
|
conn.delete_subnet.when.called_with(
|
||||||
subnet.id).should.throw(EC2ResponseError)
|
subnet.id).should.throw(EC2ResponseError)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_subnet_tagging():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
vpc = conn.create_vpc("10.0.0.0/16")
|
||||||
|
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
|
||||||
|
|
||||||
|
subnet.add_tag("a key", "some value")
|
||||||
|
|
||||||
|
tag = conn.get_all_tags()[0]
|
||||||
|
tag.name.should.equal("a key")
|
||||||
|
tag.value.should.equal("some value")
|
||||||
|
|
||||||
|
# Refresh the subnet
|
||||||
|
subnet = conn.get_all_subnets()[0]
|
||||||
|
subnet.tags.should.have.length_of(1)
|
||||||
|
subnet.tags["a key"].should.equal("some value")
|
||||||
|
@ -21,3 +21,20 @@ def test_vpcs():
|
|||||||
|
|
||||||
conn.delete_vpc.when.called_with(
|
conn.delete_vpc.when.called_with(
|
||||||
"vpc-1234abcd").should.throw(EC2ResponseError)
|
"vpc-1234abcd").should.throw(EC2ResponseError)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_vpc_tagging():
|
||||||
|
conn = boto.connect_vpc()
|
||||||
|
vpc = conn.create_vpc("10.0.0.0/16")
|
||||||
|
|
||||||
|
vpc.add_tag("a key", "some value")
|
||||||
|
|
||||||
|
tag = conn.get_all_tags()[0]
|
||||||
|
tag.name.should.equal("a key")
|
||||||
|
tag.value.should.equal("some value")
|
||||||
|
|
||||||
|
# Refresh the vpc
|
||||||
|
vpc = conn.get_all_vpcs()[0]
|
||||||
|
vpc.tags.should.have.length_of(1)
|
||||||
|
vpc.tags["a key"].should.equal("some value")
|
||||||
|
Loading…
Reference in New Issue
Block a user