diff --git a/moto/ec2/models.py b/moto/ec2/models.py index 87d2d59e5..6631706f1 100755 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -118,21 +118,18 @@ def validate_resource_ids(resource_ids): class InstanceState(object): - def __init__(self, name='pending', code=0): self.name = name self.code = code class StateReason(object): - def __init__(self, message="", code=""): self.message = message self.code = code class TaggedEC2Resource(BaseModel): - def get_tags(self, *args, **kwargs): tags = self.ec2_backend.describe_tags( filters={'resource-id': [self.id]}) @@ -164,7 +161,6 @@ class TaggedEC2Resource(BaseModel): class NetworkInterface(TaggedEC2Resource): - def __init__(self, ec2_backend, subnet, private_ip_address, device_index=0, public_ip_auto_assign=True, group_ids=None): self.ec2_backend = ec2_backend @@ -277,7 +273,6 @@ class NetworkInterface(TaggedEC2Resource): class NetworkInterfaceBackend(object): - def __init__(self): self.enis = {} super(NetworkInterfaceBackend, self).__init__() @@ -621,7 +616,6 @@ class Instance(TaggedEC2Resource, BotoInstance): class InstanceBackend(object): - def __init__(self): self.reservations = OrderedDict() super(InstanceBackend, self).__init__() @@ -791,7 +785,6 @@ class InstanceBackend(object): class KeyPairBackend(object): - def __init__(self): self.keypairs = defaultdict(dict) super(KeyPairBackend, self).__init__() @@ -830,7 +823,6 @@ class KeyPairBackend(object): class TagBackend(object): - VALID_TAG_FILTERS = ['key', 'resource-id', 'resource-type', @@ -957,7 +949,6 @@ class TagBackend(object): class Ami(TaggedEC2Resource): - def __init__(self, ec2_backend, ami_id, instance=None, source_ami=None, name=None, description=None): self.ec2_backend = ec2_backend @@ -1036,7 +1027,6 @@ class Ami(TaggedEC2Resource): class AmiBackend(object): - def __init__(self): self.amis = {} super(AmiBackend, self).__init__() @@ -1141,14 +1131,12 @@ class AmiBackend(object): class Region(object): - def __init__(self, name, endpoint): self.name = name self.endpoint = endpoint class Zone(object): - def __init__(self, name, region_name): self.name = name self.region_name = region_name @@ -1191,7 +1179,6 @@ class RegionsAndZonesBackend(object): class SecurityRule(object): - def __init__(self, ip_protocol, from_port, to_port, ip_ranges, source_groups): self.ip_protocol = ip_protocol self.from_port = from_port @@ -1214,7 +1201,6 @@ class SecurityRule(object): class SecurityGroup(TaggedEC2Resource): - def __init__(self, ec2_backend, group_id, name, description, vpc_id=None): self.ec2_backend = ec2_backend self.id = group_id @@ -1353,7 +1339,6 @@ class SecurityGroup(TaggedEC2Resource): class SecurityGroupBackend(object): - def __init__(self): # the key in the dict group is the vpc_id or None (non-vpc) self.groups = defaultdict(dict) @@ -1597,7 +1582,6 @@ class SecurityGroupBackend(object): class SecurityGroupIngress(object): - def __init__(self, security_group, properties): self.security_group = security_group self.properties = properties @@ -1656,7 +1640,6 @@ class SecurityGroupIngress(object): class VolumeAttachment(object): - def __init__(self, volume, instance, device, status): self.volume = volume self.attach_time = utc_date_and_time() @@ -1681,7 +1664,6 @@ class VolumeAttachment(object): class Volume(TaggedEC2Resource): - def __init__(self, ec2_backend, volume_id, size, zone, snapshot_id=None, encrypted=False): self.id = volume_id self.size = size @@ -1755,7 +1737,6 @@ class Volume(TaggedEC2Resource): class Snapshot(TaggedEC2Resource): - def __init__(self, ec2_backend, snapshot_id, volume, description, encrypted=False): self.id = snapshot_id self.volume = volume @@ -1799,7 +1780,6 @@ class Snapshot(TaggedEC2Resource): class EBSBackend(object): - def __init__(self): self.volumes = {} self.attachments = {} @@ -1916,7 +1896,6 @@ class EBSBackend(object): class VPC(TaggedEC2Resource): - def __init__(self, ec2_backend, vpc_id, cidr_block, is_default, instance_tenancy='default'): self.ec2_backend = ec2_backend self.id = vpc_id @@ -1972,7 +1951,6 @@ class VPC(TaggedEC2Resource): class VPCBackend(object): - def __init__(self): self.vpcs = {} super(VPCBackend, self).__init__() @@ -2015,7 +1993,7 @@ class VPCBackend(object): if len(route_tables) > 1: raise DependencyViolationError( "The vpc {0} has dependencies and cannot be deleted." - .format(vpc_id) + .format(vpc_id) ) for route_table in route_tables: self.delete_route_table(route_table.id) @@ -2052,7 +2030,6 @@ class VPCBackend(object): class VPCPeeringConnectionStatus(object): - def __init__(self, code='initiating-request', message=''): self.code = code self.message = message @@ -2075,7 +2052,6 @@ class VPCPeeringConnectionStatus(object): class VPCPeeringConnection(TaggedEC2Resource): - def __init__(self, vpc_pcx_id, vpc, peer_vpc): self.id = vpc_pcx_id self.vpc = vpc @@ -2100,7 +2076,6 @@ class VPCPeeringConnection(TaggedEC2Resource): class VPCPeeringConnectionBackend(object): - def __init__(self): self.vpc_pcxs = {} super(VPCPeeringConnectionBackend, self).__init__() @@ -2142,7 +2117,6 @@ class VPCPeeringConnectionBackend(object): class Subnet(TaggedEC2Resource): - def __init__(self, ec2_backend, subnet_id, vpc_id, cidr_block, availability_zone, default_for_az, map_public_ip_on_launch): self.ec2_backend = ec2_backend @@ -2226,7 +2200,6 @@ class Subnet(TaggedEC2Resource): class SubnetBackend(object): - def __init__(self): # maps availability zone to dict of (subnet_id, subnet) self.subnets = defaultdict(dict) @@ -2280,7 +2253,6 @@ class SubnetBackend(object): class SubnetRouteTableAssociation(object): - def __init__(self, route_table_id, subnet_id): self.route_table_id = route_table_id self.subnet_id = subnet_id @@ -2301,7 +2273,6 @@ class SubnetRouteTableAssociation(object): class SubnetRouteTableAssociationBackend(object): - def __init__(self): self.subnet_associations = {} super(SubnetRouteTableAssociationBackend, self).__init__() @@ -2315,7 +2286,6 @@ class SubnetRouteTableAssociationBackend(object): class RouteTable(TaggedEC2Resource): - def __init__(self, ec2_backend, route_table_id, vpc_id, main=False): self.ec2_backend = ec2_backend self.id = route_table_id @@ -2368,7 +2338,6 @@ class RouteTable(TaggedEC2Resource): class RouteTableBackend(object): - def __init__(self): self.route_tables = {} super(RouteTableBackend, self).__init__() @@ -2408,7 +2377,7 @@ class RouteTableBackend(object): if route_table.associations: raise DependencyViolationError( "The routeTable '{0}' has dependencies and cannot be deleted." - .format(route_table_id) + .format(route_table_id) ) self.route_tables.pop(route_table_id) return True @@ -2454,7 +2423,6 @@ class RouteTableBackend(object): class Route(object): - def __init__(self, route_table, destination_cidr_block, local=False, gateway=None, instance=None, interface=None, vpc_pcx=None): self.id = generate_route_id(route_table.id, destination_cidr_block) @@ -2489,7 +2457,6 @@ class Route(object): class RouteBackend(object): - def __init__(self): super(RouteBackend, self).__init__() @@ -2514,7 +2481,8 @@ class RouteBackend(object): instance=self.get_instance( instance_id) if instance_id else None, interface=None, - vpc_pcx=self.get_vpc_peering_connection(vpc_peering_connection_id) if vpc_peering_connection_id else None) + vpc_pcx=self.get_vpc_peering_connection( + vpc_peering_connection_id) if vpc_peering_connection_id else None) route_table.routes[route.id] = route return route @@ -2560,7 +2528,6 @@ class RouteBackend(object): class InternetGateway(TaggedEC2Resource): - def __init__(self, ec2_backend): self.ec2_backend = ec2_backend self.id = random_internet_gateway_id() @@ -2584,7 +2551,6 @@ class InternetGateway(TaggedEC2Resource): class InternetGatewayBackend(object): - def __init__(self): self.internet_gateways = {} super(InternetGatewayBackend, self).__init__() @@ -2613,7 +2579,7 @@ class InternetGatewayBackend(object): if igw.vpc: raise DependencyViolationError( "{0} is being utilized by {1}" - .format(internet_gateway_id, igw.vpc.id) + .format(internet_gateway_id, igw.vpc.id) ) self.internet_gateways.pop(internet_gateway_id) return True @@ -2639,7 +2605,6 @@ class InternetGatewayBackend(object): class VPCGatewayAttachment(BaseModel): - def __init__(self, gateway_id, vpc_id): self.gateway_id = gateway_id self.vpc_id = vpc_id @@ -2663,7 +2628,6 @@ class VPCGatewayAttachment(BaseModel): class VPCGatewayAttachmentBackend(object): - def __init__(self): self.gateway_attachments = {} super(VPCGatewayAttachmentBackend, self).__init__() @@ -2675,7 +2639,6 @@ class VPCGatewayAttachmentBackend(object): class SpotInstanceRequest(BotoSpotRequest, TaggedEC2Resource): - def __init__(self, ec2_backend, spot_request_id, price, image_id, type, valid_from, valid_until, launch_group, availability_zone_group, key_name, security_groups, user_data, instance_type, placement, @@ -2746,7 +2709,6 @@ class SpotInstanceRequest(BotoSpotRequest, TaggedEC2Resource): @six.add_metaclass(Model) class SpotRequestBackend(object): - def __init__(self): self.spot_instance_requests = {} super(SpotRequestBackend, self).__init__() @@ -2782,7 +2744,6 @@ class SpotRequestBackend(object): class SpotFleetLaunchSpec(object): - def __init__(self, ebs_optimized, group_set, iam_instance_profile, image_id, instance_type, key_name, monitoring, spot_price, subnet_id, user_data, weighted_capacity): @@ -2800,7 +2761,6 @@ class SpotFleetLaunchSpec(object): class SpotFleetRequest(TaggedEC2Resource): - def __init__(self, ec2_backend, spot_fleet_request_id, spot_price, target_capacity, iam_fleet_role, allocation_strategy, launch_specs): @@ -2857,7 +2817,8 @@ class SpotFleetRequest(TaggedEC2Resource): ] spot_fleet_request = ec2_backend.request_spot_fleet(spot_price, - target_capacity, iam_fleet_role, allocation_strategy, launch_specs) + target_capacity, iam_fleet_role, allocation_strategy, + launch_specs) return spot_fleet_request @@ -2913,7 +2874,6 @@ class SpotFleetRequest(TaggedEC2Resource): class SpotFleetBackend(object): - def __init__(self): self.spot_fleet_requests = {} super(SpotFleetBackend, self).__init__() @@ -2954,7 +2914,6 @@ class SpotFleetBackend(object): class ElasticAddress(object): - def __init__(self, domain): self.public_ip = random_ip() self.allocation_id = random_eip_allocation_id() if domain == "vpc" else None @@ -2995,7 +2954,6 @@ class ElasticAddress(object): class ElasticAddressBackend(object): - def __init__(self): self.addresses = [] super(ElasticAddressBackend, self).__init__() @@ -3102,7 +3060,6 @@ class ElasticAddressBackend(object): class DHCPOptionsSet(TaggedEC2Resource): - def __init__(self, ec2_backend, domain_name_servers=None, domain_name=None, ntp_servers=None, netbios_name_servers=None, netbios_node_type=None): @@ -3153,7 +3110,6 @@ class DHCPOptionsSet(TaggedEC2Resource): class DHCPOptionsSetBackend(object): - def __init__(self): self.dhcp_options_sets = {} super(DHCPOptionsSetBackend, self).__init__() @@ -3220,7 +3176,6 @@ class DHCPOptionsSetBackend(object): class VPNConnection(TaggedEC2Resource): - def __init__(self, ec2_backend, id, type, customer_gateway_id, vpn_gateway_id): self.ec2_backend = ec2_backend @@ -3236,7 +3191,6 @@ class VPNConnection(TaggedEC2Resource): class VPNConnectionBackend(object): - def __init__(self): self.vpn_connections = {} super(VPNConnectionBackend, self).__init__() @@ -3287,7 +3241,6 @@ class VPNConnectionBackend(object): class NetworkAclBackend(object): - def __init__(self): self.network_acls = {} super(NetworkAclBackend, self).__init__() @@ -3338,6 +3291,24 @@ class NetworkAclBackend(object): network_acl.network_acl_entries.append(network_acl_entry) return network_acl_entry + def delete_network_acl_entry(self, network_acl_id, rule_number, egress): + network_acl = self.get_network_acl(network_acl_id) + entry = next(entry for entry in network_acl.netword_acl_entries + if entry.egress == egress and entry.rule_number == rule_number) + if entry is not None: + network_acl.netword_acl_entries.remove(entry) + return entry + + def replace_network_acl_entry(self, network_acl_id, rule_number, protocol, rule_action, egress, + cidr_block, icmp_code, icmp_type, port_range_from, port_range_to): + + self.delete_network_acl_entry(network_acl_id, rule_number, egress) + network_acl_entry = self.create_network_acl_entry(network_acl_id, rule_number, + protocol, rule_action, egress, + cidr_block, icmp_code, icmp_type, + port_range_from, port_range_to) + return network_acl_entry + def replace_network_acl_association(self, association_id, network_acl_id): @@ -3369,7 +3340,6 @@ class NetworkAclBackend(object): class NetworkAclAssociation(object): - def __init__(self, ec2_backend, new_association_id, subnet_id, network_acl_id): self.ec2_backend = ec2_backend @@ -3381,7 +3351,6 @@ class NetworkAclAssociation(object): class NetworkAcl(TaggedEC2Resource): - def __init__(self, ec2_backend, network_acl_id, vpc_id, default=False): self.ec2_backend = ec2_backend self.id = network_acl_id @@ -3410,7 +3379,6 @@ class NetworkAcl(TaggedEC2Resource): class NetworkAclEntry(TaggedEC2Resource): - def __init__(self, ec2_backend, network_acl_id, rule_number, protocol, rule_action, egress, cidr_block, icmp_code, icmp_type, port_range_from, @@ -3429,7 +3397,6 @@ class NetworkAclEntry(TaggedEC2Resource): class VpnGateway(TaggedEC2Resource): - def __init__(self, ec2_backend, id, type): self.ec2_backend = ec2_backend self.id = id @@ -3439,7 +3406,6 @@ class VpnGateway(TaggedEC2Resource): class VpnGatewayAttachment(object): - def __init__(self, vpc_id, state): self.vpc_id = vpc_id self.state = state @@ -3447,7 +3413,6 @@ class VpnGatewayAttachment(object): class VpnGatewayBackend(object): - def __init__(self): self.vpn_gateways = {} super(VpnGatewayBackend, self).__init__() @@ -3491,7 +3456,6 @@ class VpnGatewayBackend(object): class CustomerGateway(TaggedEC2Resource): - def __init__(self, ec2_backend, id, type, ip_address, bgp_asn): self.ec2_backend = ec2_backend self.id = id @@ -3503,7 +3467,6 @@ class CustomerGateway(TaggedEC2Resource): class CustomerGatewayBackend(object): - def __init__(self): self.customer_gateways = {} super(CustomerGatewayBackend, self).__init__() @@ -3534,7 +3497,6 @@ class CustomerGatewayBackend(object): class NatGateway(object): - def __init__(self, backend, subnet_id, allocation_id): # public properties self.id = random_nat_gateway_id() @@ -3583,7 +3545,6 @@ class NatGateway(object): class NatGatewayBackend(object): - def __init__(self): self.nat_gateways = {} @@ -3609,7 +3570,6 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend, SpotRequestBackend, ElasticAddressBackend, KeyPairBackend, DHCPOptionsSetBackend, NetworkAclBackend, VpnGatewayBackend, CustomerGatewayBackend, NatGatewayBackend): - def __init__(self, region_name): super(EC2Backend, self).__init__() self.region_name = region_name diff --git a/moto/ec2/responses/network_acls.py b/moto/ec2/responses/network_acls.py index bf9833d13..6c89d72d1 100644 --- a/moto/ec2/responses/network_acls.py +++ b/moto/ec2/responses/network_acls.py @@ -39,8 +39,32 @@ class NetworkACLs(BaseResponse): return template.render() def delete_network_acl_entry(self): - raise NotImplementedError( - 'NetworkACLs(AmazonVPC).delete_network_acl_entry is not yet implemented') + network_acl_id = self.querystring.get('NetworkAclId')[0] + rule_number = self.querystring.get('RuleNumber')[0] + egress = self.querystring.get('Egress')[0] + self.ec2_backend.delete_network_acl(network_acl_id, rule_number, egress) + template = self.response_template(DELETE_NETWORK_ACL_ENTRY_RESPONSE) + return template.render() + + def replace_network_acl_entry(self): + network_acl_id = self.querystring.get('NetworkAclId')[0] + rule_number = self.querystring.get('RuleNumber')[0] + protocol = self.querystring.get('Protocol')[0] + rule_action = self.querystring.get('RuleAction')[0] + egress = self.querystring.get('Egress')[0] + cidr_block = self.querystring.get('CidrBlock')[0] + icmp_code = self.querystring.get('Icmp.Code', [None])[0] + icmp_type = self.querystring.get('Icmp.Type', [None])[0] + port_range_from = self.querystring.get('PortRange.From')[0] + port_range_to = self.querystring.get('PortRange.To')[0] + + self.ec2_backend.replace_network_acl_entry( + network_acl_id, rule_number, protocol, rule_action, + egress, cidr_block, icmp_code, icmp_type, + port_range_from, port_range_to) + + template = self.response_template(REPLACE_NETWORK_ACL_ENTRY_RESPONSE) + return template.render() def describe_network_acls(self): network_acl_ids = network_acl_ids_from_querystring(self.querystring) @@ -61,9 +85,7 @@ class NetworkACLs(BaseResponse): template = self.response_template(REPLACE_NETWORK_ACL_ASSOCIATION) return template.render(association=association) - def replace_network_acl_entry(self): - raise NotImplementedError( - 'NetworkACLs(AmazonVPC).replace_network_acl_entry is not yet implemented') + CREATE_NETWORK_ACL_RESPONSE = """ @@ -147,6 +169,13 @@ CREATE_NETWORK_ACL_ENTRY_RESPONSE = """ """ +REPLACE_NETWORK_ACL_ENTRY_RESPONSE = """ + + 59dbff89-35bd-4eac-99ed-be587EXAMPLE + true + +""" + REPLACE_NETWORK_ACL_ASSOCIATION = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE @@ -160,3 +189,10 @@ DELETE_NETWORK_ACL_ASSOCIATION = """ true """ + +DELETE_NETWORK_ACL_ENTRY_RESPONSE = """ + + 59dbff89-35bd-4eac-99ed-be587EXAMPLE + true + +""" \ No newline at end of file diff --git a/tests/test_ec2/test_network_acls.py b/tests/test_ec2/test_network_acls.py index 91158e0bf..fd2ec105e 100644 --- a/tests/test_ec2/test_network_acls.py +++ b/tests/test_ec2/test_network_acls.py @@ -62,6 +62,61 @@ def test_network_acl_entries(): entries[0].rule_action.should.equal('ALLOW') +@mock_ec2_deprecated +def test_delete_network_acl_entry(): + conn = boto.connect_vpc('the_key', 'the secret') + vpc = conn.create_vpc("10.0.0.0/16") + + network_acl = conn.create_network_acl(vpc.id) + + conn.create_network_acl_entry( + network_acl.id, 110, 6, + 'ALLOW', '0.0.0.0/0', False, + port_range_from='443', + port_range_to='443' + ) + conn.delete_network_acl_entry( + network_acl.id, 110, False + ) + + all_network_acls = conn.get_all_network_acls() + + test_network_acl = next(na for na in all_network_acls + if na.id == network_acl.id) + entries = test_network_acl.network_acl_entries + entries.should.have.length_of(0) + + +@mock_ec2_deprecated +def test_replace_network_acl_entry(): + conn = boto.connect_vpc('the_key', 'the secret') + vpc = conn.create_vpc("10.0.0.0/16") + + network_acl = conn.create_network_acl(vpc.id) + + conn.create_network_acl_entry( + network_acl.id, 110, 6, + 'ALLOW', '0.0.0.0/0', False, + port_range_from='443', + port_range_to='443' + ) + conn.replace_network_acl_entry( + network_acl.id, 110, -1, + 'DENY', '0.0.0.0/0', False, + port_range_from='22', + port_range_to='22' + ) + + all_network_acls = conn.get_all_network_acls() + + test_network_acl = next(na for na in all_network_acls + if na.id == network_acl.id) + entries = test_network_acl.network_acl_entries + entries.should.have.length_of(1) + entries[0].rule_number.should.equal('110') + entries[0].protocol.should.equal('-1') + entries[0].rule_action.should.equal('DENY') + @mock_ec2_deprecated def test_associate_new_network_acl_with_subnet(): conn = boto.connect_vpc('the_key', 'the secret')