From 887ed8d1b650ac18fac3f58213cd7cf897f5d885 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Mon, 25 Jul 2016 16:48:28 +0100 Subject: [PATCH] Rename --fetch-digests to --push-images and remove auto-pull Signed-off-by: Aanand Prasad --- compose/bundle.py | 43 +++++++++++++++++------------------- compose/cli/main.py | 35 +++++++++++++++++++++-------- tests/unit/bundle_test.py | 46 ++++++++++++++------------------------- 3 files changed, 62 insertions(+), 62 deletions(-) diff --git a/compose/bundle.py b/compose/bundle.py index 44f6954b7..afbdabfa8 100644 --- a/compose/bundle.py +++ b/compose/bundle.py @@ -60,7 +60,7 @@ def serialize_bundle(config, image_digests): return json.dumps(to_bundle(config, image_digests), indent=2, sort_keys=True) -def get_image_digests(project, allow_fetch=False): +def get_image_digests(project, allow_push=False): digests = {} needs_push = set() needs_pull = set() @@ -69,7 +69,7 @@ def get_image_digests(project, allow_fetch=False): try: digests[service.name] = get_image_digest( service, - allow_fetch=allow_fetch, + allow_push=allow_push, ) except NeedsPush as e: needs_push.add(e.image_name) @@ -82,7 +82,7 @@ def get_image_digests(project, allow_fetch=False): return digests -def get_image_digest(service, allow_fetch=False): +def get_image_digest(service, allow_push=False): if 'image' not in service.options: raise UserError( "Service '{s.name}' doesn't define an image tag. An image name is " @@ -108,27 +108,24 @@ def get_image_digest(service, allow_fetch=False): # digests return image['RepoDigests'][0] - if not allow_fetch: - if 'build' in service.options: - raise NeedsPush(service.image_name) - else: - raise NeedsPull(service.image_name) - - return fetch_image_digest(service) - - -def fetch_image_digest(service): if 'build' not in service.options: - digest = service.pull() - else: - try: - digest = service.push() - except: - log.error( - "Failed to push image for service '{s.name}'. Please use an " - "image tag that can be pushed to a Docker " - "registry.".format(s=service)) - raise + raise NeedsPull(service.image_name) + + if not allow_push: + raise NeedsPush(service.image_name) + + return push_image(service) + + +def push_image(service): + try: + digest = service.push() + except: + log.error( + "Failed to push image for service '{s.name}'. Please use an " + "image tag that can be pushed to a Docker " + "registry.".format(s=service)) + raise if not digest: raise ValueError("Failed to get digest for %s" % service.name) diff --git a/compose/cli/main.py b/compose/cli/main.py index 3f153d0d8..db06a5e14 100644 --- a/compose/cli/main.py +++ b/compose/cli/main.py @@ -223,15 +223,16 @@ class TopLevelCommand(object): Generate a Distributed Application Bundle (DAB) from the Compose file. Images must have digests stored, which requires interaction with a - Docker registry. If digests aren't stored for all images, you can pass - `--fetch-digests` to automatically fetch them. Images for services - with a `build` key will be pushed. Images for services without a - `build` key will be pulled. + Docker registry. If digests aren't stored for all images, you can fetch + them with `docker-compose pull` or `docker-compose push`. To push images + automatically when bundling, pass `--push-images`. Only services with + a `build` option specified will have their images pushed. Usage: bundle [options] Options: - --fetch-digests Automatically fetch image digests if missing + --push-images Automatically push images for any services + which have a `build` option specified. -o, --output PATH Path to write the bundle file to. Defaults to ".dab". @@ -247,7 +248,7 @@ class TopLevelCommand(object): try: image_digests = get_image_digests( self.project, - allow_fetch=options['--fetch-digests'], + allow_push=options['--push-images'], ) except MissingDigests as e: def list_images(images): @@ -256,12 +257,28 @@ class TopLevelCommand(object): paras = ["Some images are missing digests."] if e.needs_push: - paras += ["The following images need to be pushed:", list_images(e.needs_push)] + command_hint = ( + "Use `docker-compose push {}` to push them. " + "You can do this automatically with `docker-compose bundle --push-images`." + .format(" ".join(sorted(e.needs_push))) + ) + paras += [ + "The following images can be pushed:", + list_images(e.needs_push), + command_hint, + ] if e.needs_pull: - paras += ["The following images need to be pulled:", list_images(e.needs_pull)] + command_hint = ( + "Use `docker-compose pull {}` to pull them. " + .format(" ".join(sorted(e.needs_pull))) + ) - paras.append("If this is OK, run `docker-compose bundle --fetch-digests`.") + paras += [ + "The following images need to be pulled:", + list_images(e.needs_pull), + command_hint, + ] raise UserError("\n\n".join(paras)) diff --git a/tests/unit/bundle_test.py b/tests/unit/bundle_test.py index ff4c0dceb..223b3b07a 100644 --- a/tests/unit/bundle_test.py +++ b/tests/unit/bundle_test.py @@ -41,44 +41,30 @@ def test_get_image_digest_no_image(mock_service): assert "doesn't define an image tag" in exc.exconly() -def test_fetch_image_digest_for_image_with_saved_digest(mock_service): - mock_service.options['image'] = image_id = 'abcd' - mock_service.pull.return_value = expected = 'sha256:thedigest' - mock_service.image.return_value = {'RepoDigests': ['digest1']} - - digest = bundle.fetch_image_digest(mock_service) - assert digest == image_id + '@' + expected - - mock_service.pull.assert_called_once_with() - assert not mock_service.push.called - assert not mock_service.client.pull.called - - -def test_fetch_image_digest_for_image(mock_service): - mock_service.options['image'] = image_id = 'abcd' - mock_service.pull.return_value = expected = 'sha256:thedigest' - mock_service.image.return_value = {'RepoDigests': []} - - digest = bundle.fetch_image_digest(mock_service) - assert digest == image_id + '@' + expected - - mock_service.pull.assert_called_once_with() - assert not mock_service.push.called - mock_service.client.pull.assert_called_once_with(digest) - - -def test_fetch_image_digest_for_build(mock_service): +def test_push_image_with_saved_digest(mock_service): mock_service.options['build'] = '.' mock_service.options['image'] = image_id = 'abcd' mock_service.push.return_value = expected = 'sha256:thedigest' mock_service.image.return_value = {'RepoDigests': ['digest1']} - digest = bundle.fetch_image_digest(mock_service) + digest = bundle.push_image(mock_service) assert digest == image_id + '@' + expected mock_service.push.assert_called_once_with() - assert not mock_service.pull.called - assert not mock_service.client.pull.called + assert not mock_service.client.push.called + + +def test_push_image(mock_service): + mock_service.options['build'] = '.' + mock_service.options['image'] = image_id = 'abcd' + mock_service.push.return_value = expected = 'sha256:thedigest' + mock_service.image.return_value = {'RepoDigests': []} + + digest = bundle.push_image(mock_service) + assert digest == image_id + '@' + expected + + mock_service.push.assert_called_once_with() + mock_service.client.pull.assert_called_once_with(digest) def test_to_bundle():