mirror of https://github.com/docker/compose.git
Remove migrate-to-labels.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
defcf5a21f
commit
a21f9993b3
|
@ -12,7 +12,6 @@ from docker.errors import APIError
|
||||||
from requests.exceptions import ReadTimeout
|
from requests.exceptions import ReadTimeout
|
||||||
|
|
||||||
from .. import __version__
|
from .. import __version__
|
||||||
from .. import legacy
|
|
||||||
from ..config import ConfigurationError
|
from ..config import ConfigurationError
|
||||||
from ..config import parse_environment
|
from ..config import parse_environment
|
||||||
from ..const import DEFAULT_TIMEOUT
|
from ..const import DEFAULT_TIMEOUT
|
||||||
|
@ -55,7 +54,7 @@ def main():
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
log.error("\nAborting.")
|
log.error("\nAborting.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except (UserError, NoSuchService, ConfigurationError, legacy.LegacyError) as e:
|
except (UserError, NoSuchService, ConfigurationError) as e:
|
||||||
log.error(e.msg)
|
log.error(e.msg)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except NoSuchCommand as e:
|
except NoSuchCommand as e:
|
||||||
|
@ -147,9 +146,7 @@ class TopLevelCommand(DocoptCommand):
|
||||||
stop Stop services
|
stop Stop services
|
||||||
unpause Unpause services
|
unpause Unpause services
|
||||||
up Create and start containers
|
up Create and start containers
|
||||||
migrate-to-labels Recreate containers to add labels
|
|
||||||
version Show the Docker-Compose version information
|
version Show the Docker-Compose version information
|
||||||
|
|
||||||
"""
|
"""
|
||||||
base_dir = '.'
|
base_dir = '.'
|
||||||
|
|
||||||
|
@ -550,32 +547,6 @@ class TopLevelCommand(DocoptCommand):
|
||||||
log_printer = build_log_printer(to_attach, service_names, monochrome)
|
log_printer = build_log_printer(to_attach, service_names, monochrome)
|
||||||
attach_to_logs(project, log_printer, service_names, timeout)
|
attach_to_logs(project, log_printer, service_names, timeout)
|
||||||
|
|
||||||
def migrate_to_labels(self, project, _options):
|
|
||||||
"""
|
|
||||||
Recreate containers to add labels
|
|
||||||
|
|
||||||
If you're coming from Compose 1.2 or earlier, you'll need to remove or
|
|
||||||
migrate your existing containers after upgrading Compose. This is
|
|
||||||
because, as of version 1.3, Compose uses Docker labels to keep track
|
|
||||||
of containers, and so they need to be recreated with labels added.
|
|
||||||
|
|
||||||
If Compose detects containers that were created without labels, it
|
|
||||||
will refuse to run so that you don't end up with two sets of them. If
|
|
||||||
you want to keep using your existing containers (for example, because
|
|
||||||
they have data volumes you want to preserve) you can migrate them with
|
|
||||||
the following command:
|
|
||||||
|
|
||||||
docker-compose migrate-to-labels
|
|
||||||
|
|
||||||
Alternatively, if you're not worried about keeping them, you can
|
|
||||||
remove them - Compose will just create new ones.
|
|
||||||
|
|
||||||
docker rm -f myapp_web_1 myapp_db_1 ...
|
|
||||||
|
|
||||||
Usage: migrate-to-labels
|
|
||||||
"""
|
|
||||||
legacy.migrate_project_to_labels(project)
|
|
||||||
|
|
||||||
def version(self, project, options):
|
def version(self, project, options):
|
||||||
"""
|
"""
|
||||||
Show version informations
|
Show version informations
|
||||||
|
@ -618,18 +589,10 @@ def run_one_off_container(container_options, project, service, options):
|
||||||
if project.use_networking:
|
if project.use_networking:
|
||||||
project.ensure_network_exists()
|
project.ensure_network_exists()
|
||||||
|
|
||||||
try:
|
container = service.create_container(
|
||||||
container = service.create_container(
|
quiet=True,
|
||||||
quiet=True,
|
one_off=True,
|
||||||
one_off=True,
|
**container_options)
|
||||||
**container_options)
|
|
||||||
except APIError:
|
|
||||||
legacy.check_for_legacy_containers(
|
|
||||||
project.client,
|
|
||||||
project.name,
|
|
||||||
[service.name],
|
|
||||||
allow_one_off=False)
|
|
||||||
raise
|
|
||||||
|
|
||||||
if options['-d']:
|
if options['-d']:
|
||||||
container.start()
|
container.start()
|
||||||
|
|
|
@ -1,182 +0,0 @@
|
||||||
import logging
|
|
||||||
import re
|
|
||||||
|
|
||||||
from .const import LABEL_VERSION
|
|
||||||
from .container import Container
|
|
||||||
from .container import get_container_name
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: remove this section when migrate_project_to_labels is removed
|
|
||||||
NAME_RE = re.compile(r'^([^_]+)_([^_]+)_(run_)?(\d+)$')
|
|
||||||
|
|
||||||
ERROR_MESSAGE_FORMAT = """
|
|
||||||
Compose found the following containers without labels:
|
|
||||||
|
|
||||||
{names_list}
|
|
||||||
|
|
||||||
As of Compose 1.3.0, containers are identified with labels instead of naming
|
|
||||||
convention. If you want to continue using these containers, run:
|
|
||||||
|
|
||||||
$ docker-compose migrate-to-labels
|
|
||||||
|
|
||||||
Alternatively, remove them:
|
|
||||||
|
|
||||||
$ docker rm -f {rm_args}
|
|
||||||
"""
|
|
||||||
|
|
||||||
ONE_OFF_ADDENDUM_FORMAT = """
|
|
||||||
You should also remove your one-off containers:
|
|
||||||
|
|
||||||
$ docker rm -f {rm_args}
|
|
||||||
"""
|
|
||||||
|
|
||||||
ONE_OFF_ERROR_MESSAGE_FORMAT = """
|
|
||||||
Compose found the following containers without labels:
|
|
||||||
|
|
||||||
{names_list}
|
|
||||||
|
|
||||||
As of Compose 1.3.0, containers are identified with labels instead of naming convention.
|
|
||||||
|
|
||||||
Remove them before continuing:
|
|
||||||
|
|
||||||
$ docker rm -f {rm_args}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def check_for_legacy_containers(
|
|
||||||
client,
|
|
||||||
project,
|
|
||||||
services,
|
|
||||||
allow_one_off=True):
|
|
||||||
"""Check if there are containers named using the old naming convention
|
|
||||||
and warn the user that those containers may need to be migrated to
|
|
||||||
using labels, so that compose can find them.
|
|
||||||
"""
|
|
||||||
containers = get_legacy_containers(client, project, services, one_off=False)
|
|
||||||
|
|
||||||
if containers:
|
|
||||||
one_off_containers = get_legacy_containers(client, project, services, one_off=True)
|
|
||||||
|
|
||||||
raise LegacyContainersError(
|
|
||||||
[c.name for c in containers],
|
|
||||||
[c.name for c in one_off_containers],
|
|
||||||
)
|
|
||||||
|
|
||||||
if not allow_one_off:
|
|
||||||
one_off_containers = get_legacy_containers(client, project, services, one_off=True)
|
|
||||||
|
|
||||||
if one_off_containers:
|
|
||||||
raise LegacyOneOffContainersError(
|
|
||||||
[c.name for c in one_off_containers],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class LegacyError(Exception):
|
|
||||||
def __unicode__(self):
|
|
||||||
return self.msg
|
|
||||||
|
|
||||||
__str__ = __unicode__
|
|
||||||
|
|
||||||
|
|
||||||
class LegacyContainersError(LegacyError):
|
|
||||||
def __init__(self, names, one_off_names):
|
|
||||||
self.names = names
|
|
||||||
self.one_off_names = one_off_names
|
|
||||||
|
|
||||||
self.msg = ERROR_MESSAGE_FORMAT.format(
|
|
||||||
names_list="\n".join(" {}".format(name) for name in names),
|
|
||||||
rm_args=" ".join(names),
|
|
||||||
)
|
|
||||||
|
|
||||||
if one_off_names:
|
|
||||||
self.msg += ONE_OFF_ADDENDUM_FORMAT.format(rm_args=" ".join(one_off_names))
|
|
||||||
|
|
||||||
|
|
||||||
class LegacyOneOffContainersError(LegacyError):
|
|
||||||
def __init__(self, one_off_names):
|
|
||||||
self.one_off_names = one_off_names
|
|
||||||
|
|
||||||
self.msg = ONE_OFF_ERROR_MESSAGE_FORMAT.format(
|
|
||||||
names_list="\n".join(" {}".format(name) for name in one_off_names),
|
|
||||||
rm_args=" ".join(one_off_names),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def add_labels(project, container):
|
|
||||||
project_name, service_name, one_off, number = NAME_RE.match(container.name).groups()
|
|
||||||
if project_name != project.name or service_name not in project.service_names:
|
|
||||||
return
|
|
||||||
service = project.get_service(service_name)
|
|
||||||
service.recreate_container(container)
|
|
||||||
|
|
||||||
|
|
||||||
def migrate_project_to_labels(project):
|
|
||||||
log.info("Running migration to labels for project %s", project.name)
|
|
||||||
|
|
||||||
containers = get_legacy_containers(
|
|
||||||
project.client,
|
|
||||||
project.name,
|
|
||||||
project.service_names,
|
|
||||||
one_off=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
for container in containers:
|
|
||||||
add_labels(project, container)
|
|
||||||
|
|
||||||
|
|
||||||
def get_legacy_containers(
|
|
||||||
client,
|
|
||||||
project,
|
|
||||||
services,
|
|
||||||
one_off=False):
|
|
||||||
|
|
||||||
return list(_get_legacy_containers_iter(
|
|
||||||
client,
|
|
||||||
project,
|
|
||||||
services,
|
|
||||||
one_off=one_off,
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
def _get_legacy_containers_iter(
|
|
||||||
client,
|
|
||||||
project,
|
|
||||||
services,
|
|
||||||
one_off=False):
|
|
||||||
|
|
||||||
containers = client.containers(all=True)
|
|
||||||
|
|
||||||
for service in services:
|
|
||||||
for container in containers:
|
|
||||||
if LABEL_VERSION in (container.get('Labels') or {}):
|
|
||||||
continue
|
|
||||||
|
|
||||||
name = get_container_name(container)
|
|
||||||
if has_container(project, service, name, one_off=one_off):
|
|
||||||
yield Container.from_ps(client, container)
|
|
||||||
|
|
||||||
|
|
||||||
def has_container(project, service, name, one_off=False):
|
|
||||||
if not name or not is_valid_name(name, one_off):
|
|
||||||
return False
|
|
||||||
container_project, container_service, _container_number = parse_name(name)
|
|
||||||
return container_project == project and container_service == service
|
|
||||||
|
|
||||||
|
|
||||||
def is_valid_name(name, one_off=False):
|
|
||||||
match = NAME_RE.match(name)
|
|
||||||
if match is None:
|
|
||||||
return False
|
|
||||||
if one_off:
|
|
||||||
return match.group(3) == 'run_'
|
|
||||||
else:
|
|
||||||
return match.group(3) is None
|
|
||||||
|
|
||||||
|
|
||||||
def parse_name(name):
|
|
||||||
match = NAME_RE.match(name)
|
|
||||||
(project, service_name, _, suffix) = match.groups()
|
|
||||||
return (project, service_name, int(suffix))
|
|
|
@ -15,7 +15,6 @@ from .const import LABEL_ONE_OFF
|
||||||
from .const import LABEL_PROJECT
|
from .const import LABEL_PROJECT
|
||||||
from .const import LABEL_SERVICE
|
from .const import LABEL_SERVICE
|
||||||
from .container import Container
|
from .container import Container
|
||||||
from .legacy import check_for_legacy_containers
|
|
||||||
from .service import ContainerNet
|
from .service import ContainerNet
|
||||||
from .service import ConvergenceStrategy
|
from .service import ConvergenceStrategy
|
||||||
from .service import Net
|
from .service import Net
|
||||||
|
@ -287,13 +286,6 @@ class Project(object):
|
||||||
def matches_service_names(container):
|
def matches_service_names(container):
|
||||||
return container.labels.get(LABEL_SERVICE) in service_names
|
return container.labels.get(LABEL_SERVICE) in service_names
|
||||||
|
|
||||||
if not containers:
|
|
||||||
check_for_legacy_containers(
|
|
||||||
self.client,
|
|
||||||
self.name,
|
|
||||||
self.service_names,
|
|
||||||
)
|
|
||||||
|
|
||||||
return [c for c in containers if matches_service_names(c)]
|
return [c for c in containers if matches_service_names(c)]
|
||||||
|
|
||||||
def get_network(self):
|
def get_network(self):
|
||||||
|
|
|
@ -26,7 +26,6 @@ from .const import LABEL_PROJECT
|
||||||
from .const import LABEL_SERVICE
|
from .const import LABEL_SERVICE
|
||||||
from .const import LABEL_VERSION
|
from .const import LABEL_VERSION
|
||||||
from .container import Container
|
from .container import Container
|
||||||
from .legacy import check_for_legacy_containers
|
|
||||||
from .parallel import parallel_execute
|
from .parallel import parallel_execute
|
||||||
from .parallel import parallel_remove
|
from .parallel import parallel_remove
|
||||||
from .parallel import parallel_start
|
from .parallel import parallel_start
|
||||||
|
@ -122,21 +121,12 @@ class Service(object):
|
||||||
def containers(self, stopped=False, one_off=False, filters={}):
|
def containers(self, stopped=False, one_off=False, filters={}):
|
||||||
filters.update({'label': self.labels(one_off=one_off)})
|
filters.update({'label': self.labels(one_off=one_off)})
|
||||||
|
|
||||||
containers = list(filter(None, [
|
return 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=filters)]))
|
filters=filters)]))
|
||||||
|
|
||||||
if not containers:
|
|
||||||
check_for_legacy_containers(
|
|
||||||
self.client,
|
|
||||||
self.project,
|
|
||||||
[self.name],
|
|
||||||
)
|
|
||||||
|
|
||||||
return containers
|
|
||||||
|
|
||||||
def get_container(self, number=1):
|
def get_container(self, number=1):
|
||||||
"""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`.
|
||||||
|
|
|
@ -164,15 +164,6 @@ _docker_compose_logs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_docker_compose_migrate_to_labels() {
|
|
||||||
case "$cur" in
|
|
||||||
-*)
|
|
||||||
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_docker_compose_pause() {
|
_docker_compose_pause() {
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
|
@ -385,7 +376,6 @@ _docker_compose() {
|
||||||
help
|
help
|
||||||
kill
|
kill
|
||||||
logs
|
logs
|
||||||
migrate-to-labels
|
|
||||||
pause
|
pause
|
||||||
port
|
port
|
||||||
ps
|
ps
|
||||||
|
|
|
@ -212,11 +212,6 @@ __docker-compose_subcommand() {
|
||||||
'--no-color[Produce monochrome output.]' \
|
'--no-color[Produce monochrome output.]' \
|
||||||
'*:services:__docker-compose_services_all' && ret=0
|
'*:services:__docker-compose_services_all' && ret=0
|
||||||
;;
|
;;
|
||||||
(migrate-to-labels)
|
|
||||||
_arguments -A '-*' \
|
|
||||||
$opts_help \
|
|
||||||
'(-):Recreate containers to add labels' && ret=0
|
|
||||||
;;
|
|
||||||
(pause)
|
(pause)
|
||||||
_arguments \
|
_arguments \
|
||||||
$opts_help \
|
$opts_help \
|
||||||
|
|
|
@ -98,7 +98,7 @@ be recreated with labels added.
|
||||||
If Compose detects containers that were created without labels, it will refuse
|
If Compose detects containers that were created without labels, it will refuse
|
||||||
to run so that you don't end up with two sets of them. If you want to keep using
|
to run so that you don't end up with two sets of them. If you want to keep using
|
||||||
your existing containers (for example, because they have data volumes you want
|
your existing containers (for example, because they have data volumes you want
|
||||||
to preserve) you can migrate them with the following command:
|
to preserve) you can use compose 1.5.x to migrate them with the following command:
|
||||||
|
|
||||||
$ docker-compose migrate-to-labels
|
$ docker-compose migrate-to-labels
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ Commands:
|
||||||
stop Stop services
|
stop Stop services
|
||||||
unpause Unpause services
|
unpause Unpause services
|
||||||
up Create and start containers
|
up Create and start containers
|
||||||
migrate-to-labels Recreate containers to add labels
|
|
||||||
version Show the Docker-Compose version information
|
version Show the Docker-Compose version information
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,218 +0,0 @@
|
||||||
import unittest
|
|
||||||
|
|
||||||
from docker.errors import APIError
|
|
||||||
|
|
||||||
from .. import mock
|
|
||||||
from .testcases import DockerClientTestCase
|
|
||||||
from compose import legacy
|
|
||||||
from compose.project import Project
|
|
||||||
|
|
||||||
|
|
||||||
class UtilitiesTestCase(unittest.TestCase):
|
|
||||||
def test_has_container(self):
|
|
||||||
self.assertTrue(
|
|
||||||
legacy.has_container("composetest", "web", "composetest_web_1", one_off=False),
|
|
||||||
)
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.has_container("composetest", "web", "composetest_web_run_1", one_off=False),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_has_container_one_off(self):
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.has_container("composetest", "web", "composetest_web_1", one_off=True),
|
|
||||||
)
|
|
||||||
self.assertTrue(
|
|
||||||
legacy.has_container("composetest", "web", "composetest_web_run_1", one_off=True),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_has_container_different_project(self):
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.has_container("composetest", "web", "otherapp_web_1", one_off=False),
|
|
||||||
)
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.has_container("composetest", "web", "otherapp_web_run_1", one_off=True),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_has_container_different_service(self):
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.has_container("composetest", "web", "composetest_db_1", one_off=False),
|
|
||||||
)
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.has_container("composetest", "web", "composetest_db_run_1", one_off=True),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_is_valid_name(self):
|
|
||||||
self.assertTrue(
|
|
||||||
legacy.is_valid_name("composetest_web_1", one_off=False),
|
|
||||||
)
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.is_valid_name("composetest_web_run_1", one_off=False),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_is_valid_name_one_off(self):
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.is_valid_name("composetest_web_1", one_off=True),
|
|
||||||
)
|
|
||||||
self.assertTrue(
|
|
||||||
legacy.is_valid_name("composetest_web_run_1", one_off=True),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_is_valid_name_invalid(self):
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.is_valid_name("foo"),
|
|
||||||
)
|
|
||||||
self.assertFalse(
|
|
||||||
legacy.is_valid_name("composetest_web_lol_1", one_off=True),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_get_legacy_containers(self):
|
|
||||||
client = mock.Mock()
|
|
||||||
client.containers.return_value = [
|
|
||||||
{
|
|
||||||
"Id": "abc123",
|
|
||||||
"Image": "def456",
|
|
||||||
"Name": "composetest_web_1",
|
|
||||||
"Labels": None,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": "ghi789",
|
|
||||||
"Image": "def456",
|
|
||||||
"Name": None,
|
|
||||||
"Labels": None,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": "jkl012",
|
|
||||||
"Image": "def456",
|
|
||||||
"Labels": None,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
containers = legacy.get_legacy_containers(client, "composetest", ["web"])
|
|
||||||
|
|
||||||
self.assertEqual(len(containers), 1)
|
|
||||||
self.assertEqual(containers[0].id, 'abc123')
|
|
||||||
|
|
||||||
|
|
||||||
class LegacyTestCase(DockerClientTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(LegacyTestCase, self).setUp()
|
|
||||||
self.containers = []
|
|
||||||
|
|
||||||
db = self.create_service('db')
|
|
||||||
web = self.create_service('web', links=[(db, 'db')])
|
|
||||||
nginx = self.create_service('nginx', links=[(web, 'web')])
|
|
||||||
|
|
||||||
self.services = [db, web, nginx]
|
|
||||||
self.project = Project('composetest', self.services, self.client)
|
|
||||||
|
|
||||||
# Create a legacy container for each service
|
|
||||||
for service in self.services:
|
|
||||||
service.ensure_image_exists()
|
|
||||||
container = self.client.create_container(
|
|
||||||
name='{}_{}_1'.format(self.project.name, service.name),
|
|
||||||
**service.options
|
|
||||||
)
|
|
||||||
self.client.start(container)
|
|
||||||
self.containers.append(container)
|
|
||||||
|
|
||||||
# Create a single one-off legacy container
|
|
||||||
self.containers.append(self.client.create_container(
|
|
||||||
name='{}_{}_run_1'.format(self.project.name, db.name),
|
|
||||||
**self.services[0].options
|
|
||||||
))
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super(LegacyTestCase, self).tearDown()
|
|
||||||
for container in self.containers:
|
|
||||||
try:
|
|
||||||
self.client.kill(container)
|
|
||||||
except APIError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
self.client.remove_container(container)
|
|
||||||
except APIError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_legacy_containers(self, **kwargs):
|
|
||||||
return legacy.get_legacy_containers(
|
|
||||||
self.client,
|
|
||||||
self.project.name,
|
|
||||||
[s.name for s in self.services],
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_get_legacy_container_names(self):
|
|
||||||
self.assertEqual(len(self.get_legacy_containers()), len(self.services))
|
|
||||||
|
|
||||||
def test_get_legacy_container_names_one_off(self):
|
|
||||||
self.assertEqual(len(self.get_legacy_containers(one_off=True)), 1)
|
|
||||||
|
|
||||||
def test_migration_to_labels(self):
|
|
||||||
# Trying to get the container list raises an exception
|
|
||||||
|
|
||||||
with self.assertRaises(legacy.LegacyContainersError) as cm:
|
|
||||||
self.project.containers(stopped=True)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
set(cm.exception.names),
|
|
||||||
set(['composetest_db_1', 'composetest_web_1', 'composetest_nginx_1']),
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
set(cm.exception.one_off_names),
|
|
||||||
set(['composetest_db_run_1']),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Migrate the containers
|
|
||||||
|
|
||||||
legacy.migrate_project_to_labels(self.project)
|
|
||||||
|
|
||||||
# Getting the list no longer raises an exception
|
|
||||||
|
|
||||||
containers = self.project.containers(stopped=True)
|
|
||||||
self.assertEqual(len(containers), len(self.services))
|
|
||||||
|
|
||||||
def test_migration_one_off(self):
|
|
||||||
# We've already migrated
|
|
||||||
|
|
||||||
legacy.migrate_project_to_labels(self.project)
|
|
||||||
|
|
||||||
# Trying to create a one-off container results in a Docker API error
|
|
||||||
|
|
||||||
with self.assertRaises(APIError) as cm:
|
|
||||||
self.project.get_service('db').create_container(one_off=True)
|
|
||||||
|
|
||||||
# Checking for legacy one-off containers raises an exception
|
|
||||||
|
|
||||||
with self.assertRaises(legacy.LegacyOneOffContainersError) as cm:
|
|
||||||
legacy.check_for_legacy_containers(
|
|
||||||
self.client,
|
|
||||||
self.project.name,
|
|
||||||
['db'],
|
|
||||||
allow_one_off=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
set(cm.exception.one_off_names),
|
|
||||||
set(['composetest_db_run_1']),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Remove the old one-off container
|
|
||||||
|
|
||||||
c = self.client.inspect_container('composetest_db_run_1')
|
|
||||||
self.client.remove_container(c)
|
|
||||||
|
|
||||||
# Checking no longer raises an exception
|
|
||||||
|
|
||||||
legacy.check_for_legacy_containers(
|
|
||||||
self.client,
|
|
||||||
self.project.name,
|
|
||||||
['db'],
|
|
||||||
allow_one_off=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Creating a one-off container no longer results in an API error
|
|
||||||
|
|
||||||
self.project.get_service('db').create_container(one_off=True)
|
|
||||||
self.assertIsInstance(self.client.inspect_container('composetest_db_run_1'), dict)
|
|
|
@ -74,12 +74,6 @@ class CLITestCase(unittest.TestCase):
|
||||||
|
|
||||||
self.assertIn('Usage: up', str(ctx.exception))
|
self.assertIn('Usage: up', str(ctx.exception))
|
||||||
|
|
||||||
def test_command_help_dashes(self):
|
|
||||||
with self.assertRaises(SystemExit) as ctx:
|
|
||||||
TopLevelCommand().dispatch(['help', 'migrate-to-labels'], None)
|
|
||||||
|
|
||||||
self.assertIn('Usage: migrate-to-labels', str(ctx.exception))
|
|
||||||
|
|
||||||
def test_command_help_nonexistent(self):
|
def test_command_help_nonexistent(self):
|
||||||
with self.assertRaises(NoSuchCommand):
|
with self.assertRaises(NoSuchCommand):
|
||||||
TopLevelCommand().dispatch(['help', 'nonexistent'], None)
|
TopLevelCommand().dispatch(['help', 'nonexistent'], None)
|
||||||
|
|
Loading…
Reference in New Issue