Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,16 @@ container_image(name, base, data_path, directory, files, legacy_repository_namin
</p>
</td>
</tr>
<tr>
<td><code><i>name</i>.digest</code></td>
<td>
<code>The full Docker image's digest</code>
<p>
An image digest that can be used to refer to that image. Unlike tags,
digest references are immutable i.e. always refer to the same content.
</p>
</td>
</tr>
<tr>
<td><code><i>name</i>-layer.tar</code></td>
<td>
Expand Down
8 changes: 4 additions & 4 deletions container/container.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ container = struct(
)

# The release of the github.com/google/containerregistry to consume.
CONTAINERREGISTRY_RELEASE = "v0.0.31"
CONTAINERREGISTRY_RELEASE = "v0.0.32"

_local_tool_build_template = """
sh_binary(
Expand Down Expand Up @@ -69,7 +69,7 @@ def repositories():
name = "puller",
urls = [("https://storage.googleapis.com/containerregistry-releases/" +
CONTAINERREGISTRY_RELEASE + "/puller.par")],
sha256 = "f4971a9127d6f3df16d820f84e78d7816b1c49be13d8d6d0176f80234c082814",
sha256 = "0aea6c53809846009f42f07eb569d8b3bfa79c073b16fe97312d592f45016924",
executable = True,
)

Expand All @@ -78,7 +78,7 @@ def repositories():
name = "importer",
urls = [("https://storage.googleapis.com/containerregistry-releases/" +
CONTAINERREGISTRY_RELEASE + "/importer.par")],
sha256 = "ca8644c21f2eb99b4e14d9966fe1e31c8baf5d7e277526c2a216955ee858cfd6",
sha256 = "52dd0628fe13c698772d982279db443e70585cb9912e2825e58a88eac6e0ca8c",
executable = True,
)

Expand All @@ -87,7 +87,7 @@ def repositories():
name = "containerregistry",
urls = [("https://github.com/google/containerregistry/archive/" +
CONTAINERREGISTRY_RELEASE + ".tar.gz")],
sha256 = "54a0caf9ad3c0bfd832d454cba40e277be1febcf9b135d889e93af4c643b1660",
sha256 = "48408e0d1861c47aac88d06efda089c46bfb3265bf3a51081853963460fbcb49",
strip_prefix = "containerregistry-" + CONTAINERREGISTRY_RELEASE[1:],
)

Expand Down
35 changes: 35 additions & 0 deletions container/image.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,28 @@ def _repository_name(ctx):

return _join_path(ctx.attr.repository, ctx.label.package)

def _assemble_image_digest(ctx, name, image, image_tarball, output_digest):
blobsums = image.get("blobsum", [])
digest_args = ["--digest=%s" % f.path for f in blobsums]
blobs = image.get("zipped_layer", [])
layer_args = ["--layer=%s" % f.path for f in blobs]
config_arg = "--config=%s" % image["config"].path
output_digest_arg = "--output-digest=%s" % output_digest.path

arguments = [config_arg, output_digest_arg] + layer_args + digest_args
if image.get("legacy"):
arguments.append("--tarball=%s" % image["legacy"].path)

ctx.actions.run(
outputs = [output_digest],
inputs = [image["config"]] + blobsums + blobs +
([image["legacy"]] if image.get("legacy") else []),
executable = ctx.executable._digester,
arguments = arguments,
mnemonic = "ImageDigest",
progress_message = "Extracting image digest of %s" % image_tarball.short_path,
)

def _impl(
ctx,
name = None,
Expand All @@ -232,6 +254,7 @@ def _impl(
operating_system = None,
output_executable = None,
output_tarball = None,
output_digest = None,
output_layer = None,
workdir = None,
null_cmd = None,
Expand All @@ -258,6 +281,7 @@ def _impl(
operating_system: Operating system to target (e.g. linux, windows)
output_executable: File to use as output for script to load docker image
output_tarball: File, overrides ctx.outputs.out
output_digest: File, overrides ctx.outputs.digest
output_layer: File, overrides ctx.outputs.layer
workdir: str, overrides ctx.attr.workdir
null_cmd: bool, overrides ctx.attr.null_cmd
Expand All @@ -270,6 +294,7 @@ def _impl(
creation_time = creation_time or ctx.attr.creation_time
output_executable = output_executable or ctx.outputs.executable
output_tarball = output_tarball or ctx.outputs.out
output_digest = output_digest or ctx.outputs.digest
output_layer = output_layer or ctx.outputs.layer
null_cmd = null_cmd or ctx.attr.null_cmd
null_entrypoint = null_entrypoint or ctx.attr.null_entrypoint
Expand Down Expand Up @@ -357,6 +382,9 @@ def _impl(
# A list of paths to the layer digests.
"blobsum": shas,

# The File containing digest of the image.
"digest": output_digest,

# A list of paths to the layer .tar files
"unzipped_layer": unzipped_layers,
# A list of paths to the layer diff_ids.
Expand All @@ -381,6 +409,7 @@ def _impl(
run_flags = docker_run_flags,
)
_assemble_image(ctx, images, output_tarball)
_assemble_image_digest(ctx, name, container_parts, output_tarball, output_digest)

runfiles = ctx.runfiles(
files = unzipped_layers + diff_ids + [config_file, config_digest] +
Expand Down Expand Up @@ -443,11 +472,17 @@ _attrs = dict(_layer.attrs.items() + {
# We need these flags to distinguish them.
"null_cmd": attr.bool(default = False),
"null_entrypoint": attr.bool(default = False),
"_digester": attr.label(
default = "@containerregistry//:digester",
cfg = "host",
executable = True,
),
}.items() + _hash_tools.items() + _layer_tools.items() + _zip_tools.items())

_outputs = dict(_layer.outputs)

_outputs["out"] = "%{name}.tar"
_outputs["digest"] = "%{name}.digest"

image = struct(
attrs = _attrs,
Expand Down
16 changes: 16 additions & 0 deletions tests/docker/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ package(default_visibility = ["//visibility:public"])

load("//container:container.bzl", "container_image", "container_import")
load("//contrib:test.bzl", "container_test")
load(
"@bazel_tools//tools/build_rules:test_rules.bzl",
"file_test",
)

container_test(
name = "structure_test",
Expand Down Expand Up @@ -160,3 +164,15 @@ container_test(
driver = "tar",
image = ":basic_windows_image",
)

file_test(
name = "test_digest_output1",
content = "sha256:fd90e88f1c5dfedf89df4469747ada0a28d7c34196bb2ac879cff6f259f65ba5",
file = ":deb_image_with_dpkgs.digest",
)

file_test(
name = "test_digest_output2",
content = "sha256:acff18cc59851acc448c0f106ccefdd13907a91835d61b8b34f85a974a2e540a",
file = ":null_cmd_and_entrypoint_none.digest",
)