def test_run_service_with_restart_always(self): mock_client = mock.create_autospec(docker.APIClient) mock_client.api_version = DEFAULT_DOCKER_API_VERSION mock_client._general_configs = {} project = Project.from_config( name='composetest', client=mock_client, config_data=build_config( {'service': { 'image': 'busybox', 'restart': 'always', }}), ) command = TopLevelCommand(project) command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--label': [], '--user': None, '--no-deps': None, '--detach': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--use-aliases': None, '--publish': [], '--volume': [], '--rm': None, '--name': None, '--workdir': None, }) assert mock_client.create_host_config.call_args[1]['restart_policy'][ 'Name'] == 'always' command = TopLevelCommand(project) command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--label': [], '--user': None, '--no-deps': None, '--detach': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--use-aliases': None, '--publish': [], '--volume': [], '--rm': True, '--name': None, '--workdir': None, }) assert not mock_client.create_host_config.call_args[1].get( 'restart_policy')
def test_run_service_with_restart_always(self): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service( 'service', client=mock_client, restart={ 'Name': 'always', 'MaximumRetryCount': 0 }, image='someimage') command.run( mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '--allow-insecure-ssl': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': None, '--name': None, }) self.assertEquals( mock_client.create_host_config.call_args[1]['restart_policy'] ['Name'], 'always') command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service('service', client=mock_client, restart='always', image='someimage') command.run( mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '--allow-insecure-ssl': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': True, '--name': None, }) self.assertFalse( mock_client.create_host_config.call_args[1].get('restart_policy'))
def test_run_service_with_restart_always(self): mock_client = mock.create_autospec(docker.Client) project = Project.from_config( name='composetest', client=mock_client, config_data=build_config({ 'service': { 'image': 'busybox', 'restart': 'always', } }), ) command = TopLevelCommand(project) command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': None, '--name': None, '--workdir': None, }) self.assertEquals( mock_client.create_host_config.call_args[1]['restart_policy']['Name'], 'always' ) command = TopLevelCommand(project) command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': True, '--name': None, '--workdir': None, }) self.assertFalse( mock_client.create_host_config.call_args[1].get('restart_policy') )
def test_run_service_with_restart_always(self): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service('service', client=mock_client, restart='always', image='someimage') command.run( mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '--allow-insecure-ssl': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': None, '--name': None, }) _, _, call_kwargs = mock_client.create_container.mock_calls[0] self.assertEquals(call_kwargs['host_config']['RestartPolicy']['Name'], 'always') command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service('service', client=mock_client, restart='always', image='someimage') command.run( mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '--allow-insecure-ssl': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': True, '--name': None, }) _, _, call_kwargs = mock_client.create_container.mock_calls[0] self.assertFalse('RestartPolicy' in call_kwargs['host_config'])
def up(project_path): up_options = { "-d": True, "--no-color": False, "--no-deps": False, "--build": False, "--abort-on-container-exit": False, "--remove-orphans": False, "--no-recreate": True, "--force-recreate": False, "--no-build": False, "SERVICE": "", "--scale": [] } project = project_from_options(project_path, up_options) cmd = TopLevelCommand(project) cmd.up(up_options) ps_options = {"SERVICE": "", "-q": True} containers = sorted( project.containers(service_names=ps_options['SERVICE'], stopped=True) + project.containers(service_names=ps_options['SERVICE'], one_off=OneOffFilter.only), key=attrgetter('name')) container_ids = [] for container in containers: container_ids.append(container.id) return container_ids
def test_command_manual_and_service_ports_together(self): project = Project.from_config( name='composetest', client=None, config_data=build_config({ 'service': { 'image': 'busybox' }, }), ) command = TopLevelCommand(project) with pytest.raises(UserError): command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--label': [], '--user': None, '--no-deps': None, '--detach': True, '-T': None, '--entrypoint': None, '--service-ports': True, '--use-aliases': None, '--publish': ['80:80'], '--rm': None, '--name': None, })
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 build_and_run(options, request): project = project_from_options(os.path.dirname(__file__), options) cmd = TopLevelCommand(project) start_time = str(int(unix_time_milliseconds(datetime.utcnow()))) run_containers(cmd, options) def fin(): # Stop the containers then remove them and their volumes (--volumes option) print("containers stopping", flush=True) try: # Used for when there are multiple filewriter instances # as the service is not called "filewriter" multiple_log_options = dict(options) multiple_log_options["SERVICE"] = ["filewriter1", "filewriter2"] cmd.logs(multiple_log_options) except: log_options = dict(options) log_options["SERVICE"] = ["filewriter"] cmd.logs(log_options) options["--timeout"] = 30 cmd.down(options) print("containers stopped", flush=True) # Using a finalizer rather than yield in the fixture means # that the containers will be brought down even if tests fail request.addfinalizer(fin) # Return the start time so the filewriter knows when to start consuming data # from to get all data which was published return start_time
def docker_compose(request): """ :type request: _pytest.python.FixtureRequest """ options = {"--no-deps": False, "--abort-on-container-exit": False, "SERVICE": "", "--remove-orphans": False, "--no-recreate": True, "--force-recreate": False, "--build": False, '--no-build': False, '--no-color': False, "--rmi": "none", "--volumes": "", "--follow": False, "--timestamps": False, "--tail": "all", "-d": True, } project = project_from_options(os.path.dirname(__file__), options) cmd = TopLevelCommand(project) cmd.up(options) def fin(): cmd.logs(options) cmd.down(options) request.addfinalizer(fin)
def __init__(self, path='./'): path = './' # Path to docker-compose directory self.options = { "--file": ['docker-compose.dev.yaml', ], "--no-deps": False, "--abort-on-container-exit": False, "SERVICE": "", "--remove-orphans": False, "--no-recreate": True, "--force-recreate": False, "--build": False, '--no-build': False, '--no-color': False, "--rmi": "none", "--volumes": "", "--follow": False, "--timestamps": False, "--tail": "all", "-d": True, '--always-recreate-deps': False, '--scale': [] } self.project = project_from_options(path, self.options) self.cli = TopLevelCommand(self.project)
def test_command_manula_and_service_ports_together(self): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service( 'service', client=mock_client, restart='always', image='someimage', ) with self.assertRaises(UserError): command.run(mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '--allow-insecure-ssl': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': True, '--publish': ['80:80'], '--rm': None, })
def test_run_interactive_passes_logs_false(self, mock_pseudo_terminal, mock_run_operation): mock_client = mock.create_autospec(docker.Client) project = Project.from_config( name='composetest', client=mock_client, config_data=build_config({ 'service': {'image': 'busybox'} }), ) command = TopLevelCommand(project) with pytest.raises(SystemExit): command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '-d': False, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': None, '--name': None, '--workdir': None, }) _, _, call_kwargs = mock_run_operation.mock_calls[0] assert call_kwargs['logs'] is False
def test_run_with_environment_merged_with_options_list( self, mock_pseudo_terminal): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service( 'service', client=mock_client, environment=['FOO=ONE', 'BAR=TWO'], image='someimage') command.run( mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': ['BAR=NEW', 'OTHER=bär'.encode('utf-8')], '--user': None, '--no-deps': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': None, '--name': None, }) _, _, call_kwargs = mock_client.create_container.mock_calls[0] assert (sorted(call_kwargs['environment']) == sorted( ['FOO=ONE', 'BAR=NEW', 'OTHER=bär']))
def test_project_name_from_environment_new_var(self): command = TopLevelCommand() name = 'namefromenv' with mock.patch.dict(os.environ): os.environ['COMPOSE_PROJECT_NAME'] = name project_name = command.get_project_name(None) self.assertEquals(project_name, name)
def test_run_interactive_passes_logs_false(self, mock_pseudo_terminal, mock_run_operation): os.environ['COMPOSE_INTERACTIVE_NO_CLI'] = 'true' mock_client = mock.create_autospec(docker.APIClient) mock_client.api_version = DEFAULT_DOCKER_API_VERSION project = Project.from_config( name='composetest', client=mock_client, config_data=build_config({'service': { 'image': 'busybox' }}), ) command = TopLevelCommand(project) with pytest.raises(SystemExit): command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--label': [], '--user': None, '--no-deps': None, '--detach': False, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--volume': [], '--rm': None, '--name': None, '--workdir': None, }) _, _, call_kwargs = mock_run_operation.mock_calls[0] assert call_kwargs['logs'] is False
def test_get_project(self): command = TopLevelCommand() command.base_dir = 'tests/fixtures/longer-filename-composefile' project = command.get_project() self.assertEqual(project.name, 'longerfilenamecomposefile') self.assertTrue(project.client) self.assertTrue(project.services)
def test_run_with_environment_merged_with_options_list(self, mock_dockerpty): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service( 'service', client=mock_client, environment=['FOO=ONE', 'BAR=TWO'], image='someimage') command.run(mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': ['BAR=NEW', 'OTHER=THREE'], '--user': None, '--no-deps': None, '--allow-insecure-ssl': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': None, }) _, _, call_kwargs = mock_client.create_container.mock_calls[0] self.assertEqual( call_kwargs['environment'], {'FOO': 'ONE', 'BAR': 'NEW', 'OTHER': 'THREE'})
def test_run_interactive_passes_logs_false(self, mock_pseudo_terminal): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) mock_project = mock.Mock(client=mock_client) mock_project.get_service.return_value = Service( 'service', client=mock_client, environment=['FOO=ONE', 'BAR=TWO'], image='someimage') with pytest.raises(SystemExit): command.run(mock_project, { 'SERVICE': 'service', 'COMMAND': None, '-e': ['BAR=NEW', 'OTHER=bär'.encode('utf-8')], '--user': None, '--no-deps': None, '-d': False, '-T': None, '--entrypoint': None, '--service-ports': None, '--publish': [], '--rm': None, '--name': None, }) _, _, call_kwargs = mock_pseudo_terminal.mock_calls[0] assert call_kwargs['logs'] is False
def get_config_filename_for_files(filenames): project_dir = tempfile.mkdtemp() try: make_files(project_dir, filenames) command = TopLevelCommand() command.base_dir = project_dir return os.path.basename(command.get_config_path()) finally: shutil.rmtree(project_dir)
def get_project(path): """ get docker project given file path """ logging.debug('get project ' + path) command = TopLevelCommand() command.base_dir = path project = command.get_project(command.get_config_path()) return project
def test_default_project_name(self): cwd = os.getcwd() try: os.chdir('tests/fixtures/simple-composefile') command = TopLevelCommand() project_name = command.get_project_name('.') self.assertEquals('simplecomposefile', project_name) finally: os.chdir(cwd)
def __init__(self, docker_compose_file, options=None): self.docker_compose_file = docker_compose_file # build docker options with default ones + input overrides dockerenv_options = self.options if options: dockerenv_options.update(options) project = project_from_options(str(TESTS_DIR), dockerenv_options) self.cmd = TopLevelCommand(project) self.cmd.up(dockerenv_options)
def __init__(self, project_name, project_dir='.', file_compose='docker-compose.yml'): self._name = project_name self.file = file_compose self.project_dir = project_dir print("Reading file: {}".format(self.get_compose_file())) # TODO: get project must be called every time in order to load the compose file updated self._project = self._get_project(project_dir, project_name=self._name) self.compose = TopLevelCommand(self._project, project_dir=project_dir)
def create(self, instance_id: str, content: str, c_type: str, **kwargs) -> None: """ This creates a set of containers using docker compose. Note: the use of the docker compose python module is unsupported by docker inc. :param content: the docker compose file as a string :return: """ if c_type != 'docker-compose': raise NotImplementedError( 'The type ({type}) of cluster manager is unknown'.format( type=c_type)) # when we get the manifest, we have to dump it to a temporary file # to allow for multiple stack instances we need to have multiple projects! # this means multiple directories mani_dir = self.manifest_cache + '/' + instance_id if not os.path.exists(mani_dir): os.makedirs(mani_dir) else: LOG.info( 'The instance is already running with the following project: {mani_dir}' .format(mani_dir=mani_dir)) LOG.warning('Content in this directory will be overwritten.') # XXX shouldn't this raise an exception? # can supply external parameters here... # parameters is the name set in the OSBA spec for additional parameters supplied on provisioning # if none supplied, we use an empty dict # add optionally supplied parameters as environment variables parameters = kwargs.get('parameters', dict()) env_list = list() for k, v in parameters.items(): LOG.info('Including as environment variable: {k}={v}'.format(k=k, v=v)) env_list.append(k + '=' + v) if len(env_list) > 0: m = yaml.load(content) for k, v in m['services'].items(): v['environment'] = env_list content = yaml.dump(m) LOG.debug('writing to: {compo}'.format(compo=mani_dir + '/docker-compose.yml')) m = open(mani_dir + '/docker-compose.yml', 'wt') m.write(content) m.close() project = project_from_options(mani_dir, self.options) cmd = TopLevelCommand(project) cmd.up(self.options)
def before(self, *args, **kwargs): """ Will run `docker-compose up -d` only in case docker-compose is installed locally and there is a docker-compose.yml file in resources directory """ compose = self.find_resource_file() if compose and is_package_installed('compose'): from compose.cli.main import TopLevelCommand, project_from_options info('Starting docker-compose. Please wait.') self._options['-f'] = join(self._resources, compose), self._cmd = TopLevelCommand( project_from_options(self._resources, self._options)) self._cmd.up(self._options)
def test_run_interactive_passes_logs_false( self, mock_container_create, mock_pseudo_terminal, mock_run_operation, ): os.environ['COMPOSE_INTERACTIVE_NO_CLI'] = 'true' mock_client = mock.create_autospec(docker.APIClient) mock_client.api_version = DEFAULT_DOCKER_API_VERSION mock_client._general_configs = {} mock_container_create.return_value = Container(mock_client, { 'Id': '37b35e0ba80d91009d37e16f249b32b84f72bda269985578ed6c75a0a13fcaa8', 'Config': { 'Labels': { LABEL_SERVICE: 'service', } }, }, has_been_inspected=True) project = Project.from_config( name='composetest', client=mock_client, config_data=build_config({'service': { 'image': 'busybox' }}), ) command = TopLevelCommand(project) with pytest.raises(SystemExit): command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--label': [], '--user': None, '--no-deps': None, '--detach': False, '-T': None, '--entrypoint': None, '--service-ports': None, '--use-aliases': None, '--publish': [], '--volume': [], '--rm': None, '--name': None, '--workdir': None, }) _, _, call_kwargs = mock_run_operation.mock_calls[0] assert call_kwargs['logs'] is False
def cmd(self): if self._cmd is None: p = self.project cmd_options = { "--tlsverify": True, "--tlscacert": p.client.verify, "--tlscert": p.client.cert[0], "--tlskey": p.client.cert[1], "--host": p.client.base_url.replace("https", "tcp"), "--file": self.compose_files, "--project-name": self.name, } self._cmd = TopLevelCommand(p, cmd_options) return self._cmd
def rm(project_path): rm_options = { "--force": True, "--stop": True, "-v": False, "--rmi": "none", "--volumes": "/private", "--remove-orphans": False, "SERVICE": "" } project = project_from_options(project_path, rm_options) cmd = TopLevelCommand(project) cmd.down(rm_options)
def test_run_up_with_docker_cli_build(self, mock_project_up): os.environ['COMPOSE_DOCKER_CLI_BUILD'] = '1' mock_client = mock.create_autospec(docker.APIClient) mock_client.api_version = DEFAULT_DOCKER_API_VERSION mock_client._general_configs = {} container = Container(mock_client, { 'Id': '37b35e0ba80d91009d37e16f249b32b84f72bda269985578ed6c75a0a13fcaa8', 'Name': 'composetest_service_37b35', 'Config': { 'Labels': { LABEL_SERVICE: 'service', } }, }, has_been_inspected=True) mock_project_up.return_value = [container] project = Project.from_config( name='composetest', config_data=build_config({'service': { 'image': 'busybox' }}), client=mock_client, ) command = TopLevelCommand(project) command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--label': [], '--user': None, '--no-deps': None, '--detach': True, '-T': None, '--entrypoint': None, '--service-ports': None, '--use-aliases': None, '--publish': [], '--volume': [], '--rm': None, '--name': None, '--workdir': None, }) _, _, call_kwargs = mock_project_up.mock_calls[0] assert call_kwargs.get('cli')
def start_ioc(request): options = common_options options["--project-name"] = "ioc" options["--file"] = [os.path.join("compose", "docker-compose-ioc.yml")] project = project_from_options(os.path.dirname(__file__), options) cmd = TopLevelCommand(project) cmd.up(options) def fin(): print("Stopping zookeeper and kafka", flush=True) options["--timeout"] = 30 options["--project-name"] = "ioc" options["--file"] = [os.path.join("compose", "docker-compose-ioc.yml")] cmd.down(options) request.addfinalizer(fin)