diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index 9c1b051..a18e8dd 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -16,7 +16,5 @@ jobs:
- run: mkdir -p ~/.local/bin
- run: echo -e "#!/usr/bin/env bash\n echo '{\"ServerURL\":\"ghcr.io\",\"Username\":\"Bearer\",\"Secret\":\"${{ secrets.GITHUB_TOKEN }}\"}'" > ~/.local/bin/docker-credential-ghcr
- run: chmod +x ~/.local/bin/docker-credential-ghcr
- # Setup local toolchain
- - run: bazel build --config=ci //go/cmd/ocitool:ocitool && cp bazel-bin/go/cmd/ocitool/ocitool_/ocitool bin/ocitool-linux-amd64
# Run all tests
- run: bazel test --config=ci //...
diff --git a/BUILD.bazel b/BUILD.bazel
index 28c5c5e..3fbba4a 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,7 +1,5 @@
-load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
load("@gazelle//:def.bzl", "DEFAULT_LANGUAGES", "gazelle", "gazelle_binary")
load("@npm//:defs.bzl", "npm_link_all_packages")
-load("//oci:toolchain.bzl", "oci_local_toolchain")
# gazelle:prefix github.com/DataDog/rules_oci
# gazelle:go_naming_convention go_default_library
@@ -11,8 +9,9 @@ npm_link_all_packages(
name = "node_modules",
)
-oci_local_toolchain(
- name = "oci_local_toolchain",
+alias(
+ name = "format",
+ actual = "//tools/format",
)
gazelle(
@@ -32,23 +31,6 @@ alias(
actual = "@io_bazel_rules_go//go",
)
-write_source_files(
- name = "bootstrap",
- diff_test = False,
- executable = True,
- files = {
- "bin/ocitool-darwin-amd64": "//go/cmd/ocitool",
- "bin/ocitool-darwin-arm64": "//go/cmd/ocitool",
- "bin/ocitool-linux-amd64": "//go/cmd/ocitool",
- "bin/ocitool-linux-arm64": "//go/cmd/ocitool",
- },
-)
-
-alias(
- name = "format",
- actual = "//tools/format",
-)
-
exports_files(
["WORKSPACE"],
visibility = ["//visibility:public"],
diff --git a/MODULE.bazel b/MODULE.bazel
index aaab418..97196af 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -29,7 +29,6 @@ use_repo(
go_deps,
"com_github_blakesmith_ar",
"com_github_containerd_containerd",
- "com_github_containerd_log",
"com_github_docker_docker_credential_helpers",
"com_github_mitchellh_go_homedir",
"com_github_opencontainers_go_digest",
@@ -38,7 +37,6 @@ use_repo(
"com_github_stretchr_testify",
"com_github_urfave_cli_v2",
"land_oras_oras_go",
- "org_golang_x_sync",
)
go_deps.module_override(
patch_strip = 1,
@@ -54,14 +52,10 @@ oci_pull(
name = "ubuntu_noble",
# "noble" tag as of 2024-12-30
digest = "sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab",
- registry = "mirror.gcr.io",
+ registry = "docker.io",
repository = "library/ubuntu",
)
-register_toolchains(
- "@com_github_datadog_rules_oci//:oci_local_toolchain",
-)
-
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node", dev_dependency = True)
node.toolchain(node_version = "16.14.2")
diff --git a/README.md b/README.md
index 78c2d24..76ae584 100644
--- a/README.md
+++ b/README.md
@@ -94,20 +94,14 @@ base images.
### Developing
-#### Updating dependencies
+#### Run the tests
-Run `bzl run //:go -- get DEPENDENCY`
+Run `bazel test //...`
-#### Tests
+#### Update the docs
-Run the tests using
+Run `bzl run //docs:update`
-```
-bazel run //:bootstrap
-bazel test //...
-```
+#### Update go dependencies
-You will also need to make it possible for docker to access `ghcr.io` (see the code in
-[.github/workflows/main.yaml](.github/workflows/main.yaml) for what we do in CI; an equivalent
-method for local build using the [gh CLI](https://github.com/cli/cli) can be found
-[here](https://gist.github.com/mislav/e154d707db230dc882d7194ec85d79f6)).
+Run `bzl run //:go -- get DEPENDENCY`
diff --git a/bin/BUILD.bazel b/bin/BUILD.bazel
deleted file mode 100755
index 3e3abb4..0000000
--- a/bin/BUILD.bazel
+++ /dev/null
@@ -1,16 +0,0 @@
-load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
-load("//oci:toolchain.bzl", "create_compiled_oci_toolchains")
-
-exports_files(glob(["*"]))
-
-create_compiled_oci_toolchains(name = "oci_toolchain")
-
-pkg_files(
- name = "files",
- srcs = glob([
- "*.bzl",
- "*.bazel",
- ]),
- prefix = "bin",
- visibility = ["//release:__subpackages__"],
-)
diff --git a/docs/defs.md b/docs/defs.md
index 899e83c..93076f9 100644
--- a/docs/defs.md
+++ b/docs/defs.md
@@ -50,31 +50,6 @@ oci_image_index(name, manifests | - | List of labels | optional | `[]` |
-
-
-## oci_image_layout
-
-
-oci_image_layout(name, manifest)
-
-
-Writes an OCI Image Index and related blobs to an OCI Image Format
-directory. See https://github.com/opencontainers/image-spec/blob/main/image-layout.md
-for the specification of the OCI Image Format directory.
-
-All blobs must be provided in the manifest's OCILayout provider, in the
-files attribute. If blobs are missing, creation of the OCI Image Layout
-will fail.
-
-**ATTRIBUTES**
-
-
-| Name | Description | Type | Mandatory | Default |
-| :------------- | :------------- | :------------- | :------------- | :------------- |
-| name | A unique name for this target. | Name | required | |
-| manifest | An OCILayout index to be written to the OCI Image Format directory. | Label | optional | `None` |
-
-
## oci_push
@@ -123,3 +98,60 @@ oci_image_layer
| kwargs | Additional arguments to pass to the rule, e.g. `tags` or `visibility` | none |
+
+
+## oci_image_layout
+
+
+oci_image_layout(name, image_index, gzip, kwargs)
+
+
+Creates targets for an OCI Image Layout directory and a tar file
+
+See https://github.com/opencontainers/image-spec/blob/main/image-layout.md
+for the specification of the OCI Image Format directory.
+
+
+**PARAMETERS**
+
+
+| Name | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| name | A unique name for the rule | none |
+| image_index | An oci_image_index label | none |
+| gzip | If true, creates a tar.gz file. If false, creates a tar file | `True` |
+| kwargs | Additional arguments to pass to the underlying rules, e.g. tags or visibility | none |
+
+
+
+
+## oci_pull
+
+
+oci_pull(name, debug, digest, registry, repo_mapping, repository, scheme, shallow)
+
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| name | A unique name for this repository. | Name | required | |
+| debug | Deprecated. Does nothing | Boolean | optional | `False` |
+| digest | The digest or tag of the manifest file | String | required | |
+| registry | Remote registry host to pull from, e.g. `gcr.io` or `index.docker.io` | String | required | |
+| repo_mapping | In `WORKSPACE` context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.
For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).
This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | Dictionary: String -> String | optional | |
+| repository | Image path beneath the registry, e.g. `distroless/static` | String | required | |
+| scheme | scheme portion of the URL for fetching from the registry | String | optional | `"https"` |
+| shallow | Deprecated. Does nothing | Boolean | optional | `False` |
+
+**ENVIRONMENT VARIABLES**
+
+This repository rule depends on the following environment variables:
+* `DOCKER_CONFIG`
+* `REGISTRY_AUTH_FILE`
+* `XDG_RUNTIME_DIR`
+* `HOME`
+* `OCI_ENABLE_OAUTH2_SUPPORT`
+
+
diff --git a/docs/providers.md b/docs/providers.md
index 5ac632e..336c93c 100644
--- a/docs/providers.md
+++ b/docs/providers.md
@@ -26,45 +26,6 @@ OCIDescriptor(file, annotations | String map of aribtrary metadata |
-
-
-## OCIImageIndexManifest
-
-
-OCIImageIndexManifest(manifests, annotations)
-
-
-
-
-**FIELDS**
-
-
-| Name | Description |
-| :------------- | :------------- |
-| manifests | List of descriptors |
-| annotations | String map of arbitrary metadata |
-
-
-
-
-## OCIImageManifest
-
-
-OCIImageManifest(config, layers, annotations)
-
-
-
-
-**FIELDS**
-
-
-| Name | Description |
-| :------------- | :------------- |
-| config | Descriptor that points to a configuration object |
-| layers | List of descriptors |
-| annotations | String map of arbitrary metadata |
-
-
## OCILayout
@@ -106,21 +67,3 @@ Refers to any artifact represented by an OCI-like reference URI
| digest | a file containing the digest of the artifact |
-
-
-## OCISDK
-
-
-OCISDK(ocitool)
-
-
-The OCI SDK
-
-**FIELDS**
-
-
-| Name | Description |
-| :------------- | :------------- |
-| ocitool | - |
-
-
diff --git a/docs/repositories.md b/docs/repositories.md
index 92a0463..b155750 100644
--- a/docs/repositories.md
+++ b/docs/repositories.md
@@ -7,7 +7,7 @@ public repository rules
## oci_pull
-oci_pull(name, debug, digest, registry, repo_mapping, repository, shallow)
+oci_pull(name, debug, digest, registry, repo_mapping, repository, scheme, shallow)
**ATTRIBUTES**
@@ -16,16 +16,21 @@ oci_pull(name, debug,
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| name | A unique name for this repository. | Name | required | |
-| debug | Enable ocitool debug output | Boolean | optional | `False` |
-| digest | - | String | required | |
-| registry | - | String | required | |
+| debug | Deprecated. Does nothing | Boolean | optional | `False` |
+| digest | The digest or tag of the manifest file | String | required | |
+| registry | Remote registry host to pull from, e.g. `gcr.io` or `index.docker.io` | String | required | |
| repo_mapping | In `WORKSPACE` context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.
For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).
This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | Dictionary: String -> String | optional | |
-| repository | - | String | required | |
-| shallow | - | Boolean | optional | `True` |
+| repository | Image path beneath the registry, e.g. `distroless/static` | String | required | |
+| scheme | scheme portion of the URL for fetching from the registry | String | optional | `"https"` |
+| shallow | Deprecated. Does nothing | Boolean | optional | `False` |
**ENVIRONMENT VARIABLES**
This repository rule depends on the following environment variables:
-* `OCI_CACHE_DIR`
+* `DOCKER_CONFIG`
+* `REGISTRY_AUTH_FILE`
+* `XDG_RUNTIME_DIR`
+* `HOME`
+* `OCI_ENABLE_OAUTH2_SUPPORT`
diff --git a/examples/go-multiarch-image/BUILD.bazel b/examples/go-multiarch-image/BUILD.bazel
index c135558..1c69914 100644
--- a/examples/go-multiarch-image/BUILD.bazel
+++ b/examples/go-multiarch-image/BUILD.bazel
@@ -1,20 +1,22 @@
-load("@com_github_datadog_rules_oci//oci:defs.bzl", "oci_push")
+load("@bazel_skylib//rules:write_file.bzl", "write_file")
+load(
+ "@com_github_datadog_rules_oci//oci:defs.bzl",
+ "oci_image",
+ "oci_image_index",
+ "oci_image_layer",
+ "oci_image_layout",
+ "oci_push",
+)
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
load(":go.bzl", "go_multiarch_image")
go_library(
name = "go_default_library",
srcs = ["main.go"],
- importpath = "github.com/DataDog/rules_oci/tests/go-multiarch-image",
+ importpath = "github.com/DataDog/rules_oci/examples/go-multiarch-image",
visibility = ["//visibility:private"],
)
-go_binary(
- name = "multiarch",
- embed = [":go_default_library"],
- visibility = ["//visibility:public"],
-)
-
go_multiarch_image(
name = "image",
archs = [
@@ -32,3 +34,60 @@ oci_push(
registry = "ghcr.io",
repository = "datadog/rules_oci/hello-world",
)
+
+# Add a layer
+
+write_file(
+ name = "hello.txt.write_file",
+ out = "hello.txt",
+ content = ["Hello, World!"],
+)
+
+oci_image_layer(
+ name = "layer-hello.txt",
+ file_map = {
+ ":hello.txt": "/hello.txt",
+ },
+)
+
+_ARCHS = [
+ "amd64",
+ "arm64",
+]
+
+[
+ oci_image(
+ name = "image2.{}".format(arch),
+ arch = arch,
+ base = ":image",
+ layers = [":layer-hello.txt"],
+ os = "linux",
+ )
+ for arch in _ARCHS
+]
+
+oci_image_index(
+ name = "image2",
+ manifests = [
+ ":image2.{}".format(arch)
+ for arch in _ARCHS
+ ],
+)
+
+oci_image_layout(
+ name = "image2.dir",
+ image_index = ":image2",
+)
+
+oci_push(
+ name = "push2",
+ manifest = ":image2",
+ registry = "ghcr.io",
+ repository = "datadog/rules_oci/hello-world2",
+)
+
+go_binary(
+ name = "go-multiarch-image",
+ embed = [":go_default_library"],
+ visibility = ["//visibility:public"],
+)
diff --git a/go.mod b/go.mod
index 05cf73e..b746dab 100644
--- a/go.mod
+++ b/go.mod
@@ -3,10 +3,8 @@ module github.com/DataDog/rules_oci
go 1.22.5
require (
- github.com/bazelbuild/bazel-gazelle v0.38.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/containerd/containerd v1.7.20
- github.com/containerd/log v0.1.0
github.com/docker/docker-credential-helpers v0.8.1
github.com/mitchellh/go-homedir v1.1.0
github.com/opencontainers/go-digest v1.0.0
@@ -14,17 +12,16 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.27.2
- golang.org/x/sync v0.7.0
oras.land/oras-go v1.2.6
)
require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Microsoft/hcsshim v0.12.3 // indirect
- github.com/bazelbuild/buildtools v0.0.0-20240422193413-1429e15ae755 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
+ github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -53,6 +50,7 @@ require (
go.opentelemetry.io/otel v1.26.0 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect
go.opentelemetry.io/otel/trace v1.26.0 // indirect
+ golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect
google.golang.org/grpc v1.63.2 // indirect
diff --git a/go.sum b/go.sum
index 8786bba..a040d29 100644
--- a/go.sum
+++ b/go.sum
@@ -1,17 +1,11 @@
-cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0=
github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/bazelbuild/bazel-gazelle v0.38.0 h1:7SABASdzy94tbvklgX8ThG+1y7ZNl2eFYRVevjOXpgw=
-github.com/bazelbuild/bazel-gazelle v0.38.0/go.mod h1:hspieDFb3FIjjhQV/dZjqq8qiVxsQ4rtRiWNZMihEXg=
-github.com/bazelbuild/buildtools v0.0.0-20240422193413-1429e15ae755 h1:hqhMmuZiSNwCWVHqnpr4DZfIeZ2/aJF7fs207eg7HZo=
-github.com/bazelbuild/buildtools v0.0.0-20240422193413-1429e15ae755/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -22,13 +16,8 @@ github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuP
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
-github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
-github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
-github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
@@ -72,8 +61,6 @@ github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQ
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
-github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@@ -86,26 +73,12 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
-github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
-github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
-github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
-github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -164,7 +137,6 @@ github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQ
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@@ -238,72 +210,35 @@ go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2L
go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
-go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
-golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
-golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
-golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 h1:umK/Ey0QEzurTNlsV3R+MfxHAb78HCEX/IkuR+zH4WQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
-google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
-google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
-google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
-google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
-google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@@ -318,7 +253,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
-honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
oras.land/oras-go v1.2.6 h1:z8cmxQXBU8yZ4mkytWqXfo6tZcamPwjsuxYU81xJ8Lk=
oras.land/oras-go v1.2.6/go.mod h1:OVPc1PegSEe/K8YiLfosrlqlqTN9PUyFvOw5Y9gwrT8=
diff --git a/go/cmd/ocitool/BUILD.bazel b/go/cmd/ocitool/BUILD.bazel
index 85fe824..cb8dce9 100644
--- a/go/cmd/ocitool/BUILD.bazel
+++ b/go/cmd/ocitool/BUILD.bazel
@@ -7,13 +7,11 @@ go_library(
"createlayer_cmd.go",
"desc_helpers.go",
"digest_cmd.go",
- "gen_cmd.go",
"imagelayout_cmd.go",
"index_cmd.go",
"main.go",
"manifest_cmd.go",
"publishrules_cmd.go",
- "pull_cmd.go",
"push_cmd.go",
"pushblob_cmd.go",
],
@@ -29,15 +27,11 @@ go_library(
"@com_github_containerd_containerd//content:go_default_library",
"@com_github_containerd_containerd//images:go_default_library",
"@com_github_containerd_containerd//platforms:go_default_library",
- "@com_github_containerd_log//:go_default_library",
"@com_github_opencontainers_go_digest//:go_default_library",
"@com_github_opencontainers_image_spec//specs-go:go_default_library",
"@com_github_opencontainers_image_spec//specs-go/v1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
- "@gazelle//rule:go_default_library",
- "@land_oras_oras_go//pkg/content:go_default_library",
- "@org_golang_x_sync//semaphore:go_default_library",
],
)
diff --git a/go/cmd/ocitool/gen_cmd.go b/go/cmd/ocitool/gen_cmd.go
deleted file mode 100644
index dc7a7df..0000000
--- a/go/cmd/ocitool/gen_cmd.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package main
-
-import (
- "context"
- "fmt"
- "os"
- "path/filepath"
-
- "github.com/DataDog/rules_oci/go/pkg/ociutil"
-
- "github.com/bazelbuild/bazel-gazelle/rule"
- "github.com/containerd/containerd/images"
- "github.com/opencontainers/go-digest"
- ocispec "github.com/opencontainers/image-spec/specs-go/v1"
- log "github.com/sirupsen/logrus"
- "github.com/urfave/cli/v2"
- orascontent "oras.land/oras-go/pkg/content"
-)
-
-func GenerateBuildFilesCmd(c *cli.Context) error {
- allLocalLayoutsPaths := c.StringSlice("layout")
- if len(allLocalLayoutsPaths) > 1 {
- return fmt.Errorf("too many layouts")
- } else if len(allLocalLayoutsPaths) <= 0 {
- return fmt.Errorf("need at least one layout")
- }
-
- layoutRootPath := allLocalLayoutsPaths[0]
-
- layout, err := orascontent.NewOCI(layoutRootPath)
- if err != nil {
- return err
- }
-
- refs := layout.ListReferences()
- refDescs := make([]ocispec.Descriptor, 0, len(refs))
-
- for _, r := range refs {
- refDescs = append(refDescs, r)
- }
-
- log.Debugf("layout root: %#v", refs)
-
- err = images.Walk(
- context.Background(),
- ociutil.GenerateBuildFilesHandler(images.ChildrenHandler(layout), layoutRootPath, layout),
- refDescs...,
- )
- if err != nil {
- return err
- }
-
- imageTargetDigest := c.String("image-digest")
- if imageTargetDigest != "" {
- err = os.MkdirAll(filepath.Join(layoutRootPath, "image"), 0700)
- if err != nil {
- return err
- }
-
- imageTargetBuildFilePath := filepath.Join(layoutRootPath, "image", "BUILD.bazel")
- imageTargetBuild := rule.EmptyFile(imageTargetBuildFilePath, "")
-
- aliasRule := rule.NewRule("alias", "image")
- aliasRule.SetAttr("actual", dgstToManifestLabel(digest.Digest(imageTargetDigest)))
- aliasRule.SetAttr("visibility", ociutil.PublicVisibility)
- aliasRule.Insert(imageTargetBuild)
-
- err = imageTargetBuild.Save(imageTargetBuildFilePath)
- if err != nil {
- return err
- }
-
- log.Debugf("Created BUILD file in image package")
- }
-
- log.Debugf("Done generating build files")
-
- return nil
-}
-
-// TODO redeclared a couple other places
-func dgstToManifestLabel(dgst digest.Digest) string {
- return fmt.Sprintf("//blobs/%s:%s", dgst.Algorithm().String(), dgstToManifestLabelName(dgst))
-}
-
-func dgstToManifestLabelName(dgst digest.Digest) string {
- return fmt.Sprintf("%v-%v-%v", "manifest", dgst.Algorithm().String(), dgst.Encoded())
-}
diff --git a/go/cmd/ocitool/main.go b/go/cmd/ocitool/main.go
index 21dd325..173104b 100644
--- a/go/cmd/ocitool/main.go
+++ b/go/cmd/ocitool/main.go
@@ -18,27 +18,6 @@ var app = &cli.App{
return nil
},
Commands: []*cli.Command{
- {
- Name: "pull",
- Usage: "Pull an OCI artifact",
- Action: PullCmd,
- Flags: []cli.Flag{
- &cli.BoolFlag{
- Name: "shallow",
- Usage: "Pull only the top level manifests.",
- Value: false,
- },
- },
- },
- {
- Name: "generate-build-files",
- Action: GenerateBuildFilesCmd,
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "image-digest",
- },
- },
- },
{
Name: "create-layer",
Action: CreateLayerCmd,
diff --git a/go/cmd/ocitool/pull_cmd.go b/go/cmd/ocitool/pull_cmd.go
deleted file mode 100644
index 67f97a8..0000000
--- a/go/cmd/ocitool/pull_cmd.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package main
-
-import (
- "golang.org/x/sync/semaphore"
-
- "github.com/DataDog/rules_oci/go/pkg/ociutil"
-
- "github.com/containerd/containerd/images"
- "github.com/containerd/log"
- ocispec "github.com/opencontainers/image-spec/specs-go/v1"
- "github.com/urfave/cli/v2"
- orascontent "oras.land/oras-go/pkg/content"
-)
-
-func PullCmd(c *cli.Context) error {
- ref := c.Args().First()
-
- ctx := log.WithLogger(c.Context, log.G(c.Context).WithField("pull-ref", ref))
-
- resolver := ociutil.DefaultResolver()
-
- name, desc, err := resolver.Resolve(ctx, ref)
- if err != nil {
- return err
- }
-
- if desc.Annotations == nil {
- desc.Annotations = make(map[string]string)
- }
-
- desc.Annotations[ocispec.AnnotationRefName] = name
-
- log.G(ctx).
- WithField("name", name).
- WithField("desc", desc).
- Debug("resolved")
-
- layoutPath := c.StringSlice("layout")[0]
-
- layout, err := orascontent.NewOCI(layoutPath)
- if err != nil {
- return err
- }
-
- remoteFetcher, err := resolver.Fetcher(ctx, name)
- if err != nil {
- return err
- }
-
- provider := ociutil.FetchertoProvider(remoteFetcher)
-
- sem := semaphore.NewWeighted(int64(c.Uint("parallel")))
-
- imagesHandler := images.ChildrenHandler(provider)
- if c.Bool("shallow") {
- imagesHandler = ociutil.ContentTypesFilterHandler(imagesHandler,
- ocispec.MediaTypeImageManifest,
- ocispec.MediaTypeImageIndex,
- ocispec.MediaTypeImageConfig,
- images.MediaTypeDockerSchema2Manifest,
- images.MediaTypeDockerSchema2ManifestList,
- images.MediaTypeDockerSchema2Config,
- )
- }
-
- err = images.Dispatch(ctx, ociutil.CopyContentHandler(imagesHandler, provider, layout), sem, desc)
- if err != nil {
- return err
- }
-
- layout.AddReference(name, desc)
- err = layout.SaveIndex()
- if err != nil {
- return err
- }
-
- return nil
-}
diff --git a/go/pkg/ociutil/BUILD.bazel b/go/pkg/ociutil/BUILD.bazel
index 933946a..1876dc7 100644
--- a/go/pkg/ociutil/BUILD.bazel
+++ b/go/pkg/ociutil/BUILD.bazel
@@ -3,7 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
- "bazel.go",
"desc.go",
"diff.go",
"fetch.go",
@@ -37,7 +36,6 @@ go_library(
"@com_github_opencontainers_go_digest//:go_default_library",
"@com_github_opencontainers_image_spec//specs-go/v1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
- "@gazelle//rule:go_default_library",
"@land_oras_oras_go//pkg/oras:go_default_library",
],
)
diff --git a/go/pkg/ociutil/bazel.go b/go/pkg/ociutil/bazel.go
deleted file mode 100644
index c97543d..0000000
--- a/go/pkg/ociutil/bazel.go
+++ /dev/null
@@ -1,199 +0,0 @@
-package ociutil
-
-import (
- "context"
- "fmt"
- "os"
- "path/filepath"
- "slices"
- "sync"
-
- "github.com/bazelbuild/bazel-gazelle/rule"
- "github.com/containerd/containerd/content"
- "github.com/containerd/containerd/images"
- "github.com/opencontainers/go-digest"
- ocispec "github.com/opencontainers/image-spec/specs-go/v1"
-)
-
-// GenerateBuildFilesHandler generates build files while walking a tree.
-// TODO Ideally, this should actually be a content.WalkFunc, but ocilayout doesn't
-// implement this interface yet
-func GenerateBuildFilesHandler(handler images.HandlerFunc, layoutRoot string, provider content.Provider) images.HandlerFunc {
- blobBuildFiles := make(map[digest.Algorithm]*rule.File)
- var writemx sync.Mutex
-
- // TODO Currently only supporting SHA256
- 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:oci_blob.bzl")
- ldBlob.Add("oci_blob")
-
- 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)
- 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:oci_layout_index.bzl")
- ldLayout.Add("oci_layout_index")
- ldLayout.Insert(layoutBuild, 0)
-
- indexRule := rule.NewRule("oci_layout_index", "layout")
- indexRule.SetAttr("visibility", PublicVisibility)
- indexRule.Insert(layoutBuild)
-
- layoutBuild.Save(filepath.Join(layoutRoot, "BUILD.bazel"))
-
- // It's possible to encounter the same blob multiple times. We record the
- // ones we've already encountered so we don't process them twice.
- // Duplicate rules make bazel sad.
- handledBlobs := make([]string, 0)
-
- return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
- writemx.Lock()
- defer writemx.Unlock()
-
- if slices.Contains(handledBlobs, desc.Digest.String()) {
- // We've already seen this blob; do nothing.
- return handler(ctx, desc)
- }
-
- if !blobExists(layoutRoot, desc.Digest) {
- return nil, images.ErrSkipDesc
- }
-
- algo := desc.Digest.Algorithm()
- f, ok := blobBuildFiles[algo]
- if !ok {
- return nil, fmt.Errorf("no build file for algo '%v'", algo)
- }
-
- // Insert a rule for each blob
- blobRuleFromDescriptor(desc).Insert(f)
-
- // if the manifest is an manifest or index, add an additional rule to
- // complete graph
- switch desc.MediaType {
- case ocispec.MediaTypeImageManifest, images.MediaTypeDockerSchema2Manifest:
- manifest, err := ImageManifestFromProvider(ctx, provider, desc)
- if err != nil {
- return nil, err
- }
-
- imageManifestRule(desc, manifest).Insert(f)
- case ocispec.MediaTypeImageIndex, images.MediaTypeDockerSchema2ManifestList:
- index, err := ImageIndexFromProvider(ctx, provider, desc)
- if err != nil {
- return nil, err
- }
-
- imageIndexManifestRule(desc, index).Insert(f)
- }
-
- // Save all BUILD files
- for algo, bf := range blobBuildFiles {
- err := bf.Save(algoBUILDPath(layoutRoot, algo))
- if err != nil {
- return nil, err
- }
- }
-
- ldLayout.Insert(layoutBuild, 0)
- indexRule.SetAttr("blobs", append(indexRule.AttrStrings("blobs"), dgstToLabel(desc.Digest)))
- err := layoutBuild.Save(filepath.Join(layoutRoot, "BUILD.bazel"))
- if err != nil {
- return nil, err
- }
-
- handledBlobs = append(handledBlobs, desc.Digest.String())
- return handler(ctx, desc)
- }
-}
-
-func blobExists(layoutRoot string, dgst digest.Digest) bool {
- _, err := os.Stat(descToFilePath(layoutRoot, dgst))
- return !os.IsNotExist(err)
-}
-
-func descToFilePath(root string, dgst digest.Digest) string {
- return filepath.Join(root, "blobs", dgst.Algorithm().String(), dgst.Encoded())
-}
-
-func algoBUILDPath(root string, algo digest.Algorithm) string {
- return filepath.Join(root, "blobs", algo.String(), "BUILD.bazel")
-}
-
-func dgstToManifestLabelName(dgst digest.Digest) string {
- return fmt.Sprintf("manifest-%v-%v", dgst.Algorithm().String(), dgst.Encoded())
-}
-
-func dgstToLabelName(dgst digest.Digest) string {
- return fmt.Sprintf("%v-%v", dgst.Algorithm().String(), dgst.Encoded())
-}
-
-func dgstToLabel(dgst digest.Digest) string {
- return fmt.Sprintf("//blobs/%s:%s", dgst.Algorithm().String(), dgstToLabelName(dgst))
-}
-
-func descriptorListToLabels(desc []ocispec.Descriptor) []string {
- layerTargets := make([]string, 0, len(desc))
- for _, desc := range desc {
- layerTargets = append(layerTargets, dgstToLabel(desc.Digest))
- }
-
- return layerTargets
-}
-
-var (
- PublicVisibility = []string{"//visibility:public"}
-)
-
-func blobRuleFromDescriptor(desc ocispec.Descriptor) *rule.Rule {
- r := rule.NewRule("oci_blob", dgstToLabelName(desc.Digest))
- r.SetAttr("file", desc.Digest.Encoded())
- r.SetAttr("digest", desc.Digest.String())
- r.SetAttr("media_type", desc.MediaType)
- r.SetAttr("size", desc.Size)
- r.SetAttr("annotations", desc.Annotations)
- r.SetAttr("urls", desc.URLs)
- r.SetAttr("visibility", PublicVisibility)
-
- return r
-}
-
-func imageManifestRule(desc ocispec.Descriptor, manifest ocispec.Manifest) *rule.Rule {
- r := rule.NewRule("oci_image_manifest", dgstToManifestLabelName(desc.Digest))
-
- r.SetAttr("descriptor", dgstToLabel(desc.Digest))
- r.SetAttr("config", dgstToLabel(manifest.Config.Digest))
- // TODO(griffin) Not handling shallow well
- //r.SetAttr("layers", descriptorListToLabels(manifest.Layers))
- r.SetAttr("annotations", manifest.Annotations)
- r.SetAttr("visibility", PublicVisibility)
- r.SetAttr("layout", "//:layout")
-
- return r
-}
-
-func imageIndexManifestRule(desc ocispec.Descriptor, manifest ocispec.Index) *rule.Rule {
- r := rule.NewRule("oci_image_index_manifest", dgstToManifestLabelName(desc.Digest))
-
- r.SetAttr("descriptor", dgstToLabel(desc.Digest))
- r.SetAttr("manifests", descriptorListToLabels(manifest.Manifests))
- r.SetAttr("annotations", manifest.Annotations)
- r.SetAttr("visibility", PublicVisibility)
- r.SetAttr("layout", "//:layout")
-
- return r
-}
diff --git a/go/pkg/ociutil/fs.go b/go/pkg/ociutil/fs.go
index 6c9f964..12fc50c 100644
--- a/go/pkg/ociutil/fs.go
+++ b/go/pkg/ociutil/fs.go
@@ -4,10 +4,12 @@ import (
"context"
"io"
"io/fs"
+ "path/filepath"
"sync"
"github.com/containerd/containerd/content"
+ "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
@@ -94,3 +96,7 @@ func (f *fsFile) ReadAt(p []byte, off int64) (int, error) {
return n, nil
}
+
+func descToFilePath(root string, dgst digest.Digest) string {
+ return filepath.Join(root, "blobs", dgst.Algorithm().String(), dgst.Encoded())
+}
diff --git a/oci/BUILD.bazel b/oci/BUILD.bazel
index 48cff8a..697f3fa 100644
--- a/oci/BUILD.bazel
+++ b/oci/BUILD.bazel
@@ -9,11 +9,6 @@ exports_files(
visibility = ["//:__subpackages__"],
)
-toolchain_type(
- name = "toolchain",
- visibility = ["//visibility:public"],
-)
-
debug_flag(
name = "debug",
build_setting_default = False,
@@ -22,9 +17,7 @@ debug_flag(
bzl_library(
name = "defs",
- srcs = [
- ":defs.bzl",
- ],
+ srcs = ["defs.bzl"],
visibility = ["//visibility:public"],
deps = [
"//oci:providers.bzl",
@@ -35,26 +28,29 @@ bzl_library(
"//oci/private:oci_image_layer.bzl",
"//oci/private:oci_image_layout.bzl",
"//oci/private:oci_push.bzl",
+ "//oci/private/repositories:authn.bzl",
+ "//oci/private/repositories:download.bzl",
+ "//oci/private/repositories:oci_pull.bzl",
+ "@aspect_bazel_lib//lib:base64",
+ "@aspect_bazel_lib//lib:repo_utils",
"@aspect_bazel_lib//lib:stamping",
+ "@bazel_skylib//lib:paths",
+ "@bazel_skylib//lib:versions",
+ "@rules_pkg//pkg:bzl_srcs",
],
)
-bzl_library(
- name = "providers",
- srcs = [
- ":providers.bzl",
- ],
- visibility = ["//visibility:public"],
-)
-
bzl_library(
name = "repositories",
- srcs = [
- ":repositories.bzl",
- ],
+ srcs = ["repositories.bzl"],
visibility = ["//visibility:public"],
deps = [
+ "//oci/private/repositories:authn.bzl",
+ "//oci/private/repositories:download.bzl",
"//oci/private/repositories:oci_pull.bzl",
+ "@aspect_bazel_lib//lib:base64",
+ "@aspect_bazel_lib//lib:repo_utils",
+ "@bazel_skylib//lib:versions",
],
)
@@ -67,3 +63,15 @@ pkg_files(
prefix = "oci",
visibility = ["//release:__subpackages__"],
)
+
+bzl_library(
+ name = "providers",
+ srcs = ["providers.bzl"],
+ visibility = ["//visibility:public"],
+)
+
+bzl_library(
+ name = "toolchain",
+ srcs = ["toolchain.bzl"],
+ visibility = ["//visibility:public"],
+)
diff --git a/oci/defs.bzl b/oci/defs.bzl
index 0af379d..9c48101 100644
--- a/oci/defs.bzl
+++ b/oci/defs.bzl
@@ -5,9 +5,13 @@ 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:oci_push.bzl", _oci_push = "oci_push")
+load("//oci/private/repositories:oci_pull.bzl", _oci_pull = "oci_pull")
oci_image = _oci_image
oci_image_index = _oci_image_index
oci_image_layer = _oci_image_layer
oci_image_layout = _oci_image_layout
oci_push = _oci_push
+
+# TODO(brian.myers): Remove this (from defs.bzl, not repositories.bzl) once consumers no longer use it
+oci_pull = _oci_pull
diff --git a/oci/private/BUILD.bazel b/oci/private/BUILD.bazel
index bf21dcf..703d0cd 100644
--- a/oci/private/BUILD.bazel
+++ b/oci/private/BUILD.bazel
@@ -1,5 +1,7 @@
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
+# gazelle:lang go
+
exports_files(
glob(["*.bzl"]),
visibility = ["//oci:__subpackages__"],
diff --git a/oci/private/oci_image.bzl b/oci/private/oci_image.bzl
index 4a51013..848bd50 100644
--- a/oci/private/oci_image.bzl
+++ b/oci/private/oci_image.bzl
@@ -4,8 +4,6 @@ load("//oci:providers.bzl", "OCIDescriptor", "OCILayout")
load(":common.bzl", "get_descriptor_file")
def _impl(ctx):
- toolchain = ctx.toolchains["//oci:toolchain"]
-
base_desc = get_descriptor_file(ctx, ctx.attr.base[OCIDescriptor])
base_layout = ctx.attr.base[OCILayout]
@@ -37,7 +35,7 @@ def _impl(ctx):
)
ctx.actions.run(
- executable = toolchain.sdk.ocitool,
+ executable = ctx.executable._ocitool,
arguments = [
"--layout={}".format(base_layout.blob_index.path),
"append-layers",
@@ -143,6 +141,11 @@ oci_image = rule(
will cause that label to be deleted. For backwards compatibility, if this is not set,
then the value of annotations will be used instead.""",
),
+ "_ocitool": attr.label(
+ allow_single_file = True,
+ cfg = "exec",
+ default = "//go/cmd/ocitool",
+ executable = True,
+ ),
},
- toolchains = ["//oci:toolchain"],
)
diff --git a/oci/private/oci_image_index.bzl b/oci/private/oci_image_index.bzl
index 1faef60..e6bdd66 100644
--- a/oci/private/oci_image_index.bzl
+++ b/oci/private/oci_image_index.bzl
@@ -4,8 +4,6 @@ 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))
@@ -23,7 +21,7 @@ def _impl(ctx):
]
ctx.actions.run(
- executable = toolchain.sdk.ocitool,
+ executable = ctx.executable._ocitool,
arguments = ["--layout={}".format(m[OCILayout].blob_index.path) for m in ctx.attr.manifests] +
[
"create-index",
@@ -63,6 +61,11 @@ oci_image_index = rule(
doc = """
""",
),
+ "_ocitool": attr.label(
+ allow_single_file = True,
+ cfg = "exec",
+ default = "//go/cmd/ocitool",
+ executable = True,
+ ),
},
- toolchains = ["//oci:toolchain"],
)
diff --git a/oci/private/oci_image_layer.bzl b/oci/private/oci_image_layer.bzl
index 28cab58..42beaa4 100644
--- a/oci/private/oci_image_layer.bzl
+++ b/oci/private/oci_image_layer.bzl
@@ -38,12 +38,10 @@ def oci_image_layer(
)
def _impl(ctx):
- toolchain = ctx.toolchains["//oci:toolchain"]
-
descriptor_file = ctx.actions.declare_file("{}.descriptor.json".format(ctx.label.name))
ctx.actions.run(
- executable = toolchain.sdk.ocitool,
+ executable = ctx.executable._ocitool,
arguments = [
"create-layer",
"--out={}".format(ctx.outputs.layer.path),
@@ -78,8 +76,13 @@ _oci_image_layer = rule(
"directory": attr.string(),
"symlinks": attr.string_dict(),
"file_map": attr.label_keyed_string_dict(allow_files = True),
+ "_ocitool": attr.label(
+ allow_single_file = True,
+ cfg = "exec",
+ default = "//go/cmd/ocitool",
+ executable = True,
+ ),
},
- toolchains = ["//oci:toolchain"],
outputs = {
"layer": "%{name}-layer.tar.gz",
},
diff --git a/oci/private/oci_image_layout.bzl b/oci/private/oci_image_layout.bzl
index d8fc0ef..62a9648 100644
--- a/oci/private/oci_image_layout.bzl
+++ b/oci/private/oci_image_layout.bzl
@@ -1,21 +1,76 @@
"""A rule to create a directory in OCI Image Layout format."""
+load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
+load("@rules_pkg//pkg:pkg.bzl", "pkg_tar")
load("//oci:providers.bzl", "OCIDescriptor", "OCILayout")
load(":debug_flag.bzl", "DebugInfo")
-def _oci_image_layout_impl(ctx):
- toolchain = ctx.toolchains["//oci:toolchain"]
+def oci_image_layout(
+ *,
+ name,
+ image_index,
+ gzip = True,
+ **kwargs):
+ """Creates targets for an OCI Image Layout directory and a tar file
- layout = ctx.attr.manifest[OCILayout]
+ See https://github.com/opencontainers/image-spec/blob/main/image-layout.md
+ for the specification of the OCI Image Format directory.
+
+ Args:
+ name: A unique name for the rule
+ image_index: An oci_image_index label
+ gzip: If true, creates a tar.gz file. If false, creates a tar file
+ **kwargs: Additional arguments to pass to the underlying rules, e.g.
+ tags or visibility
+ """
+ _oci_image_layout(
+ name = name,
+ image_index = image_index,
+ **kwargs
+ )
+
+ kwargs_copy = dict(kwargs)
+ kwargs_copy.pop("visibility", None)
+ pkg_files(
+ name = "{}.pkg_files".format(name),
+ srcs = [":{}".format(name)],
+ strip_prefix = ".",
+ renames = {
+ ":{}".format(name): "./",
+ },
+ visibility = ["//visibility:private"],
+ **kwargs_copy
+ )
+
+ if gzip:
+ pkg_tar(
+ name = "{}.tar".format(name),
+ extension = "tar.gz",
+ srcs = ["{}.pkg_files".format(name)],
+ package_file_name = "{}.tar.gz".format(name),
+ strip_prefix = ".",
+ **kwargs
+ )
+ else:
+ pkg_tar(
+ name = "{}.tar".format(name),
+ srcs = ["{}.pkg_files".format(name)],
+ package_file_name = "{}.tar".format(name),
+ strip_prefix = ".",
+ **kwargs
+ )
+
+def _impl(ctx):
+ layout = ctx.attr.image_index[OCILayout]
# layout_files contains all available blobs for the image.
layout_files = ",".join([p.path for p in layout.files.to_list()])
- descriptor = ctx.attr.manifest[OCIDescriptor]
+ descriptor = ctx.attr.image_index[OCIDescriptor]
out_dir = ctx.actions.declare_directory(ctx.label.name)
ctx.actions.run(
- executable = toolchain.sdk.ocitool,
+ executable = ctx.executable._ocitool,
arguments = [
"--layout={layout}".format(layout = layout.blob_index.path),
"--debug={debug}".format(debug = str(ctx.attr._debug[DebugInfo].debug)),
@@ -31,44 +86,30 @@ def _oci_image_layout_impl(ctx):
"--layout-files={layout_files}".format(layout_files = layout_files),
"--out-dir={out_dir}".format(out_dir = out_dir.path),
],
- inputs =
- depset(
- direct = ctx.files.manifest + [layout.blob_index],
- transitive = [layout.files],
- ),
- outputs = [
- out_dir,
- ],
- use_default_shell_env = True,
+ inputs = depset(
+ direct = ctx.files.image_index + [layout.blob_index],
+ transitive = [layout.files],
+ ),
+ outputs = [out_dir],
)
- return DefaultInfo(files = depset([out_dir]))
-
-oci_image_layout = rule(
- doc = """
- Writes an OCI Image Index and related blobs to an OCI Image Format
- directory. See https://github.com/opencontainers/image-spec/blob/main/image-layout.md
- for the specification of the OCI Image Format directory.
+ return [
+ DefaultInfo(files = depset([out_dir])),
+ ]
- All blobs must be provided in the manifest's OCILayout provider, in the
- files attribute. If blobs are missing, creation of the OCI Image Layout
- will fail.
- """,
- implementation = _oci_image_layout_impl,
+_oci_image_layout = rule(
+ implementation = _impl,
attrs = {
- "manifest": attr.label(
- doc = """
- An OCILayout index to be written to the OCI Image Format directory.
- """,
- providers = [OCILayout],
- ),
+ "image_index": attr.label(providers = [OCILayout]),
"_debug": attr.label(
default = "//oci:debug",
providers = [DebugInfo],
),
+ "_ocitool": attr.label(
+ allow_single_file = True,
+ cfg = "exec",
+ default = "//go/cmd/ocitool",
+ executable = True,
+ ),
},
- provides = [
- DefaultInfo,
- ],
- toolchains = ["//oci:toolchain"],
)
diff --git a/oci/private/oci_push.bzl b/oci/private/oci_push.bzl
index 8940610..c57f1df 100644
--- a/oci/private/oci_push.bzl
+++ b/oci/private/oci_push.bzl
@@ -5,8 +5,6 @@ load("//oci:providers.bzl", "OCIDescriptor", "OCILayout", "OCIReferenceInfo")
load(":debug_flag.bzl", "DebugInfo")
def _impl(ctx):
- toolchain = ctx.toolchains["//oci:toolchain"]
-
layout = ctx.attr.manifest[OCILayout]
ref = "{registry}/{repository}".format(
@@ -65,7 +63,7 @@ done
digest_file = ctx.actions.declare_file("{name}.digest".format(name = ctx.label.name))
ctx.actions.run(
- executable = toolchain.sdk.ocitool,
+ executable = ctx.executable._ocitool,
arguments = [
"digest",
"--desc={desc}".format(desc = ctx.attr.manifest[OCIDescriptor].descriptor_file.path),
@@ -104,7 +102,7 @@ done
export OCI_REFERENCE={ref}@$(cat {digest})
""".format(
root = ctx.bin_dir.path,
- tool = toolchain.sdk.ocitool.short_path,
+ tool = ctx.executable._ocitool.short_path,
layout = layout.blob_index.short_path,
desc = ctx.attr.manifest[OCIDescriptor].descriptor_file.short_path,
ref = ref,
@@ -122,7 +120,13 @@ done
DefaultInfo(
runfiles = ctx.runfiles(
files = layout.files.to_list() +
- [toolchain.sdk.ocitool, ctx.attr.manifest[OCIDescriptor].descriptor_file, layout.blob_index, digest_file, tag_file],
+ [
+ ctx.executable._ocitool,
+ ctx.attr.manifest[OCIDescriptor].descriptor_file,
+ layout.blob_index,
+ digest_file,
+ tag_file,
+ ],
),
),
OCIReferenceInfo(
@@ -198,9 +202,14 @@ oci_push = rule(
default = "//oci:debug",
providers = [DebugInfo],
),
+ "_ocitool": attr.label(
+ allow_single_file = True,
+ cfg = "exec",
+ default = "//go/cmd/ocitool",
+ executable = True,
+ ),
}, **STAMP_ATTRS),
provides = [
OCIReferenceInfo,
],
- toolchains = ["//oci:toolchain"],
)
diff --git a/oci/private/repositories/authn.bzl b/oci/private/repositories/authn.bzl
new file mode 100644
index 0000000..2d4ae35
--- /dev/null
+++ b/oci/private/repositories/authn.bzl
@@ -0,0 +1,352 @@
+# Copied from https://github.com/bazel-contrib/rules_oci/blob/843eb01b152b884fe731a3fb4431b738ad00ea60/oci/private/authn.bzl
+# which is licensed under the Apache License, Version 2.0.
+#
+# Then slightly modified to fit the needs of this project
+
+"repository rule that locates the .docker/config.json or containers/auth.json file."
+
+load("@aspect_bazel_lib//lib:base64.bzl", "base64")
+load("@aspect_bazel_lib//lib:repo_utils.bzl", "repo_utils")
+
+# Unfortunately bazel downloader doesn't let us sniff the WWW-Authenticate header, therefore we need to
+# keep a map of known registries that require us to acquire a temporary token for authentication.
+_WWW_AUTH = {
+ "index.docker.io": {
+ "realm": "auth.docker.io/token",
+ "scope": "repository:{repository}:pull",
+ "service": "registry.docker.io",
+ },
+ "public.ecr.aws": {
+ "realm": "{registry}/token",
+ "scope": "repository:{repository}:pull",
+ "service": "{registry}",
+ },
+ "ghcr.io": {
+ "realm": "{registry}/token",
+ "scope": "repository:{repository}:pull",
+ "service": "{registry}/token",
+ },
+ "cgr.dev": {
+ "realm": "{registry}/token",
+ "scope": "repository:{repository}:pull",
+ "service": "{registry}",
+ },
+ ".azurecr.io": {
+ "realm": "{registry}/oauth2/token",
+ "scope": "repository:{repository}:pull",
+ "service": "{registry}",
+ },
+ "registry.gitlab.com": {
+ "realm": "gitlab.com/jwt/auth",
+ "scope": "repository:{repository}:pull",
+ "service": "container_registry",
+ },
+ ".app.snowflake.com": {
+ "realm": "{registry}/v2/token",
+ "scope": "repository:{repository}:pull",
+ "service": "{registry}",
+ },
+ "docker.elastic.co": {
+ "realm": "docker-auth.elastic.co/auth",
+ "scope": "repository:{repository}:pull",
+ "service": "token-service",
+ },
+ "quay.io": {
+ "realm": "{registry}/v2/auth",
+ "scope": "repository:{repository}:pull",
+ "service": "{registry}",
+ },
+ "nvcr.io": {
+ "realm": "{registry}/proxy_auth",
+ "scope": "repository:{repository}:pull",
+ "service": "{registry}",
+ },
+ "registry.ddbuild.io": {
+ "realm": "registry-auth.ddbuild.io/token",
+ "scope": "repository:{repository}:pull",
+ "service": "registry.ddbuild.io",
+ },
+}
+
+def _strip_host(url):
+ # TODO: a principled way of doing this
+ return url.replace("http://", "").replace("https://", "").replace("/v1/", "")
+
+# Path of the auth file is determined by the order described here;
+# https://github.com/google/go-containerregistry/tree/main/pkg/authn#tldr-for-consumers-of-this-package
+def _get_auth_file_path(rctx):
+ HOME = repo_utils.get_env_var(rctx, "HOME", "ERR_NO_HOME_SET")
+
+ # this is the standard path where registry credentials are stored
+ # https://docs.docker.com/engine/reference/commandline/cli/#configuration-files
+ DOCKER_CONFIG = "{}/.docker".format(HOME)
+
+ # set DOCKER_CONFIG to $DOCKER_CONFIG env if present
+ if "DOCKER_CONFIG" in rctx.os.environ:
+ DOCKER_CONFIG = rctx.os.environ["DOCKER_CONFIG"]
+
+ config_path = "{}/config.json".format(DOCKER_CONFIG)
+
+ if _file_exists(rctx, config_path):
+ return config_path
+
+ # https://docs.podman.io/en/latest/markdown/podman-login.1.html#authfile-path
+ XDG_RUNTIME_DIR = "{}/.config".format(HOME)
+
+ # set XDG_RUNTIME_DIR to $XDG_RUNTIME_DIR env if present
+ if "XDG_RUNTIME_DIR" in rctx.os.environ:
+ XDG_RUNTIME_DIR = rctx.os.environ["XDG_RUNTIME_DIR"]
+
+ config_path = "{}/containers/auth.json".format(XDG_RUNTIME_DIR)
+
+ # podman support overriding the standard path for the auth file via this special environment variable.
+ # https://docs.podman.io/en/latest/markdown/podman-login.1.html#authfile-path
+ if "REGISTRY_AUTH_FILE" in rctx.os.environ:
+ config_path = rctx.os.environ["REGISTRY_AUTH_FILE"]
+
+ if _file_exists(rctx, config_path):
+ return config_path
+
+ return None
+
+def _fetch_auth_via_creds_helper(rctx, raw_host, helper_name, allow_fail = False):
+ executable = "{}.sh".format(helper_name)
+ rctx.file(
+ executable,
+ content = """\
+#!/usr/bin/env bash
+exec "docker-credential-{}" get <<< "$1" """.format(helper_name),
+ )
+ result = rctx.execute([rctx.path(executable), raw_host])
+ rctx.delete(rctx.path(executable))
+ if result.return_code:
+ if not allow_fail:
+ fail("credential helper failed: \nSTDOUT:\n{}\nSTDERR:\n{}".format(result.stdout, result.stderr))
+ else:
+ return {}
+
+ response = json.decode(result.stdout)
+
+ return {
+ "type": "basic",
+ "login": response["Username"],
+ "password": response["Secret"],
+ }
+
+OAUTH_2_SCRIPT_CURL = """\
+url=$1
+service=$2
+scope=$3
+refresh_token=$4
+
+response=$(curl --silent --show-error --fail --request POST --data "grant_type=refresh_token&service=$service&scope=$scope&refresh_token=$refresh_token" $url)
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+echo "$response"
+"""
+
+OAUTH_2_SCRIPT_WGET = """\
+url=$1
+service=$2
+scope=$3
+refresh_token=$4
+
+response=$(wget --quiet --output-document=- --post-data "grant_type=refresh_token&service=$service&scope=$scope&refresh_token=$refresh_token" $url)
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+echo "$response"
+"""
+
+def _oauth2(rctx, realm, scope, service, secret):
+ if rctx.which("curl"):
+ executable = "oauth2.sh"
+ rctx.file(executable, content = OAUTH_2_SCRIPT_CURL)
+ result = rctx.execute(["bash", rctx.path(executable), realm, service, scope, secret])
+ elif rctx.which("wget"):
+ executable = "oauth2.sh"
+ rctx.file(executable, content = OAUTH_2_SCRIPT_WGET)
+ result = rctx.execute(["bash", rctx.path(executable), realm, service, scope, secret])
+ else:
+ fail("oauth2 failed, could not find either of: curl, wget, powershell")
+
+ if result.return_code:
+ fail("oauth2 failed:\nSTDOUT:\n{}\nSTDERR:\n{}".format(result.stdout, result.stderr))
+ return result.stdout
+
+def _get_auth(rctx, state, registry):
+ # if we have a cached auth for this registry then just return it.
+ # this will prevent repetitive calls to external cred helper binaries.
+ if registry in state["auth"]:
+ return state["auth"][registry]
+
+ pattern = {}
+ config = state["config"]
+
+ # first look into per registry credHelpers if it exists
+ if "credHelpers" in config:
+ for host_raw in config["credHelpers"]:
+ host = _strip_host(host_raw)
+ if host == registry:
+ helper_val = config["credHelpers"][host_raw]
+ pattern = _fetch_auth_via_creds_helper(rctx, host_raw, helper_val)
+
+ # if no match for per registry credential helper for the host then look into auths dictionary
+ if "auths" in config and len(pattern.keys()) == 0:
+ for host_raw in config["auths"]:
+ host = _strip_host(host_raw)
+ if host == registry:
+ auth_val = config["auths"][host_raw]
+
+ if len(auth_val.keys()) == 0:
+ # zero keys indicates that credentials are stored in credsStore helper.
+ pattern = _fetch_auth_via_creds_helper(rctx, host_raw, config["credsStore"])
+
+ elif "auth" in auth_val:
+ # base64 encoded plaintext username and password
+ raw_auth = auth_val["auth"]
+ login, sep, password = base64.decode(raw_auth).partition(":")
+ if not sep:
+ fail("auth string must be in form username:password")
+ if not password and "identitytoken" in auth_val:
+ password = auth_val["identitytoken"]
+ pattern = {
+ "type": "basic",
+ "login": login,
+ "password": password,
+ }
+
+ elif "username" in auth_val and "password" in auth_val:
+ # plain text username and password
+ pattern = {
+ "type": "basic",
+ "login": auth_val["username"],
+ "password": auth_val["password"],
+ }
+
+ # look for generic credentials-store all lookups for host-specific auth fails
+ if "credsStore" in config and len(pattern.keys()) == 0:
+ pattern = _fetch_auth_via_creds_helper(rctx, registry, config["credsStore"], allow_fail = True)
+
+ # cache the result so that we don't do this again unnecessarily.
+ state["auth"][registry] = pattern
+
+ return pattern
+
+IDENTITY_TOKEN_WARNING = """\
+OAuth2 support for oci_pull is highly experimental and is not enabled by default.
+
+We may change or abandon it without a notice. Use it at your own peril!
+
+To enable this feature, add `common --repo_env=OCI_ENABLE_OAUTH2_SUPPORT=1` to the `.bazelrc` file.
+"""
+
+def _get_token(rctx, state, registry, repository):
+ pattern = _get_auth(rctx, state, registry)
+
+ for registry_pattern in _WWW_AUTH.keys():
+ if (registry == registry_pattern) or registry.endswith(registry_pattern):
+ www_authenticate = _WWW_AUTH[registry_pattern]
+ url = "https://{realm}?scope={scope}&service={service}".format(
+ realm = www_authenticate["realm"].format(registry = registry),
+ service = www_authenticate["service"].format(registry = registry),
+ scope = www_authenticate["scope"].format(repository = repository),
+ )
+
+ # if a token for this repository and registry is acquired, use that instead.
+ if url in state["token"]:
+ return state["token"][url]
+
+ auth = None
+ if pattern.get("login", None) == "":
+ if not rctx.os.environ.get("OCI_ENABLE_OAUTH2_SUPPORT"):
+ fail(IDENTITY_TOKEN_WARNING)
+
+ response = _oauth2(
+ rctx = rctx,
+ realm = "https://" + www_authenticate["realm"].format(registry = registry),
+ scope = www_authenticate["scope"].format(repository = repository),
+ service = www_authenticate["service"].format(registry = registry),
+ secret = pattern["password"],
+ )
+
+ rctx.file(
+ "www-authenticate.json",
+ content = response,
+ executable = False,
+ )
+ else:
+ rctx.download(
+ url = [url],
+ output = "www-authenticate.json",
+ # optionally, sending the credentials to authenticate using the credentials.
+ # this is for fetching from private repositories that require WWW-Authenticate
+ auth = {url: pattern},
+ )
+
+ auth_raw = rctx.read("www-authenticate.json")
+ auth = json.decode(auth_raw)
+
+ token = ""
+ if "token" in auth:
+ token = auth["token"]
+ if "access_token" in auth:
+ token = auth["access_token"]
+ if token == "":
+ fail("could not find token in neither field 'token' nor 'access_token' in the response from the registry")
+ pattern = {
+ "type": "pattern",
+ "pattern": "Bearer ",
+ "password": token,
+ }
+
+ # put the token into cache so that we don't do the token exchange again.
+ state["token"][url] = pattern
+ return pattern
+
+NO_CONFIG_FOUND_ERROR = """\
+Could not find the `$HOME/.docker/config.json` and `$XDG_RUNTIME_DIR/containers/auth.json` file
+
+Running one of `podman login`, `docker login`, `crane login` may help.
+"""
+
+def _explain(state):
+ if not state["config"]:
+ return NO_CONFIG_FOUND_ERROR
+ return None
+
+def _new_auth(rctx, config_path = None):
+ if not config_path:
+ config_path = _get_auth_file_path(rctx)
+ config = {}
+ if config_path:
+ config = json.decode(rctx.read(config_path))
+ state = {
+ "config": config,
+ "auth": {},
+ "token": {},
+ }
+ return struct(
+ get_token = lambda reg, repo: _get_token(rctx, state, reg, repo),
+ explain = lambda: _explain(state),
+ )
+
+authn = struct(
+ new = _new_auth,
+ ENVIRON = [
+ "DOCKER_CONFIG",
+ "REGISTRY_AUTH_FILE",
+ "XDG_RUNTIME_DIR",
+ "HOME",
+ "OCI_ENABLE_OAUTH2_SUPPORT",
+ ],
+)
+
+def _file_exists(rctx, path):
+ result = rctx.execute(["stat", path])
+ return result.return_code == 0
diff --git a/oci/private/repositories/download.bzl b/oci/private/repositories/download.bzl
new file mode 100644
index 0000000..24bbdc8
--- /dev/null
+++ b/oci/private/repositories/download.bzl
@@ -0,0 +1,146 @@
+""" download utilities """
+
+load("@bazel_skylib//lib:versions.bzl", "versions")
+
+MEDIA_TYPE_DOCKER_INDEX = "application/vnd.docker.distribution.manifest.list.v2+json"
+MEDIA_TYPE_DOCKER_MANIFEST = "application/vnd.docker.distribution.manifest.v2+json"
+MEDIA_TYPE_OCI_INDEX = "application/vnd.oci.image.index.v1+json"
+MEDIA_TYPE_OCI_MANIFEST = "application/vnd.oci.image.manifest.v1+json"
+
+_RESOURCE_BLOB = "blobs"
+_RESOURCE_INDEX_OR_MANIFEST = "manifests"
+
+def download_blob(
+ rctx,
+ *,
+ authn, # authn object
+ digest, # str
+ non_blocking = None): # list[PendingDownload] | None
+ # -> struct(path: str, sha256: str) | None
+ """Download a blob by digest and write it to the blobs/sha256 directory
+
+ Args:
+ rctx: The repository context
+ authn: An authn object
+ digest: The digest of the blob to download
+ non_blocking:
+ - If you want the download to block, set this to None (the default)
+ - If you want the download to be non-blocking, pass a list here.
+ This is an outparam. The function will append a PendingDownload
+ object to this list. Later, you can call .wait() on that object
+ to block until the download is complete
+ """
+ sha256 = digest[len("sha256:"):]
+ return _download(
+ rctx,
+ authn = authn,
+ digest = digest,
+ outpath = rctx.path("blobs/sha256/{}".format(sha256)),
+ resource = _RESOURCE_BLOB,
+ non_blocking = non_blocking,
+ )
+
+def download_index_or_manifest(
+ rctx,
+ *,
+ authn,
+ digest, # str
+ outpath, # str
+ non_blocking = None): # list[PendingDownload] | None
+ # -> struct(path: str, sha256: str) | None
+ """Download an index or manifest by digest
+
+ Args:
+ rctx: The repository context
+ authn: An authn object
+ digest: The digest of the blob to download
+ outpath: The path to write the downloaded index or manifest to
+ non_blocking:
+ - If you want the download to block, set this to None (the default)
+ - If you want the download to be non-blocking, pass a list here.
+ This is an outparam. The function will append a PendingDownload
+ object to this list. Later, you can call .wait() on that object
+ to block until the download is complete
+ """
+ return _download(
+ rctx,
+ authn = authn,
+ digest = digest,
+ outpath = rctx.path(outpath),
+ resource = _RESOURCE_INDEX_OR_MANIFEST,
+ non_blocking = non_blocking,
+ )
+
+def _download(
+ rctx,
+ *,
+ authn,
+ digest, # str
+ outpath, # str
+ resource, # str
+ non_blocking = None): # list[result] | None
+ # -> struct(path: str, sha256: str) | None
+
+ non_blocking_type = type(non_blocking)
+ if non_blocking_type == type([]):
+ block = False
+ elif non_blocking_type == type(None):
+ block = True
+ else:
+ fail("Wrong type for non_blocking parameter. Got {non_blocking_type}. Expected a list or None")
+ if not digest.startswith("sha256:"):
+ fail("Invalid value for digest parameter. Must start with 'sha256:'")
+
+ auth = authn.get_token(rctx.attr.registry, rctx.attr.repository)
+
+ sha256 = digest[len("sha256:"):]
+
+ url = "{scheme}://{registry}/v2/{repository}/{resource}/{digest}".format(
+ scheme = rctx.attr.scheme,
+ registry = rctx.attr.registry,
+ repository = rctx.attr.repository,
+ resource = resource,
+ digest = digest,
+ )
+
+ is_gt_bazel_7_1 = versions.is_at_least("7.1.0", versions.get())
+
+ # On Bazel 7.1.0 and later, use non-blocking download (if requested) and forward headers
+ extra_args = {}
+ if is_gt_bazel_7_1:
+ extra_args["block"] = block
+ extra_args["headers"] = {
+ "Accept": ",".join([
+ MEDIA_TYPE_DOCKER_INDEX,
+ MEDIA_TYPE_DOCKER_MANIFEST,
+ MEDIA_TYPE_OCI_INDEX,
+ MEDIA_TYPE_OCI_MANIFEST,
+ ]),
+ "Docker-Distribution-API-Version": "registry/2.0",
+ }
+
+ res = rctx.download(
+ auth = {url: auth},
+ output = outpath,
+ sha256 = sha256,
+ url = url,
+ **extra_args
+ )
+
+ if is_gt_bazel_7_1 and not block:
+ non_blocking.append(res)
+ return None
+
+ if not res.success:
+ fail(
+ "Failed to download OCI object with digest {}\nStdout: {}\nStderr: {}".format(
+ digest,
+ res.stdout.strip(),
+ res.stderr.strip(),
+ ),
+ )
+
+ return struct(
+ path = outpath,
+ sha256 = sha256,
+ )
diff --git a/oci/private/repositories/oci_blob.bzl b/oci/private/repositories/oci_blob.bzl
deleted file mode 100644
index 314ea03..0000000
--- a/oci/private/repositories/oci_blob.bzl
+++ /dev/null
@@ -1,56 +0,0 @@
-""" oci_blob """
-
-load("@com_github_datadog_rules_oci//oci:providers.bzl", "OCIDescriptor")
-
-def _impl(ctx):
- return [OCIDescriptor(
- file = ctx.file.file,
- media_type = ctx.attr.media_type,
- size = ctx.attr.size,
- urls = ctx.attr.urls,
- digest = ctx.attr.digest,
- annotations = ctx.attr.annotations,
- )]
-
-oci_blob = rule(
- 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.
- """,
- provides = [OCIDescriptor],
- attrs = {
- "file": attr.label(
- doc = """
-The blob stored as a file on disk.
- """,
- allow_single_file = True,
- ),
- "digest": attr.string(
- doc = """
-A digest of the contents of the file, in the format '$ALGO:%HASH_IN_HEX', for
-example 'sha256:abcd...'
- """,
- ),
- "media_type": attr.string(
- doc = """
-MIME type of blob.
- """,
- ),
- "size": attr.int(
- doc = """
-Size of content in bytes.
- """,
- ),
- "urls": attr.string_list(
- doc = """
-A list of URLs from which this object MAY be downloaded.
- """,
- ),
- "annotations": attr.string_dict(
- doc = """
-A map of arbitrary metadata relating to the targeted content.
- """,
- ),
- },
-)
diff --git a/oci/private/repositories/oci_image_index_manifest.bzl b/oci/private/repositories/oci_image_index_manifest.bzl
deleted file mode 100644
index e0689a2..0000000
--- a/oci/private/repositories/oci_image_index_manifest.bzl
+++ /dev/null
@@ -1,30 +0,0 @@
-""" 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/oci_image_manifest.bzl b/oci/private/repositories/oci_image_manifest.bzl
deleted file mode 100644
index 5e72957..0000000
--- a/oci/private/repositories/oci_image_manifest.bzl
+++ /dev/null
@@ -1,36 +0,0 @@
-""" oci_image_manifest """
-
-load(
- "@com_github_datadog_rules_oci//oci:providers.bzl",
- "OCIDescriptor",
- "OCIImageManifest",
- "OCILayout",
-)
-
-def _impl(ctx):
- return [OCIImageManifest(
- config = ctx.attr.config[OCIDescriptor],
- layers = [layer[OCIDescriptor] for layer in ctx.attr.layers],
- annotations = ctx.attr.annotations,
- ), ctx.attr.layout[OCILayout], ctx.attr.descriptor[OCIDescriptor]]
-
-oci_image_manifest = rule(
- implementation = _impl,
- provides = [OCIImageManifest],
- attrs = {
- "descriptor": attr.label(
- mandatory = True,
- providers = [OCIDescriptor],
- ),
- "config": attr.label(
- mandatory = True,
- providers = [OCIDescriptor],
- ),
- "layers": attr.label_list(
- mandatory = False,
- providers = [OCIDescriptor],
- ),
- "annotations": attr.string_dict(),
- "layout": attr.label(),
- },
-)
diff --git a/oci/private/repositories/oci_layout_index.bzl b/oci/private/repositories/oci_layout_index.bzl
deleted file mode 100644
index fe44eeb..0000000
--- a/oci/private/repositories/oci_layout_index.bzl
+++ /dev/null
@@ -1,45 +0,0 @@
-""" oci_layout_index """
-
-load("@com_github_datadog_rules_oci//oci:providers.bzl", "OCIDescriptor", "OCILayout")
-
-def _impl(ctx):
- blobs_map = {}
- all_files = []
- for blob in ctx.attr.blobs:
- desc = blob[OCIDescriptor]
- blobs_map[desc.digest] = desc.file.path
- all_files.append(desc.file)
-
- obj = {
- # TODO
- #"index": ctx.attr.index[OCIDescriptor].file.path,
- "blobs": blobs_map,
- }
-
- ctx.actions.write(
- output = ctx.outputs.json,
- content = json.encode(obj),
- )
-
- return [
- OCILayout(
- blob_index = ctx.outputs.json,
- files = depset(all_files),
- ),
- ]
-
-oci_layout_index = rule(
- implementation = _impl,
- attrs = {
- "index": attr.label(
- providers = [OCIDescriptor],
- ),
- "blobs": attr.label_list(
- providers = [OCIDescriptor],
- ),
- },
- outputs = {
- "json": "%{name}.layout.json",
- },
- provides = [OCILayout],
-)
diff --git a/oci/private/repositories/oci_pull.bzl b/oci/private/repositories/oci_pull.bzl
index 36225c6..8155e19 100644
--- a/oci/private/repositories/oci_pull.bzl
+++ b/oci/private/repositories/oci_pull.bzl
@@ -1,139 +1,406 @@
""" oci_pull """
-# A directory to store cached OCI artifacts
-# TODO(griffin) currently not used, but going to start depending on this for
-# integration into the bzl wrapper.
-OCI_CACHE_DIR_ENV = "OCI_CACHE_DIR"
-
-# XXX(griffin): quick hack to get Bazel to spit out debug info for oci_pull
-DEBUG = False
-
-def failout(msg, cmd_result):
- fail(
- "{msg}\n stdout: {stdout} \n stderr: {stderr}"
- .format(msg = msg, stdout = cmd_result.stdout, stderr = cmd_result.stderr),
+load(":authn.bzl", _authn = "authn")
+load(
+ ":download.bzl",
+ "MEDIA_TYPE_DOCKER_INDEX",
+ "MEDIA_TYPE_DOCKER_MANIFEST",
+ "MEDIA_TYPE_OCI_INDEX",
+ "MEDIA_TYPE_OCI_MANIFEST",
+ "download_blob",
+ "download_index_or_manifest",
+)
+
+_SUPPORTED_PLATFORMS = [
+ struct(arch = "amd64", os = "linux", variant = None),
+ struct(arch = "arm64", os = "linux", variant = "v8"),
+ struct(arch = "arm64", os = "linux", variant = None),
+]
+
+def _impl(rctx):
+ non_blocking = [] # list of 'PendingDownload's
+
+ authn = _authn.new(rctx, config_path = None) # authn object
+
+ # Download the index or manifest. At this point, we do not know if the
+ # user provided an index or a amanifest. We will determine which it is by
+ # inspecting the downloaded file below
+ index_or_manifest = download_index_or_manifest(
+ rctx,
+ authn = authn,
+ digest = rctx.attr.digest,
+ outpath = "temp.json",
+ )
+
+ index_or_manifest_bytes = rctx.read(index_or_manifest.path)
+ index_or_manifest_json = json.decode(index_or_manifest_bytes)
+ rctx.delete(index_or_manifest.path)
+
+ schema_version = index_or_manifest_json["schemaVersion"]
+ if schema_version != 2:
+ fail("""
+The registry sent a manifest with schemaVersion != 2.
+This commonly occurs when fetching from a registry that needs the Docker-Distribution-API-Version header to be set.
+See: https://github.com/bazel-contrib/rules_oci/blob/843eb01b152b884fe731a3fb4431b738ad00ea60/docs/pull.md#authentication-using-credential-helpers
+ """.strip())
+
+ media_type = index_or_manifest_json["mediaType"]
+ if media_type in [
+ MEDIA_TYPE_DOCKER_INDEX,
+ MEDIA_TYPE_OCI_INDEX,
+ ]:
+ _handle_index(
+ rctx,
+ authn = authn,
+ index_json = index_or_manifest_json,
+ non_blocking = non_blocking,
+ )
+ elif media_type in [
+ MEDIA_TYPE_DOCKER_MANIFEST,
+ MEDIA_TYPE_OCI_MANIFEST,
+ ]:
+ _handle_manifest(
+ rctx,
+ authn = authn,
+ manifest_bytes = index_or_manifest_bytes,
+ manifest_json = index_or_manifest_json,
+ manifest_sha256 = index_or_manifest.sha256,
+ non_blocking = non_blocking,
+ )
+ else:
+ fail(
+ """
+oci_pull can only be used to pull an image index or an image manifest.
+Got media type: {media_type}.
+Expected one of: {expected}.
+ """.strip().foramt(
+ media_type = media_type,
+ expected = [
+ MEDIA_TYPE_DOCKER_INDEX,
+ MEDIA_TYPE_DOCKER_MANIFEST,
+ MEDIA_TYPE_OCI_INDEX,
+ MEDIA_TYPE_OCI_MANIFEST,
+ ],
+ ),
+ )
+
+ rctx.file(
+ rctx.path("oci-layout"),
+ content = json.encode({"imageLayoutVersion": "1.0.0"}),
+ executable = False,
)
-# buildifier: disable=function-docstring
-def pull(rctx, layout_root, repository, digest, registry = "", shallow = False, debug = False):
- cmd = [
- rctx.path(_repo_toolchain(rctx, "ocitool")),
+ # Wait for all downloads to complete
+ for result in non_blocking:
+ result.wait()
+
+ # Get the filenames of all the files in the blobs/sha256 directory
+ res = rctx.execute(
+ ["find", ".", "-maxdepth", "1", "-type", "f"],
+ working_directory = "blobs/sha256",
+ )
+ blobs = [
+ s.removeprefix("./")
+ for s in res.stdout.strip().split("\n")
]
- if debug:
- cmd.append("--debug")
-
- cmd.extend([
- "--layout={layout_root}".format(layout_root = layout_root),
- "pull",
- "--shallow={shallow}".format(shallow = shallow),
- "{registry}/{repository}@{digest}".format(
- registry = registry,
- repository = repository,
- digest = digest,
+ # Create all the BUILD.bazel files
+
+ rctx.file(
+ rctx.path("BUILD.bazel"),
+ content = """
+exports_files(
+ ["index.json", "oci-layout"],
+ visibility = ["//:__subpackages__"],
+)
+""".strip(),
+ executable = False,
+ )
+
+ rctx.file(
+ rctx.path("image/BUILD.bazel"),
+ content = """
+load(
+ "@com_github_datadog_rules_oci//oci/private/repositories:oci_pulled_image.bzl",
+ "oci_pulled_image",
+)
+load("@rules_pkg//pkg:pkg.bzl", "pkg_tar")
+
+oci_pulled_image(
+ name = "image",
+ index = "//:index.json",
+ blobs = [
+{blobs}
+ ],
+ visibility = ["//visibility:public"],
+)
+
+pkg_tar(
+ name = "tar",
+ srcs = [
+ "//:index.json",
+ "//:oci-layout",
+ "//blobs/sha256:blobs",
+ ],
+ extension = "tar.gz",
+ package_file_name = "image.tar.gz",
+ tags = ["manual"],
+ visibility = ["//visibility:public"],
+)
+""".strip().format(
+ blobs = ",\n".join([
+ ' "//blobs/sha256:{}\"'.format(blob)
+ for blob in blobs
+ ]),
),
- ])
-
- res = rctx.execute(cmd, quiet = not DEBUG)
- if res.return_code > 0:
- failout("failed to pull manifest", res)
-
-def generate_build_files(rctx, layout_root, digest = ""):
- cmd = [
- rctx.path(_repo_toolchain(rctx, "ocitool")),
- "--debug",
- "--layout={layout_root}".format(layout_root = layout_root),
- "generate-build-files",
- "--image-digest={digest}".format(digest = digest),
- ]
+ executable = False,
+ )
- res = rctx.execute(cmd, quiet = not DEBUG)
- if res.return_code > 0:
- failout("failed to pull manifest", res)
+ rctx.file(
+ rctx.path("blobs/sha256/BUILD.bazel"),
+ content = """
+load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
-def _impl(rctx):
- pull(
+exports_files(
+ glob(["**/*"]),
+ visibility = ["//:__subpackages__"],
+)
+
+pkg_files(
+ name = "blobs",
+ srcs = glob(["**/*"]),
+ prefix = "blobs/sha256",
+ visibility = ["//:__subpackages__"],
+)
+""".strip(),
+ executable = False,
+ )
+
+def _handle_index(
rctx,
- rctx.path("."),
- repository = rctx.attr.repository,
- digest = rctx.attr.digest,
- registry = rctx.attr.registry,
- shallow = rctx.attr.shallow,
+ *,
+ authn, # authn object
+ index_json, # dict[str, any]
+ non_blocking): # list[PendingDownload]
+ # -> None
+
+ # Filter out unsupported platforms
+ original_manifest_jsons = index_json["manifests"][:]
+ index_json["manifests"] = []
+ for manifest_json in original_manifest_jsons:
+ platform = struct(
+ arch = manifest_json["platform"]["architecture"],
+ os = manifest_json["platform"]["os"],
+ variant = manifest_json["platform"].get("variant", None),
+ )
+ if platform not in _SUPPORTED_PLATFORMS:
+ continue
+ index_json["manifests"].append(manifest_json)
+
+ index_bytes = json.encode(index_json)
+
+ # Write the index to index.json
+ index_path = "index.json"
+ rctx.file(index_path, content = index_bytes, executable = False)
+ index_sha256 = _sha256sum(rctx, path = index_path)
+
+ # Write the index to the blobs/sha256 directory
+ rctx.file(
+ "blobs/sha256/{}".format(index_sha256),
+ content = index_bytes,
+ executable = False,
)
- generate_build_files(
+ # For each manifest
+ for item in index_json["manifests"]:
+ # Download the manifest
+ manifest_digest = item["digest"]
+ manifest_sha256 = manifest_digest[len("sha256:"):]
+ manifest = download_index_or_manifest(
+ rctx,
+ authn = authn,
+ digest = manifest_digest,
+ outpath = "blobs/sha256/{}".format(manifest_sha256),
+ )
+ manifest_bytes = rctx.read(manifest.path)
+ manifest_json = json.decode(manifest_bytes)
+
+ # Download the config
+ config_digest = manifest_json["config"]["digest"]
+ download_blob(
+ rctx,
+ authn = authn,
+ digest = config_digest,
+ non_blocking = non_blocking,
+ )
+
+ # Download the layers
+ for item in manifest_json["layers"]:
+ layer_digest = item["digest"]
+ download_blob(
+ rctx,
+ authn = authn,
+ digest = layer_digest,
+ non_blocking = non_blocking,
+ )
+
+def _handle_manifest(
rctx,
- rctx.path("."),
- digest = rctx.attr.digest,
+ *,
+ authn, # authn object
+ manifest_bytes, # bytes
+ manifest_json, # dict[str, any]
+ manifest_sha256, # str
+ non_blocking): # list[PendingDownload]
+ # -> None
+
+ # Write the manifest to the blobs directory
+ rctx.file(
+ "blobs/sha256/{}".format(manifest_sha256),
+ content = manifest_bytes,
+ executable = False,
+ )
+
+ # Download the config
+ config_digest = manifest_json["config"]["digest"]
+ config = download_blob(rctx, authn = authn, digest = config_digest)
+ config_bytes = rctx.read(config.path)
+ config_json = json.decode(config_bytes)
+
+ # Read the config for information about the arch/os/variant
+ platform = struct(
+ arch = config_json["architecture"],
+ os = config_json["os"],
+ variant = config_json.get("variant", None),
+ )
+
+ # Error on unsupported platforms
+ if platform not in _SUPPORTED_PLATFORMS:
+ fail(
+ """
+Unsupported platform. Got {}. Expected one of: {supported_platforms}
+""".strip().format(
+ platform = platform,
+ supported_platforms = _SUPPORTED_PLATFORMS,
+ ),
+ )
+
+ # Create an index and write it to index.json
+ index_json = {
+ "manifests": [{
+ "digest": "sha256:{}".format(manifest_sha256),
+ "mediaType": MEDIA_TYPE_OCI_MANIFEST,
+ "platform": {
+ "architecture": platform.arch,
+ "os": platform.os,
+ },
+ "size": len(manifest_bytes),
+ }],
+ "mediaType": MEDIA_TYPE_OCI_INDEX,
+ "schemaVersion": 2,
+ }
+ if platform.variant != None:
+ index_json["manifests"][0]["platform"]["variant"] = platform.variant
+
+ index_path = "index.json"
+ index_bytes = json.encode(index_json)
+ rctx.file(index_path, content = index_bytes, executable = False)
+ index_sha256 = _sha256sum(rctx, path = index_path)
+
+ # Write the index to the blobs/sha256 directory
+ rctx.file(
+ "blobs/sha256/{}".format(index_sha256),
+ content = index_bytes,
+ executable = False,
+ )
+
+ # Download the layers
+ for item in manifest_json["layers"]:
+ layer_digest = item["digest"]
+ download_blob(
+ rctx,
+ authn = authn,
+ digest = layer_digest,
+ non_blocking = non_blocking,
+ )
+
+def _sha256sum(
+ rctx,
+ *,
+ path): # str
+ # -> str
+ temp_exe = "sha256-temp.sh"
+ rctx.file(
+ temp_exe,
+ executable = True,
+ content = """
+#!/usr/bin/env bash
+set -euo pipefail
+
+if [[ $# -ne 1 ]]; then
+ echo "Wrong number of arguments" >&2
+ echo "Usage: $0 " >&2
+ exit 1
+fi
+
+path="$1"
+
+os="$(uname -s)"
+case "$os" in
+ Linux) sha256sum "$path" | cut -d ' ' -f 1 ;;
+ Darwin) shasum -a 256 "$path" | cut -d ' ' -f 1 ;;
+ *) echo "Unsupported OS. Got $os. Expected of one Darwin or Linux" >&2 ; exit 1 ;;
+esac
+""".strip().format(
+ path = path,
+ ),
)
+ res = rctx.execute(["./" + temp_exe, path])
+ if res.return_code != 0:
+ fail(
+ """
+Failed to calculate the sha256 of index.json
+Exit code: {exit_code}
+Stdout: {stdout}
+Stderr: {stderr}
+""".strip().format(
+ exit_code = res.return_code,
+ stdout = res.stdout.strip(),
+ stderr = res.stderr.strip(),
+ ),
+ )
+ rctx.delete(temp_exe)
+ sha256 = res.stdout.strip().split(" ")[0]
+ return sha256
oci_pull = repository_rule(
implementation = _impl,
- doc = """
- """,
attrs = {
- "registry": attr.string(
+ "debug": attr.bool(
+ # TODO(brian.myers): Remove this once consumers no longer use it
+ doc = "Deprecated. Does nothing",
+ ),
+ "digest": attr.string(
+ doc = "The digest or tag of the manifest file",
mandatory = True,
- doc = """
- """,
),
- "repository": attr.string(
+ "registry": attr.string(
+ doc = "Remote registry host to pull from, e.g. `gcr.io` or `index.docker.io`",
mandatory = True,
- doc = """
- """,
),
- # XXX We're specifically *NOT* supporting pulling by tags as it's
- # difficult for users to control when the tag resolution is done.
- "digest": attr.string(
+ "repository": attr.string(
+ doc = "Image path beneath the registry, e.g. `distroless/static`",
mandatory = True,
- doc = """
- """,
),
- "debug": attr.bool(
- default = False,
- doc = "Enable ocitool debug output",
+ "scheme": attr.string(
+ doc = "scheme portion of the URL for fetching from the registry",
+ values = ["http", "https"],
+ default = "https",
),
"shallow": attr.bool(
- default = True,
- doc = """
- """,
- ),
- "_ocitool_darwin_amd64": attr.label(
- default = "@com_github_datadog_rules_oci//bin:ocitool-darwin-amd64",
- ),
- "_ocitool_darwin_arm64": attr.label(
- default = "@com_github_datadog_rules_oci//bin:ocitool-darwin-arm64",
- ),
- "_ocitool_linux_amd64": attr.label(
- default = "@com_github_datadog_rules_oci//bin:ocitool-linux-amd64",
- ),
- "_ocitool_linux_arm64": attr.label(
- default = "@com_github_datadog_rules_oci//bin:ocitool-linux-arm64",
+ # TODO(brian.myers): Remove this once consumers no longer use it
+ doc = "Deprecated. Does nothing",
),
},
- environ = [
- OCI_CACHE_DIR_ENV,
- ],
+ environ = _authn.ENVIRON,
)
-
-def _repo_toolchain(rctx, tool_name):
- goos = ""
- goarch = ""
-
- if rctx.os.name.lower().startswith("mac os"):
- goos = "darwin"
- elif rctx.os.name.lower().startswith("linux"):
- goos = "linux"
- else:
- fail("unknown os: {}".format(rctx.os.name))
-
- # TODO update to use rctx.os.arch when released
- arch = rctx.execute(["uname", "-m"]).stdout.strip()
- if arch.lower().find("x86") != -1:
- goarch = "amd64"
- elif arch.lower().find("arm64") != -1 or arch.lower().find("aarch64") != -1:
- goarch = "arm64"
- else:
- fail("unknown arch: {}".format(rctx.os.arch))
-
- return getattr(rctx.attr, "_{tool}_{os}_{arch}".format(tool = tool_name, os = goos, arch = goarch))
diff --git a/oci/private/repositories/oci_pulled_image.bzl b/oci/private/repositories/oci_pulled_image.bzl
new file mode 100644
index 0000000..050a91e
--- /dev/null
+++ b/oci/private/repositories/oci_pulled_image.bzl
@@ -0,0 +1,125 @@
+""" oci_pulled_image """
+
+load("@com_github_datadog_rules_oci//oci:providers.bzl", "OCIDescriptor", "OCILayout")
+load(":download.bzl", "MEDIA_TYPE_OCI_INDEX")
+
+_COREUTILS_TOOLCHAIN = "@aspect_bazel_lib//lib:coreutils_toolchain_type"
+
+def oci_pulled_image(
+ *,
+ name,
+ index, # label
+ blobs, # list[label]
+ **kwargs):
+ """oci_pulled_image
+
+ Args:
+ name: A unique name for this rule
+ index: The OCI index.json file
+ blobs: A list of the blob files
+ **kwargs: Additional arguments to pass to the rule, e.g. tags or visibility
+ """
+ _oci_pulled_image(
+ name = name,
+ index = index,
+ blobs = blobs,
+ **kwargs
+ )
+
+def _impl(ctx):
+ coreutils = ctx.toolchains[_COREUTILS_TOOLCHAIN].coreutils_info.bin
+
+ # Create the descriptor file for the index.json of the image
+ descriptor_file = ctx.actions.declare_file("{}.index.descriptor.json".format(ctx.label.name))
+ ctx.actions.run_shell(
+ inputs = [ctx.file.index],
+ outputs = [descriptor_file],
+ tools = [coreutils],
+ command = """
+#!/usr/bin/env bash
+set -euo pipefail
+
+coreutils={coreutils}
+inpath={inpath}
+media_type={media_type}
+outpath={outpath}
+
+sha256=$($coreutils sha256sum $inpath | $coreutils cut -d ' ' -f 1)
+size=$($coreutils wc -c $inpath | $coreutils cut -d ' ' -f 1)
+
+cat < $outpath
+{{
+ "digest": "sha256:$sha256",
+ "mediaType": "$media_type",
+ "size": $size
+}}
+EOF
+""".strip().format(
+ coreutils = coreutils.path,
+ inpath = ctx.file.index.path,
+ media_type = MEDIA_TYPE_OCI_INDEX,
+ outpath = descriptor_file.path,
+ ),
+ )
+
+ # Create the "blob index" file (also called a "layout" file) for the image
+ blob_index = ctx.actions.declare_file("{}.index.layout.json".format(ctx.label.name))
+ ctx.actions.run_shell(
+ inputs = ctx.files.blobs,
+ outputs = [blob_index],
+ command = """
+#!/usr/bin/env bash
+set -euo pipefail
+
+blobs=({blobs})
+outpath={outpath}
+
+cat < $outpath
+{{
+ "blobs": {{
+EOF
+
+first=1 # true=1 and false=0
+for blob in ${{blobs[@]}}; do
+ sha256=$(basename $blob)
+ if [[ $first -eq 1 ]]; then
+ first=0
+ else
+ echo "," >> $outpath
+ fi
+ echo -n " \\"sha256:$sha256\\": \\"$blob\\"" >> $outpath
+done
+
+cat <> $outpath
+
+ }}
+}}
+EOF
+""".strip().format(
+ blobs = " ".join([f.path for f in ctx.files.blobs]),
+ outpath = blob_index.path,
+ ),
+ )
+
+ return [
+ DefaultInfo(
+ files = depset([descriptor_file, blob_index]),
+ ),
+ OCIDescriptor(
+ descriptor_file = descriptor_file,
+ file = ctx.file.index,
+ ),
+ OCILayout(
+ blob_index = blob_index,
+ files = depset(ctx.files.blobs),
+ ),
+ ]
+
+_oci_pulled_image = rule(
+ implementation = _impl,
+ attrs = {
+ "blobs": attr.label_list(allow_files = True, mandatory = True),
+ "index": attr.label(allow_single_file = True, mandatory = True),
+ },
+ toolchains = [_COREUTILS_TOOLCHAIN],
+)
diff --git a/oci/providers.bzl b/oci/providers.bzl
index d22ff88..820e955 100644
--- a/oci/providers.bzl
+++ b/oci/providers.bzl
@@ -1,25 +1,5 @@
""" public providers """
-OCIReferenceInfo = provider(
- doc = "Refers to any artifact represented by an OCI-like reference URI",
- fields = {
- "registry": "the URI where the artifact is stored",
- "repository": "a namespace for an artifact",
- "tag": "a organizational reference within a repository",
- "tag_file": "a file containing the organizational reference within a repository",
- "digest": "a file containing the digest of the artifact",
- },
-)
-
-# buildifier: disable=name-conventions
-OCILayout = provider(
- "OCI Layout",
- fields = {
- "blob_index": "",
- "files": "",
- },
-)
-
# buildifier: disable=name-conventions
OCIDescriptor = provider(
doc = "",
@@ -35,27 +15,21 @@ OCIDescriptor = provider(
)
# buildifier: disable=name-conventions
-OCIImageManifest = provider(
- doc = "",
- fields = {
- "config": "Descriptor that points to a configuration object",
- "layers": "List of descriptors",
- "annotations": "String map of arbitrary metadata",
- },
-)
-
-# buildifier: disable=name-conventions
-OCIImageIndexManifest = provider(
- doc = "",
+OCILayout = provider(
+ "OCI Layout",
fields = {
- "manifests": "List of descriptors",
- "annotations": "String map of arbitrary metadata",
+ "blob_index": "",
+ "files": "",
},
)
-OCISDK = provider(
- "The OCI SDK",
+OCIReferenceInfo = provider(
+ doc = "Refers to any artifact represented by an OCI-like reference URI",
fields = {
- "ocitool": "",
+ "registry": "the URI where the artifact is stored",
+ "repository": "a namespace for an artifact",
+ "tag": "a organizational reference within a repository",
+ "tag_file": "a file containing the organizational reference within a repository",
+ "digest": "a file containing the digest of the artifact",
},
)
diff --git a/oci/toolchain.bzl b/oci/toolchain.bzl
index d8811a9..a671a11 100644
--- a/oci/toolchain.bzl
+++ b/oci/toolchain.bzl
@@ -1,110 +1,3 @@
-""" toolchain """
-
-load(":providers.bzl", "OCISDK")
-
-# Follow golang's conventions for naming os and arch
-OS_CONSTRAINTS = {
- "darwin": "@platforms//os:osx",
- "linux": "@platforms//os:linux",
-}
-
-ARCH_CONSTRAINTS = {
- "amd64": "@platforms//cpu:x86_64",
- "arm64": "@platforms//cpu:arm64",
-}
-
-def _oci_toolchain_impl(ctx):
- return [platform_common.ToolchainInfo(
- sdk = ctx.attr.sdk[OCISDK],
- )]
-
-_oci_toolchain = rule(
- implementation = _oci_toolchain_impl,
- attrs = {
- "sdk": attr.label(
- mandatory = True,
- providers = [OCISDK],
- cfg = "exec",
- ),
- },
- provides = [platform_common.ToolchainInfo],
-)
-
-def oci_toolchain(
- name,
- exec_compatible_with = [],
- target_compatible_with = [],
- **kwargs):
- oci_toolchain_name = "{name}.oci_toolchain".format(name = name)
- _oci_toolchain(
- name = oci_toolchain_name,
- **kwargs
- )
-
- native.toolchain(
- name = name,
- toolchain = oci_toolchain_name,
- exec_compatible_with = exec_compatible_with,
- target_compatible_with = target_compatible_with,
- toolchain_type = "@com_github_datadog_rules_oci//oci:toolchain",
- )
-
-def _oci_sdk_impl(ctx):
- return [
- OCISDK(
- ocitool = ctx.executable.ocitool,
- ),
- ]
-
-oci_sdk = rule(
- implementation = _oci_sdk_impl,
- attrs = {
- "ocitool": attr.label(
- mandatory = True,
- allow_single_file = True,
- executable = True,
- cfg = "exec",
- ),
- },
- provides = [OCISDK],
-)
-
-def oci_local_toolchain(name, **kwargs):
- sdk_name = "{}.sdk".format(name)
- oci_sdk(
- name = sdk_name,
- ocitool = "@com_github_datadog_rules_oci//go/cmd/ocitool",
- )
-
- oci_toolchain(
- name = name,
- sdk = sdk_name,
- **kwargs
- )
-
-# buildifier: disable=function-docstring
-def create_compiled_oci_toolchains(name, **kwargs):
- for os, os_const in OS_CONSTRAINTS.items():
- for arch, arch_const in ARCH_CONSTRAINTS.items():
- sdk_name = "{name}_sdk_{os}_{arch}".format(name = name, os = os, arch = arch)
- oci_sdk(
- name = sdk_name,
- ocitool = "@com_github_datadog_rules_oci//bin:ocitool-{os}-{arch}".format(os = os, arch = arch),
- )
-
- toolchain_name = "{name}_toolchain_{os}_{arch}".format(name = name, os = os, arch = arch)
- oci_toolchain(
- name = toolchain_name,
- sdk = sdk_name,
- exec_compatible_with = [
- os_const,
- arch_const,
- ],
- **kwargs
- )
-
-def register_compiled_oci_toolchains(name):
- for os, _ in OS_CONSTRAINTS.items():
- for arch, _ in ARCH_CONSTRAINTS.items():
- toolchain_name = "{name}_toolchain_{os}_{arch}".format(name = name, os = os, arch = arch)
- native.register_toolchains("@com_github_datadog_rules_oci//bin:{}".format(toolchain_name))
+# TODO(brian.myers): Remove this once consumers no longer use it
+def register_compiled_oci_toolchains(**kwargs):
+ pass
diff --git a/release/BUILD.bazel b/release/BUILD.bazel
index b5a81dd..851588a 100644
--- a/release/BUILD.bazel
+++ b/release/BUILD.bazel
@@ -1,11 +1,8 @@
load("@rules_pkg//pkg:pkg.bzl", "pkg_tar")
-load(":pkg_go_binary_multiple_platforms.bzl", "pkg_go_binary_multiple_platforms")
pkg_tar(
name = "release",
srcs = [
- ":ocitool",
- "//bin:files",
"//oci:files",
"//oci/private:files",
"//oci/private/repositories:files",
@@ -13,10 +10,3 @@ pkg_tar(
empty_files = ["BUILD.bazel"],
extension = "tar.gz",
)
-
-pkg_go_binary_multiple_platforms(
- name = "ocitool",
- go_binary = ["//go/cmd/ocitool:go_default_library"],
- mode = "0755",
- prefix = "bin",
-)
diff --git a/release/README.md b/release/README.md
index 50ba96d..fbd4ba5 100644
--- a/release/README.md
+++ b/release/README.md
@@ -11,8 +11,8 @@ bzl run //go/cmd/ocitool -- push-blob --ref "ghcr.io/datadog/rules_oci/rules:lat
## Updating Licenses and Headers
```
-go install github.com/DataDog/temporalite/internal/licensecheck@latest
-go install github.com/DataDog/temporalite/internal/copyright@latest
+bzl run //:go -- install github.com/DataDog/temporalite/internal/licensecheck@latest
+bzl run //:go -- install github.com/DataDog/temporalite/internal/copyright@latest
licensecheck
copyright
```
diff --git a/release/pkg_go_binary_multiple_platforms.bzl b/release/pkg_go_binary_multiple_platforms.bzl
deleted file mode 100644
index 4b4ded6..0000000
--- a/release/pkg_go_binary_multiple_platforms.bzl
+++ /dev/null
@@ -1,59 +0,0 @@
-""" pkg_go_binary_multiple_platforms """
-
-load("@io_bazel_rules_go//go:def.bzl", _go_binary = "go_binary")
-load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_files")
-
-_GOOSS = ["darwin", "linux"]
-_GOARCHS = ["amd64", "arm64"]
-
-# buildifier: disable=function-docstring
-def pkg_go_binary_multiple_platforms(
- *,
- name, # str
- go_binary, # label
- mode, # str
- prefix, # str | None
- **kwargs):
- """ pkg_go_binary_multiple_platforms
-
- Creates a pkg_files target called that includes multiple go binary
- executables (one for each platform) based off the provided go binary target.
-
- In other words, the following 4 exectuable will be included in the pkg_files
- target called :
- - -darwin-amd64
- - -darwin-arm64
- - -linux-amd64
- - -linux-arm64
-
- Args:
- name:
- - The name of the pkg_files target to create
- - Also determines the names of the executables insde the pkg_files
- target, which will be of the form "--".
- go_binary: The go_binary target to embed multiple versions of
- mode: The mode of the executables in pkg_files
- prefix: The prefix to pass to pkg_files
- **kwargs: Additional arguments to pass to pkg_files
- """
- all_binaries = []
- for goos in _GOOSS:
- for goarch in _GOARCHS:
- bin_name = "{}-{}-{}".format(name, goos, goarch)
- _go_binary(
- name = bin_name,
- embed = go_binary,
- goos = goos,
- goarch = goarch,
- )
- all_binaries.append(bin_name)
-
- pkg_files(
- name = name,
- srcs = all_binaries,
- attributes = pkg_attributes(
- mode = mode,
- ),
- prefix = prefix,
- **kwargs
- )