def top_level_cmd(self): try: compose_files = self.get_compose_files() config_path = get_config_path_from_options( ".", {}, {"COMPOSE_FILE": compose_files}, ) os.environ["COMPOSE_FILE"] = compose_files for k, v in self.settings.items(): if k == "CONFIGURATION_OPTIONAL_SCOPES": continue if isinstance(v, bool): v = f"{v}".lower() if isinstance(v, int): v = str(v) os.environ[k] = v env = Environment() env.update(os.environ) project = get_project(os.getcwd(), config_path, environment=env) tlc = TopLevelCommand(project) yield tlc except Exception: # noqa: B902 raise
def test_get_simple(self): env = Environment({ 'FOO': 'bar', 'BAR': '1', 'BAZ': '' }) assert env.get('FOO') == 'bar' assert env.get('BAR') == '1' assert env.get('BAZ') == ''
def test_get_boolean(self): env = Environment({ 'FOO': '', 'BAR': '0', 'BAZ': 'FALSE', 'FOOBAR': 'true', }) assert env.get_boolean('FOO') is False assert env.get_boolean('BAR') is False assert env.get_boolean('BAZ') is False assert env.get_boolean('FOOBAR') is True assert env.get_boolean('UNDEFINED') is False
def config(self, config_options, options): """ Validate and view the compose file. Usage: config [options] Options: -q, --quiet Only validate the configuration, don't print anything. --services Print the service names, one per line. """ print "project dir:" + self.project_dir environment = Environment.from_env_file(self.project_dir) print environment config_path = get_config_path_from_options(self.project_dir, config_options, environment) compose_config = config.load( config.find(self.project_dir, config_path, environment)) if options['--quiet']: return if options['--services']: print('\n'.join(service['name'] for service in compose_config.services)) return print(serialize_config(compose_config))
def setUpClass(cls): if engine_version_too_low_for_v2(): version = API_VERSIONS[V1] else: version = API_VERSIONS[V2_0] cls.client = docker_client(Environment(), version)
def load_docker_env(): # TODO: remove this since it is likely no longer needed from compose.config.environment import Environment environment = os.environ # environment.update({key: val for key, val in config["DOCKER_ENV"].items()}) return Environment(environment)
def test_unicode_path_from_env(self): with mock.patch.dict(os.environ): os.environ['COMPOSE_FILE'] = b'\xe5\xb0\xb1\xe5\x90\x83\xe9\xa5\xad/docker-compose.yml' environment = Environment.from_env_file('.') assert get_config_path_from_options( '.', {}, environment ) == ['就吃饭/docker-compose.yml']
def test_unicode_path_from_options(self): paths = [b'\xe5\xb0\xb1\xe5\x90\x83\xe9\xa5\xad/docker-compose.yml'] opts = {'--file': paths} environment = Environment.from_env_file('.') assert get_config_path_from_options( '.', opts, environment ) == ['就吃饭/docker-compose.yml']
def test_unicode_path_from_env(self): with mock.patch.dict(os.environ): os.environ[ 'COMPOSE_FILE'] = b'\xe5\xb0\xb1\xe5\x90\x83\xe9\xa5\xad/docker-compose.yml' environment = Environment.from_env_file('.') assert get_config_path_from_options( '.', {}, environment) == ['就吃饭/docker-compose.yml']
def test_tls_simple_with_tls_version(self): tls_version = 'TLSv1' options = {'--tls': True} environment = Environment({'COMPOSE_TLS_VERSION': tls_version}) result = tls_config_from_options(options, environment) assert isinstance(result, docker.tls.TLSConfig) assert result.ssl_version == ssl.PROTOCOL_TLSv1
def containers(): """ active containers """ version = API_VERSIONS[V2_0] client = docker_client(Environment(), version) return client.containers()
def test_multiple_path_from_env_windows(self): with mock.patch.dict(os.environ): os.environ['COMPOSE_FILE'] = 'one.yml;two.yml' environment = Environment.from_env_file('.') assert get_config_path_from_options( '.', {}, environment ) == ['one.yml', 'two.yml']
def test_multiple_path_from_env_custom_separator(self): with mock.patch.dict(os.environ): os.environ['COMPOSE_PATH_SEPARATOR'] = '^' os.environ['COMPOSE_FILE'] = 'c:\\one.yml^.\\semi;colon.yml' environment = Environment.from_env_file('.') assert get_config_path_from_options( {}, environment) == ['c:\\one.yml', '.\\semi;colon.yml']
def test_interpolate_environment_variables_in_services(mock_env): services = { 'servicea': { 'image': 'example:${USER}', 'volumes': ['$FOO:/target'], 'logging': { 'driver': '${FOO}', 'options': { 'user': '******', } } } } expected = { 'servicea': { 'image': 'example:jenny', 'volumes': ['bar:/target'], 'logging': { 'driver': 'bar', 'options': { 'user': '******', } } } } assert interpolate_environment_variables( services, 'service', Environment.from_env_file(None) ) == expected
def config(self, config_options, options): """ Validate and view the compose file. Usage: config [options] Options: -q, --quiet Only validate the configuration, don't print anything. --services Print the service names, one per line. """ print "project dir:" + self.project_dir environment = Environment.from_env_file(self.project_dir) print environment config_path = get_config_path_from_options( self.project_dir, config_options, environment ) compose_config = config.load( config.find(self.project_dir, config_path, environment) ) if options['--quiet']: return if options['--services']: print('\n'.join(service['name'] for service in compose_config.services)) return print(serialize_config(compose_config))
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_multiple_path_from_env_custom_separator(self): with mock.patch.dict(os.environ): os.environ['COMPOSE_PATH_SEPARATOR'] = '^' os.environ['COMPOSE_FILE'] = 'c:\\one.yml^.\\semi;colon.yml' environment = Environment.from_env_file('.') assert get_config_path_from_options( '.', {}, environment ) == ['c:\\one.yml', '.\\semi;colon.yml']
def test_get_project(self): base_dir = 'tests/fixtures/longer-filename-composefile' env = Environment.from_env_file(base_dir) env['COMPOSE_API_VERSION'] = DEFAULT_DOCKER_API_VERSION project = get_project(base_dir, environment=env) assert project.name == 'longer-filename-composefile' assert project.client assert project.services
def test_tls_mixed_environment_and_flags(self): options = {'--tls': True, '--tlsverify': False} environment = Environment({'DOCKER_CERT_PATH': 'tests/fixtures/tls/'}) result = tls_config_from_options(options, environment) assert isinstance(result, docker.tls.TLSConfig) assert result.cert == (self.client_cert, self.key) assert result.ca_cert == self.ca_cert assert result.verify is False
def get_project(path): """ get docker project given file path """ logging.debug('get project ' + path) environment = Environment.from_env_file(path) config_path = get_config_path_from_options(path, dict(), environment) project = compose_get_project(path, config_path) return project
def get_project(path, project_name=None): """ get docker project given file path """ environment = Environment.from_env_file(path) config_path = get_config_path_from_options(path, dict(), environment) project = compose_get_project(path, config_path, project_name=project_name, host='{0}:{1}'.format(config.swarm_scheduling_host, config.swarm_scheduling_port)) return project
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 load_config(self, project_dir, options): try: environment = Environment.from_env_file(project_dir) config_path = get_config_path_from_options(project_dir, options, environment) config_details = config.find(project_dir, config_path, environment) self.config = config.load(config_details) except ComposeFileNotFound: self.config = False self._load_plugins()
def __get_compose_project(self): client = docker_client(Environment()) config_data = config.load( config.ConfigDetails( self.home_path, [config.ConfigFile.from_filename(self.compose_file)])) return DockerComposeProject.from_config(name='metal', client=client, config_data=config_data)
def test_tls_verify_default_cert_path(self): environment = Environment({'DOCKER_TLS_VERIFY': '1'}) options = {'--tls': True} with mock.patch('compose.cli.docker_client.default_cert_path') as dcp: dcp.return_value = 'tests/fixtures/tls/' result = tls_config_from_options(options, environment) assert isinstance(result, docker.tls.TLSConfig) assert result.verify is True assert result.ca_cert == self.ca_cert assert result.cert == (self.client_cert, self.key)
def get_project(template_path): """ Get compose project with given template file path :param template_path: path of the compose template file :return: project object """ environment = Environment.from_env_file(template_path) config_path = compose_get_config_path_from_options(template_path, dict(), environment) project = compose_get_project(template_path, config_path) return project
def mock_env(): return Environment({ 'USER': '******', 'FOO': 'bar', 'TRUE': 'True', 'FALSE': 'OFF', 'POSINT': '50', 'NEGINT': '-200', 'FLOAT': '0.145', 'MODE': '0600', })
def init_project(orgId): print("[init_project]: Compose project init started...") namespace, api_data, repl = create_customer(orgId) environment = Environment.from_env_file(FOLDER_PATH) config_path = get_config_path_from_options(FOLDER_PATH, dict(), environment) project = get_project(FOLDER_PATH, config_path, namespace) project_name = get_project_name(FOLDER_PATH, namespace) print("[init_project]: Compose project init finished...") return (project, namespace, api_data, repl)
def test_env_file_override(self): base_dir = 'tests/fixtures/env-file-override' dispatch(base_dir, ['--env-file', '.env.override', 'up']) project = get_project(project_dir=base_dir, config_path=['docker-compose.yml'], environment=Environment.from_env_file( base_dir, '.env.override'), override_dir=base_dir) containers = project.containers(stopped=True) assert len(containers) == 1 assert "WHEREAMI=override" in containers[0].get('Config.Env') assert "DEFAULT_CONF_LOADED=true" in containers[0].get('Config.Env') dispatch(base_dir, ['--env-file', '.env.override', 'down'], None)
def test_dot_env_file(self): base_dir = 'tests/fixtures/env-file-override' # '.env' is relative to the project_dir (base_dir) env = Environment.from_env_file(base_dir, None) dispatch(base_dir, ['up']) project = get_project(project_dir=base_dir, config_path=['docker-compose.yml'], environment=env, override_dir=base_dir) containers = project.containers(stopped=True) assert len(containers) == 1 assert "WHEREAMI=default" in containers[0].get('Config.Env') dispatch(base_dir, ['down'], None)
def create_service(self, name, **kwargs): if 'image' not in kwargs and 'build' not in kwargs: kwargs['image'] = 'busybox:latest' if 'command' not in kwargs: kwargs['command'] = ["top"] kwargs['environment'] = resolve_environment( kwargs, Environment.from_env_file(None) ) labels = dict(kwargs.setdefault('labels', {})) labels['com.docker.compose.test-name'] = self.id() return Service(name, client=self.client, project='composetest', **kwargs)
def generate(self): logger.info('Writing .env file') env = Environment.from_env_file('.') to_add = [] for key, fun in self.keys.items(): if env.get(key): logger.debug( '%s already present in .env, not modified' % key) else: logger.debug('Adding %s to .env' % key) to_add.append('%s=%s' % (key, fun())) for line in to_add: # append line to file (echo[line] >> '.env')()
def test_tls_verify_flag_no_override(self): environment = Environment({ 'DOCKER_TLS_VERIFY': 'true', 'COMPOSE_TLS_VERSION': 'TLSv1' }) options = {'--tls': True, '--tlsverify': False} result = tls_config_from_options(options, environment) assert isinstance(result, docker.tls.TLSConfig) assert result.ssl_version == ssl.PROTOCOL_TLSv1 # verify is a special case - since `--tlsverify` = False means it # wasn't used, we set it if either the environment or the flag is True # see https://github.com/docker/compose/issues/5632 assert result.verify is True
def get_version_info(self, original_fnc, no_cache=False, pull=False, force_rm=False): tmp_docker_file_name_with_path = None if 'build' in self.options: environment = merge_two_dicts(self.options.get('environment', {}), dict(Environment.from_env_file('.'))) build_path = self.options['build']['context'] if 'dockerfile' in self.options['build']: docker_file_name = self.options['build']['dockerfile'] else: docker_file_name = 'Dockerfile' docker_file_name_with_path = os.path.join(build_path, docker_file_name) tmp_docker_file_name_with_path = os.path.join( build_path, '.tmp_' + docker_file_name) with open(docker_file_name_with_path, 'r') as docker_file,\ open(tmp_docker_file_name_with_path, 'w') as tmp_docker_file: for line in docker_file: line_to_write = None for command in docker_build_interpolatable_commands: if line.strip().startswith(command): line_to_write = interpolate(line, environment) if line_to_write is None: line_to_write = line tmp_docker_file.write(line_to_write) self.options['build']['dockerfile'] = tmp_docker_file_name_with_path try: return_value = original_fnc(self, no_cache, pull, force_rm) if tmp_docker_file_name_with_path is not None: os.remove(tmp_docker_file_name_with_path) return return_value except BuildError as e: if tmp_docker_file_name_with_path is not None: os.remove(tmp_docker_file_name_with_path) raise e
def get_dork_project_name(working_dir, project_name=None, environment=None): def normalize_name(name): # Full copy because compose strips dashes from project names. return re.sub(r'[^a-z0-9\-]', '', name.lower()) if not environment: environment = Environment.from_env_file(working_dir) project_name = project_name or environment.get('COMPOSE_PROJECT_NAME') if project_name: return normalize_name(project_name) project = os.path.basename(os.path.abspath(working_dir)) if project: return normalize_name(project) return 'default'
def test_tls_flags_override_environment(self): environment = Environment({ 'DOCKER_CERT_PATH': '/completely/wrong/path', 'DOCKER_TLS_VERIFY': 'false' }) options = { '--tlscacert': '"{}"'.format(self.ca_cert), '--tlscert': '"{}"'.format(self.client_cert), '--tlskey': '"{}"'.format(self.key), '--tlsverify': True } result = tls_config_from_options(options, environment) assert isinstance(result, docker.tls.TLSConfig) assert result.cert == (self.client_cert, self.key) assert result.ca_cert == self.ca_cert assert result.verify is True
def test_interpolate_environment_variables_in_volumes(mock_env): volumes = { 'data': { 'driver': '$FOO', 'driver_opts': { 'max': 2, 'user': '******' } }, 'other': None, } expected = { 'data': { 'driver': 'bar', 'driver_opts': { 'max': 2, 'user': '******' } }, 'other': {}, } assert interpolate_environment_variables( volumes, 'volume', Environment.from_env_file(None) ) == expected
def test_no_path(self): environment = Environment.from_env_file('.') assert not get_config_path_from_options('.', {}, environment)
def test_path_from_options(self): paths = ['one.yml', 'two.yml'] opts = {'--file': paths} environment = Environment.from_env_file('.') assert get_config_path_from_options('.', opts, environment) == paths
def test_get_undefined(self): env = Environment({ 'FOO': 'bar' }) assert env.get('FOOBAR') is None