m/p/localregistry: init

Adds the localregistry package, which serves Bazel-built container
images via the Docker/OCI V2 registry API.

This will be used to serve test images instead of preseeding them.

Change-Id: I0c2ceb9a83f807c9c87ab03bc1141ca67cc64268
Reviewed-on: https://review.monogon.dev/c/monogon/+/1926
Tested-by: Jenkins CI
Reviewed-by: Leopold Schabel <leo@monogon.tech>
diff --git a/metropolis/pkg/localregistry/def.bzl b/metropolis/pkg/localregistry/def.bzl
new file mode 100644
index 0000000..061a63d
--- /dev/null
+++ b/metropolis/pkg/localregistry/def.bzl
@@ -0,0 +1,44 @@
+load("@io_bazel_rules_docker//container:providers.bzl", "ImageInfo")
+
+def _localregistry_manifest_impl(ctx):
+    manifest_out = ctx.actions.declare_file(ctx.label.name+".prototxt")
+    
+    images = []
+    referenced = [manifest_out]
+    for i in ctx.attr.images:
+        image_info = i[ImageInfo].container_parts
+        referenced.append(image_info['config'])
+        referenced.append(image_info['config_digest'])
+        image = struct(
+            name = i.label.package + "/" + i.label.name,
+            config = struct(
+                file_path = image_info['config'].short_path,
+                digest_path = image_info['config_digest'].short_path,
+            ),
+            layers = [],
+        )
+        for layer in zip(image_info['zipped_layer'], image_info['blobsum']):
+            referenced.append(layer[0])
+            referenced.append(layer[1])
+            image.layers.append(struct(file_path = layer[0].short_path, digest_path=layer[1].short_path))
+        images.append(image)
+    
+    ctx.actions.write(manifest_out, proto.encode_text(struct(images = images)))
+    return [DefaultInfo(runfiles = ctx.runfiles(files = referenced), files = depset([manifest_out]))]
+
+
+localregistry_manifest = rule(
+    implementation = _localregistry_manifest_impl,
+    doc = """
+        Builds a manifest for serving images directly from the build files.
+    """,
+    attrs = {
+        "images": attr.label_list(
+            mandatory = True,
+            doc = """
+                List of images (with ImageInfo provider) to be served from the local registry.
+            """,
+           providers = [ImageInfo],
+        ),
+    },
+)