Esempio n. 1
0
    def get_units(self, assigned_revisions):
        """
        Get currently assigned FlotillaUnits.
        :param assigned_revisions: Assigned revisions
        :return: Revisions.
        """

        # Fetch every revision and index units:
        revisions = {}
        unit_revisions = defaultdict(list)
        revision_keys = [{
            'rev_hash': assigned_revision
        } for assigned_revision in set(assigned_revisions)]
        for revision_item in self._revisions.batch_get(revision_keys):
            rev_hash = revision_item['rev_hash']
            revision = FlotillaServiceRevision(label=revision_item['label'])
            revisions[rev_hash] = revision
            for unit in revision_item['units']:
                unit_revisions[unit].append(rev_hash)

        # Fetch every unit:
        units = []
        unit_keys = [{
            'unit_hash': unit_hash
        } for unit_hash in sorted(unit_revisions.keys())]
        logger.debug('Fetching %d units for %d/%d revisions.', len(unit_keys),
                     len(revisions), len(assigned_revisions))
        for unit_item in self._units.batch_get(unit_keys):
            env_key = unit_item.get('environment_key')
            if env_key:
                decrypted_key = self._kms.decrypt(env_key.decode('base64'))
                iv = unit_item['environment_iv'].decode('base64')
                aes = AES.new(decrypted_key['Plaintext'], AES.MODE_CBC, iv)
                ciphertext = unit_item['environment_data'].decode('base64')
                plaintext = aes.decrypt(ciphertext)
                unit_environment = json.loads(plaintext)
            else:
                unit_environment = unit_item['environment']
            unit_file = unit_item['unit_file']
            unit = FlotillaUnit(unit_item['name'], unit_file, unit_environment)
            unit_hash = unit.unit_hash
            if unit_hash != unit_item['unit_hash']:
                logger.warn('Unit hash %s expected %s', unit_hash,
                            unit_item['unit_hash'])
                unit_hash = unit_item['unit_hash']

            for revision in unit_revisions[unit_hash]:
                rev_unit = FlotillaUnit(unit_item['name'], unit_file,
                                        unit_environment, rev_hash)
                units.append(rev_unit)
                revisions[revision].units.append(rev_unit)

        # Verify each revision matches expected hash:
        for expected_hash, revision in revisions.items():
            revision_hash = revision.revision_hash
            if revision_hash != expected_hash:
                # FIXME: enforce?
                logger.warn('Revision hash %s expected %s', revision_hash,
                            expected_hash)
        return units
Esempio n. 2
0
class TestFlotillaUnit(unittest.TestCase):
    def setUp(self):
        self.unit = FlotillaUnit(UNIT_NAME, UNIT_FILE)

    def test_constructor(self):
        self.assertEqual(self.unit.name, UNIT_NAME)
        self.assertEqual(self.unit.unit_file, UNIT_FILE)

    def test_unit_hash(self):
        self.assertEqual(self.unit.unit_hash, UNIT_HASH)

    def test_to_string(self):
        self.assertTrue(self.unit.__str__().find(UNIT_NAME) > -1)

    def test_environment(self):
        self.unit = FlotillaUnit(UNIT_NAME,
                                 UNIT_FILE,
                                 environment={'foo': 'bar'})
        self.assertNotEqual(self.unit.unit_hash, UNIT_HASH)

    def test_full_name(self):
        self.assertEqual(self.unit.full_name, UNIT_FULL_NAME)

    def test_full_name_rev_hash(self):
        self.unit.rev_hash = '000000'
        self.assertEqual(self.unit.full_name, 'flotilla-test-000000.service')
Esempio n. 3
0
def get_units(services, environments):
    units = []
    for name, service in services.items():
        env = environments.get(name, {})
        unit = FlotillaUnit('%s.service' % name, service, env)
        units.append(unit)
    for name, env in environments.items():
        if name in services:
            continue

        image = env.get('DOCKER_IMAGE')
        if not image:
            continue
        del env['DOCKER_IMAGE']

        ports = {}
        for key, value in env.items():
            try:
                if key.startswith('DOCKER_PORT_'):
                    ports[int(key[12:])] = int(value)
                    del env[key]
            except:
                continue

        logdriver = env.get('DOCKER_LOG_DRIVER')
        if logdriver:
            del env['DOCKER_LOG_DRIVER']

        unit = FlotillaDockerService('%s.service' % name, image, ports=ports,
                                     environment=env, logdriver=logdriver)
        units.append(unit)
    return units
Esempio n. 4
0
    def test_set_units_service_mapping(self):
        depending_unit = FlotillaUnit('dependent.service', '''[Unit]
After=redis.service
''')
        self.systemd.set_units([self.flotilla_unit, depending_unit])

        unit_path = '%s/%s' % (self.unit_dir, depending_unit.full_name)
        self.assertTrue(os.path.isfile(unit_path))
        with open(unit_path) as unit_in:
            unit_contents = unit_in.read()
        self.assertFalse('redis.service' in unit_contents)
        self.assertTrue(self.flotilla_unit.full_name in unit_contents)
Esempio n. 5
0
def get_units(files):
    services = {}
    environments = {}

    for path, contents in files.items():
        filename = os.path.basename(path)
        name, extension = os.path.splitext(filename)

        if extension == '.service' and contents:
            services[name] = contents
        elif extension == '.env':
            environments[name] = parse_env(contents)

    units = []
    for name, service in services.items():
        env = environments.get(name, {})
        unit = FlotillaUnit('%s.service' % name, service, env)
        units.append(unit)

    for name, env in environments.items():
        if name in services:
            continue

        image = env.get('DOCKER_IMAGE')
        if not image:
            continue
        del env['DOCKER_IMAGE']

        ports = {}
        for key, value in env.items():
            try:
                if key.startswith('DOCKER_PORT_'):
                    ports[int(key[12:])] = int(value)
                    del env[key]
            except:
                continue

        logdriver = env.get('DOCKER_LOG_DRIVER')
        if logdriver:
            del env['DOCKER_LOG_DRIVER']

        unit = FlotillaDockerService('%s.service' % name,
                                     image,
                                     ports=ports,
                                     environment=env,
                                     logdriver=logdriver)
        units.append(unit)

    return units
Esempio n. 6
0
    def get_revisions(self, service):
        try:
            service_item = self._services.get_item(service_name=service)
        except ItemNotFound:
            return []

        # Select revisions and build weight-only return values:
        rev_hashes = [k for k in service_item.keys() if k != 'service_name']
        logger.debug('Found %d revisions in %s.', len(rev_hashes), service)
        flotilla_revisions = {}
        for rev_hash in rev_hashes:
            flotilla_revisions[rev_hash] = FlotillaServiceRevision(
                weight=service_item[rev_hash])

        # Load revisions, collect units and index:
        unit_rev = defaultdict(list)
        revisions = self._revisions.batch_get(keys=[{
            'rev_hash': rev_hash
        } for rev_hash in rev_hashes])
        for revision in revisions:
            rev_hash = revision['rev_hash']
            for unit in revision['units']:
                unit_rev[unit].append(rev_hash)
            flotilla_revisions[rev_hash].label = revision['label']
        logger.debug('Mapped %d revisions to %s units.', len(rev_hashes),
                     len(unit_rev))

        # Load units, add to return values
        service_units = self._units.batch_get(keys=[{
            'unit_hash': unit_hash
        } for unit_hash in unit_rev.keys()])
        for unit in service_units:
            flotilla_unit = FlotillaUnit(unit['name'], unit['unit_file'],
                                         unit['environment'])

            unit_revs = unit_rev[unit['unit_hash']]
            logger.debug('Adding to %d revisions.', len(unit_revs))
            for rev in unit_revs:
                flotilla_revisions[rev].units.append(flotilla_unit)
        return flotilla_revisions.values()
Esempio n. 7
0
 def setUp(self):
     self.unit = FlotillaUnit(UNIT_NAME, UNIT_FILE)
     self.revision = FlotillaServiceRevision(label=REV_LABEL,
                                             units=[self.unit])
Esempio n. 8
0
 def test_environment(self):
     self.unit = FlotillaUnit(UNIT_NAME,
                              UNIT_FILE,
                              environment={'foo': 'bar'})
     self.assertNotEqual(self.unit.unit_hash, UNIT_HASH)
Esempio n. 9
0
 def setUp(self):
     self.unit = FlotillaUnit(UNIT_NAME, UNIT_FILE)