diff --git a/docs/cli.md b/docs/cli.md index 6b4497e78..86c7d3b27 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -36,6 +36,10 @@ Print the public port for a port binding List containers. +## pull + +Pulls service images. + ## rm Remove stopped service containers. diff --git a/fig/cli/main.py b/fig/cli/main.py index 732b4d29e..3ecc87b23 100644 --- a/fig/cli/main.py +++ b/fig/cli/main.py @@ -86,6 +86,7 @@ class TopLevelCommand(Command): logs View output from containers port Print the public port for a port binding ps List containers + pull Pulls service images rm Remove stopped containers run Run a one-off command scale Set number of containers for a service @@ -204,6 +205,14 @@ class TopLevelCommand(Command): ]) print(Formatter().table(headers, rows)) + def pull(self, project, options): + """ + Pulls images for services. + + Usage: pull [SERVICE...] + """ + project.pull(service_names=options['SERVICE']) + def rm(self, project, options): """ Remove stopped service containers. diff --git a/fig/project.py b/fig/project.py index c224c5967..6ef6a7c52 100644 --- a/fig/project.py +++ b/fig/project.py @@ -180,6 +180,10 @@ class Project(object): return running_containers + def pull(self, service_names=None): + for service in self.get_services(service_names, include_links=True): + service.pull() + 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 29ad34874..496b81c6e 100644 --- a/fig/service.py +++ b/fig/service.py @@ -410,6 +410,11 @@ class Service(object): return False return True + def pull(self): + if 'image' in self.options: + log.info('Pulling %s (%s)...' % (self.name, self.options.get('image'))) + self.client.pull(self.options.get('image')) + NAME_RE = re.compile(r'^([^_]+)_([^_]+)_(run_)?(\d+)$') diff --git a/tests/integration/cli_test.py b/tests/integration/cli_test.py index 3c0f2aa7f..c8bf09816 100644 --- a/tests/integration/cli_test.py +++ b/tests/integration/cli_test.py @@ -53,6 +53,12 @@ class CLITestCase(DockerClientTestCase): self.assertNotIn('multiplefigfiles_another_1', output) self.assertIn('multiplefigfiles_yetanother_1', output) + @patch('fig.service.log') + def test_pull(self, mock_logging): + self.command.dispatch(['pull'], None) + mock_logging.info.assert_any_call('Pulling simple (busybox:latest)...') + mock_logging.info.assert_any_call('Pulling another (busybox:latest)...') + @patch('sys.stdout', new_callable=StringIO) def test_build_no_cache(self, mock_stdout): self.command.base_dir = 'tests/fixtures/simple-dockerfile' @@ -68,7 +74,6 @@ class CLITestCase(DockerClientTestCase): self.command.dispatch(['build', '--no-cache', 'simple'], None) output = mock_stdout.getvalue() self.assertNotIn(cache_indicator, output) - def test_up(self): self.command.dispatch(['up', '-d'], None) service = self.project.get_service('simple')