Skip to content

Commit

Permalink
Rename --fetch-digests to --push-images and remove auto-pull
Browse files Browse the repository at this point in the history
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
  • Loading branch information
aanand committed Jul 27, 2016
1 parent b72f911 commit 0488dd3
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 55 deletions.
39 changes: 18 additions & 21 deletions compose/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
Expand All @@ -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 "
Expand All @@ -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)
if 'build' not in service.options:
raise NeedsPull(service.image_name)

return fetch_image_digest(service)
if not allow_push:
raise NeedsPush(service.image_name)

return push_image(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

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)
Expand Down
37 changes: 27 additions & 10 deletions compose/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,16 @@ def bundle(self, config_options, options):
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 "<project name>.dab".
Expand All @@ -247,7 +248,7 @@ def bundle(self, config_options, options):
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):
Expand All @@ -256,12 +257,28 @@ def list_images(images):
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)]

paras.append("If this is OK, run `docker-compose bundle --fetch-digests`.")
command_hint = (
"Use `docker-compose pull {}` to pull them. "
.format(" ".join(sorted(e.needs_pull)))
)

paras += [
"The following images need to be pulled:",
list_images(e.needs_pull),
command_hint,
]

raise UserError("\n\n".join(paras))

Expand Down
34 changes: 10 additions & 24 deletions tests/unit/bundle_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
def test_push_image_with_saved_digest(mock_service):
mock_service.options['build'] = '.'
mock_service.options['image'] = image_id = 'abcd'
mock_service.pull.return_value = expected = 'sha256:thedigest'
mock_service.push.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)
digest = bundle.push_image(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)
mock_service.push.assert_called_once_with()
assert not mock_service.client.push.called


def test_fetch_image_digest_for_build(mock_service):
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': ['digest1']}
mock_service.image.return_value = {'RepoDigests': []}

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
mock_service.client.pull.assert_called_once_with(digest)


def test_to_bundle():
Expand Down

0 comments on commit 0488dd3

Please sign in to comment.