Browse Source

Prevent dependencies rescaling when executing `docker-compose run`

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 8 years ago
parent
commit
9daced4c04
4 changed files with 28 additions and 8 deletions
  1. 3 1
      compose/cli/main.py
  2. 4 2
      compose/project.py
  3. 10 5
      compose/service.py
  4. 11 0
      tests/acceptance/cli_test.py

+ 3 - 1
compose/cli/main.py

@@ -1138,7 +1138,9 @@ def run_one_off_container(container_options, project, service, options):
             project.up(
                 service_names=deps,
                 start_deps=True,
-                strategy=ConvergenceStrategy.never)
+                strategy=ConvergenceStrategy.never,
+                rescale=False
+            )
 
     project.initialize()
 

+ 4 - 2
compose/project.py

@@ -382,7 +382,8 @@ class Project(object):
            timeout=None,
            detached=False,
            remove_orphans=False,
-           scale_override=None):
+           scale_override=None,
+           rescale=True):
 
         warn_for_swarm_mode(self.client)
 
@@ -405,7 +406,8 @@ class Project(object):
                 plans[service.name],
                 timeout=timeout,
                 detached=detached,
-                scale_override=scale_override.get(service.name)
+                scale_override=scale_override.get(service.name),
+                rescale=rescale
             )
 
         def get_deps(service):

+ 10 - 5
compose/service.py

@@ -390,7 +390,7 @@ class Service(object):
             return containers
 
     def _execute_convergence_recreate(self, containers, scale, timeout, detached, start):
-            if len(containers) > scale:
+            if scale is not None and len(containers) > scale:
                 self._downscale(containers[scale:], timeout)
                 containers = containers[:scale]
 
@@ -408,14 +408,14 @@ class Service(object):
             for error in errors.values():
                 raise OperationFailedError(error)
 
-            if len(containers) < scale:
+            if scale is not None and len(containers) < scale:
                 containers.extend(self._execute_convergence_create(
                     scale - len(containers), detached, start
                 ))
             return containers
 
     def _execute_convergence_start(self, containers, scale, timeout, detached, start):
-            if len(containers) > scale:
+            if scale is not None and len(containers) > scale:
                 self._downscale(containers[scale:], timeout)
                 containers = containers[:scale]
             if start:
@@ -429,7 +429,7 @@ class Service(object):
                 for error in errors.values():
                     raise OperationFailedError(error)
 
-            if len(containers) < scale:
+            if scale is not None and len(containers) < scale:
                 containers.extend(self._execute_convergence_create(
                     scale - len(containers), detached, start
                 ))
@@ -448,7 +448,7 @@ class Service(object):
         )
 
     def execute_convergence_plan(self, plan, timeout=None, detached=False,
-                                 start=True, scale_override=None):
+                                 start=True, scale_override=None, rescale=True):
         (action, containers) = plan
         scale = scale_override if scale_override is not None else self.scale_num
         containers = sorted(containers, key=attrgetter('number'))
@@ -460,6 +460,11 @@ class Service(object):
                 scale, detached, start
             )
 
+        # The create action needs always needs an initial scale, but otherwise,
+        # we set scale to none in no-rescale scenarios (`run` dependencies)
+        if not rescale:
+            scale = None
+
         if action == 'recreate':
             return self._execute_convergence_recreate(
                 containers, scale, timeout, detached, start

+ 11 - 0
tests/acceptance/cli_test.py

@@ -1211,6 +1211,17 @@ class CLITestCase(DockerClientTestCase):
         self.assertEqual(len(db.containers()), 1)
         self.assertEqual(len(console.containers()), 0)
 
+    def test_run_service_with_scaled_dependencies(self):
+        self.base_dir = 'tests/fixtures/v2-dependencies'
+        self.dispatch(['up', '-d', '--scale', 'db=2', '--scale', 'console=0'])
+        db = self.project.get_service('db')
+        console = self.project.get_service('console')
+        assert len(db.containers()) == 2
+        assert len(console.containers()) == 0
+        self.dispatch(['run', 'web', '/bin/true'], None)
+        assert len(db.containers()) == 2
+        assert len(console.containers()) == 0
+
     def test_run_with_no_deps(self):
         self.base_dir = 'tests/fixtures/links-composefile'
         self.dispatch(['run', '--no-deps', 'web', '/bin/true'])