From 352ad7a38c68c736725ea82177e5614a45bae5f1 Mon Sep 17 00:00:00 2001 From: sebastianneubauer Date: Fri, 21 Mar 2014 19:34:19 +0100 Subject: [PATCH] Scaling down removes containers Squashed version of #162. Closes #121. --- fig/cli/main.py | 9 +-------- fig/project.py | 11 +++++++++++ fig/service.py | 10 ++++++++++ tests/project_test.py | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/fig/cli/main.py b/fig/cli/main.py index 4188d7708..2e6a748f0 100644 --- a/fig/cli/main.py +++ b/fig/cli/main.py @@ -298,20 +298,13 @@ class TopLevelCommand(Command): """ detached = options['-d'] - (old, new) = self.project.recreate_containers(service_names=options['SERVICE']) + new = self.project.up(service_names=options['SERVICE']) if not detached: to_attach = [c for (s, c) in new] print("Attaching to", list_containers(to_attach)) log_printer = LogPrinter(to_attach, attach_params={"logs": True}) - for (service, container) in new: - service.start_container(container) - - for (service, container) in old: - container.remove() - - if not detached: try: log_printer.run() finally: diff --git a/fig/project.py b/fig/project.py index 12ec7069b..f89202054 100644 --- a/fig/project.py +++ b/fig/project.py @@ -137,6 +137,17 @@ class Project(object): else: log.info('%s uses an image, skipping' % service.name) + def up(self, service_names=None): + (old, new) = self.recreate_containers(service_names=service_names) + + for (service, container) in new: + service.start_container(container) + + for (service, container) in old: + container.remove() + + return new + def remove_stopped(self, service_names=None, **options): for service in self.get_services(service_names): service.remove_stopped(**options) diff --git a/fig/service.py b/fig/service.py index cf600dc19..d0de2c2b4 100644 --- a/fig/service.py +++ b/fig/service.py @@ -85,6 +85,14 @@ class Service(object): c.kill(**options) def scale(self, desired_num): + """ + Adjusts the number of containers to the specified number and ensures they are running. + + - creates containers until there are at least `desired_num` + - stops containers until there are at most `desired_num` running + - starts containers until there are at least `desired_num` running + - removes all stopped containers + """ if not self.can_be_scaled(): raise CannotBeScaledError() @@ -117,6 +125,8 @@ class Service(object): self.start_container(c) running_containers.append(c) + self.remove_stopped() + def remove_stopped(self, **options): for c in self.containers(stopped=True): diff --git a/tests/project_test.py b/tests/project_test.py index 07f383404..b8a5d6823 100644 --- a/tests/project_test.py +++ b/tests/project_test.py @@ -118,3 +118,41 @@ class ProjectTest(DockerClientTestCase): project.remove_stopped() self.assertEqual(len(project.containers(stopped=True)), 0) + + def test_project_up(self): + web = self.create_service('web') + db = self.create_service('db') + project = Project('figtest', [web, db], self.client) + project.start() + self.assertEqual(len(project.containers()), 0) + project.up() + self.assertEqual(len(project.containers()), 2) + project.kill() + project.remove_stopped() + + def test_unscale_after_restart(self): + web = self.create_service('web') + project = Project('figtest', [web], self.client) + + project.start() + + service = project.get_service('web') + service.scale(1) + self.assertEqual(len(service.containers()), 1) + service.scale(3) + self.assertEqual(len(service.containers()), 3) + project.up() + service = project.get_service('web') + self.assertEqual(len(service.containers()), 3) + service.scale(1) + self.assertEqual(len(service.containers()), 1) + project.up() + service = project.get_service('web') + self.assertEqual(len(service.containers()), 1) + # does scale=0 ,makes any sense? after recreating at least 1 container is running + service.scale(0) + project.up() + service = project.get_service('web') + self.assertEqual(len(service.containers()), 1) + project.kill() + project.remove_stopped()