瀏覽代碼

Merge pull request #2467 from dnephin/remove_migrate_to_labels

Remove migrate-to-labels.
Aanand Prasad 10 年之前
父節點
當前提交
ecf2dd11f9

+ 5 - 42
compose/cli/main.py

@@ -12,7 +12,6 @@ from docker.errors import APIError
 from requests.exceptions import ReadTimeout
 
 from .. import __version__
-from .. import legacy
 from ..config import ConfigurationError
 from ..config import parse_environment
 from ..const import DEFAULT_TIMEOUT
@@ -50,7 +49,7 @@ def main():
     except KeyboardInterrupt:
         log.error("\nAborting.")
         sys.exit(1)
-    except (UserError, NoSuchService, ConfigurationError, legacy.LegacyError) as e:
+    except (UserError, NoSuchService, ConfigurationError) as e:
         log.error(e.msg)
         sys.exit(1)
     except NoSuchCommand as e:
@@ -142,9 +141,7 @@ class TopLevelCommand(DocoptCommand):
       stop               Stop services
       unpause            Unpause services
       up                 Create and start containers
-      migrate-to-labels  Recreate containers to add labels
       version            Show the Docker-Compose version information
-
     """
     base_dir = '.'
 
@@ -533,32 +530,6 @@ class TopLevelCommand(DocoptCommand):
             log_printer = build_log_printer(to_attach, service_names, monochrome)
             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):
         """
         Show version informations
@@ -601,18 +572,10 @@ def run_one_off_container(container_options, project, service, options):
     if project.use_networking:
         project.ensure_network_exists()
 
-    try:
-        container = service.create_container(
-            quiet=True,
-            one_off=True,
-            **container_options)
-    except APIError:
-        legacy.check_for_legacy_containers(
-            project.client,
-            project.name,
-            [service.name],
-            allow_one_off=False)
-        raise
+    container = service.create_container(
+        quiet=True,
+        one_off=True,
+        **container_options)
 
     if options['-d']:
         container.start()

+ 0 - 182
compose/legacy.py

@@ -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))

+ 0 - 8
compose/project.py

@@ -15,7 +15,6 @@ from .const import LABEL_ONE_OFF
 from .const import LABEL_PROJECT
 from .const import LABEL_SERVICE
 from .container import Container
-from .legacy import check_for_legacy_containers
 from .service import ContainerNet
 from .service import ConvergenceStrategy
 from .service import Net
@@ -287,13 +286,6 @@ class Project(object):
         def matches_service_names(container):
             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)]
 
     def get_network(self):

+ 1 - 11
compose/service.py

@@ -26,7 +26,6 @@ from .const import LABEL_PROJECT
 from .const import LABEL_SERVICE
 from .const import LABEL_VERSION
 from .container import Container
-from .legacy import check_for_legacy_containers
 from .parallel import parallel_execute
 from .parallel import parallel_remove
 from .parallel import parallel_start
@@ -122,21 +121,12 @@ class Service(object):
     def containers(self, stopped=False, one_off=False, filters={}):
         filters.update({'label': self.labels(one_off=one_off)})
 
-        containers = list(filter(None, [
+        return list(filter(None, [
             Container.from_ps(self.client, container)
             for container in self.client.containers(
                 all=stopped,
                 filters=filters)]))
 
-        if not containers:
-            check_for_legacy_containers(
-                self.client,
-                self.project,
-                [self.name],
-            )
-
-        return containers
-
     def get_container(self, number=1):
         """Return a :class:`compose.container.Container` for this service. The
         container must be active, and match `number`.

+ 0 - 10
contrib/completion/bash/docker-compose

@@ -164,15 +164,6 @@ _docker_compose_logs() {
 }
 
 
-_docker_compose_migrate_to_labels() {
-	case "$cur" in
-		-*)
-			COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
-			;;
-	esac
-}
-
-
 _docker_compose_pause() {
 	case "$cur" in
 		-*)
@@ -385,7 +376,6 @@ _docker_compose() {
 		help
 		kill
 		logs
-		migrate-to-labels
 		pause
 		port
 		ps

+ 0 - 5
contrib/completion/zsh/_docker-compose

@@ -212,11 +212,6 @@ __docker-compose_subcommand() {
                 '--no-color[Produce monochrome output.]' \
                 '*:services:__docker-compose_services_all' && ret=0
             ;;
-        (migrate-to-labels)
-            _arguments -A '-*' \
-                $opts_help \
-                '(-):Recreate containers to add labels' && ret=0
-            ;;
         (pause)
             _arguments \
                 $opts_help \

+ 1 - 1
docs/install.md

@@ -98,7 +98,7 @@ 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:
+to preserve) you can use compose 1.5.x to migrate them with the following command:
 
     $ docker-compose migrate-to-labels
 

+ 0 - 1
docs/reference/docker-compose.md

@@ -40,7 +40,6 @@ Commands:
   stop               Stop services
   unpause            Unpause services
   up                 Create and start containers
-  migrate-to-labels  Recreate containers to add labels
   version            Show the Docker-Compose version information
 ```
 

+ 0 - 218
tests/integration/legacy_test.py

@@ -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)

+ 0 - 6
tests/unit/cli_test.py

@@ -74,12 +74,6 @@ class CLITestCase(unittest.TestCase):
 
         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):
         with self.assertRaises(NoSuchCommand):
             TopLevelCommand().dispatch(['help', 'nonexistent'], None)