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
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')
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
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)
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
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()
def setUp(self): self.unit = FlotillaUnit(UNIT_NAME, UNIT_FILE) self.revision = FlotillaServiceRevision(label=REV_LABEL, units=[self.unit])
def test_environment(self): self.unit = FlotillaUnit(UNIT_NAME, UNIT_FILE, environment={'foo': 'bar'}) self.assertNotEqual(self.unit.unit_hash, UNIT_HASH)
def setUp(self): self.unit = FlotillaUnit(UNIT_NAME, UNIT_FILE)