Skip to content

Commit

Permalink
feat: support all hash algorithms (#433)
Browse files Browse the repository at this point in the history
  • Loading branch information
thesayyn authored Dec 12, 2023
1 parent 9fc0477 commit f0e265d
Showing 1 changed file with 16 additions and 44 deletions.
60 changes: 16 additions & 44 deletions oci/private/pull.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,10 @@ _SUPPORTED_MEDIA_TYPES = {
def _is_tag(str):
return str.find(":") == -1

def _trim_hash_algorithm(identifier):
"Optionally remove the sha256: prefix from identifier, if present"
parts = identifier.split(":", 1)
if len(parts) != 2:
return identifier
return parts[1]
def _digest_into_blob_path(digest):
"convert sha256:deadbeef into sha256/deadbeef"
digest_path = digest.replace(":", "/", 1)
return "blobs/{}".format(digest_path)

def _download(rctx, state, identifier, output, resource, download_fn = download.bazel, headers = {}, allow_fail = False):
"Use the Bazel Downloader to fetch from the remote registry"
Expand Down Expand Up @@ -325,31 +323,9 @@ def _create_downloader(rctx):
)

_BUILD_FILE_TMPL = """\
"Generated by oci_pull"
"Generated by oci_pull. DO NOT EDIT!"
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
load("@aspect_bazel_lib//lib:copy_file.bzl", "copy_file")
load("@aspect_bazel_lib//lib:jq.bzl", "jq")
load("@bazel_skylib//rules:write_file.bzl", "write_file")
package(default_visibility = ["//visibility:public"])
copy_file(
name = "manifest",
src = "manifest.json",
out = "{image_digest}"
)
copy_to_directory(
name = "blobs",
# TODO(https://github.com/bazel-contrib/rules_oci/issues/73): other hash algorithms
out = "blobs/sha256",
include_external_repositories = ["*"],
srcs = {tars} + [
":{image_digest}",
":{config_file}",
],
)
copy_to_directory(
name = "{target_name}",
Expand All @@ -360,6 +336,7 @@ copy_to_directory(
"oci-layout",
"index.json",
],
visibility = ["//visibility:public"]
)
"""

Expand All @@ -385,7 +362,7 @@ def _oci_pull_impl(rctx):
if manifest["mediaType"] in _SUPPORTED_MEDIA_TYPES["manifest"]:
if rctx.attr.platform:
fail("{}/{} is a single-architecture image, so attribute 'platforms' should not be set.".format(rctx.attr.registry, rctx.attr.repository))

elif manifest["mediaType"] in _SUPPORTED_MEDIA_TYPES["index"]:
if not rctx.attr.platform:
fail("{}/{} is a multi-architecture image, so attribute 'platforms' is required.".format(rctx.attr.registry, rctx.attr.repository))
Expand All @@ -398,34 +375,29 @@ def _oci_pull_impl(rctx):
manifest, size, digest = downloader.download_manifest(matching_manifest["digest"], "manifest.json")
else:
fail("Unrecognized mediaType {} in manifest file".format(manifest["mediaType"]))

# symlink manifest.json to blobs with it's digest.
# it is okay to use symlink here as copy_to_directory will dereference it when creating the TreeArtifact.
rctx.symlink("manifest.json", _digest_into_blob_path(digest))

# download the image config
config_file = _trim_hash_algorithm(manifest["config"]["digest"])
downloader.download_blob(manifest["config"]["digest"], config_file)
downloader.download_blob(manifest["config"]["digest"], _digest_into_blob_path(manifest["config"]["digest"]))

# download all layers
# TODO: we should avoid eager-download of the layers ("shallow pull")
tars = []
for layer in manifest["layers"]:
blob_digest = _trim_hash_algorithm(layer["digest"])
downloader.download_blob(layer["digest"], blob_digest)

if blob_digest not in tars:
tars.append(blob_digest)
downloader.download_blob(layer["digest"], _digest_into_blob_path(layer["digest"]))

rctx.file("index.json", util.build_manifest_json(
media_type = manifest["mediaType"],
size = size,
digest = digest,
platform = rctx.attr.platform
platform = rctx.attr.platform,
))
rctx.file("oci-layout", json.encode_indent({"imageLayoutVersion": "1.0.0"}, indent = " "))

rctx.file("BUILD.bazel", content = _BUILD_FILE_TMPL.format(
target_name = rctx.attr.target_name,
tars = tars,
image_digest = _trim_hash_algorithm(digest),
config_file = config_file,
target_name = rctx.attr.target_name
))

oci_pull = repository_rule(
Expand Down

0 comments on commit f0e265d

Please sign in to comment.