Merge pull request #3178 from aanand/2774-off-one-offs
Remove one-off containers in `rm` and `down`
This commit is contained in:
commit
a20b84e6d2
6 changed files with 105 additions and 35 deletions
|
|
@ -22,6 +22,7 @@ from ..const import DEFAULT_TIMEOUT
|
|||
from ..const import IS_WINDOWS_PLATFORM
|
||||
from ..progress_stream import StreamOutputError
|
||||
from ..project import NoSuchService
|
||||
from ..project import OneOffFilter
|
||||
from ..service import BuildAction
|
||||
from ..service import BuildError
|
||||
from ..service import ConvergenceStrategy
|
||||
|
|
@ -437,7 +438,7 @@ class TopLevelCommand(object):
|
|||
"""
|
||||
containers = sorted(
|
||||
self.project.containers(service_names=options['SERVICE'], stopped=True) +
|
||||
self.project.containers(service_names=options['SERVICE'], one_off=True),
|
||||
self.project.containers(service_names=options['SERVICE'], one_off=OneOffFilter.only),
|
||||
key=attrgetter('name'))
|
||||
|
||||
if options['-q']:
|
||||
|
|
@ -491,8 +492,21 @@ class TopLevelCommand(object):
|
|||
Options:
|
||||
-f, --force Don't ask to confirm removal
|
||||
-v Remove volumes associated with containers
|
||||
-a, --all Also remove one-off containers created by
|
||||
docker-compose run
|
||||
"""
|
||||
all_containers = self.project.containers(service_names=options['SERVICE'], stopped=True)
|
||||
if options.get('--all'):
|
||||
one_off = OneOffFilter.include
|
||||
else:
|
||||
log.warn(
|
||||
'Not including one-off containers created by `docker-compose run`.\n'
|
||||
'To include them, use `docker-compose rm --all`.\n'
|
||||
'This will be the default behavior in the next version of Compose.\n')
|
||||
one_off = OneOffFilter.exclude
|
||||
|
||||
all_containers = self.project.containers(
|
||||
service_names=options['SERVICE'], stopped=True, one_off=one_off
|
||||
)
|
||||
stopped_containers = [c for c in all_containers if not c.is_running]
|
||||
|
||||
if len(stopped_containers) > 0:
|
||||
|
|
@ -501,7 +515,8 @@ class TopLevelCommand(object):
|
|||
or yesno("Are you sure? [yN] ", default=False):
|
||||
self.project.remove_stopped(
|
||||
service_names=options['SERVICE'],
|
||||
v=options.get('-v', False)
|
||||
v=options.get('-v', False),
|
||||
one_off=one_off
|
||||
)
|
||||
else:
|
||||
print("No stopped containers")
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import logging
|
|||
import operator
|
||||
from functools import reduce
|
||||
|
||||
import enum
|
||||
from docker.errors import APIError
|
||||
|
||||
from . import parallel
|
||||
|
|
@ -35,6 +36,24 @@ from .volume import ProjectVolumes
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@enum.unique
|
||||
class OneOffFilter(enum.Enum):
|
||||
include = 0
|
||||
exclude = 1
|
||||
only = 2
|
||||
|
||||
@classmethod
|
||||
def update_labels(cls, value, labels):
|
||||
if value == cls.only:
|
||||
labels.append('{0}={1}'.format(LABEL_ONE_OFF, "True"))
|
||||
elif value == cls.exclude:
|
||||
labels.append('{0}={1}'.format(LABEL_ONE_OFF, "False"))
|
||||
elif value == cls.include:
|
||||
pass
|
||||
else:
|
||||
raise ValueError("Invalid value for one_off: {}".format(repr(value)))
|
||||
|
||||
|
||||
class Project(object):
|
||||
"""
|
||||
A collection of services.
|
||||
|
|
@ -46,11 +65,11 @@ class Project(object):
|
|||
self.volumes = volumes or ProjectVolumes({})
|
||||
self.networks = networks or ProjectNetworks({}, False)
|
||||
|
||||
def labels(self, one_off=False):
|
||||
return [
|
||||
'{0}={1}'.format(LABEL_PROJECT, self.name),
|
||||
'{0}={1}'.format(LABEL_ONE_OFF, "True" if one_off else "False"),
|
||||
]
|
||||
def labels(self, one_off=OneOffFilter.exclude):
|
||||
labels = ['{0}={1}'.format(LABEL_PROJECT, self.name)]
|
||||
|
||||
OneOffFilter.update_labels(one_off, labels)
|
||||
return labels
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, name, config_data, client):
|
||||
|
|
@ -220,8 +239,8 @@ class Project(object):
|
|||
|
||||
return containers
|
||||
|
||||
def stop(self, service_names=None, **options):
|
||||
containers = self.containers(service_names)
|
||||
def stop(self, service_names=None, one_off=OneOffFilter.exclude, **options):
|
||||
containers = self.containers(service_names, one_off=one_off)
|
||||
|
||||
def get_deps(container):
|
||||
# actually returning inversed dependencies
|
||||
|
|
@ -249,13 +268,15 @@ class Project(object):
|
|||
def kill(self, service_names=None, **options):
|
||||
parallel.parallel_kill(self.containers(service_names), options)
|
||||
|
||||
def remove_stopped(self, service_names=None, **options):
|
||||
parallel.parallel_remove(self.containers(service_names, stopped=True), options)
|
||||
def remove_stopped(self, service_names=None, one_off=OneOffFilter.exclude, **options):
|
||||
parallel.parallel_remove(self.containers(
|
||||
service_names, stopped=True, one_off=one_off
|
||||
), options)
|
||||
|
||||
def down(self, remove_image_type, include_volumes, remove_orphans=False):
|
||||
self.stop()
|
||||
self.stop(one_off=OneOffFilter.include)
|
||||
self.find_orphan_containers(remove_orphans)
|
||||
self.remove_stopped(v=include_volumes)
|
||||
self.remove_stopped(v=include_volumes, one_off=OneOffFilter.include)
|
||||
|
||||
self.networks.remove()
|
||||
|
||||
|
|
@ -412,7 +433,7 @@ class Project(object):
|
|||
for service in self.get_services(service_names, include_deps=False):
|
||||
service.pull(ignore_pull_failures)
|
||||
|
||||
def _labeled_containers(self, stopped=False, one_off=False):
|
||||
def _labeled_containers(self, stopped=False, one_off=OneOffFilter.exclude):
|
||||
return list(filter(None, [
|
||||
Container.from_ps(self.client, container)
|
||||
for container in self.client.containers(
|
||||
|
|
@ -420,7 +441,7 @@ class Project(object):
|
|||
filters={'label': self.labels(one_off=one_off)})])
|
||||
)
|
||||
|
||||
def containers(self, service_names=None, stopped=False, one_off=False):
|
||||
def containers(self, service_names=None, stopped=False, one_off=OneOffFilter.exclude):
|
||||
if service_names:
|
||||
self.validate_service_names(service_names)
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue