예제 #1
0
    def __get_spot_instance_request_map(self, result): \
            # pylint: disable=no-self-use
        sir_map = {}
        adapter_cfg_map = {}

        adapter = Aws()

        # Create map of spot instance requests keyed on EC2 region
        for sir_id, resource_adapter_configuration in result:
            if resource_adapter_configuration not in adapter_cfg_map:
                adapter_cfg = adapter.getResourceAdapterConfig(
                    resource_adapter_configuration)

                adapter_cfg_map[resource_adapter_configuration] = \
                    adapter_cfg
            else:
                adapter_cfg = adapter_cfg_map[
                    resource_adapter_configuration]

            if adapter_cfg['region'].name not in sir_map:
                sir_map[adapter_cfg['region'].name] = []

            sir_map[adapter_cfg['region'].name].append(sir_id)

        return sir_map
def test_expand_cloud_init_user_data_template(load_config_dict_mock,
                                              get_config_path_mock):     \
        # pylint: disable=unused-argument
    """
    Load sample data as Jinja2 template
    """

    tmpl = '''
#!/usr/bin/env python

installer = '{{ installer }}'


def main():
    pass


if __name__ == '__main__':
    main()
'''

    adapter = Aws()

    config = adapter.getResourceAdapterConfig()

    result = adapter.expand_cloud_init_user_data_template(
        config, template=Template(tmpl))

    assert result and isinstance(result, str)

    assert get_config_path_mock.called_with('notblah.txt')
def test_get_user_data(load_config_dict_mock, get_config_path_mock):     \
        # pylint: disable=unused-argument
    """
    Use mock data to expand SETTINGS macro
    """

    file_contents = '''
#!/usr/bin/env python

### SETTINGS


def main():
    pass


if __name__ == '__main__':
    main()
'''

    fp = io.StringIO(file_contents)

    adapter = Aws()

    config = adapter.getResourceAdapterConfig()

    result = adapter._Aws__get_user_data_script(fp, config)

    assert result and isinstance(result, str)

    assert get_config_path_mock.called_with('blah.txt')
def test_missing_ami_setting(load_config_dict_mock, dbm):
    load_config_dict_mock.return_value = {}

    with dbm.session() as session:
        with pytest.raises(ConfigurationError):
            adapter = Aws()
            adapter.session = session

            adapter.getResourceAdapterConfig()
def test_invalid_adapter_configuration(dbm):
    """Ensure exception is raissed from missing required settings"""

    with dbm.session() as session:
        with pytest.raises(ConfigurationError):
            with patch.object(
                    ResourceAdapter, '_load_config_from_database', return_value={}):
                adapter = Aws()
                adapter.session = session

                adapter.getResourceAdapterConfig()
    def runCommand(self):
        self.parseArgs()

        adapter = Aws()

        configDict = adapter.getResourceAdapterConfig(
            self.getOptions().resource_adapter_configuration)

        conn = adapter.getEC2Connection(configDict)

        vpc_conn = boto.vpc.VPCConnection()

        if self.getOptions().availability_zone:
            # Command-line overrides configured availability zone
            zone = self.getOptions().availability_zone
        elif 'zone' not in configDict or not configDict['zone']:
            # Determine availability zone from configured subnet
            if 'subnet_id' in configDict:
                vpc_subnet = vpc_conn.get_all_subnets(
                    subnet_ids=[configDict['subnet_id']])

                zone = vpc_subnet[0].availability_zone
            else:
                zone = None
        else:
            zone = configDict['zone']

        product_description = 'Linux/UNIX (Amazon VPC)' \
            if 'subnet_id' in configDict else 'Linux/UNIX'

        start_time = None
        end_time = None

        now = datetime.datetime.utcnow()

        start_time = now.strftime('%Y-%m-%dT%H:%M:%S.000Z')
        end_time = start_time

        if zone == 'all':
            # Query EC2 for all zones in configured region
            zones = [zone_.name for zone_ in conn.get_all_zones()]
        else:
            zones = [zone]

        for availability_zone in zones:
            for spot_price in conn.get_spot_price_history(
                    instance_type=configDict['instancetype'],
                    product_description=product_description,
                    start_time=start_time, end_time=end_time,
                    availability_zone=availability_zone):
                print(availability_zone, spot_price.instance_type,
                      spot_price.price,
                      spot_price.product_description)
def test_invalid_settings(load_config_dict_mock, dbm):
    load_config_dict_mock.return_value = {
        'ami': 'ami-XXXXXXXX',
        'unrecognized': 'setting',
        'another_bad_setting': 'value',
    }

    with dbm.session() as session:
        with pytest.raises(ConfigurationError):
            adapter = Aws()
            adapter.session = session

            adapter.getResourceAdapterConfig()
def test_use_instance_hostname(load_config_dict_mock, dbm):
    load_config_dict_mock.return_value = {
        'ami': 'ami-XXXXXX',
        'override_dns_domain': 'true',
        'dns_domain': 'cloud.example.com',
        'use_instance_hostname': 'false',
    }

    with dbm.session() as session:
        adapter = Aws()
        adapter.session = session

        result = adapter.getResourceAdapterConfig()

        assert result['dns_domain'] == 'cloud.example.com'
예제 #9
0
def test_invalid_adapter_configuration():
    """Ensure exception is raissed from missing required settings"""

    with pytest.raises(ConfigurationError):
        with patch.object(ResourceAdapter,
                          'getResourceAdapterConfig',
                          return_value={}):
            Aws().getResourceAdapterConfig()
def test_minimal_config(dbm, minimal_configDict):
    with dbm.session() as session:
        with patch.object(
                ResourceAdapter, '_load_config_from_database',
                return_value=minimal_configDict):
            adapter = Aws()
            adapter.session = session

            config = adapter.getResourceAdapterConfig()

            assert 'ami' in config

            assert config['ami'] == 'ami-XXXXXXXX'

            assert isinstance(config['override_dns_domain'], bool)

            assert not config['override_dns_domain']
def test_override_dns_domain_enabled_with_dns_domain(dbm):
    configDict = {
        'ami': 'ami-XXXXXXXX',
        'override_dns_domain': 'true',
        'dns_domain': 'mydomain',
    }

    with dbm.session() as session:
        with patch.object(
                ResourceAdapter, '_load_config_from_database',
                return_value=configDict):
            adapter = Aws()
            adapter.session = session

            config = adapter.getResourceAdapterConfig()

            assert isinstance(config['override_dns_domain'], bool)

            assert config['override_dns_domain']

            assert config['dns_domain'] == 'mydomain'
예제 #12
0
    def runCommand(self):
        self.parseArgs()

        cfg = configparser.ConfigParser()
        cfg.read(
            os.path.join(ConfigManager().getRoot(), 'var',
                         'spot-instances.conf'))

        if not cfg.sections():
            sys.exit(0)

        adapter = Aws()
        adapter_cfg = adapter.getResourceAdapterConfig(
            self.getOptions().resource_adapter_configuration)

        session = boto3.session.Session(region_name=adapter_cfg['region'].name)

        ec2_conn = session.client('ec2')

        result = ec2_conn.describe_spot_instance_requests(
            SpotInstanceRequestIds=cfg.sections())

        for sir in result[u'SpotInstanceRequests']:
            node = cfg.get(sir[u'SpotInstanceRequestId'], 'node') \
                if cfg.has_option(sir[u'SpotInstanceRequestId'], 'node') else \
                None

            if not node:
                print('{0} {1} {2}'.format(sir['SpotInstanceRequestId'],
                                           sir[u'State'],
                                           sir[u'Status'][u'Code']))
            else:
                node_label = node \
                    if node != '<unknown>' and self.getOptions().verbose else \
                    node.split('.', 1)[0]

                print('{0} ({3}) {1} {2}'.format(sir[u'SpotInstanceRequestId'],
                                                 sir[u'State'],
                                                 sir[u'Status'][u'Code'],
                                                 node_label))
def test_get_user_data_with_node(
        load_config_dict_mock, get_config_path_mock): \
        # pylint: disable=unused-argument
    """
    Use mock data to expand SETTINGS macro
    """

    file_contents = '''
#!/usr/bin/env python

### SETTINGS


def main():
    pass


if __name__ == '__main__':
    main()
'''

    fp = io.StringIO(file_contents)

    adapter = Aws()

    config = adapter.get_config()

    class DummyNode:
        def __init__(self, name):
            self.name = name

    node = DummyNode('mynode.example.com')

    result = adapter._Aws__get_user_data_script(fp, config, node=node)

    assert result and isinstance(result, str)

    assert get_config_path_mock.called_with('blah.txt')
def test_override_dns_domain_enabled(dbm):
    configDict = {
        'ami': 'ami-XXXXXXXX',
        'override_dns_domain': 'true',
    }

    with dbm.session() as session:
        with patch.object(
                ResourceAdapter, '_load_config_from_database',
                return_value=configDict):
            adapter = Aws()
            adapter.session = session

            config = adapter.getResourceAdapterConfig()

            assert isinstance(config['override_dns_domain'], bool)

            assert config['override_dns_domain']

            # when 'dns_domain' is not specified in the resource adapter
            # configuration, the current private DNS zone is used. We don't
            # care what the value is as long as there is one.
            assert isinstance(config['dns_domain'], str)
            assert config['dns_domain']
def test_defaults(load_config_dict_mock, dbm):
    load_config_dict_mock.return_value = {
        'ami': 'ami-XXXXXXXX',
    }

    with dbm.session() as session:
        adapter = Aws()
        adapter.session = session

        result = adapter.getResourceAdapterConfig()

        assert result['ami'] == 'ami-XXXXXXXX'

        assert result['use_instance_hostname']

        assert result['associate_public_ip_address']

        assert not result['cloud_init']

        assert not result.get('override_dns_domain', None)

        assert not result.get('use_domain_from_dhcp_option_set', None)

        assert result['region'] == 'us-east-1'
예제 #16
0
def test_minimal_config(minimal_configDict):
    with patch.object(ResourceAdapter,
                      'getResourceAdapterConfig',
                      return_value=minimal_configDict):
        config = Aws().getResourceAdapterConfig()

        assert 'ami' in config

        assert config['ami'] == 'ami-XXXXXXXX'

        assert isinstance(config['override_dns_domain'], bool)

        assert not config['override_dns_domain']

        assert config['dns_domain'] is None
예제 #17
0
def test_override_dns_domain_enabled_with_dns_domain():
    configDict = {
        'ami': 'ami-XXXXXXXX',
        'override_dns_domain': str(True),
        'dns_domain': 'mydomain',
    }

    with patch.object(ResourceAdapter,
                      'getResourceAdapterConfig',
                      return_value=configDict):
        config = Aws().getResourceAdapterConfig()

        assert isinstance(config['override_dns_domain'], bool)

        assert config['override_dns_domain']

        assert config['dns_domain'] == 'mydomain'
예제 #18
0
def test_override_dns_domain_enabled():
    configDict = {
        'ami': 'ami-XXXXXXXX',
        'override_dns_domain': str(True),
    }

    with patch.object(ResourceAdapter,
                      'getResourceAdapterConfig',
                      return_value=configDict):
        config = Aws().getResourceAdapterConfig()

        assert isinstance(config['override_dns_domain'], bool)

        assert config['override_dns_domain']

        # when 'dns_domain' is not specified in the resource adapter
        # configuration, the current private DNS zone is used. We don't
        # care what the value is as long as there is one.
        assert isinstance(config['dns_domain'], str)
        assert config['dns_domain']
예제 #19
0
 def setUp(self):
     self.adapter = Aws()
예제 #20
0
class AwsAdapterTestSuite(unittest.TestCase):
    def setUp(self):
        self.adapter = Aws()

    def teardown(self):
        self.adapter = None

    def test_size_block_device_mapping(self):
        # One block device mapping entry
        sda_size = 60

        bdm = self.adapter._Aws__process_block_device_map('/dev/sda=:%d' %
                                                          (sda_size))

        self.assertTrue('/dev/sda' in bdm)

        self.assertEqual(int(bdm['/dev/sda'].size), sda_size)

    def test_ephemeral_block_device_mapping(self):
        ephemeral_name = 'ephemeral0'

        bdm = self.adapter._Aws__process_block_device_map('/dev/sdb=%s' %
                                                          (ephemeral_name))

        self.assertEqual(bdm['/dev/sdb'].ephemeral_name, ephemeral_name)

    def test_two_block_device_mapping(self):
        # Two block device mapping entries

        sda_size = 60
        ephemeral_name = 'ephemeral0'

        bdm = self.adapter._Aws__process_block_device_map(
            '/dev/sda=:%d,/dev/sdb=%s' % (sda_size, ephemeral_name))

        self.assertEqual(len(list(bdm.keys())), 2)

        self.assertTrue('/dev/sda' in bdm and '/dev/sdb' in bdm)

        self.assertEqual(int(bdm['/dev/sda'].size), sda_size)
        self.assertEqual(bdm['/dev/sdb'].ephemeral_name, ephemeral_name)

    def test_failed_block_device_mapping(self):
        self.assertRaises(InvalidArgument,
                          self.adapter._Aws__process_block_device_map,
                          'chicken')

    def test_simple_snapshot_device_mapping(self):
        snapshot_id = 'snap-ABABABAB'

        bdm = self.adapter._Aws__process_block_device_map('/dev/sda=%s' %
                                                          (snapshot_id))

        # Match snapshot_name
        self.assertEqual(bdm['/dev/sda'].snapshot_id, snapshot_id)

    def test_io1_device_mapping(self):
        volume_type = 'io1'
        iops = 500

        bdm = self.adapter._Aws__process_block_device_map('/dev/sda=:::%s:%d' %
                                                          (volume_type, iops))

        # Match volume_type
        self.assertEqual(bdm['/dev/sda'].volume_type, volume_type)

        # Match iops
        self.assertEqual(int(bdm['/dev/sda'].iops), iops)

    def test_invalid_io1_device_mapping(self):
        volume_type = 'io1'

        self.assertRaises(InvalidArgument,
                          self.adapter._Aws__process_block_device_map,
                          '/dev/sda=:::%s' % (volume_type))

    def test_simple_encrypted_device_mapping(self):
        bdm = self.adapter._Aws__process_block_device_map(
            '/dev/sda=::::encrypted')

        self.assertTrue(bdm['/dev/sda'].encrypted)

    def test_snapshot_and_encrypted_device_mapping(self):
        snapshot_id = 'snap-BBBBBBBB'
        bdm = self.adapter._Aws__process_block_device_map(
            '/dev/sda=%s::::encrypted' % (snapshot_id))

        self.assertEqual(bdm['/dev/sda'].snapshot_id, snapshot_id)
        self.assertTrue(bdm['/dev/sda'].encrypted)

    def test_empty_device_mapping(self):
        bdm = self.adapter._Aws__process_block_device_map('/dev/sda=::::')

        self.assertFalse(bdm['/dev/sda'].encrypted)