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_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_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 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_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_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_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, mock_run_operation): mock_client = mock.create_autospec(docker.APIClient) project = Project.from_config( name='composetest', client=mock_client, config_data=build_config({ 'service': {'image': 'busybox'} }), ) plugin_manager = PluginManager('') command = TopLevelCommand(project, plugin_manager) 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_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, "--name": None, }, )
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 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 __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_get_project(self): command = TopLevelCommand() command.base_dir = 'tests/fixtures/longer-filename-composefile' project = command.get_project(command.get_config_path()) 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, "--name": None, }, ) _, _, call_kwargs = mock_client.create_container.mock_calls[0] self.assertEqual(call_kwargs["environment"], {"FOO": "ONE", "BAR": "NEW", "OTHER": "THREE"})
def test_command_manual_and_service_ports_together(self): project = Project.from_config( name='composetest', client=None, config_data=build_config({ 'service': {'image': 'busybox'}, }), ) plugin_manager = PluginManager('') command = TopLevelCommand(project, plugin_manager) with self.assertRaises(UserError): command.run({ 'SERVICE': 'service', 'COMMAND': None, '-e': [], '--user': None, '--no-deps': None, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': True, '--publish': ['80:80'], '--rm': None, '--name': None, })
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() 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, '--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
class DockerCompose(object): 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 up(self, **kwargs): self.cli.up(self.options) time.sleep(0.5) # wait for the server to be ready def down(self): self.cli.down(self.options)
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 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_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, '-d': True, '-T': None, '--entrypoint': None, '--service-ports': True, '--publish': ['80:80'], '--rm': None, '--name': None, })
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 test_compose_command(): @compose_command() def test_command(self): """ Test command Usage: config [options] Options: -o, --option Option """ return True @compose_command(standalone=True) def stest_command(self): """ Second test command Usage: config [options] Options: -o, --option Option """ return False if hasattr(TopLevelCommand, '__modified_doc__'): assert re.search( r'test_command\s+Test command', TopLevelCommand.__modified_doc__ ) is not None assert re.search( r'stest_command\s+Second test command', TopLevelCommand.__modified_doc__ ) is not None else: assert re.search( r'test_command\s+Test command', TopLevelCommand.__doc__ ) is not None assert re.search( r'stest_command\s+Second test command', TopLevelCommand.__doc__ ) is not None top_level_command = TopLevelCommand(None, None, None) assert TopLevelCommand.test_command.__standalone__ is False assert TopLevelCommand.stest_command.__standalone__ is True assert top_level_command.test_command() is True assert top_level_command.stest_command() is False with pytest.raises(PluginCommandError): test_command(None) with pytest.raises(PluginCommandError): stest_command(None)
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
class DockerCompose(Module): """ :Docker-compose module: Will automatically run `docker-compose up -d` before your test and `down` after it if this module was enabled and you have `docker-compose.yml` file in your directory. :Enable this module: - run `pip install catcher[compose]`. It will installs all requirements, if they were not installed. """ def __init__(self, resources_dir) -> None: super().__init__(resources_dir) self._cmd = None self._options = { '--detach': True, 'SERVICE': "", '--no-deps': False, '--abort-on-container-exit': False, '--no-recreate': True, '--remove-orphans': False, '--always-recreate-deps': False, '--force-recreate': False, '--build': False, '--no-build': False, '--no-color': False, '--rmi': 'none', '--volumes': "", '--follow': False, '--timestamps': False, '--scale': {} } 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 after(self, *args, **kwargs): if self._cmd: self._cmd.down(self._options) def filter_resource(self, file: str) -> bool: # use only default docker-compose.yml for now, will change it in future if needed. return isfile(join(self._resources, file)) and file == 'docker-compose.yml'
def test_default_project_name(self): cwd = os.getcwd() try: os.chdir('tests/fixtures/simple-composefile') command = TopLevelCommand() project_name = command.get_project_name(command.get_config_path()) self.assertEquals('simplecomposefile', project_name) finally: os.chdir(cwd)
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 run_compose_with_file(project_name, yml_file, manager_services, timeout): class ContainerKiller(object): def __init__(self, project_description): self.project_description = project_description self.has_been_killed = False self.kill_lock = threading.Lock() self.exception_on_kill = None def kill(self, exception_on_kill=None): self.kill_lock.acquire() if self.has_been_killed: return None self.has_been_killed = True self.exception_on_kill = exception_on_kill # Kill all running containers command.dispatch(self.project_description + ["kill"], None) # Remove containers(Cleaning up) command.dispatch(self.project_description + ["rm", "--force"], None) self.kill_lock.release() """ :param project_name: A name used to identify containers of this project :param yml_file; Path of YAML file which docker-compose is going to be run with. :param manager_services: list of services which are supposed to act as managers. Runs docker-compose and waits until manager containers stop. Kills all the container afterwards. Streams managers' logs to the output. """ if not manager_services: manager_services = [] command = TopLevelCommand() project_description = ["-f", [yml_file], "-p", project_name] # Start docker-compose as a daemon command.dispatch(project_description + ["up", "-d"], None) # Attach to manager container(s)' logs. Waits for manager container to stop. # if no service is mentioned as manager(i.e. manager_services is an empty list) # automatically attaches to all containers logs container_killer = ContainerKiller(project_description) timer = None if timeout: timer = threading.Timer(timeout, container_killer.kill, kwargs={"exception_on_kill": TimeoutError()}) try: if timeout: timer.start() command.dispatch(project_description + ["logs"] + manager_services, None) finally: container_killer.kill() if timeout: timer.cancel() if container_killer.exception_on_kill is not None: raise container_killer.exception_on_kill
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 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 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 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 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 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)
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): 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): mock_client = mock.create_autospec(docker.APIClient) 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': [], '--volume': [], '--rm': None, '--name': None, '--workdir': None, }) self.assertEqual( 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': [], '--volume': [], '--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={'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_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 mock_client._general_configs = {} 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 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, }, ) 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): 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 test_project_name_with_explicit_project_name(self): command = TopLevelCommand() name = 'explicit-project-name' project_name = command.get_project_name(None, project_name=name) self.assertEquals('explicitprojectname', project_name)
def test_command_help_nonexistent(self): with pytest.raises(NoSuchCommand): TopLevelCommand.help({'COMMAND': 'nonexistent'})
def test_project_name_with_explicit_base_dir(self): command = TopLevelCommand() command.base_dir = 'tests/fixtures/simple-composefile' project_name = command.get_project_name(command.get_config_path()) self.assertEquals('simplecomposefile', project_name)
def test_project_name_with_explicit_uppercase_base_dir(self): command = TopLevelCommand() command.base_dir = 'tests/fixtures/UpperCaseDir' project_name = command.get_project_name(command.get_config_path()) self.assertEquals('uppercasedir', project_name)
def setUp(self): super(CLITestCase, self).setUp() self.old_sys_exit = sys.exit sys.exit = lambda code=0: None self.command = TopLevelCommand() self.command.base_dir = 'tests/fixtures/simple-composefile'
class CLITestCase(DockerClientTestCase): def setUp(self): super(CLITestCase, self).setUp() self.old_sys_exit = sys.exit sys.exit = lambda code=0: None self.command = TopLevelCommand() self.command.base_dir = 'tests/fixtures/simple-composefile' def tearDown(self): sys.exit = self.old_sys_exit self.project.kill() self.project.remove_stopped() @property def project(self): return self.command.get_project(self.command.get_config_path()) def test_help(self): old_base_dir = self.command.base_dir self.command.base_dir = 'tests/fixtures/no-composefile' with self.assertRaises(SystemExit) as exc_context: self.command.dispatch(['help', 'up'], None) self.assertIn('Usage: up [options] [SERVICE...]', str(exc_context.exception)) # self.project.kill() fails during teardown # unless there is a composefile. self.command.base_dir = old_base_dir # TODO: address the "Inappropriate ioctl for device" warnings in test output @patch('sys.stdout', new_callable=StringIO) def test_ps(self, mock_stdout): self.project.get_service('simple').create_container() self.command.dispatch(['ps'], None) self.assertIn('simplecomposefile_simple_1', mock_stdout.getvalue()) @patch('sys.stdout', new_callable=StringIO) def test_ps_default_composefile(self, mock_stdout): self.command.base_dir = 'tests/fixtures/multiple-composefiles' self.command.dispatch(['up', '-d'], None) self.command.dispatch(['ps'], None) output = mock_stdout.getvalue() self.assertIn('multiplecomposefiles_simple_1', output) self.assertIn('multiplecomposefiles_another_1', output) self.assertNotIn('multiplecomposefiles_yetanother_1', output) @patch('sys.stdout', new_callable=StringIO) def test_ps_alternate_composefile(self, mock_stdout): self.command.base_dir = 'tests/fixtures/multiple-composefiles' self.command.dispatch(['-f', 'compose2.yml', 'up', '-d'], None) self.command.dispatch(['-f', 'compose2.yml', 'ps'], None) output = mock_stdout.getvalue() self.assertNotIn('multiplecomposefiles_simple_1', output) self.assertNotIn('multiplecomposefiles_another_1', output) self.assertIn('multiplecomposefiles_yetanother_1', output) @patch('compose.service.log') def test_pull(self, mock_logging): self.command.dispatch(['pull'], None) mock_logging.info.assert_any_call('Pulling simple (busybox:latest)...') mock_logging.info.assert_any_call('Pulling another (busybox:latest)...') @patch('sys.stdout', new_callable=StringIO) def test_build_no_cache(self, mock_stdout): self.command.base_dir = 'tests/fixtures/simple-dockerfile' self.command.dispatch(['build', 'simple'], None) mock_stdout.truncate(0) cache_indicator = 'Using cache' self.command.dispatch(['build', 'simple'], None) output = mock_stdout.getvalue() self.assertIn(cache_indicator, output) mock_stdout.truncate(0) self.command.dispatch(['build', '--no-cache', 'simple'], None) output = mock_stdout.getvalue() self.assertNotIn(cache_indicator, output) def test_up(self): self.command.dispatch(['up', '-d'], None) service = self.project.get_service('simple') another = self.project.get_service('another') self.assertEqual(len(service.containers()), 1) self.assertEqual(len(another.containers()), 1) # Ensure containers don't have stdin and stdout connected in -d mode config = service.containers()[0].inspect()['Config'] self.assertFalse(config['AttachStderr']) self.assertFalse(config['AttachStdout']) self.assertFalse(config['AttachStdin']) def test_up_with_links(self): self.command.base_dir = 'tests/fixtures/links-composefile' self.command.dispatch(['up', '-d', 'web'], None) web = self.project.get_service('web') db = self.project.get_service('db') console = self.project.get_service('console') self.assertEqual(len(web.containers()), 1) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(console.containers()), 0) def test_up_with_no_deps(self): self.command.base_dir = 'tests/fixtures/links-composefile' self.command.dispatch(['up', '-d', '--no-deps', 'web'], None) web = self.project.get_service('web') db = self.project.get_service('db') console = self.project.get_service('console') self.assertEqual(len(web.containers()), 1) self.assertEqual(len(db.containers()), 0) self.assertEqual(len(console.containers()), 0) def test_up_with_recreate(self): self.command.dispatch(['up', '-d'], None) service = self.project.get_service('simple') self.assertEqual(len(service.containers()), 1) old_ids = [c.id for c in service.containers()] self.command.dispatch(['up', '-d'], None) self.assertEqual(len(service.containers()), 1) new_ids = [c.id for c in service.containers()] self.assertNotEqual(old_ids, new_ids) def test_up_with_keep_old(self): self.command.dispatch(['up', '-d'], None) service = self.project.get_service('simple') self.assertEqual(len(service.containers()), 1) old_ids = [c.id for c in service.containers()] self.command.dispatch(['up', '-d', '--no-recreate'], None) self.assertEqual(len(service.containers()), 1) new_ids = [c.id for c in service.containers()] self.assertEqual(old_ids, new_ids) @patch('dockerpty.start') def test_run_service_without_links(self, mock_stdout): self.command.base_dir = 'tests/fixtures/links-composefile' self.command.dispatch(['run', 'console', '/bin/true'], None) self.assertEqual(len(self.project.containers()), 0) # Ensure stdin/out was open container = self.project.containers(stopped=True, one_off=True)[0] config = container.inspect()['Config'] self.assertTrue(config['AttachStderr']) self.assertTrue(config['AttachStdout']) self.assertTrue(config['AttachStdin']) @patch('dockerpty.start') def test_run_service_with_links(self, __): self.command.base_dir = 'tests/fixtures/links-composefile' self.command.dispatch(['run', 'web', '/bin/true'], None) db = self.project.get_service('db') console = self.project.get_service('console') self.assertEqual(len(db.containers()), 1) self.assertEqual(len(console.containers()), 0) @patch('dockerpty.start') def test_run_with_no_deps(self, __): self.command.base_dir = 'tests/fixtures/links-composefile' self.command.dispatch(['run', '--no-deps', 'web', '/bin/true'], None) db = self.project.get_service('db') self.assertEqual(len(db.containers()), 0) @patch('dockerpty.start') def test_run_does_not_recreate_linked_containers(self, __): self.command.base_dir = 'tests/fixtures/links-composefile' self.command.dispatch(['up', '-d', 'db'], None) db = self.project.get_service('db') self.assertEqual(len(db.containers()), 1) old_ids = [c.id for c in db.containers()] self.command.dispatch(['run', 'web', '/bin/true'], None) self.assertEqual(len(db.containers()), 1) new_ids = [c.id for c in db.containers()] self.assertEqual(old_ids, new_ids) @patch('dockerpty.PseudoTerminal') def test_run_without_command(self, __): self.command.base_dir = 'tests/fixtures/commands-composefile' self.check_build('tests/fixtures/simple-dockerfile', tag='composetest_test') for c in self.project.containers(stopped=True, one_off=True): c.remove() self.command.dispatch(['run', 'implicit'], None) service = self.project.get_service('implicit') containers = service.containers(stopped=True, one_off=True) self.assertEqual( [c.human_readable_command for c in containers], [u'/bin/sh -c echo "success"'], ) self.command.dispatch(['run', 'explicit'], None) service = self.project.get_service('explicit') containers = service.containers(stopped=True, one_off=True) self.assertEqual( [c.human_readable_command for c in containers], [u'/bin/true'], ) @patch('dockerpty.PseudoTerminal') def test_run_service_with_entrypoint_overridden(self, _): self.command.base_dir = 'tests/fixtures/dockerfile_with_entrypoint' name = 'service' self.command.dispatch( ['run', '--entrypoint', '/bin/echo', name, 'helloworld'], None ) service = self.project.get_service(name) container = service.containers(stopped=True, one_off=True)[0] self.assertEqual( container.human_readable_command, u'/bin/echo helloworld' ) @patch('dockerpty.start') def test_run_service_with_environement_overridden(self, _): name = 'service' self.command.base_dir = 'tests/fixtures/environment-composefile' self.command.dispatch( ['run', '-e', 'foo=notbar', '-e', 'allo=moto=bobo', '-e', 'alpha=beta', name], None ) service = self.project.get_service(name) container = service.containers(stopped=True, one_off=True)[0] # env overriden self.assertEqual('notbar', container.environment['foo']) # keep environement from yaml self.assertEqual('world', container.environment['hello']) # added option from command line self.assertEqual('beta', container.environment['alpha']) # make sure a value with a = don't crash out self.assertEqual('moto=bobo', container.environment['allo']) @patch('dockerpty.start') def test_run_service_without_map_ports(self, __): # create one off container self.command.base_dir = 'tests/fixtures/ports-composefile' self.command.dispatch(['run', '-d', 'simple'], None) container = self.project.get_service('simple').containers(one_off=True)[0] # get port information port_random = container.get_local_port(3000) port_assigned = container.get_local_port(3001) # close all one off containers we just created container.stop() # check the ports self.assertEqual(port_random, None) self.assertEqual(port_assigned, None) @patch('dockerpty.start') def test_run_service_with_map_ports(self, __): # create one off container self.command.base_dir = 'tests/fixtures/ports-composefile' self.command.dispatch(['run', '-d', '--service-ports', 'simple'], None) container = self.project.get_service('simple').containers(one_off=True)[0] # get port information port_random = container.get_local_port(3000) port_assigned = container.get_local_port(3001) # close all one off containers we just created container.stop() # check the ports self.assertNotEqual(port_random, None) self.assertIn("0.0.0.0", port_random) self.assertEqual(port_assigned, "0.0.0.0:9999") def test_rm(self): service = self.project.get_service('simple') service.create_container() service.kill() self.assertEqual(len(service.containers(stopped=True)), 1) self.command.dispatch(['rm', '--force'], None) self.assertEqual(len(service.containers(stopped=True)), 0) def test_kill(self): self.command.dispatch(['up', '-d'], None) service = self.project.get_service('simple') self.assertEqual(len(service.containers()), 1) self.assertTrue(service.containers()[0].is_running) self.command.dispatch(['kill'], None) self.assertEqual(len(service.containers(stopped=True)), 1) self.assertFalse(service.containers(stopped=True)[0].is_running) def test_kill_signal_sigint(self): self.command.dispatch(['up', '-d'], None) service = self.project.get_service('simple') self.assertEqual(len(service.containers()), 1) self.assertTrue(service.containers()[0].is_running) self.command.dispatch(['kill', '-s', 'SIGINT'], None) self.assertEqual(len(service.containers()), 1) # The container is still running. It has been only interrupted self.assertTrue(service.containers()[0].is_running) def test_kill_interrupted_service(self): self.command.dispatch(['up', '-d'], None) service = self.project.get_service('simple') self.command.dispatch(['kill', '-s', 'SIGINT'], None) self.assertTrue(service.containers()[0].is_running) self.command.dispatch(['kill', '-s', 'SIGKILL'], None) self.assertEqual(len(service.containers(stopped=True)), 1) self.assertFalse(service.containers(stopped=True)[0].is_running) def test_restart(self): service = self.project.get_service('simple') container = service.create_container() service.start_container(container) started_at = container.dictionary['State']['StartedAt'] self.command.dispatch(['restart'], None) container.inspect() self.assertNotEqual( container.dictionary['State']['FinishedAt'], '0001-01-01T00:00:00Z', ) self.assertNotEqual( container.dictionary['State']['StartedAt'], started_at, ) def test_scale(self): project = self.project self.command.scale(project, {'SERVICE=NUM': ['simple=1']}) self.assertEqual(len(project.get_service('simple').containers()), 1) self.command.scale(project, {'SERVICE=NUM': ['simple=3', 'another=2']}) self.assertEqual(len(project.get_service('simple').containers()), 3) self.assertEqual(len(project.get_service('another').containers()), 2) self.command.scale(project, {'SERVICE=NUM': ['simple=1', 'another=1']}) self.assertEqual(len(project.get_service('simple').containers()), 1) self.assertEqual(len(project.get_service('another').containers()), 1) self.command.scale(project, {'SERVICE=NUM': ['simple=1', 'another=1']}) self.assertEqual(len(project.get_service('simple').containers()), 1) self.assertEqual(len(project.get_service('another').containers()), 1) self.command.scale(project, {'SERVICE=NUM': ['simple=0', 'another=0']}) self.assertEqual(len(project.get_service('simple').containers()), 0) self.assertEqual(len(project.get_service('another').containers()), 0) def test_port(self): self.command.base_dir = 'tests/fixtures/ports-composefile' self.command.dispatch(['up', '-d'], None) container = self.project.get_service('simple').get_container() @patch('sys.stdout', new_callable=StringIO) def get_port(number, mock_stdout): self.command.dispatch(['port', 'simple', str(number)], None) return mock_stdout.getvalue().rstrip() self.assertEqual(get_port(3000), container.get_local_port(3000)) self.assertEqual(get_port(3001), "0.0.0.0:9999") self.assertEqual(get_port(3002), "")
def test_help(self): command = TopLevelCommand() with self.assertRaises(SystemExit): command.dispatch(['-h'], None)