def test_nonexistent_path(self): with self.assertRaises(config.ConfigurationError): config.load( config.ConfigDetails({ 'foo': { 'build': 'nonexistent.path' }, }, 'working_dir', 'filename.yml'))
def test_load_throws_error_when_not_dict(self): with self.assertRaises(config.ConfigurationError): config.load( config.ConfigDetails( {'web': 'busybox:latest'}, 'working_dir', 'filename.yml' ) )
def test_circular(self): try: config.load("tests/fixtures/extends/circle-1.yml") raise Exception("Expected config.CircularReference to be raised") except config.CircularReference as e: self.assertEqual( [(os.path.basename(filename), service_name) for (filename, service_name) in e.trail], [("circle-1.yml", "web"), ("circle-2.yml", "web"), ("circle-1.yml", "web")], )
def test_nonexistent_path(self): with self.assertRaises(config.ConfigurationError): config.load( config.ConfigDetails( { 'foo': {'build': 'nonexistent.path'}, }, 'working_dir', 'filename.yml' ) )
def test_circular(self): try: config.load('tests/fixtures/extends/circle-1.yml') raise Exception("Expected config.CircularReference to be raised") except config.CircularReference as e: self.assertEqual( [(os.path.basename(filename), service_name) for (filename, service_name) in e.trail], [ ('circle-1.yml', 'web'), ('circle-2.yml', 'web'), ('circle-1.yml', 'web'), ], )
def parse_compose(file_dir, file_name=None): options = {} if file_name is not None: options["--file"] = [file_name] environment = Environment.from_env_file(file_dir) config_path = get_config_path_from_options(options, environment) return config.load(config.find(file_dir, config_path, environment))
def test_nested(self): service_dicts = config.load("tests/fixtures/extends/nested.yml") self.assertEqual( service_dicts, [{"name": "myweb", "image": "busybox", "command": "/bin/true", "environment": {"FOO": "2", "BAR": "2"}}], )
def test_parent_build_path_dne(self): child = config.load("tests/fixtures/extends/nonexistent-path-child.yml") self.assertEqual( child, [{"name": "dnechild", "image": "busybox", "command": "/bin/true", "environment": {"FOO": "1", "BAR": "2"}}], )
def test_extends(self): service_dicts = config.load('tests/fixtures/extends/docker-compose.yml') service_dicts = sorted( service_dicts, key=lambda sd: sd['name'], ) self.assertEqual(service_dicts, [ { 'name': 'mydb', 'image': 'busybox', 'command': 'sleep 300', }, { 'name': 'myweb', 'image': 'busybox', 'command': 'sleep 300', 'links': ['mydb:db'], 'environment': { "FOO": "1", "BAR": "2", "BAZ": "2", }, } ])
def test_from_file(self): service_dict = config.load( 'tests/fixtures/build-path/docker-compose.yml') self.assertEquals(service_dict, [{ 'name': 'foo', 'build': self.abs_context_path }])
def test_load(self): service_dicts = config.load( config.ConfigDetails( { 'foo': {'image': 'busybox'}, 'bar': {'environment': ['FOO=1']}, }, 'working_dir', 'filename.yml' ) ) self.assertEqual( sorted(service_dicts, key=lambda d: d['name']), sorted([ { 'name': 'bar', 'environment': {'FOO': '1'}, }, { 'name': 'foo', 'image': 'busybox', } ]) )
def _load_compose_config(self): with (self.kard.path / self.COMPOSE_FILE).open('r') as cp_file: compose_data = yaml.safe_load(cp_file) return docker_config.load( docker_config.config.ConfigDetails( str(self.kard.path), [docker_config.config.ConfigFile( self.COMPOSE_FILE, compose_data)]))
def test_volume_path(self): dicts = config.load('tests/fixtures/volume-path/docker-compose.yml') paths = [ '%s:/foo' % os.path.abspath('tests/fixtures/volume-path/common/foo'), '%s:/bar' % os.path.abspath('tests/fixtures/volume-path/bar'), ] self.assertEqual(set(dicts[0]['volumes']), set(paths))
def test_volume_path(self): dicts = config.load("tests/fixtures/volume-path/docker-compose.yml") paths = [ "%s:/foo" % os.path.abspath("tests/fixtures/volume-path/common/foo"), "%s:/bar" % os.path.abspath("tests/fixtures/volume-path/bar"), ] self.assertEqual(set(dicts[0]["volumes"]), set(paths))
def open_compose_data(self, project_id): """ Use Docker Compose to load the data of a project given in parameter. Return a Docker Compose data object. """ project_dir = '/data/%s' % project_id config_files = config.config.get_default_config_files(project_dir) environment = Environment.from_env_file(project_dir) config_details = config.find(project_dir, config_files, environment) return config.load(config_details)
def gen_services(path): parent = str(path.parent) env = config.environment.Environment.from_env_file(parent) details = config.find(parent, [path.name], env) resolved = config.load(details) for s in resolved.services: if "image" not in s: raise RuntimeError("Service {!r} have no 'image' field".format( s["name"])) yield s
def get_config(basedir, files): """ Returns the config object for the selected docker-compose.yml This is an instance of `compose.config.config.Config`. """ config_details = config.find( basedir, files, environment.Environment.from_env_file(basedir)) return config.load(config_details)
def test_load(self): service_dicts = config.load( config.ConfigDetails( {"foo": {"image": "busybox"}, "bar": {"environment": ["FOO=1"]}}, "working_dir", "filename.yml" ) ) self.assertEqual( sorted(service_dicts, key=lambda d: d["name"]), sorted([{"name": "bar", "environment": {"FOO": "1"}}, {"name": "foo", "image": "busybox"}]), )
def get_compose_context(options): base_dir = str(options['project_dir']) environment = compose_config.environment.Environment.from_env_file(base_dir) config_details = compose_config.find(base_dir, options['compose_files'], environment) config = compose_config.load(config_details) unknown_services = set(options['services']) - set(x['name'] for x in config.services) if unknown_services: log.error('Unknown services: %s' % ', '.join(unknown_services)) raise SystemExit(1) if not options['services']: options['services'] = tuple(x['name'] for x in config.services) return config, config_details, environment
def from_compose(self, project_name=None, filename='docker-compose.yml'): """Return a host group with hosts names extracted from compose file""" from compose.project import Project from compose import config project_dir = os.getcwd() project_name = project_name or os.path.basename(project_dir) conf = config.load(config.find(project_dir, [filename], os.environ)) project = Project.from_config('', conf, client=None) for service in project.get_services(): name = '{0}-{1.name}-1'.format(project_name, service) self.get_or_create_node(hostname=name) return self
def get_project(compose_file=COMPOSE_FILE): from compose import __version__ as compose_version from compose.config import find, load from compose.project import Project from compose.cli.docker_client import docker_client if compose_version.startswith('1.4'): yaml_file = find('.', str(compose_file)) else: # compose >= 1.5 yaml_file = find('.', [str(compose_file)]) config = load(yaml_file) return Project.from_dicts(PROJECT_NAME, config, docker_client())
def test_nested(self): service_dicts = config.load('tests/fixtures/extends/nested.yml') self.assertEqual(service_dicts, [ { 'name': 'myweb', 'image': 'busybox', 'command': '/bin/true', 'environment': { "FOO": "2", "BAR": "2", }, }, ])
def test_parent_build_path_dne(self): child = config.load('tests/fixtures/extends/nonexistent-path-child.yml') self.assertEqual(child, [ { 'name': 'dnechild', 'image': 'busybox', 'command': '/bin/true', 'environment': { "FOO": "1", "BAR": "2", }, }, ])
def get_compose_context(options): base_dir = str(options["project_dir"]) environment = compose_config.environment.Environment.from_env_file( base_dir) config_details = compose_config.find(base_dir, options["compose_files"], environment) config = compose_config.load(config_details) unknown_services = set(options["services"]) - set(x["name"] for x in config.services) if unknown_services: log.error("Unknown services: %s" % ", ".join(unknown_services)) raise SystemExit(1) if not options["services"]: options["services"] = tuple(x["name"] for x in config.services) return config, config_details, environment
def test_parent_build_path_dne(self): child = config.load( 'tests/fixtures/extends/nonexistent-path-child.yml') self.assertEqual(child, [ { 'name': 'dnechild', 'image': 'busybox', 'command': '/bin/true', 'environment': { "FOO": "1", "BAR": "2", }, }, ])
def get_compose_context(options): base_dir = str(options['project_dir']) environment = compose_config.environment.Environment.from_env_file( base_dir) config_details = compose_config.find(base_dir, options['compose_files'], environment) config = compose_config.load(config_details) unknown_services = set(options['services']) - set(x['name'] for x in config.services) if unknown_services: log.error('Unknown services: %s' % ', '.join(unknown_services)) raise SystemExit(1) if not options['services']: options['services'] = tuple(x['name'] for x in config.services) return config, config_details, environment
def test_extends(self): service_dicts = config.load("tests/fixtures/extends/docker-compose.yml") service_dicts = sorted(service_dicts, key=lambda sd: sd["name"]) self.assertEqual( service_dicts, [ {"name": "mydb", "image": "busybox", "command": "top"}, { "name": "myweb", "image": "busybox", "command": "top", "links": ["mydb:db"], "environment": {"FOO": "1", "BAR": "2", "BAZ": "2"}, }, ], )
def update_image(filename, new_image, service_name='web'): """ Update service image name to new_image. """ path = os.path.dirname(filename) conf_file = ConfigFile.from_filename(filename) conf = load(ConfigDetails(path, [conf_file], None)) # find service for i in range(len(conf.services)): service = conf.services[i] if service['name'] == service_name: conf.services[i]['image'] = new_image out = open(filename, 'w') out.write(serialize_config(conf)) out.close() return filename
def build(filename, env_dict=None, output_path=None): """ Build docker-compose.yml file from services & env. """ path = os.path.dirname(filename) conf_file = ConfigFile.from_filename(filename) env = Environment(env_dict) if env_dict else None conf = load(ConfigDetails(path, [conf_file], env)) output_path = output_path if output_path else path + '/docker-compose.yml' # try to make directory if os.path.dirname(output_path): os.makedirs(os.path.dirname(output_path)) out = open(output_path, 'w') out.write(serialize_config(conf)) out.close() return output_path
def test_extends(self): service_dicts = config.load( 'tests/fixtures/extends/docker-compose.yml') service_dicts = sorted( service_dicts, key=lambda sd: sd['name'], ) self.assertEqual(service_dicts, [{ 'name': 'mydb', 'image': 'busybox', 'command': 'sleep 300', }, { 'name': 'myweb', 'image': 'busybox', 'command': 'sleep 300', 'links': ['mydb:db'], 'environment': { "FOO": "1", "BAR": "2", "BAZ": "2", }, }])
def make_project(self, cfg): return Project.from_dicts(name='composetest', client=self.client, service_dicts=config.load( config.ConfigDetails( cfg, 'working_dir', None)))
def make_project(self, cfg): return Project.from_dicts( name='composetest', client=self.client, service_dicts=config.load(config.ConfigDetails(cfg, 'working_dir', None)) )
def _get_config(self, name): filename = path.abspath('{name}.yml'.format(name=name)) return config.load(filename)
if not os.path.exists(os.path.join(WORKDIR, '.env')): copyfile( os.path.join(WORKDIR, './.env.example'), os.path.join(WORKDIR, './.env'), ) configs = [] for file in CONFIGS: print(f'Reading file: {file}') with open(file, 'r') as f: configs.append(ConfigFile(None, yaml.safe_load(f.read()))) print('Building config') env = config.environment.Environment() details = ConfigDetails(WORKDIR, configs, env) cfg = config.load(details, False) def relativize(path: str) -> str: result = f'./{os.path.relpath(path, WORKDIR)}' if path and path.startswith( WORKDIR) else path if result in REPLACE_MOUNTS: result = REPLACE_MOUNTS[result] return result print('Preprocessing config') for service in cfg.services: print(f'\tPreprocessing service: {service["name"]}') if 'build' in service: service.pop('build')
def load_from_filename(filename): return config.load(config.find('.', filename))
UID_ENVIRONMENT_KEY = "MANAGER_UID" COMPOSE_DIRECTORY = "/compose" if __name__ == "__main__": manager_uid = os.environ.get("MANAGER_UID") listened_container = os.environ.get("MANAGER_LISTEN_SERVICE", None) WORKING_DIR = "/compose-fin" shutil.copytree(COMPOSE_DIRECTORY, WORKING_DIR) client = docker.from_env() node_id = client.info()["Swarm"]["NodeID"] config = compose_config.load( compose_config.find( WORKING_DIR, ["docker-compose.yml"], compose_config.environment.Environment(os.environ) ) ) services = config.services for service in services: if 'deploy' not in service: service['deploy'] = {} service['deploy']['placement'] = {} service['deploy']['placement']['constraints'] = [ 'node.id == ' + node_id] service['deploy']['restart_policy'] = {} service['deploy']['restart_policy']['condition'] = 'none' final_file_path = os.path.join(WORKING_DIR, 'docker-compose-final.yml')
def test_load_throws_error_when_not_dict(self): with self.assertRaises(config.ConfigurationError): config.load(config.ConfigDetails({"web": "busybox:latest"}, "working_dir", "filename.yml"))
def test_nonexistent_path(self): with self.assertRaises(config.ConfigurationError): config.load(config.ConfigDetails({"foo": {"build": "nonexistent.path"}}, "working_dir", "filename.yml"))
def test_from_file(self): service_dict = config.load("tests/fixtures/build-path/docker-compose.yml") self.assertEquals(service_dict, [{"name": "foo", "build": self.abs_context_path}])
def test_from_file(self): service_dict = config.load('tests/fixtures/build-path/docker-compose.yml') self.assertEquals(service_dict, [{'name': 'foo', 'build': self.abs_context_path}])
def build_service_dicts(service_config): return config.load(config.ConfigDetails(service_config, 'working_dir', None))