Add COMPOSE_IGNORE_ORPHANS

Signed-off-by: John Harris <john@johnharris.io>
This commit is contained in:
John Harris 2018-01-04 10:14:21 -08:00
parent c3b1bce42e
commit 963b004749
4 changed files with 62 additions and 4 deletions

View File

@ -377,9 +377,20 @@ class TopLevelCommand(object):
-t, --timeout TIMEOUT Specify a shutdown timeout in seconds.
(default: 10)
"""
environment = Environment.from_env_file(self.project_dir)
ignore_orphans = environment.get_boolean('COMPOSE_IGNORE_ORPHANS')
if ignore_orphans and options['--remove-orphans']:
raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.")
image_type = image_type_from_opt('--rmi', options['--rmi'])
timeout = timeout_from_opts(options)
self.project.down(image_type, options['--volumes'], options['--remove-orphans'], timeout=timeout)
self.project.down(
image_type,
options['--volumes'],
options['--remove-orphans'],
timeout=timeout,
ignore_orphans=ignore_orphans)
def events(self, options):
"""
@ -941,6 +952,12 @@ class TopLevelCommand(object):
if detached and timeout:
raise UserError("-d and --timeout cannot be combined.")
environment = Environment.from_env_file(self.project_dir)
ignore_orphans = environment.get_boolean('COMPOSE_IGNORE_ORPHANS')
if ignore_orphans and remove_orphans:
raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.")
if no_start:
for excluded in ['-d', '--abort-on-container-exit', '--exit-code-from']:
if options.get(excluded):
@ -955,6 +972,7 @@ class TopLevelCommand(object):
timeout=timeout,
detached=detached,
remove_orphans=remove_orphans,
ignore_orphans=ignore_orphans,
scale_override=parse_scale_args(options['--scale']),
start=not no_start
)

View File

@ -330,9 +330,16 @@ class Project(object):
service_names, stopped=True, one_off=one_off
), options)
def down(self, remove_image_type, include_volumes, remove_orphans=False, timeout=None):
def down(
self,
remove_image_type,
include_volumes,
remove_orphans=False,
timeout=None,
ignore_orphans=False):
self.stop(one_off=OneOffFilter.include, timeout=timeout)
self.find_orphan_containers(remove_orphans)
if not ignore_orphans:
self.find_orphan_containers(remove_orphans)
self.remove_stopped(v=include_volumes, one_off=OneOffFilter.include)
self.networks.remove()
@ -432,6 +439,7 @@ class Project(object):
timeout=None,
detached=False,
remove_orphans=False,
ignore_orphans=False,
scale_override=None,
rescale=True,
start=True):
@ -439,7 +447,8 @@ class Project(object):
warn_for_swarm_mode(self.client)
self.initialize()
self.find_orphan_containers(remove_orphans)
if not ignore_orphans:
self.find_orphan_containers(remove_orphans)
if scale_override is None:
scale_override = {}

View File

@ -1337,6 +1337,12 @@ class CLITestCase(DockerClientTestCase):
result = self.dispatch(['up', '-d', '-t', '1'], returncode=1)
assert "-d and --timeout cannot be combined." in result.stderr
@mock.patch.dict(os.environ)
def test_up_with_ignore_remove_orphans(self):
os.environ["COMPOSE_IGNORE_ORPHANS"] = "True"
result = self.dispatch(['up', '-d', '--remove-orphans'], returncode=1)
assert "COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined." in result.stderr
def test_up_handles_sigint(self):
proc = start_process(self.base_dir, ['up', '-t', '2'])
wait_on_condition(ContainerCountCondition(self.project, 2))

View File

@ -1633,6 +1633,31 @@ class ProjectTest(DockerClientTestCase):
if ctnr.labels.get(LABEL_SERVICE) == 'service1'
]) == 0
def test_project_up_ignore_orphans(self):
config_dict = {
'service1': {
'image': 'busybox:latest',
'command': 'top',
}
}
config_data = load_config(config_dict)
project = Project.from_config(
name='composetest', config_data=config_data, client=self.client
)
project.up()
config_dict['service2'] = config_dict['service1']
del config_dict['service1']
config_data = load_config(config_dict)
project = Project.from_config(
name='composetest', config_data=config_data, client=self.client
)
with mock.patch('compose.project.log') as mock_log:
project.up(ignore_orphans=True)
mock_log.warning.assert_not_called()
@v2_1_only()
def test_project_up_healthy_dependency(self):
config_dict = {