def test_init(self): """test __init__()""" cls = _Ec2Service(21, 43) assert cls.service_name == 'EC2' assert cls.conn is None assert cls.warning_threshold == 21 assert cls.critical_threshold == 43
def test_get_limits_instances(self): cls = _Ec2Service(21, 43) limits = cls._get_limits_instances() assert len(limits) == 55 # check a random subset of limits t2_micro = limits['Running On-Demand t2.micro instances'] assert t2_micro.default_limit == 20 assert t2_micro.limit_type == 'On-Demand instances' assert t2_micro.limit_subtype == 't2.micro' c4_8xlarge = limits['Running On-Demand c4.8xlarge instances'] assert c4_8xlarge.default_limit == 5 assert c4_8xlarge.limit_type == 'On-Demand instances' assert c4_8xlarge.limit_subtype == 'c4.8xlarge' i2_8xlarge = limits['Running On-Demand i2.8xlarge instances'] assert i2_8xlarge.default_limit == 2 assert i2_8xlarge.limit_type == 'On-Demand instances' assert i2_8xlarge.limit_subtype == 'i2.8xlarge' all_ec2 = limits['Running On-Demand EC2 instances'] assert all_ec2.default_limit == 20 assert all_ec2.limit_type == 'On-Demand instances' assert all_ec2.limit_subtype is None assert 'Running On-Demand m4.4xlarge instances' in limits for lname, lim in limits.items(): assert lim.limit_type == 'On-Demand instances' itype = lim.limit_subtype if itype is not None: assert lname == 'Running On-Demand %s instances' % itype assert lim.ta_limit_name == 'On-Demand instances - %s' % itype
def test_find_usage_spot_fleets_unknown_error(self): mock_client_conn = Mock() mock_client_conn.describe_spot_fleet_requests.side_effect = RuntimeError cls = _Ec2Service(21, 43) cls.conn = mock_client_conn with pytest.raises(RuntimeError): cls._find_usage_spot_fleets()
def test_find_usage_networking_eni_sg(self): mocks = fixtures.test_find_usage_networking_eni_sg mock_conn = Mock() mock_conn.network_interfaces.all.return_value = mocks cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_networking_eni_sg() assert mock_logger.mock_calls == [ call.debug("Getting usage for EC2 Network Interfaces"), ] limit = cls.limits['VPC security groups per elastic network interface'] sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 3 assert sorted_usage[0].limit == limit assert sorted_usage[0].resource_id == 'if-1' assert sorted_usage[0].get_value() == 0 assert sorted_usage[1].limit == limit assert sorted_usage[1].resource_id == 'if-2' assert sorted_usage[1].get_value() == 3 assert sorted_usage[2].limit == limit assert sorted_usage[2].resource_id == 'if-3' assert sorted_usage[2].get_value() == 8 assert mock_conn.mock_calls == [call.network_interfaces.all()]
def test_find_usage_instances_key_error(self): mock_inst1A = Mock(spec_set=Instance) type(mock_inst1A).id = '1A' type(mock_inst1A).instance_type = 'foobar' type(mock_inst1A).spot_instance_request_id = None mock_res1 = Mock(spec_set=Reservation) type(mock_res1).instances = [mock_inst1A] mock_conn = Mock(spec_set=EC2Connection) return_value = [mock_res1] cls = _Ec2Service(21, 43) cls.conn = mock_conn cls.limits = {'Running On-Demand t2.micro instances': Mock()} with patch('%s._instance_types' % self.pb, autospec=True) as mock_itypes: with patch('awslimitchecker.services.ec2.logger') as mock_logger: with patch('%s.boto_query_wrapper' % self.pbm) as mock_wrapper: mock_wrapper.return_value = return_value mock_itypes.return_value = ['t2.micro'] cls._instance_usage() assert mock_logger.mock_calls == [ call.debug('Getting usage for on-demand instances'), call.error("ERROR - unknown instance type '%s'; not counting", 'foobar'), ] assert mock_conn.mock_calls == [] assert mock_wrapper.mock_calls == [ call(mock_conn.get_all_reservations) ]
def test_get_reserved_instance_count(self): response = fixtures.test_get_reserved_instance_count cls = _Ec2Service(21, 43) mock_client_conn = Mock() cls.conn = mock_client_conn mock_client_conn.describe_reserved_instances.return_value = response mock_conn = Mock() cls.resource_conn = mock_conn res = cls._get_reserved_instance_count() assert res == { 'az1': { 'it1': 10, }, 'az2': { 'it2': 98, }, RI_NO_AZ: { 'it2': 9, 'it3': 6 } } assert mock_conn.mock_calls == [] assert mock_client_conn.mock_calls == [ call.describe_reserved_instances() ]
def test_find_usage_instances_key_error(self): mock_inst1A = Mock(spec_set=Instance) type(mock_inst1A).id = '1A' type(mock_inst1A).instance_type = 'foobar' type(mock_inst1A).spot_instance_request_id = None mock_res1 = Mock(spec_set=Reservation) type(mock_res1).instances = [mock_inst1A] mock_conn = Mock(spec_set=EC2Connection) return_value = [mock_res1] cls = _Ec2Service(21, 43) cls.conn = mock_conn cls.limits = {'Running On-Demand t2.micro instances': Mock()} with patch( '%s._instance_types' % self.pb, autospec=True) as mock_itypes: with patch('awslimitchecker.services.ec2.logger') as mock_logger: with patch('%s.boto_query_wrapper' % self.pbm) as mock_wrapper: mock_wrapper.return_value = return_value mock_itypes.return_value = ['t2.micro'] cls._instance_usage() assert mock_logger.mock_calls == [ call.debug('Getting usage for on-demand instances'), call.error("ERROR - unknown instance type '%s'; not counting", 'foobar'), ] assert mock_conn.mock_calls == [] assert mock_wrapper.mock_calls == [call(mock_conn.get_all_reservations)]
def test_find_usage_networking_eni_sg(self): mocks = fixtures.test_find_usage_networking_eni_sg mock_conn = Mock() mock_conn.network_interfaces.all.return_value = mocks cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_networking_eni_sg() assert mock_logger.mock_calls == [ call.debug("Getting usage for EC2 Network Interfaces"), ] limit = cls.limits['VPC security groups per elastic network interface'] sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 3 assert sorted_usage[0].limit == limit assert sorted_usage[0].resource_id == 'if-1' assert sorted_usage[0].get_value() == 0 assert sorted_usage[1].limit == limit assert sorted_usage[1].resource_id == 'if-2' assert sorted_usage[1].get_value() == 3 assert sorted_usage[2].limit == limit assert sorted_usage[2].resource_id == 'if-3' assert sorted_usage[2].get_value() == 8 assert mock_conn.mock_calls == [ call.network_interfaces.all() ]
def test_find_usage_spot_instances(self): data = fixtures.test_find_usage_spot_instances mock_conn = Mock() mock_client_conn = Mock() mock_client_conn.describe_spot_instance_requests.return_value = data cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn cls.conn = mock_client_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_spot_instances() assert mock_conn.mock_calls == [] assert mock_client_conn.mock_calls == [ call.describe_spot_instance_requests() ] lim = cls.limits['Max spot instance requests per region'] usage = lim.get_current_usage() assert len(usage) == 1 assert usage[0].get_value() == 2 assert mock_logger.mock_calls == [ call.debug('Getting spot instance request usage'), call.debug('NOT counting spot instance request %s state=%s', 'reqID1', 'closed'), call.debug('Counting spot instance request %s state=%s', 'reqID2', 'active'), call.debug('Counting spot instance request %s state=%s', 'reqID3', 'open'), call.debug('NOT counting spot instance request %s state=%s', 'reqID4', 'failed') ]
def test_find_usage_spot_instances(self): data = fixtures.test_find_usage_spot_instances mock_conn = Mock() mock_client_conn = Mock() mock_client_conn.describe_spot_instance_requests.return_value = data cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn cls.conn = mock_client_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_spot_instances() assert mock_conn.mock_calls == [] assert mock_client_conn.mock_calls == [ call.describe_spot_instance_requests() ] lim = cls.limits['Max spot instance requests per region'] usage = lim.get_current_usage() assert len(usage) == 1 assert usage[0].get_value() == 2 assert mock_logger.mock_calls == [ call.debug('Getting spot instance request usage'), call.warning('EC2 spot instance support is experimental and ' 'results may not me accurate in all cases. Please ' 'see the notes at: <http://awslimitchecker' '.readthedocs.io/en/latest/limits.html#ec2>'), call.debug('NOT counting spot instance request %s state=%s', 'reqID1', 'closed'), call.debug('Counting spot instance request %s state=%s', 'reqID2', 'active'), call.debug('Counting spot instance request %s state=%s', 'reqID3', 'open'), call.debug('NOT counting spot instance request %s state=%s', 'reqID4', 'failed'), call.debug('Setting "Max spot instance requests per region" ' 'limit (%s) current usage to: %d', lim, 2) ]
def test_find_usage_networking_eips(self): mocks = fixtures.test_find_usage_networking_eips mock_conn = Mock() mock_conn.classic_addresses.all.return_value = mocks['Classic'] mock_conn.vpc_addresses.all.return_value = mocks['Vpc'] cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_networking_eips() assert mock_logger.mock_calls == [ call.debug("Getting usage for EC2 EIPs"), ] limit = cls.limits['VPC Elastic IP addresses (EIPs)'] usage = limit.get_current_usage() assert len(usage) == 1 assert usage[0].limit == limit assert usage[0].get_value() == 2 assert usage[0].resource_id is None assert usage[0].aws_type == 'AWS::EC2::EIP' limit = cls.limits['Elastic IP addresses (EIPs)'] usage = limit.get_current_usage() assert len(usage) == 1 assert usage[0].limit == limit assert usage[0].get_value() == 1 assert usage[0].resource_id is None assert usage[0].aws_type == 'AWS::EC2::EIP' assert mock_conn.mock_calls == [ call.vpc_addresses.all(), call.classic_addresses.all() ]
def test_find_usage_networking_eips(self): mock_addr1 = Mock(spec_set=Address) type(mock_addr1).domain = "vpc" mock_addr2 = Mock(spec_set=Address) type(mock_addr2).domain = "vpc" mock_addr3 = Mock(spec_set=Address) type(mock_addr3).domain = "standard" mock_conn = Mock(spec_set=EC2Connection) mock_conn.get_all_addresses.return_value = [mock_addr1, mock_addr2, mock_addr3] cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch("awslimitchecker.services.ec2.logger") as mock_logger: cls._find_usage_networking_eips() assert mock_logger.mock_calls == [call.debug("Getting usage for EC2 EIPs")] limit = cls.limits["EC2-VPC Elastic IPs"] usage = limit.get_current_usage() assert len(usage) == 1 assert usage[0].limit == limit assert usage[0].get_value() == 2 assert usage[0].resource_id is None assert usage[0].aws_type == "AWS::EC2::EIP" limit = cls.limits["Elastic IP addresses (EIPs)"] usage = limit.get_current_usage() assert len(usage) == 1 assert usage[0].limit == limit assert usage[0].get_value() == 1 assert usage[0].resource_id is None assert usage[0].aws_type == "AWS::EC2::EIP"
def test_find_usage_networking_eni_sg(self): mock_if1 = Mock(spec_set=NetworkInterface) type(mock_if1).id = "if-1" type(mock_if1).groups = [] mock_if2 = Mock(spec_set=NetworkInterface) type(mock_if2).id = "if-2" type(mock_if2).groups = [1, 2, 3] mock_if3 = Mock(spec_set=NetworkInterface) type(mock_if3).id = "if-3" type(mock_if3).groups = [1, 2, 3, 4, 5, 6, 7, 8] mock_conn = Mock(spec_set=EC2Connection) mock_conn.get_all_network_interfaces.return_value = [mock_if1, mock_if2, mock_if3] cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch("awslimitchecker.services.ec2.logger") as mock_logger: cls._find_usage_networking_eni_sg() assert mock_logger.mock_calls == [call.debug("Getting usage for EC2 Network Interfaces")] limit = cls.limits["VPC security groups per elastic network interface"] sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 3 assert sorted_usage[0].limit == limit assert sorted_usage[0].resource_id == "if-1" assert sorted_usage[0].get_value() == 0 assert sorted_usage[1].limit == limit assert sorted_usage[1].resource_id == "if-2" assert sorted_usage[1].get_value() == 3 assert sorted_usage[2].limit == limit assert sorted_usage[2].resource_id == "if-3" assert sorted_usage[2].get_value() == 8
def test_find_usage_spot_fleets_paginated(self): data = deepcopy(fixtures.test_find_usage_spot_fleets) data['NextToken'] = 'string' mock_conn = Mock() mock_client_conn = Mock() mock_client_conn.describe_spot_fleet_requests.return_value = data cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn cls.conn = mock_client_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_spot_fleets() assert mock_conn.mock_calls == [] assert mock_client_conn.mock_calls == [ call.describe_spot_fleet_requests() ] total = cls.limits['Max active spot fleets per ' 'region'].get_current_usage() assert len(total) == 1 assert total[0].get_value() == 2 totalcap = cls.limits['Max target capacity for all spot fleets ' 'in region'].get_current_usage() assert len(totalcap) == 1 assert totalcap[0].get_value() == 44 cap_per_fleet = cls.limits['Max target capacity per spot ' 'fleet'].get_current_usage() assert len(cap_per_fleet) == 2 assert cap_per_fleet[0].get_value() == 11 assert cap_per_fleet[0].resource_id == 'req2' assert cap_per_fleet[1].get_value() == 33 assert cap_per_fleet[1].resource_id == 'req4' launch_specs = cls.limits['Max launch specifications ' 'per spot fleet'].get_current_usage() assert len(launch_specs) == 2 assert launch_specs[0].get_value() == 3 assert launch_specs[0].resource_id == 'req2' assert launch_specs[1].get_value() == 1 assert launch_specs[1].resource_id == 'req4' assert mock_logger.mock_calls == [ call.debug('Getting spot fleet request usage'), call.error('Error: describe_spot_fleet_requests() response ' 'includes pagination token, but pagination not ' 'configured in awslimitchecker.'), call.debug('Skipping spot fleet request %s in state %s', 'req1', 'failed'), call.debug('Active fleet %s: target capacity=%s, %d launch specs', 'req2', 11, 3), call.debug('Skipping spot fleet request %s in state %s', 'req3', 'modifying'), call.debug('Active fleet %s: target capacity=%s, %d launch specs', 'req4', 33, 1), call.debug( 'Total active spot fleets: %d; total target capacity ' 'for all spot fleets: %d', 2, 44) ]
def test_get_limits_all(self): """test some things all limits should conform to""" cls = _Ec2Service(21, 43) limits = cls.get_limits() for x in limits: assert isinstance(limits[x], AwsLimit) assert x == limits[x].name assert limits[x].service == cls
def test_find_usage_spot_fleets_paginated(self): data = deepcopy(fixtures.test_find_usage_spot_fleets) data['NextToken'] = 'string' mock_conn = Mock() mock_client_conn = Mock() mock_client_conn.describe_spot_fleet_requests.return_value = data cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn cls.conn = mock_client_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_spot_fleets() assert mock_conn.mock_calls == [] assert mock_client_conn.mock_calls == [ call.describe_spot_fleet_requests() ] total = cls.limits['Max active spot fleets per ' 'region'].get_current_usage() assert len(total) == 1 assert total[0].get_value() == 2 totalcap = cls.limits['Max target capacity for all spot fleets ' 'in region'].get_current_usage() assert len(totalcap) == 1 assert totalcap[0].get_value() == 44 cap_per_fleet = cls.limits['Max target capacity per spot ' 'fleet'].get_current_usage() assert len(cap_per_fleet) == 2 assert cap_per_fleet[0].get_value() == 11 assert cap_per_fleet[0].resource_id == 'req2' assert cap_per_fleet[1].get_value() == 33 assert cap_per_fleet[1].resource_id == 'req4' launch_specs = cls.limits['Max launch specifications ' 'per spot fleet'].get_current_usage() assert len(launch_specs) == 2 assert launch_specs[0].get_value() == 3 assert launch_specs[0].resource_id == 'req2' assert launch_specs[1].get_value() == 1 assert launch_specs[1].resource_id == 'req4' assert mock_logger.mock_calls == [ call.debug('Getting spot fleet request usage'), call.error('Error: describe_spot_fleet_requests() response ' 'includes pagination token, but pagination not ' 'configured in awslimitchecker.'), call.debug('Skipping spot fleet request %s in state %s', 'req1', 'failed'), call.debug('Active fleet %s: target capacity=%s, %d launch specs', 'req2', 11, 3), call.debug('Skipping spot fleet request %s in state %s', 'req3', 'modifying'), call.debug('Active fleet %s: target capacity=%s, %d launch specs', 'req4', 33, 1), call.debug('Total active spot fleets: %d; total target capacity ' 'for all spot fleets: %d', 2, 44) ]
def test_connect(self): """test connect()""" mock_conn = Mock() cls = _Ec2Service(21, 43) with patch("awslimitchecker.services.ec2.boto.connect_ec2") as mock_ec2: mock_ec2.return_value = mock_conn cls.connect() assert mock_ec2.mock_calls == [call()] assert mock_conn.mock_calls == []
def test_instance_usage(self): mock_t2_micro = Mock(spec_set=AwsLimit) mock_r3_2xlarge = Mock(spec_set=AwsLimit) mock_c4_4xlarge = Mock(spec_set=AwsLimit) mock_m4_8xlarge = Mock(spec_set=AwsLimit) limits = { "Running On-Demand t2.micro instances": mock_t2_micro, "Running On-Demand r3.2xlarge instances": mock_r3_2xlarge, "Running On-Demand c4.4xlarge instances": mock_c4_4xlarge, "Running On-Demand m4.8xlarge instances": mock_m4_8xlarge, } cls = _Ec2Service(21, 43) mock_inst1A = Mock(spec_set=Instance) type(mock_inst1A).id = "1A" type(mock_inst1A).instance_type = "t2.micro" type(mock_inst1A).spot_instance_request_id = None type(mock_inst1A).placement = "az1a" mock_inst1B = Mock(spec_set=Instance) type(mock_inst1B).id = "1B" type(mock_inst1B).instance_type = "r3.2xlarge" type(mock_inst1B).spot_instance_request_id = None type(mock_inst1B).placement = "az1a" mock_res1 = Mock(spec_set=Reservation) type(mock_res1).instances = [mock_inst1A, mock_inst1B] mock_inst2A = Mock(spec_set=Instance) type(mock_inst2A).id = "2A" type(mock_inst2A).instance_type = "c4.4xlarge" type(mock_inst2A).spot_instance_request_id = None type(mock_inst2A).placement = "az1a" mock_inst2B = Mock(spec_set=Instance) type(mock_inst2B).id = "2B" type(mock_inst2B).instance_type = "t2.micro" type(mock_inst2B).spot_instance_request_id = "1234" type(mock_inst2B).placement = "az1a" mock_inst2C = Mock(spec_set=Instance) type(mock_inst2C).id = "2C" type(mock_inst2C).instance_type = "m4.8xlarge" type(mock_inst2C).spot_instance_request_id = None type(mock_inst2C).placement = "az1a" mock_res2 = Mock(spec_set=Reservation) type(mock_res2).instances = [mock_inst2A, mock_inst2B, mock_inst2C] mock_conn = Mock(spec_set=EC2Connection) mock_conn.get_all_reservations.return_value = [mock_res1, mock_res2] cls.conn = mock_conn cls.limits = limits with patch("awslimitchecker.services.ec2._Ec2Service._instance_types", autospec=True) as mock_itypes: mock_itypes.return_value = ["t2.micro", "r3.2xlarge", "c4.4xlarge", "m4.8xlarge"] res = cls._instance_usage() assert res == {"az1a": {"t2.micro": 1, "r3.2xlarge": 1, "c4.4xlarge": 1, "m4.8xlarge": 1}}
def test_connect_again(self): """make sure we re-use the connection""" mock_conn = Mock() cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch('awslimitchecker.services.ec2.boto.connect_ec2') as mock_ec2: mock_ec2.return_value = mock_conn cls.connect() assert mock_ec2.mock_calls == [] assert mock_conn.mock_calls == []
def test_get_limits_again(self): """test that existing limits dict is returned on subsequent calls""" cls = _Ec2Service(21, 43) cls.limits = {'foo': 'bar'} with patch('%s._get_limits_instances' % self.pb) as mock_instances: with patch('%s._get_limits_networking' % self.pb) as mock_vpc: res = cls.get_limits() assert res == {'foo': 'bar'} assert mock_instances.mock_calls == [] assert mock_vpc.mock_calls == []
def test_get_limits(self): cls = _Ec2Service(21, 43) cls.limits = {} with patch("%s._get_limits_instances" % self.pb) as mock_instances: with patch("%s._get_limits_networking" % self.pb) as mock_vpc: mock_instances.return_value = {"ec2lname": "ec2lval"} mock_vpc.return_value = {"vpck": "vpcv"} res = cls.get_limits() assert res == {"ec2lname": "ec2lval", "vpck": "vpcv"} assert mock_instances.mock_calls == [call()] assert mock_vpc.mock_calls == [call()]
def test_get_limits_networking(self): cls = _Ec2Service(21, 43) limits = cls._get_limits_networking() expected = [ 'Security groups per VPC', 'Rules per VPC security group', 'VPC Elastic IP addresses (EIPs)', 'Elastic IP addresses (EIPs)', 'VPC security groups per elastic network interface', ] assert sorted(limits.keys()) == sorted(expected)
def test_connect_again(self): """make sure we re-use the connection""" mock_conn = Mock() cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch( 'awslimitchecker.services.ec2.boto.connect_ec2') as mock_ec2: mock_ec2.return_value = mock_conn cls.connect() assert mock_ec2.mock_calls == [] assert mock_conn.mock_calls == []
def test_update_limits_from_api_unsupported(self): data = fixtures.test_update_limits_from_api_unsupported mock_client_conn = Mock() mock_client_conn.describe_account_attributes.return_value = data cls = _Ec2Service(21, 43) cls.conn = mock_client_conn cls._update_limits_from_api() lim = cls.limits['Elastic IP addresses (EIPs)'] usage = lim.get_current_usage() assert len(usage) == 0
def test_get_limits_spot(self): cls = _Ec2Service(21, 43) limits = cls._get_limits_spot() expected = [ 'Max spot instance requests per region', 'Max active spot fleets per region', 'Max launch specifications per spot fleet', 'Max target capacity per spot fleet', 'Max target capacity for all spot fleets in region' ] assert sorted(limits.keys()) == sorted(expected)
def test_get_limits_networking(self): cls = _Ec2Service(21, 43) limits = cls._get_limits_networking() expected = [ "Security groups per VPC", "Rules per VPC security group", "EC2-VPC Elastic IPs", "Elastic IP addresses (EIPs)", "VPC security groups per elastic network interface", ] assert sorted(limits.keys()) == sorted(expected)
def test_get_reserved_instance_count(self): mock_res1 = Mock(spec_set=ReservedInstance) type(mock_res1).state = 'active' type(mock_res1).id = 'res1' type(mock_res1).availability_zone = 'az1' type(mock_res1).instance_type = 'it1' type(mock_res1).instance_count = 1 mock_res2 = Mock(spec_set=ReservedInstance) type(mock_res2).state = 'inactive' type(mock_res2).id = 'res2' type(mock_res2).availability_zone = 'az1' type(mock_res2).instance_type = 'it2' type(mock_res2).instance_count = 1 mock_res3 = Mock(spec_set=ReservedInstance) type(mock_res3).state = 'active' type(mock_res3).id = 'res3' type(mock_res3).availability_zone = 'az1' type(mock_res3).instance_type = 'it1' type(mock_res3).instance_count = 9 mock_res4 = Mock(spec_set=ReservedInstance) type(mock_res4).state = 'active' type(mock_res4).id = 'res4' type(mock_res4).availability_zone = 'az2' type(mock_res4).instance_type = 'it2' type(mock_res4).instance_count = 98 cls = _Ec2Service(21, 43) mock_conn = Mock(spec_set=EC2Connection) return_value = [ mock_res1, mock_res2, mock_res3, mock_res4 ] cls.conn = mock_conn with patch('%s.boto_query_wrapper' % self.pbm) as mock_wrapper: mock_wrapper.return_value = return_value res = cls._get_reserved_instance_count() assert res == { 'az1': { 'it1': 10, }, 'az2': { 'it2': 98, }, } assert mock_conn.mock_calls == [] assert mock_wrapper.mock_calls == [ call(mock_conn.get_all_reserved_instances) ]
def test_find_usage_spot_fleets_unknown_code(self): mock_client_conn = Mock() err = botocore.exceptions.ClientError( {'Error': { 'Code': 'SomeCode' }}, 'operation', ) mock_client_conn.describe_spot_fleet_requests.side_effect = err cls = _Ec2Service(21, 43) cls.conn = mock_client_conn with pytest.raises(botocore.exceptions.ClientError): cls._find_usage_spot_fleets()
def test_instance_types(self): cls = _Ec2Service(21, 43) types = cls._instance_types() assert len(types) == 54 assert 't2.micro' in types assert 'r3.8xlarge' in types assert 'c3.large' in types assert 'i2.4xlarge' in types assert 'd2.2xlarge' in types assert 'g2.8xlarge' in types assert 'hs1.8xlarge' in types assert 'cg1.4xlarge' in types assert 'm4.4xlarge' in types
def test_instance_types(self): cls = _Ec2Service(21, 43) types = cls._instance_types() assert len(types) == 53 assert 't2.micro' in types assert 'r3.8xlarge' in types assert 'c3.large' in types assert 'i2.4xlarge' in types assert 'd2.2xlarge' in types assert 'g2.8xlarge' in types assert 'hs1.8xlarge' in types assert 'cg1.4xlarge' in types assert 'm4.4xlarge' in types
def test_instance_types(self): cls = _Ec2Service(21, 43) types = cls._instance_types() assert len(types) == 52 assert "t2.micro" in types assert "r3.8xlarge" in types assert "c3.large" in types assert "i2.4xlarge" in types assert "d2.2xlarge" in types assert "g2.8xlarge" in types assert "hs1.8xlarge" in types assert "cg1.4xlarge" in types assert "m4.4xlarge" in types
def test_find_usage_networking_sgs(self): mock_sg1 = Mock(spec_set=SecurityGroup) type(mock_sg1).id = "sg-1" type(mock_sg1).vpc_id = "vpc-aaa" type(mock_sg1).rules = [] mock_sg2 = Mock(spec_set=SecurityGroup) type(mock_sg2).id = "sg-2" type(mock_sg2).vpc_id = None type(mock_sg2).rules = [1, 2, 3, 4, 5, 6] mock_sg3 = Mock(spec_set=SecurityGroup) type(mock_sg3).id = "sg-3" type(mock_sg3).vpc_id = "vpc-bbb" type(mock_sg3).rules = [1, 2, 3, 4, 5, 6, 7, 8, 9] mock_sg4 = Mock(spec_set=SecurityGroup) type(mock_sg4).id = "sg-4" type(mock_sg4).vpc_id = "vpc-aaa" type(mock_sg4).rules = [1, 2, 3] mock_conn = Mock(spec_set=EC2Connection) mock_conn.get_all_security_groups.return_value = [mock_sg1, mock_sg2, mock_sg3, mock_sg4] cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch("awslimitchecker.services.ec2.logger") as mock_logger: cls._find_usage_networking_sgs() assert mock_logger.mock_calls == [call.debug("Getting usage for EC2 VPC resources")] limit = cls.limits["Security groups per VPC"] # relies on AwsLimitUsage sorting by numeric usage value sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 2 assert sorted_usage[0].limit == limit assert sorted_usage[0].get_value() == 1 assert sorted_usage[0].resource_id == "vpc-bbb" assert sorted_usage[0].aws_type == "AWS::EC2::VPC" assert sorted_usage[1].limit == limit assert sorted_usage[1].get_value() == 2 assert sorted_usage[1].resource_id == "vpc-aaa" assert sorted_usage[1].aws_type == "AWS::EC2::VPC" limit = cls.limits["Rules per VPC security group"] sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 3 assert sorted_usage[0].limit == limit assert sorted_usage[0].resource_id == "sg-1" assert sorted_usage[0].get_value() == 0 assert sorted_usage[1].limit == limit assert sorted_usage[1].resource_id == "sg-4" assert sorted_usage[1].get_value() == 3 assert sorted_usage[2].limit == limit assert sorted_usage[2].resource_id == "sg-3" assert sorted_usage[2].get_value() == 9
def test_connect_region(self): """test connect()""" mock_conn = Mock() mock_conn_via = Mock() cls = _Ec2Service(21, 43, region='bar') with patch('%s.boto.connect_ec2' % self.pbm) as mock_ec2: with patch('%s.connect_via' % self.pb) as mock_connect_via: mock_ec2.return_value = mock_conn mock_connect_via.return_value = mock_conn_via cls.connect() assert mock_ec2.mock_calls == [] assert mock_conn.mock_calls == [] assert mock_connect_via.mock_calls == [call(connect_to_region)] assert cls.conn == mock_conn_via
def test_get_limits(self): cls = _Ec2Service(21, 43) cls.limits = {} with patch('%s._get_limits_instances' % self.pb) as mock_instances: with patch('%s._get_limits_networking' % self.pb) as mock_vpc: mock_instances.return_value = {'ec2lname': 'ec2lval'} mock_vpc.return_value = {'vpck': 'vpcv'} res = cls.get_limits() assert res == { 'ec2lname': 'ec2lval', 'vpck': 'vpcv', } assert mock_instances.mock_calls == [call()] assert mock_vpc.mock_calls == [call()]
def test_find_usage_spot_fleets_unsupported(self): mock_client_conn = Mock() err = botocore.exceptions.ClientError( {'Error': { 'Code': 'UnsupportedOperation' }}, 'operation', ) mock_client_conn.describe_spot_fleet_requests.side_effect = err cls = _Ec2Service(21, 43) cls.conn = mock_client_conn cls._find_usage_spot_fleets() total = cls.limits['Max active spot fleets per ' 'region'].get_current_usage() assert len(total) == 0
def test_required_iam_permissions(self): cls = _Ec2Service(21, 43) assert cls.required_iam_permissions() == [ "ec2:DescribeAddresses", "ec2:DescribeInstances", "ec2:DescribeInternetGateways" "ec2:DescribeNetworkAcls", "ec2:DescribeNetworkInterfaces", "ec2:DescribeReservedInstances", "ec2:DescribeRouteTables", "ec2:DescribeSecurityGroups", "ec2:DescribeSnapshots", "ec2:DescribeSubnets", "ec2:DescribeVolumes", "ec2:DescribeVpcs", ]
def test_find_usage_spot_instances_unsupported(self): mock_client_conn = Mock() err = botocore.exceptions.ClientError( {'Error': { 'Code': 'UnsupportedOperation' }}, 'operation', ) mock_client_conn.describe_spot_instance_requests.side_effect = err cls = _Ec2Service(21, 43) cls.conn = mock_client_conn cls._find_usage_spot_instances() lim = cls.limits['Max spot instance requests per region'] usage = lim.get_current_usage() assert len(usage) == 0
def test_update_limits_from_api(self): mock_conn = Mock(spec_set=EC2Connection) rs = ResultSet() a1 = AccountAttribute(connection=mock_conn) a1.attribute_name = 'supported-platforms' a1.attribute_values = ['EC2', 'VPC'] rs.append(a1) a2 = AccountAttribute(connection=mock_conn) a2.attribute_name = 'vpc-max-security-groups-per-interface' a2.attribute_values = ['5'] rs.append(a2) a3 = AccountAttribute(connection=mock_conn) a3.attribute_name = 'max-elastic-ips' a3.attribute_values = ['40'] rs.append(a3) a4 = AccountAttribute(connection=mock_conn) a4.attribute_name = 'max-instances' a4.attribute_values = ['400'] rs.append(a4) a5 = AccountAttribute(connection=mock_conn) a5.attribute_name = 'vpc-max-elastic-ips' a5.attribute_values = ['200'] rs.append(a5) a6 = AccountAttribute(connection=mock_conn) a6.attribute_name = 'default-vpc' a6.attribute_values = ['none'] rs.append(a6) cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: with patch('%s.boto_query_wrapper' % self.pbm) as mock_wrapper: mock_wrapper.return_value = rs cls._update_limits_from_api() assert mock_wrapper.mock_calls == [ call(mock_conn.describe_account_attributes) ] assert mock_conn.mock_calls == [] assert mock_logger.mock_calls == [ call.info("Querying EC2 DescribeAccountAttributes for limits"), call.debug('Done setting limits from API') ] assert cls.limits['Elastic IP addresses (EIPs)'].api_limit == 40 assert cls.limits['Running On-Demand EC2 instances'].api_limit == 400 assert cls.limits['VPC Elastic IP addresses (EIPs)'].api_limit == 200 assert cls.limits['VPC security groups per elastic ' 'network interface'].api_limit == 5
def test_find_usage_spot_fleets(self): data = fixtures.test_find_usage_spot_fleets mock_conn = Mock() mock_client_conn = Mock() mock_client_conn.describe_spot_fleet_requests.return_value = data cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn cls.conn = mock_client_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_spot_fleets() assert mock_conn.mock_calls == [] assert mock_client_conn.mock_calls == [ call.describe_spot_fleet_requests() ] total = cls.limits['Max active spot fleets per ' 'region'].get_current_usage() assert len(total) == 1 assert total[0].get_value() == 2 totalcap = cls.limits['Max target capacity for all spot fleets ' 'in region'].get_current_usage() assert len(totalcap) == 1 assert totalcap[0].get_value() == 44 cap_per_fleet = cls.limits['Max target capacity per spot ' 'fleet'].get_current_usage() assert len(cap_per_fleet) == 2 assert cap_per_fleet[0].get_value() == 11 assert cap_per_fleet[0].resource_id == 'req2' assert cap_per_fleet[1].get_value() == 33 assert cap_per_fleet[1].resource_id == 'req4' launch_specs = cls.limits['Max launch specifications ' 'per spot fleet'].get_current_usage() assert len(launch_specs) == 2 assert launch_specs[0].get_value() == 3 assert launch_specs[0].resource_id == 'req2' assert launch_specs[1].get_value() == 1 assert launch_specs[1].resource_id == 'req4' assert mock_logger.mock_calls == [ call.debug('Getting spot fleet request usage'), call.debug('Skipping spot fleet request %s in state %s', 'req1', 'failed'), call.debug('Skipping spot fleet request %s in state %s', 'req3', 'modifying') ]
def test_get_reserved_instance_count(self): mock_res1 = Mock(spec_set=ReservedInstance) type(mock_res1).state = 'active' type(mock_res1).id = 'res1' type(mock_res1).availability_zone = 'az1' type(mock_res1).instance_type = 'it1' type(mock_res1).instance_count = 1 mock_res2 = Mock(spec_set=ReservedInstance) type(mock_res2).state = 'inactive' type(mock_res2).id = 'res2' type(mock_res2).availability_zone = 'az1' type(mock_res2).instance_type = 'it2' type(mock_res2).instance_count = 1 mock_res3 = Mock(spec_set=ReservedInstance) type(mock_res3).state = 'active' type(mock_res3).id = 'res3' type(mock_res3).availability_zone = 'az1' type(mock_res3).instance_type = 'it1' type(mock_res3).instance_count = 9 mock_res4 = Mock(spec_set=ReservedInstance) type(mock_res4).state = 'active' type(mock_res4).id = 'res4' type(mock_res4).availability_zone = 'az2' type(mock_res4).instance_type = 'it2' type(mock_res4).instance_count = 98 cls = _Ec2Service(21, 43) mock_conn = Mock(spec_set=EC2Connection) return_value = [mock_res1, mock_res2, mock_res3, mock_res4] cls.conn = mock_conn with patch('%s.boto_query_wrapper' % self.pbm) as mock_wrapper: mock_wrapper.return_value = return_value res = cls._get_reserved_instance_count() assert res == { 'az1': { 'it1': 10, }, 'az2': { 'it2': 98, }, } assert mock_conn.mock_calls == [] assert mock_wrapper.mock_calls == [ call(mock_conn.get_all_reserved_instances) ]
def test_find_usage(self): with patch.multiple( self.pb, connect=DEFAULT, _find_usage_instances=DEFAULT, _find_usage_networking_sgs=DEFAULT, _find_usage_networking_eips=DEFAULT, _find_usage_networking_eni_sg=DEFAULT, autospec=True, ) as mocks: cls = _Ec2Service(21, 43) assert cls._have_usage is False cls.find_usage() assert cls._have_usage is True assert len(mocks) == 5 for m in mocks: assert mocks[m].mock_calls == [call(cls)]
def test_required_iam_permissions(self): cls = _Ec2Service(21, 43) assert len(cls.required_iam_permissions()) == 13 assert cls.required_iam_permissions() == [ "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeInstances", "ec2:DescribeInternetGateways", "ec2:DescribeNetworkAcls", "ec2:DescribeNetworkInterfaces", "ec2:DescribeReservedInstances", "ec2:DescribeRouteTables", "ec2:DescribeSecurityGroups", "ec2:DescribeSnapshots", "ec2:DescribeSubnets", "ec2:DescribeVolumes", "ec2:DescribeVpcs", ]
def test_instance_usage_key_error(self): mock_conn = Mock() data = fixtures.test_instance_usage_key_error mock_conn.instances.all.return_value = data cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn cls.limits = {'Running On-Demand t2.micro instances': Mock()} with patch('%s._instance_types' % self.pb, autospec=True) as mock_itypes: with patch('awslimitchecker.services.ec2.logger') as mock_logger: mock_itypes.return_value = ['t2.micro'] cls._instance_usage() assert mock_logger.mock_calls == [ call.debug('Getting usage for on-demand instances'), call.error("ERROR - unknown instance type '%s'; not counting", 'foobar'), ] assert mock_conn.mock_calls == [call.instances.all()]
def test_instance_types(self): cls = _Ec2Service(21, 43) types = cls._instance_types() # NOTE hi1.4xlarge is no longer in the instance type listings, # but some accounts might still have a limit for it assert len(types) == 100 assert 't2.micro' in types assert 'r3.8xlarge' in types assert 'c3.large' in types assert 'i2.4xlarge' in types assert 'i3.16xlarge' in types assert 'd2.2xlarge' in types assert 'g2.8xlarge' in types assert 'hs1.8xlarge' in types assert 'cg1.4xlarge' in types assert 'm4.4xlarge' in types assert 'p2.16xlarge' in types assert 'm4.16xlarge' in types assert 'x1.32xlarge' in types
def test_find_usage_networking_eips(self): mock_addr1 = Mock(spec_set=Address) type(mock_addr1).domain = 'vpc' mock_addr2 = Mock(spec_set=Address) type(mock_addr2).domain = 'vpc' mock_addr3 = Mock(spec_set=Address) type(mock_addr3).domain = 'standard' mock_conn = Mock(spec_set=EC2Connection) return_value = [ mock_addr1, mock_addr2, mock_addr3, ] cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: with patch('%s.boto_query_wrapper' % self.pbm) as mock_wrapper: mock_wrapper.return_value = return_value cls._find_usage_networking_eips() assert mock_logger.mock_calls == [ call.debug("Getting usage for EC2 EIPs"), ] limit = cls.limits['VPC Elastic IP addresses (EIPs)'] usage = limit.get_current_usage() assert len(usage) == 1 assert usage[0].limit == limit assert usage[0].get_value() == 2 assert usage[0].resource_id is None assert usage[0].aws_type == 'AWS::EC2::EIP' limit = cls.limits['Elastic IP addresses (EIPs)'] usage = limit.get_current_usage() assert len(usage) == 1 assert usage[0].limit == limit assert usage[0].get_value() == 1 assert usage[0].resource_id is None assert usage[0].aws_type == 'AWS::EC2::EIP' assert mock_conn.mock_calls == [] assert mock_wrapper.mock_calls == [ call(mock_conn.get_all_addresses) ]
def test_find_usage_networking_eni_sg(self): mock_if1 = Mock(spec_set=NetworkInterface) type(mock_if1).id = 'if-1' type(mock_if1).groups = [] mock_if2 = Mock(spec_set=NetworkInterface) type(mock_if2).id = 'if-2' type(mock_if2).groups = [1, 2, 3] mock_if3 = Mock(spec_set=NetworkInterface) type(mock_if3).id = 'if-3' type(mock_if3).groups = [1, 2, 3, 4, 5, 6, 7, 8] mock_conn = Mock(spec_set=EC2Connection) return_value = [ mock_if1, mock_if2, mock_if3, ] cls = _Ec2Service(21, 43) cls.conn = mock_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: with patch('%s.boto_query_wrapper' % self.pbm) as mock_wrapper: mock_wrapper.return_value = return_value cls._find_usage_networking_eni_sg() assert mock_logger.mock_calls == [ call.debug("Getting usage for EC2 Network Interfaces"), ] limit = cls.limits['VPC security groups per elastic network interface'] sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 3 assert sorted_usage[0].limit == limit assert sorted_usage[0].resource_id == 'if-1' assert sorted_usage[0].get_value() == 0 assert sorted_usage[1].limit == limit assert sorted_usage[1].resource_id == 'if-2' assert sorted_usage[1].get_value() == 3 assert sorted_usage[2].limit == limit assert sorted_usage[2].resource_id == 'if-3' assert sorted_usage[2].get_value() == 8 assert mock_conn.mock_calls == [] assert mock_wrapper.mock_calls == [ call(mock_conn.get_all_network_interfaces) ]
def test_find_usage_networking_sgs(self): mocks = fixtures.test_find_usage_networking_sgs mock_conn = Mock() mock_conn.security_groups.all.return_value = mocks cls = _Ec2Service(21, 43) cls.resource_conn = mock_conn with patch('awslimitchecker.services.ec2.logger') as mock_logger: cls._find_usage_networking_sgs() assert mock_logger.mock_calls == [ call.debug("Getting usage for EC2 VPC resources"), ] limit = cls.limits['Security groups per VPC'] # relies on AwsLimitUsage sorting by numeric usage value sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 2 assert sorted_usage[0].limit == limit assert sorted_usage[0].get_value() == 1 assert sorted_usage[0].resource_id == 'vpc-bbb' assert sorted_usage[0].aws_type == 'AWS::EC2::VPC' assert sorted_usage[1].limit == limit assert sorted_usage[1].get_value() == 2 assert sorted_usage[1].resource_id == 'vpc-aaa' assert sorted_usage[1].aws_type == 'AWS::EC2::VPC' limit = cls.limits['Rules per VPC security group'] sorted_usage = sorted(limit.get_current_usage()) assert len(sorted_usage) == 3 assert sorted_usage[0].limit == limit assert sorted_usage[0].resource_id == 'sg-1' assert sorted_usage[0].get_value() == 0 assert sorted_usage[1].limit == limit assert sorted_usage[1].resource_id == 'sg-4' assert sorted_usage[1].get_value() == 3 assert sorted_usage[2].limit == limit assert sorted_usage[2].resource_id == 'sg-3' assert sorted_usage[2].get_value() == 9 assert mock_conn.mock_calls == [call.security_groups.all()]