From 9d2508cf585261f0f7167df1dbfb363940ebe5c6 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 23 May 2019 15:59:21 +0100 Subject: [PATCH 01/26] Pass environment when calling through to docker cli. This ensures that settings from any `.env` file (such as `DOCKER_HOST`) are passed on to the cli. Unit tests are adjusted for the new parameter and a new case is added to ensure it is propagated as expected. Fixes: 6661 Signed-off-by: Ian Campbell --- compose/cli/main.py | 9 ++++----- tests/unit/cli/main_test.py | 21 +++++++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index e2c04bd24..78990111b 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -516,7 +516,7 @@ class TopLevelCommand(object): if IS_WINDOWS_PLATFORM or use_cli and not detach: sys.exit(call_docker( build_exec_command(options, container.id, command), - self.toplevel_options) + self.toplevel_options, environment) ) create_exec_options = { @@ -1361,7 +1361,6 @@ def run_one_off_container(container_options, project, service, options, toplevel environment_file = options.get('--env-file') environment = Environment.from_env_file(project_dir, environment_file) use_cli = not environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') - signals.set_signal_handler_to_shutdown() signals.set_signal_handler_to_hang_up() try: @@ -1370,7 +1369,7 @@ def run_one_off_container(container_options, project, service, options, toplevel service.connect_container_to_networks(container, use_network_aliases) exit_code = call_docker( ["start", "--attach", "--interactive", container.id], - toplevel_options + toplevel_options, environment ) else: operation = RunOperation( @@ -1450,7 +1449,7 @@ def exit_if(condition, message, exit_code): raise SystemExit(exit_code) -def call_docker(args, dockeropts): +def call_docker(args, dockeropts, environment): executable_path = find_executable('docker') if not executable_path: raise UserError(errors.docker_not_found_msg("Couldn't find `docker` binary.")) @@ -1480,7 +1479,7 @@ def call_docker(args, dockeropts): args = [executable_path] + tls_options + args log.debug(" ".join(map(pipes.quote, args))) - return subprocess.call(args) + return subprocess.call(args, env=environment) def parse_scale_args(options): diff --git a/tests/unit/cli/main_test.py b/tests/unit/cli/main_test.py index eb6a99d72..7fed6bccc 100644 --- a/tests/unit/cli/main_test.py +++ b/tests/unit/cli/main_test.py @@ -123,13 +123,13 @@ def mock_find_executable(exe): class TestCallDocker(object): def test_simple_no_options(self): with mock.patch('subprocess.call') as fake_call: - call_docker(['ps'], {}) + call_docker(['ps'], {}, {}) assert fake_call.call_args[0][0] == ['docker', 'ps'] def test_simple_tls_option(self): with mock.patch('subprocess.call') as fake_call: - call_docker(['ps'], {'--tls': True}) + call_docker(['ps'], {'--tls': True}, {}) assert fake_call.call_args[0][0] == ['docker', '--tls', 'ps'] @@ -140,7 +140,7 @@ class TestCallDocker(object): '--tlscacert': './ca.pem', '--tlscert': './cert.pem', '--tlskey': './key.pem', - }) + }, {}) assert fake_call.call_args[0][0] == [ 'docker', '--tls', '--tlscacert', './ca.pem', '--tlscert', @@ -149,7 +149,7 @@ class TestCallDocker(object): def test_with_host_option(self): with mock.patch('subprocess.call') as fake_call: - call_docker(['ps'], {'--host': 'tcp://mydocker.net:2333'}) + call_docker(['ps'], {'--host': 'tcp://mydocker.net:2333'}, {}) assert fake_call.call_args[0][0] == [ 'docker', '--host', 'tcp://mydocker.net:2333', 'ps' @@ -157,7 +157,7 @@ class TestCallDocker(object): def test_with_http_host(self): with mock.patch('subprocess.call') as fake_call: - call_docker(['ps'], {'--host': 'http://mydocker.net:2333'}) + call_docker(['ps'], {'--host': 'http://mydocker.net:2333'}, {}) assert fake_call.call_args[0][0] == [ 'docker', '--host', 'tcp://mydocker.net:2333', 'ps', @@ -165,8 +165,17 @@ class TestCallDocker(object): def test_with_host_option_shorthand_equal(self): with mock.patch('subprocess.call') as fake_call: - call_docker(['ps'], {'--host': '=tcp://mydocker.net:2333'}) + call_docker(['ps'], {'--host': '=tcp://mydocker.net:2333'}, {}) assert fake_call.call_args[0][0] == [ 'docker', '--host', 'tcp://mydocker.net:2333', 'ps' ] + + def test_with_env(self): + with mock.patch('subprocess.call') as fake_call: + call_docker(['ps'], {}, {'DOCKER_HOST': 'tcp://mydocker.net:2333'}) + + assert fake_call.call_args[0][0] == [ + 'docker', 'ps' + ] + assert fake_call.call_args[1]['env'] == {'DOCKER_HOST': 'tcp://mydocker.net:2333'} From fb4d5aa7e6019df20075139468d924a18fc05fcb Mon Sep 17 00:00:00 2001 From: Brett Randall Date: Sun, 17 Mar 2019 14:38:24 +1100 Subject: [PATCH 02/26] Include required but missing VAR name and assignment in interpolation error message. Error message format is now e.g.: ERROR: Missing mandatory value for "environment" option interpolating ['MYENV=${MYVAR:?}'] in service "myservice": Fixed #6587. Signed-off-by: Brett Randall --- compose/config/interpolation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compose/config/interpolation.py b/compose/config/interpolation.py index 0f878be14..18be8562c 100644 --- a/compose/config/interpolation.py +++ b/compose/config/interpolation.py @@ -64,12 +64,12 @@ def interpolate_value(name, config_key, value, section, interpolator): string=e.string)) except UnsetRequiredSubstitution as e: raise ConfigurationError( - 'Missing mandatory value for "{config_key}" option in {section} "{name}": {err}'.format( - config_key=config_key, - name=name, - section=section, - err=e.err - ) + 'Missing mandatory value for "{config_key}" option interpolating {value} ' + 'in {section} "{name}": {err}'.format(config_key=config_key, + value=value, + name=name, + section=section, + err=e.err) ) From d68113f5c0590128bed842222f957761c3b40009 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Fri, 24 May 2019 21:59:14 +0200 Subject: [PATCH 03/26] Add bash completion for `config --no-interpolate` Signed-off-by: Harald Albers --- contrib/completion/bash/docker-compose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/completion/bash/docker-compose b/contrib/completion/bash/docker-compose index 941f25a3b..e9168b1b1 100644 --- a/contrib/completion/bash/docker-compose +++ b/contrib/completion/bash/docker-compose @@ -150,7 +150,7 @@ _docker_compose_config() { ;; esac - COMPREPLY=( $( compgen -W "--hash --help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--hash --help --no-interpolate --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) } From b29b6a1538a1554a5b805938b930a8c70aae452f Mon Sep 17 00:00:00 2001 From: Inconnu08 Date: Fri, 31 May 2019 20:29:09 +0600 Subject: [PATCH 04/26] replace sets with set literal syntax for efficiency Signed-off-by: Taufiq Rahman --- compose/cli/command.py | 15 +-------------- tests/acceptance/cli_test.py | 18 ++++++------------ 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/compose/cli/command.py b/compose/cli/command.py index 21ab9a39f..a756630fd 100644 --- a/compose/cli/command.py +++ b/compose/cli/command.py @@ -21,20 +21,7 @@ from .utils import get_version_info log = logging.getLogger(__name__) -SILENT_COMMANDS = set(( - 'events', - 'exec', - 'kill', - 'logs', - 'pause', - 'ps', - 'restart', - 'rm', - 'start', - 'stop', - 'top', - 'unpause', -)) +SILENT_COMMANDS = {'events', 'exec', 'kill', 'logs', 'pause', 'ps', 'restart', 'rm', 'start', 'stop', 'top', 'unpause'} def project_from_options(project_dir, options, additional_options={}): diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 8e66c48e2..b9005df8b 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -1446,7 +1446,7 @@ class CLITestCase(DockerClientTestCase): if v['Name'].split('/')[-1].startswith('{}_'.format(self.project.name)) ] - assert set([v['Name'].split('/')[-1] for v in volumes]) == set([volume_with_label]) + assert set([v['Name'].split('/')[-1] for v in volumes]) == {volume_with_label} assert 'label_key' in volumes[0]['Labels'] assert volumes[0]['Labels']['label_key'] == 'label_val' @@ -2111,7 +2111,7 @@ class CLITestCase(DockerClientTestCase): for _, config in networks.items(): # TODO: once we drop support for API <1.24, this can be changed to: # assert config['Aliases'] == [container.short_id] - aliases = set(config['Aliases'] or []) - set([container.short_id]) + aliases = set(config['Aliases'] or []) - {container.short_id} assert not aliases @v2_only() @@ -2131,7 +2131,7 @@ class CLITestCase(DockerClientTestCase): for _, config in networks.items(): # TODO: once we drop support for API <1.24, this can be changed to: # assert config['Aliases'] == [container.short_id] - aliases = set(config['Aliases'] or []) - set([container.short_id]) + aliases = set(config['Aliases'] or []) - {container.short_id} assert not aliases assert self.lookup(container, 'app') @@ -2741,7 +2741,7 @@ class CLITestCase(DockerClientTestCase): self.base_dir = 'tests/fixtures/extends' self.dispatch(['up', '-d'], None) - assert set([s.name for s in self.project.services]) == set(['mydb', 'myweb']) + assert set([s.name for s in self.project.services]) == {'mydb', 'myweb'} # Sort by name so we get [db, web] containers = sorted( @@ -2753,15 +2753,9 @@ class CLITestCase(DockerClientTestCase): web = containers[1] db_name = containers[0].name_without_project - assert set(get_links(web)) == set( - ['db', db_name, 'extends_{}'.format(db_name)] - ) + assert set(get_links(web)) == {'db', db_name, 'extends_{}'.format(db_name)} - expected_env = set([ - "FOO=1", - "BAR=2", - "BAZ=2", - ]) + expected_env = {"FOO=1", "BAR=2", "BAZ=2"} assert expected_env <= set(web.get('Config.Env')) def test_top_services_not_running(self): From c37fb783feaedf1bf9338c1a3c3fbeef9fb9f373 Mon Sep 17 00:00:00 2001 From: Inconnu08 Date: Sat, 1 Jun 2019 01:31:35 +0600 Subject: [PATCH 05/26] replace sets with set literal syntax for efficiency Signed-off-by: Taufiq Rahman --- tests/integration/project_test.py | 18 +++++++----------- tests/unit/config/config_test.py | 24 ++++++++++++------------ tests/unit/service_test.py | 6 ++---- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py index fe6ace90e..b76b63f3c 100644 --- a/tests/integration/project_test.py +++ b/tests/integration/project_test.py @@ -104,7 +104,7 @@ class ProjectTest(DockerClientTestCase): self.create_service('extra').create_container() project = Project('composetest', [web, db], self.client) - assert set(project.containers(stopped=True)) == set([web_1, db_1]) + assert set(project.containers(stopped=True)) == {web_1, db_1} def test_parallel_pull_with_no_image(self): config_data = build_config( @@ -305,9 +305,7 @@ class ProjectTest(DockerClientTestCase): db_container = db.create_container() project.start(service_names=['web']) - assert set(c.name for c in project.containers() if c.is_running) == set( - [web_container_1.name, web_container_2.name] - ) + assert set(c.name for c in project.containers() if c.is_running) == {web_container_1.name, web_container_2.name} project.start() assert set(c.name for c in project.containers() if c.is_running) == set( @@ -315,14 +313,12 @@ class ProjectTest(DockerClientTestCase): ) project.pause(service_names=['web']) - assert set([c.name for c in project.containers() if c.is_paused]) == set( - [web_container_1.name, web_container_2.name] - ) + assert set([c.name for c in project.containers() if c.is_paused]) == {web_container_1.name, + web_container_2.name} project.pause() - assert set([c.name for c in project.containers() if c.is_paused]) == set( - [web_container_1.name, web_container_2.name, db_container.name] - ) + assert set([c.name for c in project.containers() if c.is_paused]) == {web_container_1.name, + web_container_2.name, db_container.name} project.unpause(service_names=['db']) assert len([c.name for c in project.containers() if c.is_paused]) == 2 @@ -331,7 +327,7 @@ class ProjectTest(DockerClientTestCase): assert len([c.name for c in project.containers() if c.is_paused]) == 0 project.stop(service_names=['web'], timeout=1) - assert set(c.name for c in project.containers() if c.is_running) == set([db_container.name]) + assert set(c.name for c in project.containers() if c.is_running) == {db_container.name} project.kill(service_names=['db']) assert len([c for c in project.containers() if c.is_running]) == 0 diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 163c9cd16..2f27a5b20 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -3821,35 +3821,35 @@ class MergePathMappingTest(object): {self.config_name: ['/foo:/code', '/data']}, {}, DEFAULT_VERSION) - assert set(service_dict[self.config_name]) == set(['/foo:/code', '/data']) + assert set(service_dict[self.config_name]) == {'/foo:/code', '/data'} def test_no_base(self): service_dict = config.merge_service_dicts( {}, {self.config_name: ['/bar:/code']}, DEFAULT_VERSION) - assert set(service_dict[self.config_name]) == set(['/bar:/code']) + assert set(service_dict[self.config_name]) == {'/bar:/code'} def test_override_explicit_path(self): service_dict = config.merge_service_dicts( {self.config_name: ['/foo:/code', '/data']}, {self.config_name: ['/bar:/code']}, DEFAULT_VERSION) - assert set(service_dict[self.config_name]) == set(['/bar:/code', '/data']) + assert set(service_dict[self.config_name]) == {'/bar:/code', '/data'} def test_add_explicit_path(self): service_dict = config.merge_service_dicts( {self.config_name: ['/foo:/code', '/data']}, {self.config_name: ['/bar:/code', '/quux:/data']}, DEFAULT_VERSION) - assert set(service_dict[self.config_name]) == set(['/bar:/code', '/quux:/data']) + assert set(service_dict[self.config_name]) == {'/bar:/code', '/quux:/data'} def test_remove_explicit_path(self): service_dict = config.merge_service_dicts( {self.config_name: ['/foo:/code', '/quux:/data']}, {self.config_name: ['/bar:/code', '/data']}, DEFAULT_VERSION) - assert set(service_dict[self.config_name]) == set(['/bar:/code', '/data']) + assert set(service_dict[self.config_name]) == {'/bar:/code', '/data'} class MergeVolumesTest(unittest.TestCase, MergePathMappingTest): @@ -4053,28 +4053,28 @@ class MergeStringsOrListsTest(unittest.TestCase): {'dns': '8.8.8.8'}, {}, DEFAULT_VERSION) - assert set(service_dict['dns']) == set(['8.8.8.8']) + assert set(service_dict['dns']) == {'8.8.8.8'} def test_no_base(self): service_dict = config.merge_service_dicts( {}, {'dns': '8.8.8.8'}, DEFAULT_VERSION) - assert set(service_dict['dns']) == set(['8.8.8.8']) + assert set(service_dict['dns']) == {'8.8.8.8'} def test_add_string(self): service_dict = config.merge_service_dicts( {'dns': ['8.8.8.8']}, {'dns': '9.9.9.9'}, DEFAULT_VERSION) - assert set(service_dict['dns']) == set(['8.8.8.8', '9.9.9.9']) + assert set(service_dict['dns']) == {'8.8.8.8', '9.9.9.9'} def test_add_list(self): service_dict = config.merge_service_dicts( {'dns': '8.8.8.8'}, {'dns': ['9.9.9.9']}, DEFAULT_VERSION) - assert set(service_dict['dns']) == set(['8.8.8.8', '9.9.9.9']) + assert set(service_dict['dns']) == {'8.8.8.8', '9.9.9.9'} class MergeLabelsTest(unittest.TestCase): @@ -4146,7 +4146,7 @@ class MergeBuildTest(unittest.TestCase): assert result['context'] == override['context'] assert result['dockerfile'] == override['dockerfile'] assert result['args'] == {'x': '12', 'y': '2'} - assert set(result['cache_from']) == set(['ubuntu', 'debian']) + assert set(result['cache_from']) == {'ubuntu', 'debian'} assert result['labels'] == override['labels'] def test_empty_override(self): @@ -4350,7 +4350,7 @@ class EnvTest(unittest.TestCase): "tests/fixtures/env", ) ).services[0] - assert set(service_dict['volumes']) == set([VolumeSpec.parse('/tmp:/host/tmp')]) + assert set(service_dict['volumes']) == {VolumeSpec.parse('/tmp:/host/tmp')} service_dict = config.load( build_config_details( @@ -4358,7 +4358,7 @@ class EnvTest(unittest.TestCase): "tests/fixtures/env", ) ).services[0] - assert set(service_dict['volumes']) == set([VolumeSpec.parse('/opt/tmp:/opt/host/tmp')]) + assert set(service_dict['volumes']) == {VolumeSpec.parse('/opt/tmp:/opt/host/tmp')} def load_from_filename(filename, override_dir=None): diff --git a/tests/unit/service_test.py b/tests/unit/service_test.py index 8c381f15d..0cff08ab6 100644 --- a/tests/unit/service_test.py +++ b/tests/unit/service_test.py @@ -1334,10 +1334,8 @@ class ServiceVolumesTest(unittest.TestCase): number=1, ) - assert set(self.mock_client.create_host_config.call_args[1]['binds']) == set([ - '/host/path:/data1:rw', - '/host/path:/data2:rw', - ]) + assert set(self.mock_client.create_host_config.call_args[1]['binds']) == {'/host/path:/data1:rw', + '/host/path:/data2:rw'} def test_get_container_create_options_with_different_host_path_in_container_json(self): service = Service( From 57055e0e66a033de493b27d55df10ef36eae429b Mon Sep 17 00:00:00 2001 From: Inconnu08 Date: Sun, 2 Jun 2019 20:21:21 +0600 Subject: [PATCH 06/26] Replace sets with set literal syntax for efficiency Signed-off-by: Taufiq Rahman --- compose/cli/command.py | 15 ++++++++++++++- tests/integration/project_test.py | 16 ++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/compose/cli/command.py b/compose/cli/command.py index a756630fd..2f38fe5af 100644 --- a/compose/cli/command.py +++ b/compose/cli/command.py @@ -21,7 +21,20 @@ from .utils import get_version_info log = logging.getLogger(__name__) -SILENT_COMMANDS = {'events', 'exec', 'kill', 'logs', 'pause', 'ps', 'restart', 'rm', 'start', 'stop', 'top', 'unpause'} +SILENT_COMMANDS = { + 'events', + 'exec', + 'kill', + 'logs', + 'pause', + 'ps', + 'restart', + 'rm', + 'start', + 'stop', + 'top', + 'unpause', +} def project_from_options(project_dir, options, additional_options={}): diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py index b76b63f3c..1d9495ff8 100644 --- a/tests/integration/project_test.py +++ b/tests/integration/project_test.py @@ -305,20 +305,20 @@ class ProjectTest(DockerClientTestCase): db_container = db.create_container() project.start(service_names=['web']) - assert set(c.name for c in project.containers() if c.is_running) == {web_container_1.name, web_container_2.name} + assert set(c.name for c in project.containers() if c.is_running) == { + web_container_1.name, web_container_2.name} project.start() - assert set(c.name for c in project.containers() if c.is_running) == set( - [web_container_1.name, web_container_2.name, db_container.name] - ) + assert set(c.name for c in project.containers() if c.is_running) == { + web_container_1.name, web_container_2.name, db_container.name} project.pause(service_names=['web']) - assert set([c.name for c in project.containers() if c.is_paused]) == {web_container_1.name, - web_container_2.name} + assert set([c.name for c in project.containers() if c.is_paused]) == { + web_container_1.name, web_container_2.name} project.pause() - assert set([c.name for c in project.containers() if c.is_paused]) == {web_container_1.name, - web_container_2.name, db_container.name} + assert set([c.name for c in project.containers() if c.is_paused]) == { + web_container_1.name, web_container_2.name, db_container.name} project.unpause(service_names=['db']) assert len([c.name for c in project.containers() if c.is_paused]) == 2 From 8c387c6013c509eff7a2bf5cb284782b82a9ae36 Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Fri, 14 Jun 2019 14:58:17 +0100 Subject: [PATCH 07/26] Add .fossa.yml file This commit adds a .fossa.yml file used by fossa.io It allows for fossa to scan the dependencies and figure out which oss licenses are in use. This can be added to CI at some point in the near future. Signed-off-by: Dave Tucker --- .fossa.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .fossa.yml diff --git a/.fossa.yml b/.fossa.yml new file mode 100644 index 000000000..b50761ef1 --- /dev/null +++ b/.fossa.yml @@ -0,0 +1,14 @@ +# Generated by FOSSA CLI (https://github.com/fossas/fossa-cli) +# Visit https://fossa.io to learn more + +version: 2 +cli: + server: https://app.fossa.io + fetcher: custom + project: git@github.com:docker/compose +analyze: + modules: + - name: . + type: pip + target: . + path: . From cacc9752a39418775282e931f018133e0fc41b1a Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Tue, 2 Jul 2019 13:42:41 +0200 Subject: [PATCH 08/26] Pin busybox image version in tests Signed-off-by: Ulysses Souza --- tests/acceptance/cli_test.py | 10 +++++----- tests/fixtures/environment-exec/docker-compose.yml | 2 +- tests/fixtures/links-composefile/docker-compose.yml | 6 +++--- tests/fixtures/simple-composefile/docker-compose.yml | 2 +- tests/fixtures/simple-dockerfile/Dockerfile | 2 +- tests/fixtures/v2-simple/docker-compose.yml | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 8e66c48e2..fcb034a7c 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -41,7 +41,7 @@ ProcessResult = namedtuple('ProcessResult', 'stdout stderr') BUILD_CACHE_TEXT = 'Using cache' -BUILD_PULL_TEXT = 'Status: Image is up to date for busybox:latest' +BUILD_PULL_TEXT = 'Status: Image is up to date for busybox:1.27.2' def start_process(base_dir, options): @@ -688,15 +688,15 @@ class CLITestCase(DockerClientTestCase): self.base_dir = 'tests/fixtures/links-composefile' result = self.dispatch(['pull', '--no-parallel', 'web']) assert sorted(result.stderr.split('\n'))[1:] == [ - 'Pulling web (busybox:latest)...', + 'Pulling web (busybox:1.27.2)...', ] def test_pull_with_include_deps(self): self.base_dir = 'tests/fixtures/links-composefile' result = self.dispatch(['pull', '--no-parallel', '--include-deps', 'web']) assert sorted(result.stderr.split('\n'))[1:] == [ - 'Pulling db (busybox:latest)...', - 'Pulling web (busybox:latest)...', + 'Pulling db (busybox:1.27.2)...', + 'Pulling web (busybox:1.27.2)...', ] def test_build_plain(self): @@ -2669,7 +2669,7 @@ class CLITestCase(DockerClientTestCase): container, = self.project.containers() expected_template = ' container {} {}' - expected_meta_info = ['image=busybox:latest', 'name=simple-composefile_simple_'] + expected_meta_info = ['image=busybox:1.27.2', 'name=simple-composefile_simple_'] assert expected_template.format('create', container.id) in lines[0] assert expected_template.format('start', container.id) in lines[1] diff --git a/tests/fixtures/environment-exec/docker-compose.yml b/tests/fixtures/environment-exec/docker-compose.yml index 813606eb8..e284ba8cb 100644 --- a/tests/fixtures/environment-exec/docker-compose.yml +++ b/tests/fixtures/environment-exec/docker-compose.yml @@ -2,7 +2,7 @@ version: "2.2" services: service: - image: busybox:latest + image: busybox:1.27.2 command: top environment: diff --git a/tests/fixtures/links-composefile/docker-compose.yml b/tests/fixtures/links-composefile/docker-compose.yml index 930fd4c7a..0a2f3d9ef 100644 --- a/tests/fixtures/links-composefile/docker-compose.yml +++ b/tests/fixtures/links-composefile/docker-compose.yml @@ -1,11 +1,11 @@ db: - image: busybox:latest + image: busybox:1.27.2 command: top web: - image: busybox:latest + image: busybox:1.27.2 command: top links: - db:db console: - image: busybox:latest + image: busybox:1.27.2 command: top diff --git a/tests/fixtures/simple-composefile/docker-compose.yml b/tests/fixtures/simple-composefile/docker-compose.yml index b25beaf4b..e86d3fc80 100644 --- a/tests/fixtures/simple-composefile/docker-compose.yml +++ b/tests/fixtures/simple-composefile/docker-compose.yml @@ -1,5 +1,5 @@ simple: - image: busybox:latest + image: busybox:1.27.2 command: top another: image: busybox:latest diff --git a/tests/fixtures/simple-dockerfile/Dockerfile b/tests/fixtures/simple-dockerfile/Dockerfile index dd864b838..098ff3eb1 100644 --- a/tests/fixtures/simple-dockerfile/Dockerfile +++ b/tests/fixtures/simple-dockerfile/Dockerfile @@ -1,3 +1,3 @@ -FROM busybox:latest +FROM busybox:1.27.2 LABEL com.docker.compose.test_image=true CMD echo "success" diff --git a/tests/fixtures/v2-simple/docker-compose.yml b/tests/fixtures/v2-simple/docker-compose.yml index c99ae02fc..ac754eeea 100644 --- a/tests/fixtures/v2-simple/docker-compose.yml +++ b/tests/fixtures/v2-simple/docker-compose.yml @@ -1,8 +1,8 @@ version: "2" services: simple: - image: busybox:latest + image: busybox:1.27.2 command: top another: - image: busybox:latest + image: busybox:1.27.2 command: top From ce5451c5b4a3b449ce703168d2a568b0a4d25ee6 Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Tue, 2 Jul 2019 15:49:07 +0200 Subject: [PATCH 09/26] Strip up generic versions and bump requests Replaces generic limitations with a next major value Bump the minimal `requests` to 2.20.0 Signed-off-by: Ulysses Souza --- setup.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index c6d07a86a..614478010 100644 --- a/setup.py +++ b/setup.py @@ -31,31 +31,31 @@ def find_version(*file_paths): install_requires = [ 'cached-property >= 1.2.0, < 2', - 'docopt >= 0.6.1, < 0.7', - 'PyYAML >= 3.10, < 4.3', - 'requests >= 2.6.1, != 2.11.0, != 2.12.2, != 2.18.0, < 2.23', - 'texttable >= 0.9.0, < 0.10', - 'websocket-client >= 0.32.0, < 1.0', - 'docker[ssh] >= 3.7.0, < 4.0.2', - 'dockerpty >= 0.4.1, < 0.5', + 'docopt >= 0.6.1, < 1', + 'PyYAML >= 3.10, < 5', + 'requests >= 2.20.0, < 3', + 'texttable >= 0.9.0, < 1', + 'websocket-client >= 0.32.0, < 1', + 'docker[ssh] >= 3.7.0, < 5', + 'dockerpty >= 0.4.1, < 1', 'six >= 1.3.0, < 2', 'jsonschema >= 2.5.1, < 3', ] tests_require = [ - 'pytest', + 'pytest < 6', ] if sys.version_info[:2] < (3, 4): - tests_require.append('mock >= 1.0.1') + tests_require.append('mock >= 1.0.1, < 2') extras_require = { ':python_version < "3.4"': ['enum34 >= 1.0.4, < 2'], - ':python_version < "3.5"': ['backports.ssl_match_hostname >= 3.5'], - ':python_version < "3.3"': ['ipaddress >= 1.0.16'], - ':sys_platform == "win32"': ['colorama >= 0.4, < 0.5'], + ':python_version < "3.5"': ['backports.ssl_match_hostname >= 3.5, < 4'], + ':python_version < "3.3"': ['ipaddress >= 1.0.16, < 2'], + ':sys_platform == "win32"': ['colorama >= 0.4, < 1'], 'socks': ['PySocks >= 1.5.6, != 1.5.7, < 2'], } From 57a2bb0c50a0d43ae472c8ba5580868620591ad0 Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Mon, 8 Jul 2019 13:47:19 +0200 Subject: [PATCH 10/26] Bump mock from 2.0.0 to 3.0.5 Signed-off-by: Ulysses Souza --- requirements-dev.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index b19fc2e01..27b71a268 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,6 @@ coverage==4.4.2 ddt==1.2.0 flake8==3.5.0 -mock==2.0.0 +mock==3.0.5 pytest==3.6.3 pytest-cov==2.5.1 diff --git a/setup.py b/setup.py index 614478010..4ceb6e1f8 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ tests_require = [ if sys.version_info[:2] < (3, 4): - tests_require.append('mock >= 1.0.1, < 2') + tests_require.append('mock >= 1.0.1, < 4') extras_require = { ':python_version < "3.4"': ['enum34 >= 1.0.4, < 2'], From 0bfa1c34f054d86674434770d4d6340e02508e52 Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Mon, 8 Jul 2019 14:52:30 +0200 Subject: [PATCH 11/26] Bump texttable from 0.9.1 to 1.6.2 Signed-off-by: Ulysses Souza --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index ff23516e1..e5b6883e9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,6 +19,6 @@ PySocks==1.6.7 PyYAML==4.2b1 requests==2.22.0 six==1.10.0 -texttable==0.9.1 +texttable==1.6.2 urllib3==1.24.2; python_version == '3.3' websocket-client==0.32.0 diff --git a/setup.py b/setup.py index 614478010..c9e4729d8 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ install_requires = [ 'docopt >= 0.6.1, < 1', 'PyYAML >= 3.10, < 5', 'requests >= 2.20.0, < 3', - 'texttable >= 0.9.0, < 1', + 'texttable >= 0.9.0, < 2', 'websocket-client >= 0.32.0, < 1', 'docker[ssh] >= 3.7.0, < 5', 'dockerpty >= 0.4.1, < 1', From 3d80c8e86dec5724ef50154e4448eb018b6b035b Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Mon, 8 Jul 2019 15:04:34 +0200 Subject: [PATCH 12/26] Bump macOS build dependencies * OpenSSL 1.1.1a to 1.1.1c * Python 3.7.2 to 3.7.3 Signed-off-by: Christopher Crone --- script/setup/osx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/script/setup/osx b/script/setup/osx index 1fb91edca..ea7079944 100755 --- a/script/setup/osx +++ b/script/setup/osx @@ -13,13 +13,13 @@ if ! [ ${DEPLOYMENT_TARGET} == "$(macos_version)" ]; then SDK_SHA1=dd228a335194e3392f1904ce49aff1b1da26ca62 fi -OPENSSL_VERSION=1.1.1a +OPENSSL_VERSION=1.1.1c OPENSSL_URL=https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -OPENSSL_SHA1=8fae27b4f34445a5500c9dc50ae66b4d6472ce29 +OPENSSL_SHA1=71b830a077276cbeccc994369538617a21bee808 -PYTHON_VERSION=3.7.2 +PYTHON_VERSION=3.7.3 PYTHON_URL=https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz -PYTHON_SHA1=0cd8e52d8ed1d0be12ac8e87a623a15df3a3b418 +PYTHON_SHA1=77fd17e15ef06a7f6c5c0eab2909dc4bd81678d6 # # Install prerequisites. From b0e7d801a309c38430d55aa1047eeac33ef54501 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Wed, 10 Jul 2019 17:02:27 +0200 Subject: [PATCH 13/26] Bump macOS build dependency * Python 3.7.3 to 3.7.4 Signed-off-by: Christopher Crone --- script/setup/osx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/setup/osx b/script/setup/osx index ea7079944..69280f8a2 100755 --- a/script/setup/osx +++ b/script/setup/osx @@ -17,9 +17,9 @@ OPENSSL_VERSION=1.1.1c OPENSSL_URL=https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz OPENSSL_SHA1=71b830a077276cbeccc994369538617a21bee808 -PYTHON_VERSION=3.7.3 +PYTHON_VERSION=3.7.4 PYTHON_URL=https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz -PYTHON_SHA1=77fd17e15ef06a7f6c5c0eab2909dc4bd81678d6 +PYTHON_SHA1=fb1d764be8a9dcd40f2f152a610a0ab04e0d0ed3 # # Install prerequisites. From 993bada521a325910032399f51e8773aa6a90eaf Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Wed, 10 Jul 2019 17:29:05 +0200 Subject: [PATCH 14/26] Bump Linux build dependencies * Python 3.7.2 to 3.7.4 * Docker 18.09.5 to 18.09.7 * Alpine 3.9.3 to 3.10.0 * Debian stretch-20190326 to stretch-20190708 Signed-off-by: Christopher Crone --- Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1a3c501ae..ed9d74e5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ -ARG DOCKER_VERSION=18.09.5 -ARG PYTHON_VERSION=3.7.3 -ARG BUILD_ALPINE_VERSION=3.9 +ARG DOCKER_VERSION=18.09.7 +ARG PYTHON_VERSION=3.7.4 +ARG BUILD_ALPINE_VERSION=3.10 ARG BUILD_DEBIAN_VERSION=slim-stretch -ARG RUNTIME_ALPINE_VERSION=3.9.3 -ARG RUNTIME_DEBIAN_VERSION=stretch-20190326-slim +ARG RUNTIME_ALPINE_VERSION=3.10.0 +ARG RUNTIME_DEBIAN_VERSION=stretch-20190708-slim ARG BUILD_PLATFORM=alpine From f9099c91ae9e615eb5c7150f4f20520d966967a4 Mon Sep 17 00:00:00 2001 From: Goryudyuma Date: Mon, 3 Jun 2019 21:57:07 +0900 Subject: [PATCH 15/26] fix: The correct number is displayed Signed-off-by: Kei Matsumoto --- compose/cli/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/cli/utils.py b/compose/cli/utils.py index 4cc055cc9..bd06beef8 100644 --- a/compose/cli/utils.py +++ b/compose/cli/utils.py @@ -137,7 +137,7 @@ def human_readable_file_size(size): if order >= len(suffixes): order = len(suffixes) - 1 - return '{0:.3g} {1}'.format( + return '{0:.4g} {1}'.format( size / float(1 << (order * 10)), suffixes[order] ) From 75d41edb94d5dda7b5b7c476c1ba248d6e838755 Mon Sep 17 00:00:00 2001 From: Kei Matsumoto Date: Wed, 10 Jul 2019 12:10:19 +0900 Subject: [PATCH 16/26] fix: Add test Signed-off-by: Kei Matsumoto --- tests/unit/cli/utils_test.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/unit/cli/utils_test.py b/tests/unit/cli/utils_test.py index 26524ff37..25912f77a 100644 --- a/tests/unit/cli/utils_test.py +++ b/tests/unit/cli/utils_test.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import unittest from compose.utils import unquote_path +from compose.cli.utils import human_readable_file_size class UnquotePathTest(unittest.TestCase): @@ -21,3 +22,14 @@ class UnquotePathTest(unittest.TestCase): assert unquote_path('""hello""') == '"hello"' assert unquote_path('"hel"lo"') == 'hel"lo' assert unquote_path('"hello""') == 'hello"' + + +class HumanReadableFileSizeTest(unittest.TestCase): + def test_100b(self): + assert human_readable_file_size(100) == '100 B' + + def test_1kb(self): + assert human_readable_file_size(1024) == '1 kB' + + def test_1023b(self): + assert human_readable_file_size(1023) == '1023 B' From 59491c7d775b8a2f86532aa37fd4cc72b2b9459d Mon Sep 17 00:00:00 2001 From: Goryudyuma Date: Sun, 14 Jul 2019 03:24:18 +0900 Subject: [PATCH 17/26] add: test for units Signed-off-by: Kei Matsumoto --- tests/unit/cli/utils_test.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/unit/cli/utils_test.py b/tests/unit/cli/utils_test.py index 25912f77a..b340fb947 100644 --- a/tests/unit/cli/utils_test.py +++ b/tests/unit/cli/utils_test.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals import unittest -from compose.utils import unquote_path from compose.cli.utils import human_readable_file_size +from compose.utils import unquote_path class UnquotePathTest(unittest.TestCase): @@ -33,3 +33,12 @@ class HumanReadableFileSizeTest(unittest.TestCase): def test_1023b(self): assert human_readable_file_size(1023) == '1023 B' + + def test_units(self): + assert human_readable_file_size((2 ** 10) ** 0) == '1 B' + assert human_readable_file_size((2 ** 10) ** 1) == '1 kB' + assert human_readable_file_size((2 ** 10) ** 2) == '1 MB' + assert human_readable_file_size((2 ** 10) ** 3) == '1 GB' + assert human_readable_file_size((2 ** 10) ** 4) == '1 TB' + assert human_readable_file_size((2 ** 10) ** 5) == '1 PB' + assert human_readable_file_size((2 ** 10) ** 6) == '1 EB' From cd098e0cad4a0155b37179a77c6759ec33be0d61 Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Mon, 15 Jul 2019 18:56:04 +0200 Subject: [PATCH 18/26] Pin test images on a non rolling tag Mainly busybox:latest to the current latest which is 1.31.0-uclibc Signed-off-by: Ulysses Souza --- tests/acceptance/cli_test.py | 8 +- .../fixtures/UpperCaseDir/docker-compose.yml | 4 +- .../docker-compose.yml | 4 +- .../docker-compose.yml | 4 +- tests/fixtures/build-args/Dockerfile | 2 +- tests/fixtures/build-ctx/Dockerfile | 2 +- tests/fixtures/build-memory/Dockerfile | 2 +- .../build-multiple-composefile/a/Dockerfile | 2 +- .../build-multiple-composefile/b/Dockerfile | 2 +- .../dockerfile-with-volume/Dockerfile | 2 +- .../docker-compose.yml | 4 +- .../fixtures/echo-services/docker-compose.yml | 4 +- .../fixtures/entrypoint-dockerfile/Dockerfile | 2 +- .../docker-compose.yml | 2 +- .../exit-code-from/docker-compose.yml | 4 +- .../expose-composefile/docker-compose.yml | 2 +- tests/fixtures/images-service-tag/Dockerfile | 2 +- .../docker-compose.yml | 4 +- .../logging-composefile/docker-compose.yml | 4 +- .../logs-composefile/docker-compose.yml | 4 +- .../docker-compose.yml | 4 +- .../logs-tail-composefile/docker-compose.yml | 2 +- .../docker-compose.yaml | 2 +- .../multiple-composefiles/compose2.yml | 2 +- .../multiple-composefiles/docker-compose.yml | 4 +- .../networks/default-network-config.yml | 4 +- tests/fixtures/networks/external-default.yml | 4 +- .../no-links-composefile/docker-compose.yml | 6 +- .../override-files/docker-compose.yml | 4 +- tests/fixtures/override-files/extra.yml | 2 +- .../override-yaml-files/docker-compose.yml | 4 +- .../docker-compose.yml | 2 +- .../ports-composefile/docker-compose.yml | 2 +- .../ports-composefile/expanded-notation.yml | 2 +- .../ps-services-filter/docker-compose.yml | 2 +- tests/fixtures/run-labels/docker-compose.yml | 2 +- tests/fixtures/run-workdir/docker-compose.yml | 2 +- .../docker-compose.merge.yml | 2 +- .../docker-compose.yml | 2 +- tests/fixtures/simple-composefile/digest.yml | 2 +- .../simple-composefile/docker-compose.yml | 2 +- .../ignore-pull-failures.yml | 2 +- .../simple-composefile/pull-with-build.yml | 2 +- .../simple-failing-dockerfile/Dockerfile | 2 +- .../sleeps-composefile/docker-compose.yml | 4 +- .../docker-compose.yml | 2 +- tests/fixtures/tagless-image/Dockerfile | 2 +- tests/fixtures/top/docker-compose.yml | 4 +- .../unicode-environment/docker-compose.yml | 2 +- .../user-composefile/docker-compose.yml | 2 +- .../v2-dependencies/docker-compose.yml | 6 +- tests/fixtures/v2-full/Dockerfile | 2 +- tests/fixtures/v2-full/docker-compose.yml | 2 +- tests/fixtures/v2-simple/links-invalid.yml | 4 +- tests/fixtures/v2-simple/one-container.yml | 2 +- tests/helpers.py | 6 +- tests/integration/environment_test.py | 2 +- tests/integration/project_test.py | 129 +++++++++--------- tests/integration/service_test.py | 10 +- tests/integration/state_test.py | 21 +-- tests/integration/testcases.py | 5 +- tests/unit/config/config_test.py | 29 ++-- tests/unit/container_test.py | 7 +- tests/unit/project_test.py | 61 +++++---- tests/unit/service_test.py | 2 +- 65 files changed, 222 insertions(+), 210 deletions(-) diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 167893468..3fd857f26 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -20,6 +20,7 @@ import yaml from docker import errors from .. import mock +from ..helpers import BUSYBOX_IMAGE_WITH_TAG from ..helpers import create_host_file from compose.cli.command import get_project from compose.config.errors import DuplicateOverrideFileFound @@ -266,7 +267,7 @@ class CLITestCase(DockerClientTestCase): 'volumes_from': ['service:other:rw'], }, 'other': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'volumes': ['/data'], }, @@ -639,7 +640,7 @@ class CLITestCase(DockerClientTestCase): def test_pull_with_digest(self): result = self.dispatch(['-f', 'digest.yml', 'pull', '--no-parallel']) - assert 'Pulling simple (busybox:latest)...' in result.stderr + assert 'Pulling simple ({})...'.format(BUSYBOX_IMAGE_WITH_TAG) in result.stderr assert ('Pulling digest (busybox@' 'sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b520' '04ee8502d)...') in result.stderr @@ -650,7 +651,7 @@ class CLITestCase(DockerClientTestCase): 'pull', '--ignore-pull-failures', '--no-parallel'] ) - assert 'Pulling simple (busybox:latest)...' in result.stderr + assert 'Pulling simple ({})...'.format(BUSYBOX_IMAGE_WITH_TAG) in result.stderr assert 'Pulling another (nonexisting-image:latest)...' in result.stderr assert ('repository nonexisting-image not found' in result.stderr or 'image library/nonexisting-image:latest not found' in result.stderr or @@ -777,6 +778,7 @@ class CLITestCase(DockerClientTestCase): ] assert not containers + @pytest.mark.xfail(True, reason='Flaky on local') def test_build_rm(self): containers = [ Container.from_ps(self.project.client, c) diff --git a/tests/fixtures/UpperCaseDir/docker-compose.yml b/tests/fixtures/UpperCaseDir/docker-compose.yml index b25beaf4b..09cc9519f 100644 --- a/tests/fixtures/UpperCaseDir/docker-compose.yml +++ b/tests/fixtures/UpperCaseDir/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/abort-on-container-exit-0/docker-compose.yml b/tests/fixtures/abort-on-container-exit-0/docker-compose.yml index ce41697bc..77307ef29 100644 --- a/tests/fixtures/abort-on-container-exit-0/docker-compose.yml +++ b/tests/fixtures/abort-on-container-exit-0/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: ls . diff --git a/tests/fixtures/abort-on-container-exit-1/docker-compose.yml b/tests/fixtures/abort-on-container-exit-1/docker-compose.yml index 7ec9b7e11..23290964e 100644 --- a/tests/fixtures/abort-on-container-exit-1/docker-compose.yml +++ b/tests/fixtures/abort-on-container-exit-1/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: ls /thecakeisalie diff --git a/tests/fixtures/build-args/Dockerfile b/tests/fixtures/build-args/Dockerfile index 93ebcb9cd..d1534068a 100644 --- a/tests/fixtures/build-args/Dockerfile +++ b/tests/fixtures/build-args/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc LABEL com.docker.compose.test_image=true ARG favorite_th_character RUN echo "Favorite Touhou Character: ${favorite_th_character}" diff --git a/tests/fixtures/build-ctx/Dockerfile b/tests/fixtures/build-ctx/Dockerfile index dd864b838..4acac9c7a 100644 --- a/tests/fixtures/build-ctx/Dockerfile +++ b/tests/fixtures/build-ctx/Dockerfile @@ -1,3 +1,3 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc LABEL com.docker.compose.test_image=true CMD echo "success" diff --git a/tests/fixtures/build-memory/Dockerfile b/tests/fixtures/build-memory/Dockerfile index b27349b96..076b84d77 100644 --- a/tests/fixtures/build-memory/Dockerfile +++ b/tests/fixtures/build-memory/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox +FROM busybox:1.31.0-uclibc # Report the memory (through the size of the group memory) RUN echo "memory:" $(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) diff --git a/tests/fixtures/build-multiple-composefile/a/Dockerfile b/tests/fixtures/build-multiple-composefile/a/Dockerfile index 2ba45ce55..52ed15ec6 100644 --- a/tests/fixtures/build-multiple-composefile/a/Dockerfile +++ b/tests/fixtures/build-multiple-composefile/a/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc RUN echo a CMD top diff --git a/tests/fixtures/build-multiple-composefile/b/Dockerfile b/tests/fixtures/build-multiple-composefile/b/Dockerfile index e282e8bbf..932d851d9 100644 --- a/tests/fixtures/build-multiple-composefile/b/Dockerfile +++ b/tests/fixtures/build-multiple-composefile/b/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc RUN echo b CMD top diff --git a/tests/fixtures/dockerfile-with-volume/Dockerfile b/tests/fixtures/dockerfile-with-volume/Dockerfile index 0d376ec48..f38e1d579 100644 --- a/tests/fixtures/dockerfile-with-volume/Dockerfile +++ b/tests/fixtures/dockerfile-with-volume/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc LABEL com.docker.compose.test_image=true VOLUME /data CMD top diff --git a/tests/fixtures/duplicate-override-yaml-files/docker-compose.yml b/tests/fixtures/duplicate-override-yaml-files/docker-compose.yml index 5f2909d69..6880435b3 100644 --- a/tests/fixtures/duplicate-override-yaml-files/docker-compose.yml +++ b/tests/fixtures/duplicate-override-yaml-files/docker-compose.yml @@ -1,10 +1,10 @@ web: - image: busybox:latest + image: busybox:1.31.0-uclibc command: "sleep 100" links: - db db: - image: busybox:latest + image: busybox:1.31.0-uclibc command: "sleep 200" diff --git a/tests/fixtures/echo-services/docker-compose.yml b/tests/fixtures/echo-services/docker-compose.yml index 8014f3d91..75fc45d95 100644 --- a/tests/fixtures/echo-services/docker-compose.yml +++ b/tests/fixtures/echo-services/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: echo simple another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: echo another diff --git a/tests/fixtures/entrypoint-dockerfile/Dockerfile b/tests/fixtures/entrypoint-dockerfile/Dockerfile index 49f4416c8..30ec50bac 100644 --- a/tests/fixtures/entrypoint-dockerfile/Dockerfile +++ b/tests/fixtures/entrypoint-dockerfile/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc LABEL com.docker.compose.test_image=true ENTRYPOINT ["printf"] CMD ["default", "args"] diff --git a/tests/fixtures/environment-composefile/docker-compose.yml b/tests/fixtures/environment-composefile/docker-compose.yml index 9d99fee08..5650c7c8e 100644 --- a/tests/fixtures/environment-composefile/docker-compose.yml +++ b/tests/fixtures/environment-composefile/docker-compose.yml @@ -1,5 +1,5 @@ service: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top environment: diff --git a/tests/fixtures/exit-code-from/docker-compose.yml b/tests/fixtures/exit-code-from/docker-compose.yml index 687e78b97..c38bd549b 100644 --- a/tests/fixtures/exit-code-from/docker-compose.yml +++ b/tests/fixtures/exit-code-from/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sh -c "echo hello && tail -f /dev/null" another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: /bin/false diff --git a/tests/fixtures/expose-composefile/docker-compose.yml b/tests/fixtures/expose-composefile/docker-compose.yml index d14a468de..c2a3dc424 100644 --- a/tests/fixtures/expose-composefile/docker-compose.yml +++ b/tests/fixtures/expose-composefile/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top expose: - '3000' diff --git a/tests/fixtures/images-service-tag/Dockerfile b/tests/fixtures/images-service-tag/Dockerfile index 145e0202f..1e1a1b2e0 100644 --- a/tests/fixtures/images-service-tag/Dockerfile +++ b/tests/fixtures/images-service-tag/Dockerfile @@ -1,2 +1,2 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc RUN touch /foo diff --git a/tests/fixtures/logging-composefile-legacy/docker-compose.yml b/tests/fixtures/logging-composefile-legacy/docker-compose.yml index ee9941079..efac1d6a3 100644 --- a/tests/fixtures/logging-composefile-legacy/docker-compose.yml +++ b/tests/fixtures/logging-composefile-legacy/docker-compose.yml @@ -1,9 +1,9 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top log_driver: "none" another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top log_driver: "json-file" log_opt: diff --git a/tests/fixtures/logging-composefile/docker-compose.yml b/tests/fixtures/logging-composefile/docker-compose.yml index 466d13e5b..ac231b898 100644 --- a/tests/fixtures/logging-composefile/docker-compose.yml +++ b/tests/fixtures/logging-composefile/docker-compose.yml @@ -1,12 +1,12 @@ version: "2" services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top logging: driver: "none" another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top logging: driver: "json-file" diff --git a/tests/fixtures/logs-composefile/docker-compose.yml b/tests/fixtures/logs-composefile/docker-compose.yml index ea18f162d..3ffaa9849 100644 --- a/tests/fixtures/logs-composefile/docker-compose.yml +++ b/tests/fixtures/logs-composefile/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sh -c "sleep 1 && echo hello && tail -f /dev/null" another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sh -c "sleep 1 && echo test" diff --git a/tests/fixtures/logs-restart-composefile/docker-compose.yml b/tests/fixtures/logs-restart-composefile/docker-compose.yml index 6be8b9079..2179d54de 100644 --- a/tests/fixtures/logs-restart-composefile/docker-compose.yml +++ b/tests/fixtures/logs-restart-composefile/docker-compose.yml @@ -1,7 +1,7 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sh -c "echo hello && tail -f /dev/null" another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sh -c "sleep 2 && echo world && /bin/false" restart: "on-failure:2" diff --git a/tests/fixtures/logs-tail-composefile/docker-compose.yml b/tests/fixtures/logs-tail-composefile/docker-compose.yml index b70d0cc63..18dad986e 100644 --- a/tests/fixtures/logs-tail-composefile/docker-compose.yml +++ b/tests/fixtures/logs-tail-composefile/docker-compose.yml @@ -1,3 +1,3 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sh -c "echo w && echo x && echo y && echo z" diff --git a/tests/fixtures/longer-filename-composefile/docker-compose.yaml b/tests/fixtures/longer-filename-composefile/docker-compose.yaml index a4eba2d05..5dadce44a 100644 --- a/tests/fixtures/longer-filename-composefile/docker-compose.yaml +++ b/tests/fixtures/longer-filename-composefile/docker-compose.yaml @@ -1,3 +1,3 @@ definedinyamlnotyml: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/multiple-composefiles/compose2.yml b/tests/fixtures/multiple-composefiles/compose2.yml index 568033804..530d92df6 100644 --- a/tests/fixtures/multiple-composefiles/compose2.yml +++ b/tests/fixtures/multiple-composefiles/compose2.yml @@ -1,3 +1,3 @@ yetanother: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/multiple-composefiles/docker-compose.yml b/tests/fixtures/multiple-composefiles/docker-compose.yml index b25beaf4b..09cc9519f 100644 --- a/tests/fixtures/multiple-composefiles/docker-compose.yml +++ b/tests/fixtures/multiple-composefiles/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/networks/default-network-config.yml b/tests/fixtures/networks/default-network-config.yml index 4bd0989b7..556ca9805 100644 --- a/tests/fixtures/networks/default-network-config.yml +++ b/tests/fixtures/networks/default-network-config.yml @@ -1,10 +1,10 @@ version: "2" services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top networks: default: diff --git a/tests/fixtures/networks/external-default.yml b/tests/fixtures/networks/external-default.yml index 5c9426b84..42a395656 100644 --- a/tests/fixtures/networks/external-default.yml +++ b/tests/fixtures/networks/external-default.yml @@ -1,10 +1,10 @@ version: "2" services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top networks: default: diff --git a/tests/fixtures/no-links-composefile/docker-compose.yml b/tests/fixtures/no-links-composefile/docker-compose.yml index 75a6a085c..54936f306 100644 --- a/tests/fixtures/no-links-composefile/docker-compose.yml +++ b/tests/fixtures/no-links-composefile/docker-compose.yml @@ -1,9 +1,9 @@ db: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top web: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top console: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/override-files/docker-compose.yml b/tests/fixtures/override-files/docker-compose.yml index 6c3d4e172..0119ec738 100644 --- a/tests/fixtures/override-files/docker-compose.yml +++ b/tests/fixtures/override-files/docker-compose.yml @@ -1,10 +1,10 @@ version: '2.2' services: web: - image: busybox:latest + image: busybox:1.31.0-uclibc command: "sleep 200" depends_on: - db db: - image: busybox:latest + image: busybox:1.31.0-uclibc command: "sleep 200" diff --git a/tests/fixtures/override-files/extra.yml b/tests/fixtures/override-files/extra.yml index 492c37952..d03c5096d 100644 --- a/tests/fixtures/override-files/extra.yml +++ b/tests/fixtures/override-files/extra.yml @@ -6,5 +6,5 @@ services: - other other: - image: busybox:latest + image: busybox:1.31.0-uclibc command: "top" diff --git a/tests/fixtures/override-yaml-files/docker-compose.yml b/tests/fixtures/override-yaml-files/docker-compose.yml index 5f2909d69..6880435b3 100644 --- a/tests/fixtures/override-yaml-files/docker-compose.yml +++ b/tests/fixtures/override-yaml-files/docker-compose.yml @@ -1,10 +1,10 @@ web: - image: busybox:latest + image: busybox:1.31.0-uclibc command: "sleep 100" links: - db db: - image: busybox:latest + image: busybox:1.31.0-uclibc command: "sleep 200" diff --git a/tests/fixtures/ports-composefile-scale/docker-compose.yml b/tests/fixtures/ports-composefile-scale/docker-compose.yml index 1a2bb485b..bdd39cef3 100644 --- a/tests/fixtures/ports-composefile-scale/docker-compose.yml +++ b/tests/fixtures/ports-composefile-scale/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: /bin/sleep 300 ports: - '3000' diff --git a/tests/fixtures/ports-composefile/docker-compose.yml b/tests/fixtures/ports-composefile/docker-compose.yml index c213068de..f49870278 100644 --- a/tests/fixtures/ports-composefile/docker-compose.yml +++ b/tests/fixtures/ports-composefile/docker-compose.yml @@ -1,6 +1,6 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top ports: - '3000' diff --git a/tests/fixtures/ports-composefile/expanded-notation.yml b/tests/fixtures/ports-composefile/expanded-notation.yml index 09a7a2bf9..6510e4281 100644 --- a/tests/fixtures/ports-composefile/expanded-notation.yml +++ b/tests/fixtures/ports-composefile/expanded-notation.yml @@ -1,7 +1,7 @@ version: '3.2' services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top ports: - target: 3000 diff --git a/tests/fixtures/ps-services-filter/docker-compose.yml b/tests/fixtures/ps-services-filter/docker-compose.yml index 3d8609373..180f515aa 100644 --- a/tests/fixtures/ps-services-filter/docker-compose.yml +++ b/tests/fixtures/ps-services-filter/docker-compose.yml @@ -1,5 +1,5 @@ with_image: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top with_build: build: ../build-ctx/ diff --git a/tests/fixtures/run-labels/docker-compose.yml b/tests/fixtures/run-labels/docker-compose.yml index e8cd50065..e3b237fd5 100644 --- a/tests/fixtures/run-labels/docker-compose.yml +++ b/tests/fixtures/run-labels/docker-compose.yml @@ -1,5 +1,5 @@ service: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top labels: diff --git a/tests/fixtures/run-workdir/docker-compose.yml b/tests/fixtures/run-workdir/docker-compose.yml index dc3ea86a0..9d092a55f 100644 --- a/tests/fixtures/run-workdir/docker-compose.yml +++ b/tests/fixtures/run-workdir/docker-compose.yml @@ -1,4 +1,4 @@ service: - image: busybox:latest + image: busybox:1.31.0-uclibc working_dir: /etc command: /bin/true diff --git a/tests/fixtures/simple-composefile-volume-ready/docker-compose.merge.yml b/tests/fixtures/simple-composefile-volume-ready/docker-compose.merge.yml index fe7171516..45b626d02 100644 --- a/tests/fixtures/simple-composefile-volume-ready/docker-compose.merge.yml +++ b/tests/fixtures/simple-composefile-volume-ready/docker-compose.merge.yml @@ -1,7 +1,7 @@ version: '2.2' services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc volumes: - datastore:/data1 diff --git a/tests/fixtures/simple-composefile-volume-ready/docker-compose.yml b/tests/fixtures/simple-composefile-volume-ready/docker-compose.yml index 98a7d23b7..088d71c99 100644 --- a/tests/fixtures/simple-composefile-volume-ready/docker-compose.yml +++ b/tests/fixtures/simple-composefile-volume-ready/docker-compose.yml @@ -1,2 +1,2 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc diff --git a/tests/fixtures/simple-composefile/digest.yml b/tests/fixtures/simple-composefile/digest.yml index 08f1d993e..79f043baa 100644 --- a/tests/fixtures/simple-composefile/digest.yml +++ b/tests/fixtures/simple-composefile/digest.yml @@ -1,5 +1,5 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top digest: image: busybox@sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d diff --git a/tests/fixtures/simple-composefile/docker-compose.yml b/tests/fixtures/simple-composefile/docker-compose.yml index e86d3fc80..b66a06527 100644 --- a/tests/fixtures/simple-composefile/docker-compose.yml +++ b/tests/fixtures/simple-composefile/docker-compose.yml @@ -2,5 +2,5 @@ simple: image: busybox:1.27.2 command: top another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/simple-composefile/ignore-pull-failures.yml b/tests/fixtures/simple-composefile/ignore-pull-failures.yml index a28f79223..7e7d560da 100644 --- a/tests/fixtures/simple-composefile/ignore-pull-failures.yml +++ b/tests/fixtures/simple-composefile/ignore-pull-failures.yml @@ -1,5 +1,5 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top another: image: nonexisting-image:latest diff --git a/tests/fixtures/simple-composefile/pull-with-build.yml b/tests/fixtures/simple-composefile/pull-with-build.yml index 261dc44df..3bff35c51 100644 --- a/tests/fixtures/simple-composefile/pull-with-build.yml +++ b/tests/fixtures/simple-composefile/pull-with-build.yml @@ -7,5 +7,5 @@ services: from_simple: image: simple another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/simple-failing-dockerfile/Dockerfile b/tests/fixtures/simple-failing-dockerfile/Dockerfile index c2d06b167..205021a23 100644 --- a/tests/fixtures/simple-failing-dockerfile/Dockerfile +++ b/tests/fixtures/simple-failing-dockerfile/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc LABEL com.docker.compose.test_image=true LABEL com.docker.compose.test_failing_image=true # With the following label the container wil be cleaned up automatically diff --git a/tests/fixtures/sleeps-composefile/docker-compose.yml b/tests/fixtures/sleeps-composefile/docker-compose.yml index 7c8d84f8d..26feb502a 100644 --- a/tests/fixtures/sleeps-composefile/docker-compose.yml +++ b/tests/fixtures/sleeps-composefile/docker-compose.yml @@ -3,8 +3,8 @@ version: "2" services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sleep 200 another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sleep 200 diff --git a/tests/fixtures/stop-signal-composefile/docker-compose.yml b/tests/fixtures/stop-signal-composefile/docker-compose.yml index 04f58aa98..9f99b0c75 100644 --- a/tests/fixtures/stop-signal-composefile/docker-compose.yml +++ b/tests/fixtures/stop-signal-composefile/docker-compose.yml @@ -1,5 +1,5 @@ simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: - sh - '-c' diff --git a/tests/fixtures/tagless-image/Dockerfile b/tests/fixtures/tagless-image/Dockerfile index 567410552..923055551 100644 --- a/tests/fixtures/tagless-image/Dockerfile +++ b/tests/fixtures/tagless-image/Dockerfile @@ -1,2 +1,2 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc RUN touch /blah diff --git a/tests/fixtures/top/docker-compose.yml b/tests/fixtures/top/docker-compose.yml index d632a836e..36a3917d7 100644 --- a/tests/fixtures/top/docker-compose.yml +++ b/tests/fixtures/top/docker-compose.yml @@ -1,6 +1,6 @@ service_a: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top service_b: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/unicode-environment/docker-compose.yml b/tests/fixtures/unicode-environment/docker-compose.yml index a41af4f07..307678cd0 100644 --- a/tests/fixtures/unicode-environment/docker-compose.yml +++ b/tests/fixtures/unicode-environment/docker-compose.yml @@ -1,7 +1,7 @@ version: '2' services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: sh -c 'echo $$FOO' environment: FOO: ${BAR} diff --git a/tests/fixtures/user-composefile/docker-compose.yml b/tests/fixtures/user-composefile/docker-compose.yml index 3eb7d3977..11283d9d9 100644 --- a/tests/fixtures/user-composefile/docker-compose.yml +++ b/tests/fixtures/user-composefile/docker-compose.yml @@ -1,4 +1,4 @@ service: - image: busybox:latest + image: busybox:1.31.0-uclibc user: notauser command: id diff --git a/tests/fixtures/v2-dependencies/docker-compose.yml b/tests/fixtures/v2-dependencies/docker-compose.yml index 2e14b94bb..45ec8501e 100644 --- a/tests/fixtures/v2-dependencies/docker-compose.yml +++ b/tests/fixtures/v2-dependencies/docker-compose.yml @@ -1,13 +1,13 @@ version: "2.0" services: db: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top web: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top depends_on: - db console: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/v2-full/Dockerfile b/tests/fixtures/v2-full/Dockerfile index 51ed0d907..6fa7a726c 100644 --- a/tests/fixtures/v2-full/Dockerfile +++ b/tests/fixtures/v2-full/Dockerfile @@ -1,4 +1,4 @@ -FROM busybox:latest +FROM busybox:1.31.0-uclibc RUN echo something CMD top diff --git a/tests/fixtures/v2-full/docker-compose.yml b/tests/fixtures/v2-full/docker-compose.yml index a973dd0cf..20c14f0f7 100644 --- a/tests/fixtures/v2-full/docker-compose.yml +++ b/tests/fixtures/v2-full/docker-compose.yml @@ -18,7 +18,7 @@ services: - other other: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top volumes: - /data diff --git a/tests/fixtures/v2-simple/links-invalid.yml b/tests/fixtures/v2-simple/links-invalid.yml index 481aa4045..a88eb1d52 100644 --- a/tests/fixtures/v2-simple/links-invalid.yml +++ b/tests/fixtures/v2-simple/links-invalid.yml @@ -1,10 +1,10 @@ version: "2" services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top links: - another another: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/fixtures/v2-simple/one-container.yml b/tests/fixtures/v2-simple/one-container.yml index 22cd9863c..2d5c2ca66 100644 --- a/tests/fixtures/v2-simple/one-container.yml +++ b/tests/fixtures/v2-simple/one-container.yml @@ -1,5 +1,5 @@ version: "2" services: simple: - image: busybox:latest + image: busybox:1.31.0-uclibc command: top diff --git a/tests/helpers.py b/tests/helpers.py index dd1299811..327715ee2 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -7,6 +7,10 @@ from compose.config.config import ConfigDetails from compose.config.config import ConfigFile from compose.config.config import load +BUSYBOX_IMAGE_NAME = 'busybox' +BUSYBOX_DEFAULT_TAG = '1.31.0-uclibc' +BUSYBOX_IMAGE_WITH_TAG = '{}:{}'.format(BUSYBOX_IMAGE_NAME, BUSYBOX_DEFAULT_TAG) + def build_config(contents, **kwargs): return load(build_config_details(contents, **kwargs)) @@ -22,7 +26,7 @@ def build_config_details(contents, working_dir='working_dir', filename='filename def create_custom_host_file(client, filename, content): dirname = os.path.dirname(filename) container = client.create_container( - 'busybox:latest', + BUSYBOX_IMAGE_WITH_TAG, ['sh', '-c', 'echo -n "{}" > {}'.format(content, filename)], volumes={dirname: {}}, host_config=client.create_host_config( diff --git a/tests/integration/environment_test.py b/tests/integration/environment_test.py index 07619eec1..ac31d2e1f 100644 --- a/tests/integration/environment_test.py +++ b/tests/integration/environment_test.py @@ -20,7 +20,7 @@ class EnvironmentTest(DockerClientTestCase): cls.compose_file.write(bytes("""version: '3.2' services: svc: - image: busybox:latest + image: busybox:1.31.0-uclibc environment: TEST_VARIABLE: ${TEST_VARIABLE}""", encoding='utf-8')) cls.compose_file.flush() diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py index 1d9495ff8..4c88f3d6b 100644 --- a/tests/integration/project_test.py +++ b/tests/integration/project_test.py @@ -15,6 +15,7 @@ from docker.errors import NotFound from .. import mock from ..helpers import build_config as load_config +from ..helpers import BUSYBOX_IMAGE_WITH_TAG from ..helpers import create_host_file from .testcases import DockerClientTestCase from .testcases import SWARM_SKIP_CONTAINERS_ALL @@ -128,11 +129,11 @@ class ProjectTest(DockerClientTestCase): name='composetest', config_data=load_config({ 'data': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': ['/var/data'], }, 'db': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes_from': ['data'], }, }), @@ -145,7 +146,7 @@ class ProjectTest(DockerClientTestCase): def test_volumes_from_container(self): data_container = Container.create( self.client, - image='busybox:latest', + image=BUSYBOX_IMAGE_WITH_TAG, volumes=['/var/data'], name='composetest_data_container', labels={LABEL_PROJECT: 'composetest'}, @@ -155,7 +156,7 @@ class ProjectTest(DockerClientTestCase): name='composetest', config_data=load_config({ 'db': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes_from': ['composetest_data_container'], }, }), @@ -174,11 +175,11 @@ class ProjectTest(DockerClientTestCase): 'version': str(V2_0), 'services': { 'net': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"] }, 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'network_mode': 'service:net', 'command': ["top"] }, @@ -202,7 +203,7 @@ class ProjectTest(DockerClientTestCase): 'version': str(V2_0), 'services': { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'network_mode': 'container:composetest_net_container' }, }, @@ -217,7 +218,7 @@ class ProjectTest(DockerClientTestCase): net_container = Container.create( self.client, - image='busybox:latest', + image=BUSYBOX_IMAGE_WITH_TAG, name='composetest_net_container', command='top', labels={LABEL_PROJECT: 'composetest'}, @@ -237,11 +238,11 @@ class ProjectTest(DockerClientTestCase): name='composetest', config_data=load_config({ 'net': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"] }, 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'net': 'container:net', 'command': ["top"] }, @@ -262,7 +263,7 @@ class ProjectTest(DockerClientTestCase): name='composetest', config_data=load_config({ 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'net': 'container:composetest_net_container' }, }), @@ -276,7 +277,7 @@ class ProjectTest(DockerClientTestCase): net_container = Container.create( self.client, - image='busybox:latest', + image=BUSYBOX_IMAGE_WITH_TAG, name='composetest_net_container', command='top', labels={LABEL_PROJECT: 'composetest'}, @@ -549,20 +550,20 @@ class ProjectTest(DockerClientTestCase): name='composetest', config_data=load_config({ 'console': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"], }, 'data': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"] }, 'db': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"], 'volumes_from': ['data'], }, 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"], 'links': ['db'], }, @@ -584,20 +585,20 @@ class ProjectTest(DockerClientTestCase): name='composetest', config_data=load_config({ 'console': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"], }, 'data': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"] }, 'db': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"], 'volumes_from': ['data'], }, 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': ["top"], 'links': ['db'], }, @@ -623,7 +624,7 @@ class ProjectTest(DockerClientTestCase): 'version': '2.1', 'services': { 'foo': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'tmpfs': ['/dev/shm'], 'volumes': ['/dev/shm'] } @@ -664,7 +665,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'networks': { 'foo': None, @@ -709,7 +710,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': {'front': None}, }], networks={ @@ -769,7 +770,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': {'front': None}, }], networks={ @@ -804,7 +805,7 @@ class ProjectTest(DockerClientTestCase): version=V2_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'networks': { 'static_test': { @@ -856,7 +857,7 @@ class ProjectTest(DockerClientTestCase): version=V2_3, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': { 'n1': { 'priority': p1, @@ -919,7 +920,7 @@ class ProjectTest(DockerClientTestCase): version=V2_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'networks': { 'static_test': { @@ -962,7 +963,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': { 'static_test': { 'ipv4_address': '172.16.100.100', @@ -998,7 +999,7 @@ class ProjectTest(DockerClientTestCase): version=V2_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': { 'linklocaltest': { 'link_local_ips': ['169.254.8.8'] @@ -1035,7 +1036,7 @@ class ProjectTest(DockerClientTestCase): 'name': 'web', 'volumes': [VolumeSpec.parse('foo:/container-path')], 'networks': {'foo': {}}, - 'image': 'busybox:latest' + 'image': BUSYBOX_IMAGE_WITH_TAG }], networks={ 'foo': { @@ -1071,7 +1072,7 @@ class ProjectTest(DockerClientTestCase): version=V2_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'isolation': 'default' }], ) @@ -1091,7 +1092,7 @@ class ProjectTest(DockerClientTestCase): version=V2_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'isolation': 'foobar' }], ) @@ -1111,7 +1112,7 @@ class ProjectTest(DockerClientTestCase): version=V2_3, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'runtime': 'runc' }], ) @@ -1131,7 +1132,7 @@ class ProjectTest(DockerClientTestCase): version=V2_3, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'runtime': 'foobar' }], ) @@ -1151,7 +1152,7 @@ class ProjectTest(DockerClientTestCase): version=V2_3, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'runtime': 'nvidia' }], ) @@ -1171,7 +1172,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': {'internal': None}, }], networks={ @@ -1200,7 +1201,7 @@ class ProjectTest(DockerClientTestCase): version=V2_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': {network_name: None} }], networks={ @@ -1233,7 +1234,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={vol_name: {'driver': 'local'}}, @@ -1260,7 +1261,7 @@ class ProjectTest(DockerClientTestCase): version=V2_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': [VolumeSpec.parse('{}:/data'.format(volume_name))] }], volumes={ @@ -1299,9 +1300,9 @@ class ProjectTest(DockerClientTestCase): { 'version': str(V2_0), 'services': { - 'simple': {'image': 'busybox:latest', 'command': 'top'}, + 'simple': {'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top'}, 'another': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'logging': { 'driver': "json-file", @@ -1352,7 +1353,7 @@ class ProjectTest(DockerClientTestCase): 'version': str(V2_0), 'services': { 'simple': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'ports': ['1234:1234'] }, @@ -1386,7 +1387,7 @@ class ProjectTest(DockerClientTestCase): version=V2_2, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'scale': 3 }] @@ -1416,7 +1417,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={vol_name: {}}, @@ -1440,7 +1441,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={vol_name: {}}, @@ -1464,7 +1465,7 @@ class ProjectTest(DockerClientTestCase): version=V3_1, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'cat /run/secrets/special', 'secrets': [ types.ServiceSecret.parse({'source': 'super', 'target': 'special'}), @@ -1502,7 +1503,7 @@ class ProjectTest(DockerClientTestCase): 'services': [ { 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'cat /run/secrets/special', 'environment': ['constraint:node=={}'.format(node if node is not None else '')] } @@ -1555,7 +1556,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={vol_name: {'driver': 'foobar'}}, @@ -1578,7 +1579,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={vol_name: {'driver': 'local'}}, @@ -1620,7 +1621,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={ @@ -1662,7 +1663,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={vol_name: {'driver': 'local'}}, @@ -1701,7 +1702,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={ @@ -1725,7 +1726,7 @@ class ProjectTest(DockerClientTestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top' }], volumes={ @@ -1753,7 +1754,7 @@ class ProjectTest(DockerClientTestCase): 'version': str(V2_0), 'services': { 'simple': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'volumes': ['{0}:/data'.format(vol_name)] }, @@ -1782,7 +1783,7 @@ class ProjectTest(DockerClientTestCase): def test_project_up_orphans(self): config_dict = { 'service1': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', } } @@ -1819,7 +1820,7 @@ class ProjectTest(DockerClientTestCase): def test_project_up_ignore_orphans(self): config_dict = { 'service1': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', } } @@ -1847,7 +1848,7 @@ class ProjectTest(DockerClientTestCase): 'version': '2.1', 'services': { 'svc1': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'healthcheck': { 'test': 'exit 0', @@ -1857,7 +1858,7 @@ class ProjectTest(DockerClientTestCase): }, }, 'svc2': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'depends_on': { 'svc1': {'condition': 'service_healthy'}, @@ -1884,7 +1885,7 @@ class ProjectTest(DockerClientTestCase): 'version': '2.1', 'services': { 'svc1': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'healthcheck': { 'test': 'exit 1', @@ -1894,7 +1895,7 @@ class ProjectTest(DockerClientTestCase): }, }, 'svc2': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'depends_on': { 'svc1': {'condition': 'service_healthy'}, @@ -1923,14 +1924,14 @@ class ProjectTest(DockerClientTestCase): 'version': '2.1', 'services': { 'svc1': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'healthcheck': { 'disable': True }, }, 'svc2': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'depends_on': { 'svc1': {'condition': 'service_healthy'}, @@ -1967,7 +1968,7 @@ class ProjectTest(DockerClientTestCase): 'version': '2.3', 'services': { 'svc1': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'security_opt': ['seccomp:"{}"'.format(profile_path)] } @@ -1991,7 +1992,7 @@ class ProjectTest(DockerClientTestCase): 'version': '2.3', 'services': { 'svc1': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'ls', 'volumes': ['foo:/foo:rw'], 'networks': ['bar'], diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index b49ae7106..9750f581c 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -15,6 +15,7 @@ from six import StringIO from six import text_type from .. import mock +from ..helpers import BUSYBOX_IMAGE_WITH_TAG from .testcases import docker_client from .testcases import DockerClientTestCase from .testcases import get_links @@ -373,7 +374,7 @@ class ServiceTest(DockerClientTestCase): self.client.create_volume(volume_name) service = Service('db', client=client, volumes=[ MountSpec(type='volume', source=volume_name, target=container_path) - ], image='busybox:latest', command=['top'], project='composetest') + ], image=BUSYBOX_IMAGE_WITH_TAG, command=['top'], project='composetest') container = service.create_container() service.start_container(container) mount = container.get_mount(container_path) @@ -388,7 +389,7 @@ class ServiceTest(DockerClientTestCase): container_path = '/container-tmpfs' service = Service('db', client=client, volumes=[ MountSpec(type='tmpfs', target=container_path) - ], image='busybox:latest', command=['top'], project='composetest') + ], image=BUSYBOX_IMAGE_WITH_TAG, command=['top'], project='composetest') container = service.create_container() service.start_container(container) mount = container.get_mount(container_path) @@ -474,7 +475,7 @@ class ServiceTest(DockerClientTestCase): volume_container_1 = volume_service.create_container() volume_container_2 = Container.create( self.client, - image='busybox:latest', + image=BUSYBOX_IMAGE_WITH_TAG, command=["top"], labels={LABEL_PROJECT: 'composetest'}, host_config={}, @@ -1232,9 +1233,8 @@ class ServiceTest(DockerClientTestCase): # }) def test_create_with_image_id(self): - # Get image id for the current busybox:latest pull_busybox(self.client) - image_id = self.client.inspect_image('busybox:latest')['Id'][:12] + image_id = self.client.inspect_image(BUSYBOX_IMAGE_WITH_TAG)['Id'][:12] service = self.create_service('foo', image=image_id) service.create_container() diff --git a/tests/integration/state_test.py b/tests/integration/state_test.py index 0d69217cf..714945ee5 100644 --- a/tests/integration/state_test.py +++ b/tests/integration/state_test.py @@ -10,6 +10,7 @@ import copy import py from docker.errors import ImageNotFound +from ..helpers import BUSYBOX_IMAGE_WITH_TAG from .testcases import DockerClientTestCase from .testcases import get_links from .testcases import no_cluster @@ -42,8 +43,8 @@ class BasicProjectTest(ProjectTestCase): super(BasicProjectTest, self).setUp() self.cfg = { - 'db': {'image': 'busybox:latest', 'command': 'top'}, - 'web': {'image': 'busybox:latest', 'command': 'top'}, + 'db': {'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top'}, + 'web': {'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top'}, } def test_no_change(self): @@ -99,16 +100,16 @@ class ProjectWithDependenciesTest(ProjectTestCase): self.cfg = { 'db': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'tail -f /dev/null', }, 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'tail -f /dev/null', 'links': ['db'], }, 'nginx': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'tail -f /dev/null', 'links': ['web'], }, @@ -173,7 +174,7 @@ class ProjectWithDependenciesTest(ProjectTestCase): def test_service_removed_while_down(self): next_cfg = { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'tail -f /dev/null', }, 'nginx': self.cfg['nginx'], @@ -219,16 +220,16 @@ class ProjectWithDependsOnDependenciesTest(ProjectTestCase): 'version': '2', 'services': { 'db': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'tail -f /dev/null', }, 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'tail -f /dev/null', 'depends_on': ['db'], }, 'nginx': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'tail -f /dev/null', 'depends_on': ['web'], }, @@ -385,7 +386,7 @@ class ServiceStateTest(DockerClientTestCase): assert ('recreate', [container]) == web.convergence_plan() def test_trigger_recreate_with_nonexistent_image_tag(self): - web = self.create_service('web', image="busybox:latest") + web = self.create_service('web', image=BUSYBOX_IMAGE_WITH_TAG) container = web.create_container() web = self.create_service('web', image="nonexistent-image") diff --git a/tests/integration/testcases.py b/tests/integration/testcases.py index cfdf22f7e..fe70d1f72 100644 --- a/tests/integration/testcases.py +++ b/tests/integration/testcases.py @@ -9,6 +9,7 @@ from docker.errors import APIError from docker.utils import version_lt from .. import unittest +from ..helpers import BUSYBOX_IMAGE_WITH_TAG from compose.cli.docker_client import docker_client from compose.config.config import resolve_environment from compose.config.environment import Environment @@ -32,7 +33,7 @@ SWARM_ASSUME_MULTINODE = os.environ.get('SWARM_ASSUME_MULTINODE', '0') != '0' def pull_busybox(client): - client.pull('busybox:latest', stream=False) + client.pull(BUSYBOX_IMAGE_WITH_TAG, stream=False) def get_links(container): @@ -123,7 +124,7 @@ class DockerClientTestCase(unittest.TestCase): def create_service(self, name, **kwargs): if 'image' not in kwargs and 'build' not in kwargs: - kwargs['image'] = 'busybox:latest' + kwargs['image'] = BUSYBOX_IMAGE_WITH_TAG if 'command' not in kwargs: kwargs['command'] = ["top"] diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 2f27a5b20..b583422f5 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -15,6 +15,7 @@ import pytest import yaml from ...helpers import build_config_details +from ...helpers import BUSYBOX_IMAGE_WITH_TAG from compose.config import config from compose.config import types from compose.config.config import resolve_build_args @@ -343,7 +344,7 @@ class ConfigTest(unittest.TestCase): with pytest.raises(ConfigurationError): config.load( build_config_details( - {'web': 'busybox:latest'}, + {'web': BUSYBOX_IMAGE_WITH_TAG}, 'working_dir', 'filename.yml' ) @@ -353,7 +354,7 @@ class ConfigTest(unittest.TestCase): with pytest.raises(ConfigurationError): config.load( build_config_details( - {'version': '2', 'services': {'web': 'busybox:latest'}}, + {'version': '2', 'services': {'web': BUSYBOX_IMAGE_WITH_TAG}}, 'working_dir', 'filename.yml' ) @@ -364,7 +365,7 @@ class ConfigTest(unittest.TestCase): config.load( build_config_details({ 'version': '2', - 'services': {'web': 'busybox:latest'}, + 'services': {'web': BUSYBOX_IMAGE_WITH_TAG}, 'networks': { 'invalid': {'foo', 'bar'} } @@ -847,15 +848,15 @@ class ConfigTest(unittest.TestCase): def test_load_sorts_in_dependency_order(self): config_details = build_config_details({ 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'links': ['db'], }, 'db': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes_from': ['volume:ro'] }, 'volume': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': ['/tmp'], } }) @@ -1280,7 +1281,7 @@ class ConfigTest(unittest.TestCase): 'version': '2', 'services': { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': ['data0028:/data:ro'], }, }, @@ -1296,7 +1297,7 @@ class ConfigTest(unittest.TestCase): 'version': '2', 'services': { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': ['./data0028:/data:ro'], }, }, @@ -1312,7 +1313,7 @@ class ConfigTest(unittest.TestCase): 'base.yaml', { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': ['data0028:/data:ro'], }, } @@ -1329,7 +1330,7 @@ class ConfigTest(unittest.TestCase): 'version': '2.3', 'services': { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': [ { 'target': '/anonymous', 'type': 'volume' @@ -1374,7 +1375,7 @@ class ConfigTest(unittest.TestCase): 'version': '3.4', 'services': { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': [ {'type': 'bind', 'source': './web', 'target': '/web'}, ], @@ -1396,7 +1397,7 @@ class ConfigTest(unittest.TestCase): 'version': '3.4', 'services': { 'web': { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes': [ {'type': 'bind', 'source': '~/web', 'target': '/web'}, ], @@ -2293,7 +2294,7 @@ class ConfigTest(unittest.TestCase): def test_merge_mixed_ports(self): base = { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'ports': [ { @@ -2310,7 +2311,7 @@ class ConfigTest(unittest.TestCase): actual = config.merge_service_dicts(base, override, V3_1) assert actual == { - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'command': 'top', 'ports': [types.ServicePort('1245', '1245', 'udp', None, None)] } diff --git a/tests/unit/container_test.py b/tests/unit/container_test.py index fde17847a..626b466d4 100644 --- a/tests/unit/container_test.py +++ b/tests/unit/container_test.py @@ -5,6 +5,7 @@ import docker from .. import mock from .. import unittest +from ..helpers import BUSYBOX_IMAGE_WITH_TAG from compose.const import LABEL_ONE_OFF from compose.const import LABEL_SLUG from compose.container import Container @@ -17,7 +18,7 @@ class ContainerTest(unittest.TestCase): self.container_id = "abcabcabcbabc12345" self.container_dict = { "Id": self.container_id, - "Image": "busybox:latest", + "Image": BUSYBOX_IMAGE_WITH_TAG, "Command": "top", "Created": 1387384730, "Status": "Up 8 seconds", @@ -43,7 +44,7 @@ class ContainerTest(unittest.TestCase): has_been_inspected=True) assert container.dictionary == { "Id": self.container_id, - "Image": "busybox:latest", + "Image": BUSYBOX_IMAGE_WITH_TAG, "Name": "/composetest_db_1", } @@ -58,7 +59,7 @@ class ContainerTest(unittest.TestCase): has_been_inspected=True) assert container.dictionary == { "Id": self.container_id, - "Image": "busybox:latest", + "Image": BUSYBOX_IMAGE_WITH_TAG, "Name": "/composetest_db_1", } diff --git a/tests/unit/project_test.py b/tests/unit/project_test.py index 89b080d20..93a9aa292 100644 --- a/tests/unit/project_test.py +++ b/tests/unit/project_test.py @@ -10,6 +10,7 @@ from docker.errors import NotFound from .. import mock from .. import unittest +from ..helpers import BUSYBOX_IMAGE_WITH_TAG from compose.config.config import Config from compose.config.types import VolumeFromSpec from compose.const import COMPOSEFILE_V1 as V1 @@ -39,11 +40,11 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, }, { 'name': 'db', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, }, ], networks=None, @@ -58,9 +59,9 @@ class ProjectTest(unittest.TestCase): ) assert len(project.services) == 2 assert project.get_service('web').name == 'web' - assert project.get_service('web').options['image'] == 'busybox:latest' + assert project.get_service('web').options['image'] == BUSYBOX_IMAGE_WITH_TAG assert project.get_service('db').name == 'db' - assert project.get_service('db').options['image'] == 'busybox:latest' + assert project.get_service('db').options['image'] == BUSYBOX_IMAGE_WITH_TAG assert not project.networks.use_networking @mock.patch('compose.network.Network.true_name', lambda n: n.full_name) @@ -70,11 +71,11 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, }, { 'name': 'db', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, }, ], networks=None, @@ -91,7 +92,7 @@ class ProjectTest(unittest.TestCase): project='composetest', name='web', client=None, - image="busybox:latest", + image=BUSYBOX_IMAGE_WITH_TAG, ) project = Project('test', [web], None) assert project.get_service('web') == web @@ -176,7 +177,7 @@ class ProjectTest(unittest.TestCase): version=V2_0, services=[{ 'name': 'test', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes_from': [VolumeFromSpec('aaa', 'rw', 'container')] }], networks=None, @@ -194,7 +195,7 @@ class ProjectTest(unittest.TestCase): "Name": container_name, "Names": [container_name], "Id": container_name, - "Image": 'busybox:latest' + "Image": BUSYBOX_IMAGE_WITH_TAG } ] project = Project.from_config( @@ -205,11 +206,11 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'vol', - 'image': 'busybox:latest' + 'image': BUSYBOX_IMAGE_WITH_TAG }, { 'name': 'test', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes_from': [VolumeFromSpec('vol', 'rw', 'service')] } ], @@ -233,11 +234,11 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'vol', - 'image': 'busybox:latest' + 'image': BUSYBOX_IMAGE_WITH_TAG }, { 'name': 'test', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'volumes_from': [VolumeFromSpec('vol', 'rw', 'service')] } ], @@ -543,7 +544,7 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'test', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, } ], networks=None, @@ -568,7 +569,7 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'test', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'network_mode': 'container:aaa' }, ], @@ -588,7 +589,7 @@ class ProjectTest(unittest.TestCase): "Name": container_name, "Names": [container_name], "Id": container_name, - "Image": 'busybox:latest' + "Image": BUSYBOX_IMAGE_WITH_TAG } ] project = Project.from_config( @@ -599,11 +600,11 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'aaa', - 'image': 'busybox:latest' + 'image': BUSYBOX_IMAGE_WITH_TAG }, { 'name': 'test', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'network_mode': 'service:aaa' }, ], @@ -626,7 +627,7 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'foo', - 'image': 'busybox:latest' + 'image': BUSYBOX_IMAGE_WITH_TAG }, ], networks=None, @@ -647,7 +648,7 @@ class ProjectTest(unittest.TestCase): services=[ { 'name': 'foo', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, 'networks': {'custom': None} }, ], @@ -662,9 +663,9 @@ class ProjectTest(unittest.TestCase): def test_container_without_name(self): self.mock_client.containers.return_value = [ - {'Image': 'busybox:latest', 'Id': '1', 'Name': '1'}, - {'Image': 'busybox:latest', 'Id': '2', 'Name': None}, - {'Image': 'busybox:latest', 'Id': '3'}, + {'Image': BUSYBOX_IMAGE_WITH_TAG, 'Id': '1', 'Name': '1'}, + {'Image': BUSYBOX_IMAGE_WITH_TAG, 'Id': '2', 'Name': None}, + {'Image': BUSYBOX_IMAGE_WITH_TAG, 'Id': '3'}, ] self.mock_client.inspect_container.return_value = { 'Id': '1', @@ -681,7 +682,7 @@ class ProjectTest(unittest.TestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, }], networks=None, volumes=None, @@ -699,7 +700,7 @@ class ProjectTest(unittest.TestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, }], networks={'default': {}}, volumes={'data': {}}, @@ -711,7 +712,7 @@ class ProjectTest(unittest.TestCase): self.mock_client.remove_volume.side_effect = NotFound(None, None, 'oops') project.down(ImageType.all, True) - self.mock_client.remove_image.assert_called_once_with("busybox:latest") + self.mock_client.remove_image.assert_called_once_with(BUSYBOX_IMAGE_WITH_TAG) def test_no_warning_on_stop(self): self.mock_client.info.return_value = {'Swarm': {'LocalNodeState': 'active'}} @@ -744,7 +745,7 @@ class ProjectTest(unittest.TestCase): def test_project_platform_value(self): service_config = { 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, } config_data = Config( version=V2_4, services=[service_config], networks={}, volumes={}, secrets=None, configs=None @@ -771,8 +772,8 @@ class ProjectTest(unittest.TestCase): config_data = Config( version=V3_7, services=[ - {'name': 'web', 'image': 'busybox:latest'}, - {'name': 'db', 'image': 'busybox:latest', 'stop_grace_period': '1s'}, + {'name': 'web', 'image': BUSYBOX_IMAGE_WITH_TAG}, + {'name': 'db', 'image': BUSYBOX_IMAGE_WITH_TAG, 'stop_grace_period': '1s'}, ], networks={}, volumes={}, secrets=None, configs=None, ) @@ -804,7 +805,7 @@ class ProjectTest(unittest.TestCase): version=V2_0, services=[{ 'name': 'web', - 'image': 'busybox:latest', + 'image': BUSYBOX_IMAGE_WITH_TAG, }], networks=None, volumes=None, diff --git a/tests/unit/service_test.py b/tests/unit/service_test.py index 0cff08ab6..a6a633db8 100644 --- a/tests/unit/service_test.py +++ b/tests/unit/service_test.py @@ -828,7 +828,7 @@ class ServiceTest(unittest.TestCase): assert service.specifies_host_port() def test_image_name_from_config(self): - image_name = 'example/web:latest' + image_name = 'example/web:mytag' service = Service('foo', image=image_name) assert service.image_name == image_name From c641ea08ae550200a76a944f85e1e1d4b2409ecc Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Mon, 22 Jul 2019 17:27:10 +0200 Subject: [PATCH 19/26] Fix stdin_open when running docker-compose run This fix makes sure that stdin_open specified in the service is considering when shelling out to the CLI Signed-off-by: Ulysses Souza --- compose/cli/main.py | 16 ++++++++-- tests/unit/cli/main_test.py | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index 78990111b..6391bd3ea 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -885,6 +885,8 @@ class TopLevelCommand(object): else: command = service.options.get('command') + options['stdin_open'] = service.options.get('stdin_open', True) + container_options = build_one_off_container_options(options, detach, command) run_one_off_container( container_options, self.project, service, options, @@ -1286,7 +1288,7 @@ def build_one_off_container_options(options, detach, command): container_options = { 'command': command, 'tty': not (detach or options['-T'] or not sys.stdin.isatty()), - 'stdin_open': not detach, + 'stdin_open': options.get('stdin_open'), 'detach': detach, } @@ -1368,7 +1370,7 @@ def run_one_off_container(container_options, project, service, options, toplevel if IS_WINDOWS_PLATFORM or use_cli: service.connect_container_to_networks(container, use_network_aliases) exit_code = call_docker( - ["start", "--attach", "--interactive", container.id], + get_docker_start_call(container_options, container.id), toplevel_options, environment ) else: @@ -1395,6 +1397,16 @@ def run_one_off_container(container_options, project, service, options, toplevel sys.exit(exit_code) +def get_docker_start_call(container_options, container_id): + docker_call = ["start"] + if not container_options.get('detach'): + docker_call.append("--attach") + if container_options.get('stdin_open'): + docker_call.append("--interactive") + docker_call.append(container_id) + return docker_call + + def log_printer_from_project( project, containers, diff --git a/tests/unit/cli/main_test.py b/tests/unit/cli/main_test.py index 7fed6bccc..aadb9d459 100644 --- a/tests/unit/cli/main_test.py +++ b/tests/unit/cli/main_test.py @@ -9,9 +9,11 @@ import pytest from compose import container from compose.cli.errors import UserError from compose.cli.formatter import ConsoleWarningFormatter +from compose.cli.main import build_one_off_container_options from compose.cli.main import call_docker from compose.cli.main import convergence_strategy_from_opts from compose.cli.main import filter_containers_to_service_names +from compose.cli.main import get_docker_start_call from compose.cli.main import setup_console_handler from compose.cli.main import warn_for_swarm_mode from compose.service import ConvergenceStrategy @@ -65,6 +67,64 @@ class TestCLIMainTestCase(object): warn_for_swarm_mode(mock_client) assert fake_log.warning.call_count == 1 + def test_build_one_off_container_options(self): + command = 'build myservice' + detach = False + options = { + '-e': ['MYVAR=MYVALUE'], + '-T': True, + '--label': ['MYLABEL'], + '--entrypoint': 'bash', + '--user': 'MYUSER', + '--service-ports': [], + '--publish': '', + '--name': 'MYNAME', + '--workdir': '.', + '--volume': [], + 'stdin_open': False, + } + + expected_container_options = { + 'command': command, + 'tty': False, + 'stdin_open': False, + 'detach': detach, + 'entrypoint': 'bash', + 'environment': {'MYVAR': 'MYVALUE'}, + 'labels': {'MYLABEL': ''}, + 'name': 'MYNAME', + 'ports': [], + 'restart': None, + 'user': 'MYUSER', + 'working_dir': '.', + } + + container_options = build_one_off_container_options(options, detach, command) + assert container_options == expected_container_options + + def test_get_docker_start_call(self): + container_id = 'my_container_id' + + mock_container_options = {'detach': False, 'stdin_open': True} + expected_docker_start_call = ['start', '--attach', '--interactive', container_id] + docker_start_call = get_docker_start_call(mock_container_options, container_id) + assert expected_docker_start_call == docker_start_call + + mock_container_options = {'detach': False, 'stdin_open': False} + expected_docker_start_call = ['start', '--attach', container_id] + docker_start_call = get_docker_start_call(mock_container_options, container_id) + assert expected_docker_start_call == docker_start_call + + mock_container_options = {'detach': True, 'stdin_open': True} + expected_docker_start_call = ['start', '--interactive', container_id] + docker_start_call = get_docker_start_call(mock_container_options, container_id) + assert expected_docker_start_call == docker_start_call + + mock_container_options = {'detach': True, 'stdin_open': False} + expected_docker_start_call = ['start', container_id] + docker_start_call = get_docker_start_call(mock_container_options, container_id) + assert expected_docker_start_call == docker_start_call + class TestSetupConsoleHandlerTestCase(object): From 99464d9c2bfc9052ca341dc0e57c0ab2760cd8a2 Mon Sep 17 00:00:00 2001 From: Klaas Hoekema Date: Sun, 16 Jun 2019 22:57:04 -0400 Subject: [PATCH 20/26] Handle environment file override within TopLevelCommand Several (but not all) of the subcommands are accepting and processing the `--env-file` option, but only because they need to look for a specific value in the environment. The work of applying the override makes more sense as the domain of TopLevelCommand, and moving it there and removing the option from the subcommands makes things simpler. Signed-off-by: Klaas Hoekema --- compose/cli/main.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index 6391bd3ea..e11554ac0 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -247,6 +247,11 @@ class TopLevelCommand(object): def project_dir(self): return self.toplevel_options.get('--project-directory') or '.' + @property + def environment(self): + environment_file = self.toplevel_options.get('--env-file') + return Environment.from_env_file(self.project_dir, environment_file) + def build(self, options): """ Build or rebuild services. @@ -276,9 +281,7 @@ class TopLevelCommand(object): '--build-arg is only supported when services are specified for API version < 1.25.' ' Please use a Compose file version > 2.2 or specify which services to build.' ) - environment_file = options.get('--env-file') - environment = Environment.from_env_file(self.project_dir, environment_file) - build_args = resolve_build_args(build_args, environment) + build_args = resolve_build_args(build_args, self.environment) self.project.build( service_names=options['SERVICE'], @@ -429,11 +432,8 @@ class TopLevelCommand(object): Compose file -t, --timeout TIMEOUT Specify a shutdown timeout in seconds. (default: 10) - --env-file PATH Specify an alternate environment file """ - environment_file = options.get('--env-file') - environment = Environment.from_env_file(self.project_dir, environment_file) - ignore_orphans = environment.get_boolean('COMPOSE_IGNORE_ORPHANS') + ignore_orphans = self.environment.get_boolean('COMPOSE_IGNORE_ORPHANS') if ignore_orphans and options['--remove-orphans']: raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.") @@ -489,11 +489,8 @@ class TopLevelCommand(object): -e, --env KEY=VAL Set environment variables (can be used multiple times, not supported in API < 1.25) -w, --workdir DIR Path to workdir directory for this command. - --env-file PATH Specify an alternate environment file """ - environment_file = options.get('--env-file') - environment = Environment.from_env_file(self.project_dir, environment_file) - use_cli = not environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') + use_cli = not self.environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') index = int(options.get('--index')) service = self.project.get_service(options['SERVICE']) detach = options.get('--detach') @@ -1051,7 +1048,6 @@ class TopLevelCommand(object): container. Implies --abort-on-container-exit. --scale SERVICE=NUM Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. - --env-file PATH Specify an alternate environment file """ start_deps = not options['--no-deps'] always_recreate_deps = options['--always-recreate-deps'] @@ -1066,9 +1062,7 @@ class TopLevelCommand(object): if detached and (cascade_stop or exit_value_from): raise UserError("--abort-on-container-exit and -d cannot be combined.") - environment_file = options.get('--env-file') - environment = Environment.from_env_file(self.project_dir, environment_file) - ignore_orphans = environment.get_boolean('COMPOSE_IGNORE_ORPHANS') + ignore_orphans = self.environment.get_boolean('COMPOSE_IGNORE_ORPHANS') if ignore_orphans and remove_orphans: raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.") @@ -1360,7 +1354,7 @@ def run_one_off_container(container_options, project, service, options, toplevel if options['--rm']: project.client.remove_container(container.id, force=True, v=True) - environment_file = options.get('--env-file') + environment_file = toplevel_options.get('--env-file') environment = Environment.from_env_file(project_dir, environment_file) use_cli = not environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') signals.set_signal_handler_to_shutdown() From 35eb40424c45209df3c23a33ae9831413abf7f26 Mon Sep 17 00:00:00 2001 From: Klaas Hoekema Date: Thu, 11 Jul 2019 22:28:18 -0400 Subject: [PATCH 21/26] Call TopLevelCommand's environment 'toplevel_environment' To help prevent confusion between the different meanings and sources of "environment", rename the method that loads the environment from the .env or --env-file (i.e. the one that applies at a project level) to 'toplevel_environment'. Signed-off-by: Klaas Hoekema --- compose/cli/main.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index e11554ac0..eb6e7d820 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -248,7 +248,7 @@ class TopLevelCommand(object): return self.toplevel_options.get('--project-directory') or '.' @property - def environment(self): + def toplevel_environment(self): environment_file = self.toplevel_options.get('--env-file') return Environment.from_env_file(self.project_dir, environment_file) @@ -281,7 +281,7 @@ class TopLevelCommand(object): '--build-arg is only supported when services are specified for API version < 1.25.' ' Please use a Compose file version > 2.2 or specify which services to build.' ) - build_args = resolve_build_args(build_args, self.environment) + build_args = resolve_build_args(build_args, self.toplevel_environment) self.project.build( service_names=options['SERVICE'], @@ -433,7 +433,7 @@ class TopLevelCommand(object): -t, --timeout TIMEOUT Specify a shutdown timeout in seconds. (default: 10) """ - ignore_orphans = self.environment.get_boolean('COMPOSE_IGNORE_ORPHANS') + ignore_orphans = self.toplevel_environment.get_boolean('COMPOSE_IGNORE_ORPHANS') if ignore_orphans and options['--remove-orphans']: raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.") @@ -490,7 +490,7 @@ class TopLevelCommand(object): not supported in API < 1.25) -w, --workdir DIR Path to workdir directory for this command. """ - use_cli = not self.environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') + use_cli = not self.toplevel_environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') index = int(options.get('--index')) service = self.project.get_service(options['SERVICE']) detach = options.get('--detach') @@ -513,7 +513,7 @@ class TopLevelCommand(object): if IS_WINDOWS_PLATFORM or use_cli and not detach: sys.exit(call_docker( build_exec_command(options, container.id, command), - self.toplevel_options, environment) + self.toplevel_options, self.toplevel_environment) ) create_exec_options = { @@ -1062,7 +1062,7 @@ class TopLevelCommand(object): if detached and (cascade_stop or exit_value_from): raise UserError("--abort-on-container-exit and -d cannot be combined.") - ignore_orphans = self.environment.get_boolean('COMPOSE_IGNORE_ORPHANS') + ignore_orphans = self.toplevel_environment.get_boolean('COMPOSE_IGNORE_ORPHANS') if ignore_orphans and remove_orphans: raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.") @@ -1355,8 +1355,9 @@ def run_one_off_container(container_options, project, service, options, toplevel project.client.remove_container(container.id, force=True, v=True) environment_file = toplevel_options.get('--env-file') - environment = Environment.from_env_file(project_dir, environment_file) - use_cli = not environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') + toplevel_environment = Environment.from_env_file(project_dir, environment_file) + use_cli = not toplevel_environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') + signals.set_signal_handler_to_shutdown() signals.set_signal_handler_to_hang_up() try: @@ -1365,7 +1366,7 @@ def run_one_off_container(container_options, project, service, options, toplevel service.connect_container_to_networks(container, use_network_aliases) exit_code = call_docker( get_docker_start_call(container_options, container.id), - toplevel_options, environment + toplevel_options, toplevel_environment ) else: operation = RunOperation( From 088a798e7a546755537cb9082b440f17d64d6bdf Mon Sep 17 00:00:00 2001 From: Klaas Hoekema Date: Thu, 11 Jul 2019 23:27:11 -0400 Subject: [PATCH 22/26] Fix typo in 'split_env' error message Signed-off-by: Klaas Hoekema --- compose/config/environment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/config/environment.py b/compose/config/environment.py index e72c88231..696356f32 100644 --- a/compose/config/environment.py +++ b/compose/config/environment.py @@ -26,7 +26,7 @@ def split_env(env): key = env if re.search(r'\s', key): raise ConfigurationError( - "environment variable name '{}' may not contains whitespace.".format(key) + "environment variable name '{}' may not contain whitespace.".format(key) ) return key, value From 69c0683bfe8f4bbb90d07f0db6516e51942f97d6 Mon Sep 17 00:00:00 2001 From: Klaas Hoekema Date: Fri, 12 Jul 2019 12:59:31 -0400 Subject: [PATCH 23/26] Pass toplevel_environment to run_one_off_container Instead of passing `project_dir` from `TopLevelCommand.run` to `run_one_off_container` then using it there to load the toplevel environment (duplicating the logic that `TopLevelCommand.toplevel_environment` encapsulates), pass the Environment object. Signed-off-by: Klaas Hoekema --- compose/cli/main.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compose/cli/main.py b/compose/cli/main.py index eb6e7d820..477b57b52 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -887,7 +887,7 @@ class TopLevelCommand(object): container_options = build_one_off_container_options(options, detach, command) run_one_off_container( container_options, self.project, service, options, - self.toplevel_options, self.project_dir + self.toplevel_options, self.toplevel_environment ) def scale(self, options): @@ -1325,7 +1325,7 @@ def build_one_off_container_options(options, detach, command): def run_one_off_container(container_options, project, service, options, toplevel_options, - project_dir='.'): + toplevel_environment): if not options['--no-deps']: deps = service.get_dependency_names() if deps: @@ -1354,8 +1354,6 @@ def run_one_off_container(container_options, project, service, options, toplevel if options['--rm']: project.client.remove_container(container.id, force=True, v=True) - environment_file = toplevel_options.get('--env-file') - toplevel_environment = Environment.from_env_file(project_dir, environment_file) use_cli = not toplevel_environment.get_boolean('COMPOSE_INTERACTIVE_NO_CLI') signals.set_signal_handler_to_shutdown() From 413e5db7b35684a543e1c14f89aad379167f9b06 Mon Sep 17 00:00:00 2001 From: Klaas Hoekema Date: Mon, 22 Jul 2019 13:59:49 -0400 Subject: [PATCH 24/26] Add shell completions for --env-file option Adds completions for the --env-file toplevel option to the bash, fish, and zsh completions files. Signed-off-by: Klaas Hoekema --- contrib/completion/bash/docker-compose | 5 +++++ contrib/completion/fish/docker-compose.fish | 1 + contrib/completion/zsh/_docker-compose | 2 ++ 3 files changed, 8 insertions(+) diff --git a/contrib/completion/bash/docker-compose b/contrib/completion/bash/docker-compose index e9168b1b1..6dc47799d 100644 --- a/contrib/completion/bash/docker-compose +++ b/contrib/completion/bash/docker-compose @@ -184,6 +184,10 @@ _docker_compose_docker_compose() { _filedir -d return ;; + --env-file) + _filedir + return + ;; $(__docker_compose_to_extglob "$daemon_options_with_args") ) return ;; @@ -612,6 +616,7 @@ _docker_compose() { --tlsverify " local daemon_options_with_args=" + --env-file --file -f --host -H --project-directory diff --git a/contrib/completion/fish/docker-compose.fish b/contrib/completion/fish/docker-compose.fish index 69ecc5056..0566e16ae 100644 --- a/contrib/completion/fish/docker-compose.fish +++ b/contrib/completion/fish/docker-compose.fish @@ -12,6 +12,7 @@ end complete -c docker-compose -s f -l file -r -d 'Specify an alternate compose file' complete -c docker-compose -s p -l project-name -x -d 'Specify an alternate project name' +complete -c docker-compose -l env-file -r -d 'Specify an alternate environment file (default: .env)' complete -c docker-compose -l verbose -d 'Show more output' complete -c docker-compose -s H -l host -x -d 'Daemon socket to connect to' complete -c docker-compose -l tls -d 'Use TLS; implied by --tlsverify' diff --git a/contrib/completion/zsh/_docker-compose b/contrib/completion/zsh/_docker-compose index 808b068a3..faf405988 100755 --- a/contrib/completion/zsh/_docker-compose +++ b/contrib/completion/zsh/_docker-compose @@ -341,6 +341,7 @@ _docker-compose() { '(- :)'{-h,--help}'[Get help]' \ '*'{-f,--file}"[${file_description}]:file:_files -g '*.yml'" \ '(-p --project-name)'{-p,--project-name}'[Specify an alternate project name (default: directory name)]:project name:' \ + '--env-file[Specify an alternate environment file (default: .env)]:env-file:_files' \ "--compatibility[If set, Compose will attempt to convert keys in v3 files to their non-Swarm equivalent]" \ '(- :)'{-v,--version}'[Print version and exit]' \ '--verbose[Show more output]' \ @@ -359,6 +360,7 @@ _docker-compose() { local -a relevant_compose_flags relevant_compose_repeatable_flags relevant_docker_flags compose_options docker_options relevant_compose_flags=( + "--env-file" "--file" "-f" "--host" "-H" "--project-name" "-p" From b03889ac2a09e8ac6145b90015f0e4328d9928c4 Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Wed, 31 Jul 2019 01:58:16 +0200 Subject: [PATCH 25/26] Add integration tests regarding environment This covers what was included in #6800 Signed-off-by: Ulysses Souza --- tests/acceptance/cli_test.py | 10 +++++++--- tests/fixtures/env-file-override/.env.conf | 2 ++ tests/fixtures/env-file-override/.env.override | 1 + .../env-file-override/docker-compose.yml | 6 ++++++ tests/integration/environment_test.py | 18 ++++++++++++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 tests/fixtures/env-file-override/.env.conf create mode 100644 tests/fixtures/env-file-override/.env.override create mode 100644 tests/fixtures/env-file-override/docker-compose.yml diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py index 3fd857f26..77b46c279 100644 --- a/tests/acceptance/cli_test.py +++ b/tests/acceptance/cli_test.py @@ -64,6 +64,12 @@ def wait_on_process(proc, returncode=0): return ProcessResult(stdout.decode('utf-8'), stderr.decode('utf-8')) +def dispatch(base_dir, options, project_options=None, returncode=0): + project_options = project_options or [] + proc = start_process(base_dir, project_options + options) + return wait_on_process(proc, returncode=returncode) + + def wait_on_condition(condition, delay=0.1, timeout=40): start_time = time.time() while not condition(): @@ -151,9 +157,7 @@ class CLITestCase(DockerClientTestCase): return self._project def dispatch(self, options, project_options=None, returncode=0): - project_options = project_options or [] - proc = start_process(self.base_dir, project_options + options) - return wait_on_process(proc, returncode=returncode) + return dispatch(self.base_dir, options, project_options, returncode) def execute(self, container, cmd): # Remove once Hijack and CloseNotifier sign a peace treaty diff --git a/tests/fixtures/env-file-override/.env.conf b/tests/fixtures/env-file-override/.env.conf new file mode 100644 index 000000000..90b8b495a --- /dev/null +++ b/tests/fixtures/env-file-override/.env.conf @@ -0,0 +1,2 @@ +WHEREAMI +DEFAULT_CONF_LOADED=true diff --git a/tests/fixtures/env-file-override/.env.override b/tests/fixtures/env-file-override/.env.override new file mode 100644 index 000000000..398fa51b3 --- /dev/null +++ b/tests/fixtures/env-file-override/.env.override @@ -0,0 +1 @@ +WHEREAMI=override diff --git a/tests/fixtures/env-file-override/docker-compose.yml b/tests/fixtures/env-file-override/docker-compose.yml new file mode 100644 index 000000000..fdae6d826 --- /dev/null +++ b/tests/fixtures/env-file-override/docker-compose.yml @@ -0,0 +1,6 @@ +version: '3.7' +services: + test: + image: busybox + env_file: .env.conf + entrypoint: env diff --git a/tests/integration/environment_test.py b/tests/integration/environment_test.py index ac31d2e1f..671e65318 100644 --- a/tests/integration/environment_test.py +++ b/tests/integration/environment_test.py @@ -7,7 +7,10 @@ from ddt import data from ddt import ddt from .. import mock +from ..acceptance.cli_test import dispatch +from compose.cli.command import get_project from compose.cli.command import project_from_options +from compose.config.environment import Environment from tests.integration.testcases import DockerClientTestCase @@ -50,3 +53,18 @@ services: # So no need to have a proper options map, the `COMMAND` key is enough project_from_options('.', options) assert fake_log.warn.call_count == 0 + + +class EnvironmentOverrideFileTest(DockerClientTestCase): + 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) From 661ac20e5d0a926fbca015133eda0574a9e4a1bd Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Tue, 6 Aug 2019 15:28:46 +0200 Subject: [PATCH 26/26] "Bump 1.25.0-rc2" Signed-off-by: Ulysses Souza --- CHANGELOG.md | 71 +++++++++++++++++++++++++++++++++++++++++++++ compose/__init__.py | 2 +- script/run/run.sh | 2 +- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a3ad8bfd..89f028812 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,77 @@ Change log ========== +1.25.0-rc2 (2019-08-06) +------------------- + +### Features + +- Add tag `docker-compose:latest` + +- Add `docker-compose:-alpine` image/tag + +- Add `docker-compose:-debian` image/tag + +- Bumped `docker-py` 4.0.1 + +- Supports `requests` up to 2.22.0 version + +- Drops empty tag on `build:cache_from` + +- `Dockerfile` now generates `libmusl` binaries for alpine + +- Only pull images that can't be built + +- Attribute `scale` can now accept `0` as a value + +- Added `--quiet` build flag + +- Added `--no-interpolate` to `docker-compose config` + +- Bump OpenSSL for macOS build (`1.1.0j` to `1.1.1a`) + +- Added `--no-rm` to `build` command + +- Added support for `credential_spec` + +- Resolve digests without pulling image + +- Upgrade `pyyaml` to `4.2b1` + +- Lowered severity to `warning` if `down` tries to remove nonexisting image + +- Use improved API fields for project events when possible + +- Update `setup.py` for modern `pypi/setuptools` and remove `pandoc` dependencies + +- Removed `Dockerfile.armhf` which is no longer needed + +### Bugfixes + +- Fixed stdin_open + +- Fixed `--remove-orphans` when used with `up --no-start` + +- Fixed `docker-compose ps --all` + +- Fixed `depends_on` dependency recreation behavior + +- Fixed bash completion for `build --memory` + +- Fixed misleading warning concerning env vars when performing an `exec` command + +- Fixed failure check in parallel_execute_watch + +- Fixed race condition after pulling image + +- Fixed error on duplicate mount points. + +- Fixed merge on networks section + +- Always connect Compose container to `stdin` + +- Fixed the presentation of failed services on 'docker-compose start' when containers are not available + 1.24.0 (2019-03-28) ------------------- diff --git a/compose/__init__.py b/compose/__init__.py index 0042896b6..df0fd3fbd 100644 --- a/compose/__init__.py +++ b/compose/__init__.py @@ -1,4 +1,4 @@ from __future__ import absolute_import from __future__ import unicode_literals -__version__ = '1.25.0dev' +__version__ = '1.25.0-rc2' diff --git a/script/run/run.sh b/script/run/run.sh index f3456720f..8756ae34a 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.24.0" +VERSION="1.25.0-rc2" IMAGE="docker/compose:$VERSION"