diff --git a/go/pkg/ociutil/bazel.go b/go/pkg/ociutil/bazel.go index a4dad16..c97543d 100644 --- a/go/pkg/ociutil/bazel.go +++ b/go/pkg/ociutil/bazel.go @@ -26,23 +26,26 @@ func GenerateBuildFilesHandler(handler images.HandlerFunc, layoutRoot string, pr blobBuildFiles[digest.SHA256] = rule.EmptyFile(algoBUILDPath(layoutRoot, digest.SHA256), "") // Add load statements for all of the oci_* rules - ldBlob := rule.NewLoad("@com_github_datadog_rules_oci//oci/private/repositories:blob.bzl") + ldBlob := rule.NewLoad("@com_github_datadog_rules_oci//oci/private/repositories:oci_blob.bzl") ldBlob.Add("oci_blob") - ldManifest := rule.NewLoad("@com_github_datadog_rules_oci//oci/private/repositories:manifests.bzl") - ldManifest.Add("oci_image_index_manifest") - ldManifest.Add("oci_image_manifest") + ldImageManifest := rule.NewLoad("@com_github_datadog_rules_oci//oci/private/repositories:oci_image_manifest.bzl") + ldImageManifest.Add("oci_image_manifest") + + ldImageIndexManifest := rule.NewLoad("@com_github_datadog_rules_oci//oci/private/repositories:oci_image_index_manifest.bzl") + ldImageIndexManifest.Add("oci_image_index_manifest") for algo, f := range blobBuildFiles { ldBlob.Insert(f, 0) - ldManifest.Insert(f, 0) + ldImageManifest.Insert(f, 0) + ldImageIndexManifest.Insert(f, 0) f.Save(algoBUILDPath(layoutRoot, algo)) } // Top level build file for used as an index of the entire layout layoutBuild := rule.EmptyFile(filepath.Join(layoutRoot, "BUILD.bazel"), "") - ldLayout := rule.NewLoad("@com_github_datadog_rules_oci//oci/private/repositories:layout.bzl") + ldLayout := rule.NewLoad("@com_github_datadog_rules_oci//oci/private/repositories:oci_layout_index.bzl") ldLayout.Add("oci_layout_index") ldLayout.Insert(layoutBuild, 0) diff --git a/oci/BUILD.bazel b/oci/BUILD.bazel index 0efabf2..48cff8a 100644 --- a/oci/BUILD.bazel +++ b/oci/BUILD.bazel @@ -28,11 +28,13 @@ bzl_library( visibility = ["//visibility:public"], deps = [ "//oci:providers.bzl", + "//oci/private:common.bzl", "//oci/private:debug_flag.bzl", - "//oci/private:image.bzl", + "//oci/private:oci_image.bzl", + "//oci/private:oci_image_index.bzl", "//oci/private:oci_image_layer.bzl", "//oci/private:oci_image_layout.bzl", - "//oci/private:push.bzl", + "//oci/private:oci_push.bzl", "@aspect_bazel_lib//lib:stamping", ], ) @@ -52,7 +54,7 @@ bzl_library( ], visibility = ["//visibility:public"], deps = [ - "//oci/private/repositories:pull.bzl", + "//oci/private/repositories:oci_pull.bzl", ], ) diff --git a/oci/defs.bzl b/oci/defs.bzl index 027a1f8..0af379d 100644 --- a/oci/defs.bzl +++ b/oci/defs.bzl @@ -1,13 +1,10 @@ """ public rules """ -load( - "//oci/private:image.bzl", - _oci_image = "oci_image", - _oci_image_index = "oci_image_index", -) +load("//oci/private:oci_image.bzl", _oci_image = "oci_image") +load("//oci/private:oci_image_index.bzl", _oci_image_index = "oci_image_index") load("//oci/private:oci_image_layer.bzl", _oci_image_layer = "oci_image_layer") load("//oci/private:oci_image_layout.bzl", _oci_image_layout = "oci_image_layout") -load("//oci/private:push.bzl", _oci_push = "oci_push") +load("//oci/private:oci_push.bzl", _oci_push = "oci_push") oci_image = _oci_image oci_image_index = _oci_image_index diff --git a/oci/private/common.bzl b/oci/private/common.bzl new file mode 100644 index 0000000..8c91387 --- /dev/null +++ b/oci/private/common.bzl @@ -0,0 +1,18 @@ +# buildifier: disable=function-docstring +def get_descriptor_file(ctx, desc): + if hasattr(desc, "descriptor_file"): + return desc.descriptor_file + + out = ctx.actions.declare_file(desc.digest) + ctx.actions.write( + output = out, + content = json.encode({ + "mediaType": desc.media_type, + "size": desc.size, + "digest": desc.digest, + "urls": desc.urls, + "annotations": desc.annotations, + }), + ) + + return out diff --git a/oci/private/image.bzl b/oci/private/oci_image.bzl similarity index 69% rename from oci/private/image.bzl rename to oci/private/oci_image.bzl index d935149..4a51013 100644 --- a/oci/private/image.bzl +++ b/oci/private/oci_image.bzl @@ -1,91 +1,9 @@ -""" image """ +""" oci_image """ load("//oci:providers.bzl", "OCIDescriptor", "OCILayout") +load(":common.bzl", "get_descriptor_file") -# buildifier: disable=function-docstring -def get_descriptor_file(ctx, desc): - if hasattr(desc, "descriptor_file"): - return desc.descriptor_file - - out = ctx.actions.declare_file(desc.digest) - ctx.actions.write( - output = out, - content = json.encode({ - "mediaType": desc.media_type, - "size": desc.size, - "digest": desc.digest, - "urls": desc.urls, - "annotations": desc.annotations, - }), - ) - - return out - -def _oci_image_index_impl(ctx): - toolchain = ctx.toolchains["//oci:toolchain"] - - layout_files = depset(None, transitive = [m[OCILayout].files for m in ctx.attr.manifests]) - - index_desc_file = ctx.actions.declare_file("{}.index.descriptor.json".format(ctx.label.name)) - index_file = ctx.actions.declare_file("{}.index.json".format(ctx.label.name)) - layout_file = ctx.actions.declare_file("{}.index.layout.json".format(ctx.label.name)) - - desc_files = [] - for manifest in ctx.attr.manifests: - desc_files.append(get_descriptor_file(ctx, manifest[OCIDescriptor])) - - outputs = [ - index_file, - index_desc_file, - layout_file, - ] - - ctx.actions.run( - executable = toolchain.sdk.ocitool, - arguments = ["--layout={}".format(m[OCILayout].blob_index.path) for m in ctx.attr.manifests] + - [ - "create-index", - "--out-index={}".format(index_file.path), - "--out-layout={}".format(layout_file.path), - "--outd={}".format(index_desc_file.path), - ] + - ["--desc={}".format(d.path) for d in desc_files] + - ["--annotations={}={}".format(k, v) for k, v in ctx.attr.annotations.items()], - inputs = desc_files + layout_files.to_list(), - outputs = outputs, - ) - - return [ - OCIDescriptor( - descriptor_file = index_desc_file, - ), - OCILayout( - blob_index = layout_file, - files = depset(direct = [index_file, layout_file], transitive = [layout_files]), - ), - DefaultInfo( - files = depset(outputs), - ), - ] - -oci_image_index = rule( - implementation = _oci_image_index_impl, - doc = """ - """, - attrs = { - "manifests": attr.label_list( - doc = """ - """, - ), - "annotations": attr.string_dict( - doc = """ - """, - ), - }, - toolchains = ["//oci:toolchain"], -) - -def _oci_image_impl(ctx): +def _impl(ctx): toolchain = ctx.toolchains["//oci:toolchain"] base_desc = get_descriptor_file(ctx, ctx.attr.base[OCIDescriptor]) @@ -179,7 +97,7 @@ def _oci_image_impl(ctx): ] oci_image = rule( - implementation = _oci_image_impl, + implementation = _impl, doc = """Creates a new image manifest and config by appending the `layers` to an existing image manifest and config defined by `base`. If `base` is an image index, then `os` and `arch` will be used to extract the image manifest.""", diff --git a/oci/private/oci_image_index.bzl b/oci/private/oci_image_index.bzl new file mode 100644 index 0000000..1faef60 --- /dev/null +++ b/oci/private/oci_image_index.bzl @@ -0,0 +1,68 @@ +""" oci_image_index """ + +load("//oci:providers.bzl", "OCIDescriptor", "OCILayout") +load(":common.bzl", "get_descriptor_file") + +def _impl(ctx): + toolchain = ctx.toolchains["//oci:toolchain"] + + layout_files = depset(None, transitive = [m[OCILayout].files for m in ctx.attr.manifests]) + + index_desc_file = ctx.actions.declare_file("{}.index.descriptor.json".format(ctx.label.name)) + index_file = ctx.actions.declare_file("{}.index.json".format(ctx.label.name)) + layout_file = ctx.actions.declare_file("{}.index.layout.json".format(ctx.label.name)) + + desc_files = [] + for manifest in ctx.attr.manifests: + desc_files.append(get_descriptor_file(ctx, manifest[OCIDescriptor])) + + outputs = [ + index_file, + index_desc_file, + layout_file, + ] + + ctx.actions.run( + executable = toolchain.sdk.ocitool, + arguments = ["--layout={}".format(m[OCILayout].blob_index.path) for m in ctx.attr.manifests] + + [ + "create-index", + "--out-index={}".format(index_file.path), + "--out-layout={}".format(layout_file.path), + "--outd={}".format(index_desc_file.path), + ] + + ["--desc={}".format(d.path) for d in desc_files] + + ["--annotations={}={}".format(k, v) for k, v in ctx.attr.annotations.items()], + inputs = desc_files + layout_files.to_list(), + outputs = outputs, + ) + + return [ + OCIDescriptor( + descriptor_file = index_desc_file, + ), + OCILayout( + blob_index = layout_file, + files = depset(direct = [index_file, layout_file], transitive = [layout_files]), + ), + DefaultInfo( + files = depset(outputs), + ), + ] + +oci_image_index = rule( + implementation = _impl, + doc = """ + """, + attrs = { + "manifests": attr.label_list( + doc = """ + """, + ), + "annotations": attr.string_dict( + doc = """ + """, + ), + }, + toolchains = ["//oci:toolchain"], +) diff --git a/oci/private/push.bzl b/oci/private/oci_push.bzl similarity index 98% rename from oci/private/push.bzl rename to oci/private/oci_push.bzl index bda0af3..8940610 100644 --- a/oci/private/push.bzl +++ b/oci/private/oci_push.bzl @@ -1,10 +1,10 @@ -""" push """ +""" oci_push """ load("@aspect_bazel_lib//lib:stamping.bzl", "STAMP_ATTRS", "maybe_stamp") load("//oci:providers.bzl", "OCIDescriptor", "OCILayout", "OCIReferenceInfo") load(":debug_flag.bzl", "DebugInfo") -def _oci_push_impl(ctx): +def _impl(ctx): toolchain = ctx.toolchains["//oci:toolchain"] layout = ctx.attr.manifest[OCILayout] @@ -137,7 +137,7 @@ oci_push = rule( doc = """ Pushes a manifest or a list of manifests to an OCI registry. """, - implementation = _oci_push_impl, + implementation = _impl, executable = True, attrs = dict({ "manifest": attr.label( diff --git a/oci/private/repositories/blob.bzl b/oci/private/repositories/oci_blob.bzl similarity index 94% rename from oci/private/repositories/blob.bzl rename to oci/private/repositories/oci_blob.bzl index 2144378..314ea03 100644 --- a/oci/private/repositories/blob.bzl +++ b/oci/private/repositories/oci_blob.bzl @@ -1,8 +1,8 @@ -""" blob """ +""" oci_blob """ load("@com_github_datadog_rules_oci//oci:providers.bzl", "OCIDescriptor") -def _oci_blob_impl(ctx): +def _impl(ctx): return [OCIDescriptor( file = ctx.file.file, media_type = ctx.attr.media_type, @@ -13,7 +13,7 @@ def _oci_blob_impl(ctx): )] oci_blob = rule( - implementation = _oci_blob_impl, + implementation = _impl, doc = """ An internal rule to represent a blob in a content-addressable store. This rule is usually generated by 'ocitool' when pulling an OCI artifact. diff --git a/oci/private/repositories/oci_image_index_manifest.bzl b/oci/private/repositories/oci_image_index_manifest.bzl new file mode 100644 index 0000000..e0689a2 --- /dev/null +++ b/oci/private/repositories/oci_image_index_manifest.bzl @@ -0,0 +1,30 @@ +""" oci_image_index_manifest """ + +load( + "@com_github_datadog_rules_oci//oci:providers.bzl", + "OCIDescriptor", + "OCIImageIndexManifest", + "OCILayout", +) + +def _impl(ctx): + return [OCIImageIndexManifest( + manifests = [m[OCIDescriptor] for m in ctx.attr.manifests], + ), ctx.attr.layout[OCILayout], ctx.attr.descriptor[OCIDescriptor]] + +oci_image_index_manifest = rule( + implementation = _impl, + attrs = { + "descriptor": attr.label( + mandatory = True, + providers = [OCIDescriptor], + ), + "manifests": attr.label_list( + mandatory = False, + providers = [OCIDescriptor], + ), + "annotations": attr.string_dict(), + "layout": attr.label(), + }, + provides = [OCIImageIndexManifest], +) diff --git a/oci/private/repositories/manifests.bzl b/oci/private/repositories/oci_image_manifest.bzl similarity index 52% rename from oci/private/repositories/manifests.bzl rename to oci/private/repositories/oci_image_manifest.bzl index af02e58..5e72957 100644 --- a/oci/private/repositories/manifests.bzl +++ b/oci/private/repositories/oci_image_manifest.bzl @@ -1,14 +1,13 @@ -""" manifests """ +""" oci_image_manifest """ load( "@com_github_datadog_rules_oci//oci:providers.bzl", "OCIDescriptor", - "OCIImageIndexManifest", "OCIImageManifest", "OCILayout", ) -def _oci_image_manifest_impl(ctx): +def _impl(ctx): return [OCIImageManifest( config = ctx.attr.config[OCIDescriptor], layers = [layer[OCIDescriptor] for layer in ctx.attr.layers], @@ -16,7 +15,7 @@ def _oci_image_manifest_impl(ctx): ), ctx.attr.layout[OCILayout], ctx.attr.descriptor[OCIDescriptor]] oci_image_manifest = rule( - implementation = _oci_image_manifest_impl, + implementation = _impl, provides = [OCIImageManifest], attrs = { "descriptor": attr.label( @@ -35,25 +34,3 @@ oci_image_manifest = rule( "layout": attr.label(), }, ) - -def _oci_image_index_manifest_impl(ctx): - return [OCIImageIndexManifest( - manifests = [m[OCIDescriptor] for m in ctx.attr.manifests], - ), ctx.attr.layout[OCILayout], ctx.attr.descriptor[OCIDescriptor]] - -oci_image_index_manifest = rule( - implementation = _oci_image_index_manifest_impl, - attrs = { - "descriptor": attr.label( - mandatory = True, - providers = [OCIDescriptor], - ), - "manifests": attr.label_list( - mandatory = False, - providers = [OCIDescriptor], - ), - "annotations": attr.string_dict(), - "layout": attr.label(), - }, - provides = [OCIImageIndexManifest], -) diff --git a/oci/private/repositories/layout.bzl b/oci/private/repositories/oci_layout_index.bzl similarity index 90% rename from oci/private/repositories/layout.bzl rename to oci/private/repositories/oci_layout_index.bzl index 06f62c4..fe44eeb 100644 --- a/oci/private/repositories/layout.bzl +++ b/oci/private/repositories/oci_layout_index.bzl @@ -1,8 +1,8 @@ -""" layout """ +""" oci_layout_index """ load("@com_github_datadog_rules_oci//oci:providers.bzl", "OCIDescriptor", "OCILayout") -def _oci_layout_index_impl(ctx): +def _impl(ctx): blobs_map = {} all_files = [] for blob in ctx.attr.blobs: @@ -29,7 +29,7 @@ def _oci_layout_index_impl(ctx): ] oci_layout_index = rule( - implementation = _oci_layout_index_impl, + implementation = _impl, attrs = { "index": attr.label( providers = [OCIDescriptor], diff --git a/oci/private/repositories/pull.bzl b/oci/private/repositories/oci_pull.bzl similarity index 98% rename from oci/private/repositories/pull.bzl rename to oci/private/repositories/oci_pull.bzl index 61fe08c..36225c6 100644 --- a/oci/private/repositories/pull.bzl +++ b/oci/private/repositories/oci_pull.bzl @@ -1,4 +1,4 @@ -""" pull """ +""" oci_pull """ # A directory to store cached OCI artifacts # TODO(griffin) currently not used, but going to start depending on this for @@ -51,7 +51,7 @@ def generate_build_files(rctx, layout_root, digest = ""): if res.return_code > 0: failout("failed to pull manifest", res) -def _oci_pull_impl(rctx): +def _impl(rctx): pull( rctx, rctx.path("."), @@ -68,7 +68,7 @@ def _oci_pull_impl(rctx): ) oci_pull = repository_rule( - implementation = _oci_pull_impl, + implementation = _impl, doc = """ """, attrs = { diff --git a/oci/repositories.bzl b/oci/repositories.bzl index 28c1ff6..394866c 100644 --- a/oci/repositories.bzl +++ b/oci/repositories.bzl @@ -1,5 +1,5 @@ """ public repository rules """ -load("//oci/private/repositories:pull.bzl", _oci_pull = "oci_pull") +load("//oci/private/repositories:oci_pull.bzl", _oci_pull = "oci_pull") oci_pull = _oci_pull