mirror of https://github.com/docker/compose.git
Merge pull request #5982 from docker/5933-retrieve-legacy-containers
Allow all Compose commands to retrieve and handle legacy-name containers
This commit is contained in:
commit
706164accd
|
@ -9,6 +9,8 @@ from docker.errors import ImageNotFound
|
||||||
from .const import LABEL_CONTAINER_NUMBER
|
from .const import LABEL_CONTAINER_NUMBER
|
||||||
from .const import LABEL_PROJECT
|
from .const import LABEL_PROJECT
|
||||||
from .const import LABEL_SERVICE
|
from .const import LABEL_SERVICE
|
||||||
|
from .const import LABEL_VERSION
|
||||||
|
from .version import ComposeVersion
|
||||||
|
|
||||||
|
|
||||||
class Container(object):
|
class Container(object):
|
||||||
|
@ -283,6 +285,12 @@ class Container(object):
|
||||||
def attach(self, *args, **kwargs):
|
def attach(self, *args, **kwargs):
|
||||||
return self.client.attach(self.id, *args, **kwargs)
|
return self.client.attach(self.id, *args, **kwargs)
|
||||||
|
|
||||||
|
def has_legacy_proj_name(self, project_name):
|
||||||
|
return (
|
||||||
|
ComposeVersion(self.labels.get(LABEL_VERSION)) < ComposeVersion('1.21.0') and
|
||||||
|
self.project != project_name
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Container: %s (%s)>' % (self.name, self.id[:6])
|
return '<Container: %s (%s)>' % (self.name, self.id[:6])
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import operator
|
import operator
|
||||||
|
import re
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
@ -70,8 +71,11 @@ class Project(object):
|
||||||
self.networks = networks or ProjectNetworks({}, False)
|
self.networks = networks or ProjectNetworks({}, False)
|
||||||
self.config_version = config_version
|
self.config_version = config_version
|
||||||
|
|
||||||
def labels(self, one_off=OneOffFilter.exclude):
|
def labels(self, one_off=OneOffFilter.exclude, legacy=False):
|
||||||
labels = ['{0}={1}'.format(LABEL_PROJECT, self.name)]
|
name = self.name
|
||||||
|
if legacy:
|
||||||
|
name = re.sub(r'[_-]', '', name)
|
||||||
|
labels = ['{0}={1}'.format(LABEL_PROJECT, name)]
|
||||||
|
|
||||||
OneOffFilter.update_labels(one_off, labels)
|
OneOffFilter.update_labels(one_off, labels)
|
||||||
return labels
|
return labels
|
||||||
|
@ -571,12 +575,21 @@ class Project(object):
|
||||||
service.push(ignore_push_failures)
|
service.push(ignore_push_failures)
|
||||||
|
|
||||||
def _labeled_containers(self, stopped=False, one_off=OneOffFilter.exclude):
|
def _labeled_containers(self, stopped=False, one_off=OneOffFilter.exclude):
|
||||||
return list(filter(None, [
|
ctnrs = list(filter(None, [
|
||||||
Container.from_ps(self.client, container)
|
Container.from_ps(self.client, container)
|
||||||
for container in self.client.containers(
|
for container in self.client.containers(
|
||||||
all=stopped,
|
all=stopped,
|
||||||
filters={'label': self.labels(one_off=one_off)})])
|
filters={'label': self.labels(one_off=one_off)})])
|
||||||
)
|
)
|
||||||
|
if ctnrs:
|
||||||
|
return ctnrs
|
||||||
|
|
||||||
|
return list(filter(lambda c: c.has_legacy_proj_name(self.name), filter(None, [
|
||||||
|
Container.from_ps(self.client, container)
|
||||||
|
for container in self.client.containers(
|
||||||
|
all=stopped,
|
||||||
|
filters={'label': self.labels(one_off=one_off, legacy=True)})])
|
||||||
|
))
|
||||||
|
|
||||||
def containers(self, service_names=None, stopped=False, one_off=OneOffFilter.exclude):
|
def containers(self, service_names=None, stopped=False, one_off=OneOffFilter.exclude):
|
||||||
if service_names:
|
if service_names:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -51,7 +52,6 @@ from .progress_stream import StreamOutputError
|
||||||
from .utils import json_hash
|
from .utils import json_hash
|
||||||
from .utils import parse_bytes
|
from .utils import parse_bytes
|
||||||
from .utils import parse_seconds_float
|
from .utils import parse_seconds_float
|
||||||
from .version import ComposeVersion
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -192,8 +192,8 @@ class Service(object):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Service: {}>'.format(self.name)
|
return '<Service: {}>'.format(self.name)
|
||||||
|
|
||||||
def containers(self, stopped=False, one_off=False, filters={}):
|
def containers(self, stopped=False, one_off=False, filters={}, labels=None):
|
||||||
filters.update({'label': self.labels(one_off=one_off)})
|
filters.update({'label': self.labels(one_off=one_off) + (labels or [])})
|
||||||
|
|
||||||
result = list(filter(None, [
|
result = list(filter(None, [
|
||||||
Container.from_ps(self.client, container)
|
Container.from_ps(self.client, container)
|
||||||
|
@ -204,10 +204,10 @@ class Service(object):
|
||||||
if result:
|
if result:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
filters.update({'label': self.labels(one_off=one_off, legacy=True)})
|
filters.update({'label': self.labels(one_off=one_off, legacy=True) + (labels or [])})
|
||||||
return list(
|
return list(
|
||||||
filter(
|
filter(
|
||||||
self.has_legacy_proj_name, filter(None, [
|
lambda c: c.has_legacy_proj_name(self.project), filter(None, [
|
||||||
Container.from_ps(self.client, container)
|
Container.from_ps(self.client, container)
|
||||||
for container in self.client.containers(
|
for container in self.client.containers(
|
||||||
all=stopped,
|
all=stopped,
|
||||||
|
@ -219,9 +219,9 @@ class Service(object):
|
||||||
"""Return a :class:`compose.container.Container` for this service. The
|
"""Return a :class:`compose.container.Container` for this service. The
|
||||||
container must be active, and match `number`.
|
container must be active, and match `number`.
|
||||||
"""
|
"""
|
||||||
labels = self.labels() + ['{0}={1}'.format(LABEL_CONTAINER_NUMBER, number)]
|
|
||||||
for container in self.client.containers(filters={'label': labels}):
|
for container in self.containers(labels=['{0}={1}'.format(LABEL_CONTAINER_NUMBER, number)]):
|
||||||
return Container.from_ps(self.client, container)
|
return container
|
||||||
|
|
||||||
raise ValueError("No container found for %s_%s" % (self.name, number))
|
raise ValueError("No container found for %s_%s" % (self.name, number))
|
||||||
|
|
||||||
|
@ -258,6 +258,11 @@ class Service(object):
|
||||||
|
|
||||||
running_containers = self.containers(stopped=False)
|
running_containers = self.containers(stopped=False)
|
||||||
num_running = len(running_containers)
|
num_running = len(running_containers)
|
||||||
|
for c in running_containers:
|
||||||
|
if not c.has_legacy_proj_name(self.project):
|
||||||
|
continue
|
||||||
|
log.info('Recreating container with legacy name %s' % c.name)
|
||||||
|
self.recreate_container(c, timeout, start_new_container=False)
|
||||||
|
|
||||||
if desired_num == num_running:
|
if desired_num == num_running:
|
||||||
# do nothing as we already have the desired number
|
# do nothing as we already have the desired number
|
||||||
|
@ -404,7 +409,7 @@ class Service(object):
|
||||||
has_diverged = False
|
has_diverged = False
|
||||||
|
|
||||||
for c in containers:
|
for c in containers:
|
||||||
if self.has_legacy_proj_name(c):
|
if c.has_legacy_proj_name(self.project):
|
||||||
log.debug('%s has diverged: Legacy project name' % c.name)
|
log.debug('%s has diverged: Legacy project name' % c.name)
|
||||||
has_diverged = True
|
has_diverged = True
|
||||||
continue
|
continue
|
||||||
|
@ -713,9 +718,14 @@ class Service(object):
|
||||||
# TODO: this would benefit from github.com/docker/docker/pull/14699
|
# TODO: this would benefit from github.com/docker/docker/pull/14699
|
||||||
# to remove the need to inspect every container
|
# to remove the need to inspect every container
|
||||||
def _next_container_number(self, one_off=False):
|
def _next_container_number(self, one_off=False):
|
||||||
containers = self._fetch_containers(
|
containers = itertools.chain(
|
||||||
all=True,
|
self._fetch_containers(
|
||||||
filters={'label': self.labels(one_off=one_off)}
|
all=True,
|
||||||
|
filters={'label': self.labels(one_off=one_off)}
|
||||||
|
), self._fetch_containers(
|
||||||
|
all=True,
|
||||||
|
filters={'label': self.labels(one_off=one_off, legacy=True)}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
numbers = [c.number for c in containers]
|
numbers = [c.number for c in containers]
|
||||||
return 1 if not numbers else max(numbers) + 1
|
return 1 if not numbers else max(numbers) + 1
|
||||||
|
@ -1243,12 +1253,6 @@ class Service(object):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def has_legacy_proj_name(self, ctnr):
|
|
||||||
return (
|
|
||||||
ComposeVersion(ctnr.labels.get(LABEL_VERSION)) < ComposeVersion('1.21.0') and
|
|
||||||
ctnr.project != self.project
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def short_id_alias_exists(container, network):
|
def short_id_alias_exists(container, network):
|
||||||
aliases = container.get(
|
aliases = container.get(
|
||||||
|
|
Loading…
Reference in New Issue