From 8ebec9a67f470e94c5dd8f446f5f4197d6db486f Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Mon, 8 Dec 2014 16:03:42 -0800 Subject: [PATCH] Pull latest tag by default This was changed in Docker recently: https://github.com/docker/docker/pull/7759 This means we aren't pulling loads of tags when we only use the latest. Signed-off-by: Ben Firshman --- fig/service.py | 22 ++++++++++++++++++++-- tests/unit/service_test.py | 23 +++++++++++++++++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/fig/service.py b/fig/service.py index 645b6adfc..c86c8a97e 100644 --- a/fig/service.py +++ b/fig/service.py @@ -381,6 +381,8 @@ class Service(object): if len(self.client.images(name=self._build_tag_name())) == 0: self.build() container_options['image'] = self._build_tag_name() + else: + container_options['image'] = self._get_image_name(container_options['image']) # Delete options which are only used when starting for key in ['privileged', 'net', 'dns', 'restart', 'cap_add', 'cap_drop']: @@ -389,6 +391,12 @@ class Service(object): return container_options + def _get_image_name(self, image): + repo, tag = parse_repository_tag(image) + if tag == "": + tag = "latest" + return '%s:%s' % (repo, tag) + def build(self, no_cache=False): log.info('Building %s...' % self.name) @@ -435,9 +443,10 @@ class Service(object): def pull(self, insecure_registry=False): if 'image' in self.options: - log.info('Pulling %s (%s)...' % (self.name, self.options.get('image'))) + image_name = self._get_image_name(self.options['image']) + log.info('Pulling %s (%s)...' % (self.name, image_name)) self.client.pull( - self.options.get('image'), + image_name, insecure_registry=insecure_registry ) @@ -509,6 +518,15 @@ def parse_volume_spec(volume_config): return VolumeSpec(external, internal, mode) +def parse_repository_tag(s): + if ":" not in s: + return s, "" + repo, tag = s.rsplit(":", 1) + if "/" in tag: + return s, "" + return repo, tag + + def build_volume_binding(volume_spec): internal = {'bind': volume_spec.internal, 'ro': volume_spec.mode == 'ro'} external = os.path.expanduser(volume_spec.external) diff --git a/tests/unit/service_test.py b/tests/unit/service_test.py index 119b41440..b4c8a6dc8 100644 --- a/tests/unit/service_test.py +++ b/tests/unit/service_test.py @@ -17,6 +17,7 @@ from fig.service import ( parse_volume_spec, build_volume_binding, APIError, + parse_repository_tag, ) @@ -131,7 +132,7 @@ class ServiceTest(unittest.TestCase): def test_split_domainname_none(self): service = Service('foo', hostname='name', client=self.mock_client) self.mock_client.containers.return_value = [] - opts = service._get_container_create_options({}) + opts = service._get_container_create_options({'image': 'foo'}) self.assertEqual(opts['hostname'], 'name', 'hostname') self.assertFalse('domainname' in opts, 'domainname') @@ -140,7 +141,7 @@ class ServiceTest(unittest.TestCase): hostname='name.domain.tld', client=self.mock_client) self.mock_client.containers.return_value = [] - opts = service._get_container_create_options({}) + opts = service._get_container_create_options({'image': 'foo'}) self.assertEqual(opts['hostname'], 'name', 'hostname') self.assertEqual(opts['domainname'], 'domain.tld', 'domainname') @@ -150,7 +151,7 @@ class ServiceTest(unittest.TestCase): domainname='domain.tld', client=self.mock_client) self.mock_client.containers.return_value = [] - opts = service._get_container_create_options({}) + opts = service._get_container_create_options({'image': 'foo'}) self.assertEqual(opts['hostname'], 'name', 'hostname') self.assertEqual(opts['domainname'], 'domain.tld', 'domainname') @@ -160,7 +161,7 @@ class ServiceTest(unittest.TestCase): domainname='domain.tld', client=self.mock_client) self.mock_client.containers.return_value = [] - opts = service._get_container_create_options({}) + opts = service._get_container_create_options({'image': 'foo'}) self.assertEqual(opts['hostname'], 'name.sub', 'hostname') self.assertEqual(opts['domainname'], 'domain.tld', 'domainname') @@ -205,6 +206,20 @@ class ServiceTest(unittest.TestCase): self.mock_client.pull.assert_called_once_with('someimage:sometag', insecure_registry=True, stream=True) mock_log.info.assert_called_once_with('Pulling image someimage:sometag...') + def test_parse_repository_tag(self): + self.assertEqual(parse_repository_tag("root"), ("root", "")) + self.assertEqual(parse_repository_tag("root:tag"), ("root", "tag")) + self.assertEqual(parse_repository_tag("user/repo"), ("user/repo", "")) + self.assertEqual(parse_repository_tag("user/repo:tag"), ("user/repo", "tag")) + self.assertEqual(parse_repository_tag("url:5000/repo"), ("url:5000/repo", "")) + self.assertEqual(parse_repository_tag("url:5000/repo:tag"), ("url:5000/repo", "tag")) + + def test_latest_is_used_when_tag_is_not_specified(self): + service = Service('foo', client=self.mock_client, image='someimage') + Container.create = mock.Mock() + service.create_container() + self.assertEqual(Container.create.call_args[1]['image'], 'someimage:latest') + class ServiceVolumesTest(unittest.TestCase):