|
|
@@ -263,43 +263,7 @@ class TopLevelCommand(object):
|
|
|
if not output:
|
|
|
output = "{}.dab".format(self.project.name)
|
|
|
|
|
|
- with errors.handle_connection_errors(self.project.client):
|
|
|
- try:
|
|
|
- image_digests = get_image_digests(
|
|
|
- self.project,
|
|
|
- allow_push=options['--push-images'],
|
|
|
- )
|
|
|
- except MissingDigests as e:
|
|
|
- def list_images(images):
|
|
|
- return "\n".join(" {}".format(name) for name in sorted(images))
|
|
|
-
|
|
|
- paras = ["Some images are missing digests."]
|
|
|
-
|
|
|
- if 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:
|
|
|
- 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))
|
|
|
+ image_digests = image_digests_for_project(self.project, options['--push-images'])
|
|
|
|
|
|
with open(output, 'w') as f:
|
|
|
f.write(serialize_bundle(compose_config, image_digests))
|
|
|
@@ -313,13 +277,20 @@ class TopLevelCommand(object):
|
|
|
Usage: config [options]
|
|
|
|
|
|
Options:
|
|
|
- -q, --quiet Only validate the configuration, don't print
|
|
|
- anything.
|
|
|
- --services Print the service names, one per line.
|
|
|
- --volumes Print the volume names, one per line.
|
|
|
+ --resolve-image-digests Pin image tags to digests.
|
|
|
+ -q, --quiet Only validate the configuration, don't print
|
|
|
+ anything.
|
|
|
+ --services Print the service names, one per line.
|
|
|
+ --volumes Print the volume names, one per line.
|
|
|
|
|
|
"""
|
|
|
+
|
|
|
compose_config = get_config_from_options(self.project_dir, config_options)
|
|
|
+ image_digests = None
|
|
|
+
|
|
|
+ if options['--resolve-image-digests']:
|
|
|
+ self.project = project_from_options('.', config_options)
|
|
|
+ image_digests = image_digests_for_project(self.project)
|
|
|
|
|
|
if options['--quiet']:
|
|
|
return
|
|
|
@@ -332,7 +303,7 @@ class TopLevelCommand(object):
|
|
|
print('\n'.join(volume for volume in compose_config.volumes))
|
|
|
return
|
|
|
|
|
|
- print(serialize_config(compose_config))
|
|
|
+ print(serialize_config(compose_config, image_digests))
|
|
|
|
|
|
def create(self, options):
|
|
|
"""
|
|
|
@@ -1034,6 +1005,45 @@ def timeout_from_opts(options):
|
|
|
return None if timeout is None else int(timeout)
|
|
|
|
|
|
|
|
|
+def image_digests_for_project(project, allow_push=False):
|
|
|
+ with errors.handle_connection_errors(project.client):
|
|
|
+ try:
|
|
|
+ return get_image_digests(
|
|
|
+ project,
|
|
|
+ allow_push=allow_push
|
|
|
+ )
|
|
|
+ except MissingDigests as e:
|
|
|
+ def list_images(images):
|
|
|
+ return "\n".join(" {}".format(name) for name in sorted(images))
|
|
|
+
|
|
|
+ paras = ["Some images are missing digests."]
|
|
|
+
|
|
|
+ if e.needs_push:
|
|
|
+ command_hint = (
|
|
|
+ "Use `docker-compose push {}` to push them. "
|
|
|
+ .format(" ".join(sorted(e.needs_push)))
|
|
|
+ )
|
|
|
+ paras += [
|
|
|
+ "The following images can be pushed:",
|
|
|
+ list_images(e.needs_push),
|
|
|
+ command_hint,
|
|
|
+ ]
|
|
|
+
|
|
|
+ if e.needs_pull:
|
|
|
+ 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))
|
|
|
+
|
|
|
+
|
|
|
def exitval_from_opts(options, project):
|
|
|
exit_value_from = options.get('--exit-code-from')
|
|
|
if exit_value_from:
|