File oci-registry-0.4.5.obscpio of Package oci-registry
07070100000000000081A400000000000000000000000166282B010000001F000000000000000000000000000000000000002100000000oci-registry-0.4.5/.dockerignore.git
dist
profdata
target
test
07070100000001000081A400000000000000000000000166282B0100000008000000000000000000000000000000000000001E00000000oci-registry-0.4.5/.gitignore/target
07070100000002000081A400000000000000000000000166282B0100001650000000000000000000000000000000000000002200000000oci-registry-0.4.5/.gitlab-ci.ymlstages:
- build
- deploy
- cleanup
services:
- name: docker:dind
command: ["--tls=false"]
variables:
CARGO_INCREMENTAL: "0"
DOCKER_DRIVER: overlay2
DOCKER_HOST: tcp://localhost:2375
DOCKER_TLS_CERTDIR: ""
RUSTC_WRAPPER: /usr/bin/sccache
SCCACHE_REGION: us-east-1
SCCACHE_ENDPOINT: rgw.storage.home.quadra-tec.net:7480
SCCACHE_S3_USE_SSL: "off"
SCCACHE_BUCKET: gitlab-sccache
cargo build and cargo test:
stage: build
image: mcronce/rust-pgo:1.76
cache:
- key: rust
paths:
- .cargo
before_script:
- |
if [ -d .cargo ]; then
rm -Rf /usr/local/cargo/registry
time mv -f .cargo/registry /usr/local/cargo/
fi
script:
- cargo build
- cargo clippy --no-deps -- -D warnings
- cargo test
after_script:
- if [ ! -d .cargo ]; then mkdir .cargo; fi
- time mv -f /usr/local/cargo/registry .cargo/
- /usr/bin/sccache -s
Build x86-64 container image:
stage: build
image: docker:20-git
artifacts:
paths:
- images/release.amd64.tar.gz
before_script:
- docker version
- apk add -U bash coreutils
- bash -ec 'find Cargo.toml src -type f | while read file; do revision="$(git rev-list -n 1 HEAD "${file}")"; timestamp="$(git show --pretty=format:%ai --abbrev-commit "${revision}" | head -n1)"; touch -d "${timestamp}" "${file}"; done'
script:
- |
BUILD_ARGS="--build-arg=CARGO_INCREMENTAL --build-arg=RUSTC_WRAPPER --build-arg=SCCACHE_REGION --build-arg=SCCACHE_ENDPOINT --build-arg=SCCACHE_BUCKET --build-arg=AWS_ACCESS_KEY_ID --build-arg=AWS_SECRET_ACCESS_KEY"
docker build $BUILD_ARGS -f Dockerfile.x86-64 --cache-from "mcronce/oci-registry-builder" --target=builder -t "mcronce/oci-registry-builder" .
docker build $BUILD_ARGS -f Dockerfile.x86-64 --cache-from "mcronce/oci-registry-builder" --cache-from "mcronce/oci-registry" -t "mcronce/oci-registry:amd64" .
- mkdir -pv images
- time docker save "mcronce/oci-registry:amd64" | gzip > images/release.amd64.tar.gz
after_script:
- docker rmi -f "mcronce/oci-registry-builder"
- docker rmi -f "mcronce/oci-registry:amd64"
only:
- tags
Build aarch64 container image:
stage: build
image: docker:20-git
artifacts:
paths:
- images/release.arm64v8.tar.gz
before_script:
- docker version
- apk add -U bash coreutils
- bash -ec 'find Cargo.toml src ui -type f | while read file; do revision="$(git rev-list -n 1 HEAD "${file}")"; timestamp="$(git show --pretty=format:%ai --abbrev-commit "${revision}" | head -n1)"; touch -d "${timestamp}" "${file}"; done'
script:
- |
BUILD_ARGS="--build-arg=CARGO_INCREMENTAL --build-arg=RUSTC_WRAPPER --build-arg=SCCACHE_REGION --build-arg=SCCACHE_ENDPOINT --build-arg=SCCACHE_BUCKET --build-arg=AWS_ACCESS_KEY_ID --build-arg=AWS_SECRET_ACCESS_KEY"
docker build $BUILD_ARGS -f Dockerfile.aarch64 --cache-from "mcronce/oci-registry-builder" --target=builder -t "mcronce/oci-registry-builder" .
docker build $BUILD_ARGS -f Dockerfile.aarch64 --cache-from "mcronce/oci-registry-builder" --cache-from "mcronce/oci-registry" -t "mcronce/oci-registry:arm64v8" .
- mkdir -pv images
- time docker save "mcronce/oci-registry:arm64v8" | gzip > images/release.arm64v8.tar.gz
after_script:
- docker rmi -f "mcronce/oci-registry-builder"
- docker rmi -f "mcronce/oci-registry:arm64v8"
only:
- tags
Lint chart:
stage: build
image: alpine/helm:latest
script:
- helm lint ./dist/helm
Push container image:
stage: deploy
image: docker:20-git
before_script:
- docker version
- echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
- zcat images/release.amd64.tar.gz | docker load
- zcat images/release.arm64v8.tar.gz | docker load
script:
- docker push "mcronce/oci-registry:amd64"
- docker push "mcronce/oci-registry:arm64v8"
- docker manifest create "mcronce/oci-registry:latest" --amend "mcronce/oci-registry:amd64" --amend "mcronce/oci-registry:arm64v8"
- docker manifest push "mcronce/oci-registry:latest"
- |
if [ "${CI_COMMIT_TAG}" != '' ]; then
docker tag "mcronce/oci-registry:amd64" "mcronce/oci-registry:${CI_COMMIT_TAG}-amd64"
docker tag "mcronce/oci-registry:arm64v8" "mcronce/oci-registry:${CI_COMMIT_TAG}-arm64v8"
docker push "mcronce/oci-registry:${CI_COMMIT_TAG}-amd64"
docker push "mcronce/oci-registry:${CI_COMMIT_TAG}-arm64v8"
docker manifest create "mcronce/oci-registry:${CI_COMMIT_TAG}" --amend "mcronce/oci-registry:${CI_COMMIT_TAG}-amd64" --amend "mcronce/oci-registry:${CI_COMMIT_TAG}-arm64v8"
docker manifest push "mcronce/oci-registry:${CI_COMMIT_TAG}"
fi
after_script:
- docker rmi -f "mcronce/oci-registry:amd64"
- docker rmi -f "mcronce/oci-registry:arm64v8"
- docker manifest rm "mcronce/oci-registry:latest"
- |
if [ "${CI_COMMIT_TAG}" != '' ]; then
docker rmi -f "mcronce/oci-registry:${CI_COMMIT_TAG}-amd64"
docker rmi -f "mcronce/oci-registry:${CI_COMMIT_TAG}-arm64v8"
docker manifest rm "mcronce/oci-registry:${CI_COMMIT_TAG}"
fi
only:
- tags
Push chart:
stage: deploy
image: alpine/helm:latest
before_script:
- apk add -U git
- helm plugin install https://github.com/chartmuseum/helm-push.git
script:
- helm cm-push ./dist/helm https://charts.cronce.io
only:
- tags
cargo cache cleanup:
stage: cleanup
image: mcronce/cargo-cache
variables:
RUSTC_WRAPPER: ""
cache:
- key: rust
paths:
- .cargo
before_script: []
script:
- CARGO_HOME=.cargo cargo cache clean-unref
after_script: []
07070100000003000081A400000000000000000000000166282B010000010F000000000000000000000000000000000000002100000000oci-registry-0.4.5/.rustfmt.tomlversion = "Two"
hard_tabs = true
max_width = 250
chain_width = 120
inline_attribute_width = 200
struct_lit_width = 60
trailing_comma = "Never"
match_block_trailing_comma = true
group_imports = "StdExternalCrate"
imports_granularity = "Item"
reorder_impl_items = true
07070100000004000081A400000000000000000000000166282B0100016543000000000000000000000000000000000000001E00000000oci-registry-0.4.5/Cargo.lock# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "actix-codec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
dependencies = [
"bitflags 2.5.0",
"bytes",
"futures-core",
"futures-sink",
"memchr",
"pin-project-lite",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "actix-http"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d223b13fd481fc0d1f83bb12659ae774d9e3601814c68a0bc539731698cca743"
dependencies = [
"actix-codec",
"actix-rt",
"actix-service",
"actix-utils",
"ahash",
"base64 0.21.7",
"bitflags 2.5.0",
"brotli",
"bytes",
"bytestring",
"derive_more",
"encoding_rs",
"flate2",
"futures-core",
"h2",
"http",
"httparse",
"httpdate",
"itoa",
"language-tags",
"local-channel",
"mime",
"percent-encoding",
"pin-project-lite",
"rand",
"sha1",
"smallvec",
"tokio",
"tokio-util",
"tracing",
"zstd",
]
[[package]]
name = "actix-macros"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [
"quote",
"syn 2.0.60",
]
[[package]]
name = "actix-router"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511"
dependencies = [
"bytestring",
"http",
"regex",
"serde",
"tracing",
]
[[package]]
name = "actix-rt"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d"
dependencies = [
"futures-core",
"tokio",
]
[[package]]
name = "actix-server"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4"
dependencies = [
"actix-rt",
"actix-service",
"actix-utils",
"futures-core",
"futures-util",
"mio",
"socket2",
"tokio",
"tracing",
]
[[package]]
name = "actix-service"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a"
dependencies = [
"futures-core",
"paste",
"pin-project-lite",
]
[[package]]
name = "actix-utils"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
dependencies = [
"local-waker",
"pin-project-lite",
]
[[package]]
name = "actix-web"
version = "4.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a6556ddebb638c2358714d853257ed226ece6023ef9364f23f0c70737ea984"
dependencies = [
"actix-codec",
"actix-http",
"actix-macros",
"actix-router",
"actix-rt",
"actix-server",
"actix-service",
"actix-utils",
"actix-web-codegen",
"ahash",
"bytes",
"bytestring",
"cfg-if 1.0.0",
"cookie",
"derive_more",
"encoding_rs",
"futures-core",
"futures-util",
"itoa",
"language-tags",
"log",
"mime",
"once_cell",
"pin-project-lite",
"regex",
"serde",
"serde_json",
"serde_urlencoded",
"smallvec",
"socket2",
"time",
"url",
]
[[package]]
name = "actix-web-codegen"
version = "4.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5"
dependencies = [
"actix-router",
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "actix-web-prometheus"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad5228fd1a6b5d0f60d636776c2a70acc9fc667034bb4ac02ec4259f0eeeab6c"
dependencies = [
"actix-service",
"actix-web",
"futures-lite 1.13.0",
"pin-project",
"prometheus",
"quanta",
"thiserror",
]
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if 1.0.0",
"getrandom",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "alloc-no-stdlib"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
[[package]]
name = "alloc-stdlib"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]]
name = "arcerror"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e27245b5205290df2dfe1069e064736c2e66afd8bf670ecbdef665ef5472ffa"
[[package]]
name = "arcstr"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f907281554a3d0312bb7aab855a8e0ef6cbf1614d06de54105039ca8b34460e"
dependencies = [
"serde",
]
[[package]]
name = "async-broadcast"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb"
dependencies = [
"event-listener 5.3.0",
"event-listener-strategy 0.5.1",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-channel"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928"
dependencies = [
"concurrent-queue",
"event-listener 5.3.0",
"event-listener-strategy 0.5.1",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-fs"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc19683171f287921f2405677dd2ed2549c3b3bda697a563ebc3a121ace2aba1"
dependencies = [
"async-lock",
"blocking",
"futures-lite 2.3.0",
]
[[package]]
name = "async-lock"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b"
dependencies = [
"event-listener 4.0.3",
"event-listener-strategy 0.4.0",
"pin-project-lite",
]
[[package]]
name = "async-stream"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
dependencies = [
"async-stream-impl",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-stream-impl"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "async-task"
version = "4.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
[[package]]
name = "async-trait"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "async-walkdir"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f6338023cbfc0555eccb8e83d3d4dcf1183b51ca9140a03b1dbb8a559193db"
dependencies = [
"async-fs",
"futures-lite 2.3.0",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "autocfg"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "backtrace"
version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [
"addr2line",
"cc",
"cfg-if 1.0.0",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "blocking"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118"
dependencies = [
"async-channel",
"async-lock",
"async-task",
"fastrand 2.0.2",
"futures-io",
"futures-lite 2.3.0",
"piper",
"tracing",
]
[[package]]
name = "brotli"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
"brotli-decompressor",
]
[[package]]
name = "brotli-decompressor"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
dependencies = [
"serde",
]
[[package]]
name = "bytestring"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72"
dependencies = [
"bytes",
]
[[package]]
name = "camino"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "castaway"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc"
dependencies = [
"rustversion",
]
[[package]]
name = "cc"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b"
dependencies = [
"jobserver",
"libc",
"once_cell",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"serde",
"windows-targets 0.52.5",
]
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "clap"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim 0.11.1",
]
[[package]]
name = "clap_derive"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "compact_str"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
dependencies = [
"castaway",
"cfg-if 1.0.0",
"itoa",
"ryu",
"serde",
"static_assertions",
]
[[package]]
name = "concurrent-queue"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "convert_case"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "cookie"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [
"percent-encoding",
"time",
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cow-utils"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79"
[[package]]
name = "cpufeatures"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools 0.10.5",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools 0.10.5",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "crypto-mac"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "darling"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn 2.0.60",
]
[[package]]
name = "darling_macro"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [
"darling_core",
"quote",
"syn 2.0.60",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
"serde",
]
[[package]]
name = "derive_more"
version = "0.99.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"rustc_version",
"syn 1.0.109",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"crypto-common",
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if 1.0.0",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dkregistry"
version = "0.5.1-alpha.0"
source = "git+https://github.com/mcronce/dkregistry-rs.git#baa34b7653a9263416302fb7454692c7292ec02f"
dependencies = [
"arcstr",
"async-stream",
"base64 0.21.7",
"bytes",
"compact_str",
"cow-utils",
"futures",
"http",
"itertools 0.11.0",
"libflate",
"log",
"mime",
"pin-project",
"regex",
"reqwest",
"serde",
"serde_ignored",
"serde_json",
"serde_with",
"sha2 0.10.8",
"strum",
"strum_macros",
"tar",
"thiserror",
"tokio",
"url",
]
[[package]]
name = "either"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
[[package]]
name = "encoding_rs"
version = "0.8.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "event-listener"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3"
dependencies = [
"event-listener 4.0.3",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3"
dependencies = [
"event-listener 5.3.0",
"pin-project-lite",
]
[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
[[package]]
name = "fastrand"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
[[package]]
name = "filetime"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall",
"windows-sys 0.52.0",
]
[[package]]
name = "flate2"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-lite"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
dependencies = [
"fastrand 1.9.0",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]]
name = "futures-lite"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
dependencies = [
"fastrand 2.0.2",
"futures-core",
"futures-io",
"parking",
"pin-project-lite",
]
[[package]]
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "h2"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 2.2.6",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "half"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"cfg-if 1.0.0",
"crunchy",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hmac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
dependencies = [
"crypto-mac",
"digest 0.9.0",
]
[[package]]
name = "http"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
"http",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.14.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]]
name = "hyper-rustls"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
dependencies = [
"http",
"hyper",
"log",
"rustls 0.20.9",
"rustls-native-certs",
"tokio",
"tokio-rustls 0.23.4",
]
[[package]]
name = "hyper-rustls"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
dependencies = [
"futures-util",
"http",
"hyper",
"rustls 0.21.11",
"tokio",
"tokio-rustls 0.24.1",
]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
"serde",
]
[[package]]
name = "indexmap"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
"serde",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "io-lifetimes"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "ipnet"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
[[package]]
name = "is-terminal"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jobserver"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "language-tags"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
[[package]]
name = "lazy-regex"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c"
dependencies = [
"lazy-regex-proc_macros",
"once_cell",
"regex",
]
[[package]]
name = "lazy-regex-proc_macros"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b"
dependencies = [
"proc-macro2",
"quote",
"regex",
"syn 2.0.60",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libflate"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ff4ae71b685bbad2f2f391fe74f6b7659a34871c08b210fdc039e43bee07d18"
dependencies = [
"adler32",
"crc32fast",
"libflate_lz77",
]
[[package]]
name = "libflate_lz77"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a52d3a8bfc85f250440e4424db7d857e241a3aebbbe301f3eb606ab15c39acbf"
dependencies = [
"rle-decode-fast",
]
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.5.0",
"libc",
]
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "local-channel"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8"
dependencies = [
"futures-core",
"futures-sink",
"local-waker",
]
[[package]]
name = "local-waker"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487"
[[package]]
name = "lock_api"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "mach"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
dependencies = [
"libc",
]
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "md-5"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
dependencies = [
"block-buffer 0.9.0",
"digest 0.9.0",
"opaque-debug",
]
[[package]]
name = "memchr"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.48.0",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "object"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]]
name = "oci-registry"
version = "0.4.5"
dependencies = [
"actix-web",
"actix-web-prometheus",
"arcerror",
"arcstr",
"async-broadcast",
"async-stream",
"async-walkdir",
"bytes",
"camino",
"clap",
"compact_str",
"criterion",
"dkregistry",
"futures",
"hex",
"humantime",
"lazy-regex",
"once_cell",
"pin-project",
"prometheus",
"regex",
"rusoto_core",
"rusoto_credential",
"rusoto_s3",
"serde",
"serde_json",
"serde_with",
"serde_yaml",
"sha2 0.10.8",
"socket-address",
"thiserror",
"tikv-jemallocator-global",
"time",
"tokio",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
dependencies = [
"parking_lot_core",
]
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openssl-probe"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.48.5",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "piper"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4"
dependencies = [
"atomic-waker",
"fastrand 2.0.2",
"futures-io",
]
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "plotters"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
[[package]]
name = "plotters-svg"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
dependencies = [
"plotters-backend",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [
"unicode-ident",
]
[[package]]
name = "procfs"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69"
dependencies = [
"bitflags 1.3.2",
"byteorder",
"hex",
"lazy_static",
"rustix 0.36.17",
]
[[package]]
name = "prometheus"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
dependencies = [
"cfg-if 1.0.0",
"fnv",
"lazy_static",
"libc",
"memchr",
"parking_lot",
"procfs",
"thiserror",
]
[[package]]
name = "quanta"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e31331286705f455e56cca62e0e717158474ff02b7936c1fa596d983f4ae27"
dependencies = [
"crossbeam-utils",
"libc",
"mach",
"once_cell",
"raw-cpuid",
"wasi 0.10.2+wasi-snapshot-preview1",
"web-sys",
"winapi",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "raw-cpuid"
version = "10.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "regex"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.4.6",
"regex-syntax 0.8.3",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
name = "regex-automata"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.8.3",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "reqwest"
version = "0.11.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
dependencies = [
"base64 0.21.7",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
"hyper-rustls 0.24.2",
"ipnet",
"js-sys",
"log",
"mime",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls 0.21.11",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-rustls 0.24.1",
"tokio-util",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
"webpki-roots",
"winreg",
]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin 0.5.2",
"untrusted 0.7.1",
"web-sys",
"winapi",
]
[[package]]
name = "ring"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if 1.0.0",
"getrandom",
"libc",
"spin 0.9.8",
"untrusted 0.9.0",
"windows-sys 0.52.0",
]
[[package]]
name = "rle-decode-fast"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
[[package]]
name = "rusoto_core"
version = "0.48.0"
source = "git+https://github.com/mcronce/rusoto.git?branch=enable-http1#bf26da8fa88b9f05311488754c14b50340e85364"
dependencies = [
"async-trait",
"base64 0.13.1",
"bytes",
"crc32fast",
"flate2",
"futures",
"http",
"hyper",
"hyper-rustls 0.23.2",
"lazy_static",
"log",
"rusoto_credential",
"rusoto_signature",
"rustc_version",
"serde",
"serde_json",
"tokio",
"xml-rs",
]
[[package]]
name = "rusoto_credential"
version = "0.48.0"
source = "git+https://github.com/mcronce/rusoto.git?branch=enable-http1#bf26da8fa88b9f05311488754c14b50340e85364"
dependencies = [
"async-trait",
"chrono",
"dirs-next",
"futures",
"hyper",
"serde",
"serde_json",
"shlex",
"tokio",
"zeroize",
]
[[package]]
name = "rusoto_s3"
version = "0.48.0"
source = "git+https://github.com/mcronce/rusoto.git?branch=enable-http1#bf26da8fa88b9f05311488754c14b50340e85364"
dependencies = [
"async-trait",
"bytes",
"futures",
"rusoto_core",
"xml-rs",
]
[[package]]
name = "rusoto_signature"
version = "0.48.0"
source = "git+https://github.com/mcronce/rusoto.git?branch=enable-http1#bf26da8fa88b9f05311488754c14b50340e85364"
dependencies = [
"base64 0.13.1",
"bytes",
"chrono",
"digest 0.9.0",
"futures",
"hex",
"hmac",
"http",
"hyper",
"log",
"md-5",
"percent-encoding",
"pin-project-lite",
"rusoto_credential",
"rustc_version",
"serde",
"sha2 0.9.9",
"tokio",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.36.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "305efbd14fde4139eb501df5f136994bb520b033fa9fbdce287507dc23b8c7ed"
dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys 0.1.4",
"windows-sys 0.45.0",
]
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys 0.4.13",
"windows-sys 0.52.0",
]
[[package]]
name = "rustls"
version = "0.20.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
dependencies = [
"log",
"ring 0.16.20",
"sct",
"webpki",
]
[[package]]
name = "rustls"
version = "0.21.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4"
dependencies = [
"log",
"ring 0.17.8",
"rustls-webpki",
"sct",
]
[[package]]
name = "rustls-native-certs"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00"
dependencies = [
"openssl-probe",
"rustls-pemfile",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pemfile"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
dependencies = [
"base64 0.21.7",
]
[[package]]
name = "rustls-webpki"
version = "0.101.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
dependencies = [
"ring 0.17.8",
"untrusted 0.9.0",
]
[[package]]
name = "rustversion"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
"ring 0.17.8",
"untrusted 0.9.0",
]
[[package]]
name = "security-framework"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "semver"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]]
name = "serde"
version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "serde_ignored"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8e319a36d1b52126a0d608f24e93b2d81297091818cd70625fcf50a15d84ddf"
dependencies = [
"serde",
]
[[package]]
name = "serde_json"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_with"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a"
dependencies = [
"base64 0.21.7",
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.2.6",
"serde",
"serde_derive",
"serde_json",
"serde_with_macros",
"time",
]
[[package]]
name = "serde_with_macros"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "serde_yaml"
version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap 2.2.6",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
"digest 0.10.7",
]
[[package]]
name = "sha2"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
dependencies = [
"block-buffer 0.9.0",
"cfg-if 1.0.0",
"cpufeatures",
"digest 0.9.0",
"opaque-debug",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
"digest 0.10.7",
"sha2-asm",
]
[[package]]
name = "sha2-asm"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27ba7066011e3fb30d808b51affff34f0a66d3a03a58edd787c6e420e40e44e"
dependencies = [
"cc",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket-address"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e009e8acc78acbfe17c42852dca91e985536b7fdbc6a5cac41c4a34955e03569"
dependencies = [
"thiserror",
]
[[package]]
name = "socket2"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
[[package]]
name = "strum_macros"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
dependencies = [
"heck 0.4.1",
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.60",
]
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "sync_wrapper"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "tar"
version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "thiserror"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if 1.0.0",
"once_cell",
]
[[package]]
name = "tikv-jemalloc-sys"
version = "0.5.4+5.3.0-patched"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "tikv-jemallocator"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca"
dependencies = [
"libc",
"tikv-jemalloc-sys",
]
[[package]]
name = "tikv-jemallocator-global"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28047b535f87b21a79b0b450c5aed8235b32a5aaf8dcc6706b638c1eadea11f"
dependencies = [
"cfg-if 0.1.10",
"tikv-jemallocator",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "tokio-rustls"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
dependencies = [
"rustls 0.20.9",
"tokio",
"webpki",
]
[[package]]
name = "tokio-rustls"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls 0.21.11",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
name = "tower-service"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "try-lock"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
name = "unsafe-libyaml"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "waker-fn"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
"try-lock",
]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.60",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "wasm-streams"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
dependencies = [
"futures-util",
"js-sys",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "web-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53"
dependencies = [
"ring 0.17.8",
"untrusted 0.9.0",
]
[[package]]
name = "webpki-roots"
version = "0.25.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134306a13c5647ad6453e8deaec55d3a44d6021970129e6188735e74bf546697"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.5",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "winreg"
version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
"cfg-if 1.0.0",
"windows-sys 0.48.0",
]
[[package]]
name = "xattr"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
dependencies = [
"libc",
"linux-raw-sys 0.4.13",
"rustix 0.38.34",
]
[[package]]
name = "xml-rs"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193"
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
[[package]]
name = "zstd"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.10+zstd.1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
dependencies = [
"cc",
"pkg-config",
]
07070100000005000081A400000000000000000000000166282B01000009BC000000000000000000000000000000000000001E00000000oci-registry-0.4.5/Cargo.toml[package]
name = "oci-registry"
version = "0.4.5"
edition = "2021"
license = "MIT"
repository = "https://github.com/mcronce/oci-registry"
description = "An implementation of the OCI Registry spec with filesystem and S3 storage back-ends"
keywords = ["container", "docker", "registry", "mirror"]
include = ["Cargo.toml", "src"]
[profile.dev]
debug = 1
[profile.release]
debug = 1
lto = "fat"
codegen-units = 1
[[bench]]
name = "main"
harness = false
[dependencies]
actix-web = "4.2.1"
actix-web-prometheus = { version = "0.1.2", features = ["process"] }
arcerror = "0.1.5"
arcstr = { version = "1.1.5", features = ["serde"] }
async-broadcast = "0.7.0"
async-stream = "0.3.3"
async-walkdir = "1.0.0"
bytes = { version = "1.2.1", features = ["serde"] }
camino = "1.1.1"
clap = { version = "4.0.12", features = ["derive", "env"] }
compact_str = { version = "0.7.0", features = ["serde"] }
dkregistry = { version = "0.5.1-alpha.0", git = "https://github.com/mcronce/dkregistry-rs.git", default-features = false, features = ["reqwest-rustls"] }
futures = "0.3.24"
hex = "0.4.3"
humantime = "2.1.0"
lazy-regex = "3.0.0"
once_cell = { version = "1.18.0", default-features = false, features = ["parking_lot"] }
pin-project = "1.1.4"
prometheus = { version = "0.13.3", default-features = false }
regex = "1.6.0"
rusoto_core = { version = "0.48.0", default-features = false, features = ["hyper-rustls", "flate2"] }
rusoto_credential = "0.48.0"
rusoto_s3 = { version = "0.48.0", default-features = false, features = ["rustls"] }
serde = { version = "1.0.145", features = ["derive"] }
serde_json = "1.0.86"
serde_with = { version = "3.0.0", default-features = false, features = ["hex"] }
serde_yaml = "0.9.13"
sha2 = { version = "0.10.6", features = ["asm"] }
socket-address = "0.1.0"
thiserror = "1.0.37"
tikv-jemallocator-global = { version = "0.5.0", features = ["tikv-jemallocator"] }
time = { version = "0.3.15", features = ["parsing"] }
tokio = { version = "1.24.1", features = ["fs", "io-util"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
[dev-dependencies]
criterion = "0.5.1"
# TODO: Once https://github.com/rusoto/rusoto/pull/1981 is merged, remove these.
[patch.crates-io]
rusoto_core = {git = "https://github.com/mcronce/rusoto.git", branch = "enable-http1"}
rusoto_credential = {git = "https://github.com/mcronce/rusoto.git", branch = "enable-http1"}
rusoto_s3 = {git = "https://github.com/mcronce/rusoto.git", branch = "enable-http1"}
070701000000060000A1FF00000000000000000000000166282B0100000011000000000000000000000000000000000000001E00000000oci-registry-0.4.5/DockerfileDockerfile.x86-6407070100000007000081A400000000000000000000000166282B01000004E8000000000000000000000000000000000000002600000000oci-registry-0.4.5/Dockerfile.aarch64FROM mcronce/rust-pgo:1.76 AS builder
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
ARG \
RUSTC_WRAPPER \
SCCACHE_REGION \
SCCACHE_ENDPOINT \
SCCACHE_S3_USE_SSL=off \
SCCACHE_BUCKET \
AWS_ACCESS_KEY_ID \
AWS_SECRET_ACCESS_KEY
WORKDIR /repo
COPY Cargo.toml /repo/
COPY benches /repo/benches
RUN \
mkdir -v /repo/src && \
echo 'fn main() {}' > /repo/src/main.rs && \
cargo build --release --target=aarch64-unknown-linux-gnu && \
bash -exc "if [ '${RUSTC_WRAPPER}' == '/usr/bin/sccache' ]; then /usr/bin/sccache -s; fi" && \
rm -Rvf /repo/src
COPY src /repo/src
ENV RUST_LOG=info,actix-web=debug
RUN \
touch src/main.rs && \
cargo build --release --target=aarch64-unknown-linux-gnu && \
bash -exc "if [ '${RUSTC_WRAPPER}' == '/usr/bin/sccache' ]; then /usr/bin/sccache -s; fi"
RUN aarch64-linux-gnu-strip /repo/target/aarch64-unknown-linux-gnu/release/oci-registry
FROM --platform=linux/arm64 arm64v8/debian:12
RUN \
apt-get update && \
apt-get install -y ca-certificates \
&& rm -Rvf /var/lib/apt
COPY --from=builder /repo/target/aarch64-unknown-linux-gnu/release/oci-registry /usr/local/bin/oci-registry
EXPOSE 80
ENV \
PORT=80 \
RUST_LOG=info,actix-web=debug
ENTRYPOINT ["/usr/local/bin/oci-registry"]
07070100000008000081A400000000000000000000000166282B0100000670000000000000000000000000000000000000002500000000oci-registry-0.4.5/Dockerfile.x86-64FROM mcronce/rust-pgo:1.76 AS builder
ARG \
RUSTC_WRAPPER \
SCCACHE_REGION \
SCCACHE_ENDPOINT \
SCCACHE_S3_USE_SSL=off \
SCCACHE_BUCKET \
AWS_ACCESS_KEY_ID \
AWS_SECRET_ACCESS_KEY
RUN apt-get update && apt-get install -y s3cmd ncat jq
WORKDIR /repo
COPY Cargo.toml /repo/
COPY benches /repo/benches
RUN \
mkdir -v /repo/src && \
echo 'fn main() {}' > /repo/src/main.rs && \
cargo pgo build && \
bash -exc "if [ '${RUSTC_WRAPPER}' == '/usr/bin/sccache' ]; then /usr/bin/sccache -s; fi" && \
rm -Rvf /repo/src
COPY src /repo/src
ENV RUST_LOG=info,actix-web=debug
RUN \
touch src/main.rs && \
cargo pgo build && \
bash -exc "if [ '${RUSTC_WRAPPER}' == '/usr/bin/sccache' ]; then /usr/bin/sccache -s; fi"
ADD tools /repo/tools
ADD testdata /repo/testdata
RUN mv -vf /repo/testdata/s3cfg ~/.s3cfg
RUN \
export LLVM_PROFILE_FILE=/repo/target/pgo-profiles/oci-registry_%m_%p.profraw && \
./tools/generate-profiles '' | sed 's/^/[ pgo] /'
RUN \
cargo pgo bolt build --with-pgo && \
bash -exc "if [ '${RUSTC_WRAPPER}' == '/usr/bin/sccache' ]; then /usr/bin/sccache -s; fi" && \
./tools/generate-profiles -bolt-instrumented | sed 's/^/[bolt] /'
RUN \
cargo pgo bolt optimize --with-pgo && \
bash -exc "if [ '${RUSTC_WRAPPER}' == '/usr/bin/sccache' ]; then /usr/bin/sccache -s; fi"
RUN strip /repo/target/x86_64-unknown-linux-gnu/release/oci-registry-bolt-optimized
FROM gcr.io/distroless/cc-debian12
COPY --from=builder /repo/target/x86_64-unknown-linux-gnu/release/oci-registry-bolt-optimized /usr/local/bin/oci-registry
EXPOSE 80
ENV \
PORT=80 \
RUST_LOG=info,actix-web=debug
ENTRYPOINT ["/usr/local/bin/oci-registry"]
07070100000009000081A400000000000000000000000166282B010000041F000000000000000000000000000000000000001B00000000oci-registry-0.4.5/LICENSECopyright (c) 2022 Mike Cronce
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
0707010000000A000081A400000000000000000000000166282B0100001E6A000000000000000000000000000000000000001D00000000oci-registry-0.4.5/README.md`oci-registry` is an implementation of the OCI Registry spec with filesystem and S3 storage back-ends.
[[_TOC_]]
# Features
* Pull-through cache for _any_ registry, not just docker.io
* This includes private, authenticated registries. **This means that you can create an unauthenticated mirror of a private registry and expose it to the Internet. Easily. Don't do that.**
* Two storage back-ends
* S3
* Local filesystem
* Small footprint; in my test system, the official `registry` uses approximately 130 MiB of memory to mirror docker.io; five replicas of `oci-registry` combined use approximately 60 MiB to mirror everything in [example.yaml](example.yaml), plus one private registry. CPU is negligible for both.
* A [helm chart][artifacthub]
# Limitations
* Pushing is not currently implemented; `oci-registry` only supports being a pull-through cache (a mirror) at this time. Push support is planned.
* Authentication is not currently implemented, but is planned
* Only SHA256 content hashes are supported, but supporting other schemes is planned
* Connecting to `oci-registry` with TLS (https) is not supported and support will not be added.
* [Using nginx as a TLS termination proxy][nginx-proxy] is easy, well-supported, and well-documented; if you require TLS between the client and `oci-registry`, that is the recommended configuration
* Connecting to upstream registries with TLS is supported, recommended, and usually required.
* If two clients request the same blob simultaneously, it will be downloaded from upstream twice in parallel instead of having the later request wait for the download to finish, then serve it from cache. There are no data corruption issues, but it is suboptimal. No fix is currently planned, but I'm open to one.
* Has not yet had the [OCI distribution spec conformance test suite][oci-test-suite] run against it; only manual compatibility testing with `docker` and `containerd` has been performed. This is planned after push support is implemented.
# Examples
## `docker`
Mirroring `docker.io` is the default configuration. Start `oci-registry`:
```bash
oci-registry --listen 0.0.0.0:8080 filesystem --root /tmp/oci-mirror
```
Configure Docker's `daemon.json` to use the registry:
```json
{
"registry-mirrors": ["http://localhost:8080"]
}
```
Restart Docker and it will start pulling images from `docker.io` through `oci-registry`.
**NOTE**: Mirroring registries other than `docker.io` is not possible with Docker.
## `containerd`
`containerd` provides a mechanism for mirroring any registry you want, and sends the upstream registry as a querystring parameter in all its requests. This means that we can mirror any number of registries to `containerd` with a single instance of `oci-registry`.
## `cri-o`
`cri-o` requires defining each registry you want to mirror, but you can use a separate path for each registry to inform `oci-registry` of which registry the request is for.
### Configure `oci-registry`
`oci-registry`'s default configuration is to mirror any registry for which it receives requests, connecting to upstream with HTTPS, rejecting invalid certs, and using the namespace as the upstream registry host - e.g. requests for `gcr.io` images will be made to https://gcr.io/ - with the exception of `docker.io`, which will be pointed to https://registry-1.docker.io
In short, `oci-registry`'s default configuration will work for most public registries, but can be added to with `--upstream-config-file`. See [example.yaml](example.yaml) for real world examples, or the following contrived private registry example:
```yaml
# namespace and host are the only two required keys
- namespace: example.com
host: registry.example.com
# Connecting with TLS is the default
tls: true
# Requiring valid TLS certs is the default
accept_invalid_certs: false
# This hypothetical registry checks the HTTP User-Agent header to make sure there's no malarkey going on, so pretend to be containerd
user_agent: "containerd/1.6.8"
# This hypothetical registry requires authentication, so let's give it our username and password
username: example
password: hunter2
# This hypothetical registry is used for active development, so let's _always_ see if we have the latest manifest for a given image
manifest_invalidation_time: 0s
# Blobs are identified by the SHA256 hash of their contents, so they probably won't change frequently, if ever
blob_invalidation_time: 30d
```
To avoid having to store credentials in a plaintext file, they can be set by storing a JSON map in the `$UPSTREAM_CREDENTIALS` environment variable, like so:
```
UPSTREAM_CREDENTIALS='{"example.com": {"username": "example", "password": "hunter2"}, "docker.io": {"username": "aaa", "password": "bbb"}}'
```
Note that this is not exposed in the Helm chart, because the configuration is already itself mounted in from a secret.
### Configure `containerd`
Recent versions of `containerd` (1.5+) use [per-host configuration files][containerd-hosts]; for older versions, config instructions can be found in the deprecated section [here][containerd-deprecated].
Assuming default paths, make sure your `/etc/containerd/config.toml` contains the following:
```toml
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
```
Then, in `/etc/containerd/certs.d`, create a directory for each registry you want to mirror and create a `hosts.toml` pointing at `oci-registry`:
```bash
mkdir /etc/containerd/certs.d/docker.io
cat > /etc/containerd/certs.d/docker.io/hosts.toml <<EOF
server = "https://registry-1.docker.io"
[host."http://localhost:8080"]
capabilities = ["pull", "resolve"]
EOF
mkdir /etc/containerd/certs.d/gcr.io
cat > /etc/containerd/certs.d/gcr.io/hosts.toml <<EOF
server = "https://gcr.io"
[host."http://localhost:8080"]
capabilities = ["pull", "resolve"]
EOF
```
The above example will configure `containerd` to attempt to pull `docker.io` and `gcr.io` manifests and blobs from `oci-registry` listening on `localhost:8080`, while sticking with the original hosts for pushing, and using the original hosts if something goes wrong with `oci-registry`.
### Configure `cri-o`
`cri-o` uses the common [`registries.conf`][registries-conf] configuration file to specify which registries to mirror.
Assuming default paths, simply add the following to `/etc/containers/registries.conf`:
```
[[registry]]
location = "docker.io"
[[registry.mirror]]
location = "localhost:8080/docker.io"
insecure = true
[[registry]]
location = "gcr.io"
[[registry.mirror]]
location = "localhost:8080/gcr.io"
insecure = true
```
The above example will configure `cri-o` to attempt to pull `docker.io` and `gcr.io` manifests and blobs from `oci-registry` listening on `localhost:8080`, while sticking with the original hosts for pushing, and using the original hosts if something goes wrong with `oci-registry`.
# Community
The Github repo is a mirror. Project management is done in the [main repo][gitlab]. In addition, there is a [Matrix room][matrix].
[artifacthub]: https://artifacthub.io/packages/helm/cronce/oci-registry
[nginx-proxy]: https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-http/
[oci-test-suite]: https://github.com/opencontainers/distribution-spec/tree/main/conformance
[containerd-hosts]: https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
[containerd-deprecated]: https://github.com/containerd/containerd/blob/main/docs/cri/registry.md#configure-registry-endpoint
[registries-conf]: https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md#remapping-and-mirroring-registries
[gitlab]: https://gitlab.cronce.io/foss/oci-registry
[matrix]: https://matrix.to/#/%23oci-registry%3Acronce.io
0707010000000B000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001B00000000oci-registry-0.4.5/benches0707010000000C000081A400000000000000000000000166282B0100000B14000000000000000000000000000000000000002300000000oci-registry-0.4.5/benches/main.rsuse criterion::criterion_group;
use criterion::criterion_main;
use criterion::BenchmarkId;
use criterion::Criterion;
fn split_image_with_ns(c: &mut Criterion) {
c.bench_with_input(BenchmarkId::new("split_image", "with ns docker.io/envoyproxy/envoy"), &(Some("docker.io"), "envoyproxy/envoy", ""), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
c.bench_with_input(BenchmarkId::new("split_image", "with ns docker.io/library/busybox"), &(Some("docker.io"), "library/busybox", ""), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
c.bench_with_input(BenchmarkId::new("split_image", "with ns gcr.io/distroless/static"), &(Some("gcr.io"), "distroless/static", ""), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
c.bench_with_input(
BenchmarkId::new("split_image", "with ns ghcr.io/buildbarn/bb-runner-installer"),
&(Some("ghcr.io"), "buildbarn/bb-runner-installer", ""),
|b, &(ns, image, default_ns)| b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
);
}
fn split_image_without_ns(c: &mut Criterion) {
c.bench_with_input(BenchmarkId::new("split_image", "without ns docker.io/envoyproxy/envoy"), &(None, "docker.io/envoyproxy/envoy", ""), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
c.bench_with_input(BenchmarkId::new("split_image", "without ns docker.io/library/busybox"), &(None, "docker.io/library/busybox", ""), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
c.bench_with_input(BenchmarkId::new("split_image", "without ns gcr.io/distroless/static"), &(None, "gcr.io/distroless/static", ""), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
c.bench_with_input(
BenchmarkId::new("split_image", "without ns ghcr.io/buildbarn/bb-runner-installer"),
&(None, "ghcr.io/buildbarn/bb-runner-installer", ""),
|b, &(ns, image, default_ns)| b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
);
}
fn split_image_fallback(c: &mut Criterion) {
c.bench_with_input(BenchmarkId::new("split_image", "fallback docker.io/envoyproxy/envoy"), &(None, "envoyproxy/envoy", "docker.io"), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
c.bench_with_input(BenchmarkId::new("split_image", "fallback docker.io/library/busybox"), &(None, "library/busybox", "docker.io"), |b, &(ns, image, default_ns)| {
b.iter(|| oci_registry::api::split_image(ns, image, default_ns))
});
}
criterion_group!(split_image, split_image_with_ns, split_image_without_ns, split_image_fallback);
criterion_main!(split_image);
0707010000000D000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001800000000oci-registry-0.4.5/dist0707010000000E000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001D00000000oci-registry-0.4.5/dist/helm0707010000000F000081A400000000000000000000000166282B0100000156000000000000000000000000000000000000002800000000oci-registry-0.4.5/dist/helm/Chart.yamlapiVersion: v1
name: oci-registry
description: oci-registry is an implementation of the OCI Registry spec with filesystem and S3 storage back-ends. Currently it only supports being a pull-through cache (a mirror); pushing is not yet implemented.
version: 0.4.5
appVersion: 0.4.5
maintainers:
- name: Mike Cronce
email: mike@cronce.io
07070100000010000081A400000000000000000000000166282B0100000A95000000000000000000000000000000000000002700000000oci-registry-0.4.5/dist/helm/README.md# oci-registry
 
oci-registry is an implementation of the OCI Registry spec with filesystem and S3 storage back-ends. Currently it only supports being a pull-through cache (a mirror); pushing is not yet implemented.
## Maintainers
| Name | Email | Url |
| ---- | ------ | --- |
| Mike Cronce | <mike@cronce.io> | |
## Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| extraLabels | object | `{}` | |
| image.name | string | `"oci-registry"` | |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.pullSecret | string | `nil` | |
| image.registry | string | `"mcronce"` | |
| image.tag | string | `"v0.3.0"` | |
| ingress.annotations | object | `{}` | |
| ingress.class | string | `nil` | |
| ingress.enabled | bool | `false` | |
| ingress.hosts[0] | string | `"oci-registry"` | |
| ingress.path | string | `"/"` | |
| ingress.tls | list | `[]` | |
| registry.invalidation_time.blobs | string | `"14d"` | |
| registry.invalidation_time.manifests | string | `"14d"` | |
| registry.storage.filesystem.path | string | `"/data"` | |
| registry.storage.mode | string | `"filesystem"` | |
| registry.storage.s3.auth_secret.access_key | string | `nil` | |
| registry.storage.s3.auth_secret.deploy | bool | `true` | |
| registry.storage.s3.auth_secret.name_override | string | `nil` | |
| registry.storage.s3.auth_secret.secret_key | string | `nil` | |
| registry.storage.s3.bucket | string | `"oci-registry"` | |
| registry.storage.s3.host | string | `nil` | |
| registry.storage.s3.region | string | `"us-east-1"` | |
| registry.upstream.config.contents | list | `[]` | |
| registry.upstream.config.deploy | bool | `true` | |
| registry.upstream.config.name_override | string | `nil` | |
| registry.upstream.default_namespace | string | `"docker.io"` | |
| replicas | int | `2` | |
| resources.limits.cpu | int | `2` | |
| resources.limits.memory | string | `"64Mi"` | |
| resources.requests.cpu | string | `"100m"` | |
| resources.requests.memory | string | `"16Mi"` | |
| service.annotations | object | `{}` | |
| service.clusterIP | string | `nil` | |
| service.externalIPs | list | `[]` | |
| service.loadBalancerIP | string | `""` | |
| service.loadBalancerSourceRanges | list | `[]` | |
| service.port | int | `80` | |
| service.type | string | `"ClusterIP"` | |
----------------------------------------------
Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0)
07070100000011000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000002700000000oci-registry-0.4.5/dist/helm/templates07070100000012000081A400000000000000000000000166282B0100000780000000000000000000000000000000000000003400000000oci-registry-0.4.5/dist/helm/templates/_helpers.tpl{{- define "oci-registry.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "oci-registry.chart" -}}
{{- .Chart.Name -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "oci-registry.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if (contains $name .Release.Name) -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "oci-registry.image" -}}
{{- with .Values.image -}}
{{- printf "%s/%s:%s" .registry .name (.tag | toString) -}}
{{- end -}}
{{- end -}}
{{- define "oci-registry.archiver_image" -}}
{{- with .Values.archiver.image -}}
{{- printf "%s/%s:%s" .registry .name (.tag | toString) -}}
{{- end -}}
{{- end -}}
{{- define "oci-registry.labels" -}}
app.kubernetes.io/name: {{ template "oci-registry.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ template "oci-registry.chart" . }}
{{- if .Values.extraLabels -}}
{{- toYaml .Values.extraLabels -}}
{{- end -}}
{{- end -}}
{{- define "oci-registry.upstream_secret_name" -}}
{{- default (printf "%s-%s" (include "oci-registry.fullname" .) "upstream") .Values.registry.upstream.config.name_override | quote }}
{{- end -}}
{{- define "oci-registry.s3_secret_name" -}}
{{- default (printf "%s-%s" (include "oci-registry.fullname" .) "s3") .Values.registry.storage.s3.auth_secret.name_override | quote }}
{{- end -}}
07070100000013000081A400000000000000000000000166282B0100000F62000000000000000000000000000000000000003700000000oci-registry-0.4.5/dist/helm/templates/deployment.yamlapiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "oci-registry.fullname" . }}
labels:
{{- include "oci-registry.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
{{- include "oci-registry.labels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "oci-registry.labels" . | nindent 8 }}
spec:
containers:
- name: oci-registry
image: "{{ .Values.image.registry }}/{{ .Values.image.name }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if eq .Values.registry.storage.mode "s3" }}
args: ["s3"]
env:
- name: S3_HOST
value: {{ .Values.registry.storage.s3.host | quote }}
- name: S3_REGION
value: {{ .Values.registry.storage.s3.region | quote }}
- name: S3_BUCKET
value: {{ .Values.registry.storage.s3.bucket | quote }}
- name: S3_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ template "oci-registry.s3_secret_name" . }}
key: access_key
- name: S3_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ template "oci-registry.s3_secret_name" . }}
key: secret_key
{{- else if eq .Values.registry.storage.mode "filesystem" }}
args: ["filesystem"]
env:
- name: FILESYSTEM_ROOT
value: /data
{{- else }}
{{- fail "registry.storage.mode must be either 's3' or 'filesystem'" -}}
{{- end }}
{{- if .Values.registry.check_cache_digest }}
- name: CHECK_CACHE_DIGEST
value: "true"
{{- end }}
- name: UPSTREAM_CONFIG_FILE
value: /upstream.yaml
- name: DEFAULT_UPSTREAM_NAMESPACE
value: {{ .Values.registry.upstream.default_namespace | quote }}
- name: RUST_LOG
value: info,actix-web=debug
{{- if .Values.resources.limits.cpu }}
- name: TOKIO_WORKER_THREADS
{{- if typeIs "string" .Values.resources.limits.cpu }}
{{- $trimmed := trimSuffix "m" .Values.resources.limits.cpu }}
{{- $value := ternary (float64 $trimmed | ceil | mul 1000) $trimmed (contains "." $trimmed) | int64 }}
{{- if eq (mod $value 1000) 0 }}
value: {{ div $value 1000 | quote }}
{{- else }}
value: {{ add1 (div $value 1000) | quote }}
{{- end }}
{{- else }}
value: {{ .Values.resources.limits.cpu | quote }}
{{- end }}
{{- range .Values.extraEnv }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- end }}
ports:
- name: http
containerPort: 80
volumeMounts:
- mountPath: /upstream.yaml
name: upstream
subPath: upstream.yaml
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 3
livenessProbe:
tcpSocket:
port: http
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 5
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
- name: upstream
secret:
secretName: {{ template "oci-registry.upstream_secret_name" . }}
nodeSelector:
{{- toYaml .Values.nodeSelector | nindent 8 }}
affinity:
{{- toYaml .Values.affinity | nindent 8 }}
tolerations:
{{- toYaml .Values.tolerations | nindent 8 }}
07070100000014000081A400000000000000000000000166282B010000076E000000000000000000000000000000000000003400000000oci-registry-0.4.5/dist/helm/templates/ingress.yaml{{- if .Values.ingress.enabled -}}
{{- $fullName := include "oci-registry.fullname" . -}}
{{- $servicePort := .Values.service.port -}}
{{- $ingressPath := .Values.ingress.path -}}
{{- $new := false }}
{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" -}}
apiVersion: networking.k8s.io/v1
{{- $new = true }}
{{- else }}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "oci-registry.labels" . | nindent 4 }}
annotations:
{{- if and (not $new) .Values.ingress.class }}
kubernetes.io/ingress.class: {{ .Values.ingress.class | quote }}
{{- end }}
{{- if .Values.ingress.annotations }}
{{- toYaml .Values.ingress.annotations | nindent 4 }}
{{- end }}
spec:
{{- if and $new .Values.ingress.class }}
ingressClassName: {{ .Values.ingress.class | quote }}
{{- end }}
{{- if or .Values.ingress.tls (hasKey .Values.ingress.annotations "kubernetes.io/tls-acme") }}
tls:
{{- if hasKey .Values.ingress.annotations "kubernetes.io/tls-acme" }}
- hosts: {{ .Values.ingress.hosts | toYaml | nindent 8 }}
secretName: {{ printf "%s-tls" .Release.Name }}
{{- else }}
{{- toYaml (list .Values.ingress.tls) | nindent 4 }}
{{- end }}
{{- end }}
rules:
{{- if $new }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
pathType: Prefix
backend:
service:
name: {{ $fullName }}
port:
number: {{ $servicePort }}
{{- end }}
{{- else }}
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
backend:
serviceName: {{ $fullName }}
servicePort: {{ $servicePort }}
{{- end }}
{{- end }}
{{- end }}
07070100000015000081A400000000000000000000000166282B01000002CA000000000000000000000000000000000000003600000000oci-registry-0.4.5/dist/helm/templates/secret-s3.yaml{{- if and (eq .Values.registry.storage.mode "s3") .Values.registry.storage.s3.auth_secret.deploy }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "oci-registry.s3_secret_name" . }}
labels:
{{- include "oci-registry.labels" . | nindent 4 }}
type: Opaque
data:
access_key: {{ required "If registry.storage.s3.auth_secret.deploy is set to true, registry.storage.s3.auth_secret.access_key is required" .Values.registry.storage.s3.auth_secret.access_key | b64enc | quote }}
secret_key: {{ required "If registry.storage.s3.auth_secret.deploy is set to true, registry.storage.s3.auth_secret.secret_key is required" .Values.registry.storage.s3.auth_secret.secret_key | b64enc | quote }}
{{- end }}
07070100000016000081A400000000000000000000000166282B0100000148000000000000000000000000000000000000003C00000000oci-registry-0.4.5/dist/helm/templates/secret-upstream.yaml{{- if .Values.registry.upstream.config.deploy }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "oci-registry.upstream_secret_name" . }}
labels:
{{- include "oci-registry.labels" . | nindent 4 }}
type: Opaque
data:
upstream.yaml: {{ .Values.registry.upstream.config.contents | toYaml | b64enc }}
{{- end }}
07070100000017000081A400000000000000000000000166282B01000003BF000000000000000000000000000000000000003400000000oci-registry-0.4.5/dist/helm/templates/service.yamlapiVersion: v1
kind: Service
metadata:
{{- if .Values.service.annotations }}
annotations:
{{- toYaml .Values.service.annotations | nindent 4 }}
{{- end }}
name: {{ template "oci-registry.fullname" . }}
labels:
{{- include "oci-registry.labels" . | nindent 4 }}
spec:
clusterIP: {{ .Values.service.clusterIP | quote }}
{{- if .Values.service.externalIPs }}
externalIPs:
{{- toYaml .Values.service.externalIPs | nindent 4 }}
{{- end }}
{{- if .Values.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.service.loadBalancerIP | quote }}
{{- end }}
{{- if .Values.service.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
{{- end }}
ports:
- name: http
protocol: TCP
port: {{ .Values.service.port }}
targetPort: http
selector:
{{- include "oci-registry.labels" . | nindent 4 }}
type: {{ .Values.service.type }}
07070100000018000081A400000000000000000000000166282B0100000565000000000000000000000000000000000000002900000000oci-registry-0.4.5/dist/helm/values.yamlimage:
registry: mcronce
name: oci-registry
tag: v0.4.5
pullPolicy: IfNotPresent
pullSecret:
replicas: 2
registry:
check_cache_digest: false
upstream:
config:
deploy: true
name_override:
contents: []
#- namespace: docker.io
# host: registry-1.docker.io
# tls: true
# accept_invalid_certs: false
# user_agent: null
# username: null
# password: null
# manifest_invalidation_time: 14d
# blob_invalidation_time: 14d
#- namespace: quay.io
# host: quay.io
#- namespace: gcr.io
# host: gcr.io
default_namespace: docker.io
storage:
mode: filesystem
filesystem:
path: /data
s3:
# Leave blank to use AWS
host:
auth_secret:
name_override:
deploy: true
access_key:
secret_key:
region: us-east-1
bucket: oci-registry
service:
port: 80
type: ClusterIP
clusterIP:
annotations: {}
externalIPs: []
loadBalancerIP: ""
loadBalancerSourceRanges: []
extraLabels: {}
extraEnv: []
ingress:
enabled: false
class:
annotations: {}
path: /
hosts:
- oci-registry
tls: []
# - secretName: oci-registry-tls
# hosts:
# oci-registry
resources:
requests:
cpu: 100m
memory: 16Mi
limits:
cpu: 2
memory: 128Mi
07070100000019000081A400000000000000000000000166282B010000020B000000000000000000000000000000000000002000000000oci-registry-0.4.5/example.yaml# Including all config items on docker.io for demo purposes
- namespace: docker.io
host: registry-1.docker.io
tls: true
accept_invalid_certs: false
user_agent: null
username: null
password: null
manifest_invalidation_time: 14d
blob_invalidation_time: 14d
# Including only required config for the rest
- namespace: quay.io
host: quay.io
- namespace: gcr.io
host: gcr.io
- namespace: ghcr.io
host: ghcr.io
- namespace: k8s.gcr.io
host: k8s.gcr.io
- namespace: registry.k8s.io
host: registry.k8s.io
0707010000001A000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001700000000oci-registry-0.4.5/src0707010000001B000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001B00000000oci-registry-0.4.5/src/api0707010000001C000081A400000000000000000000000166282B010000304C000000000000000000000000000000000000001E00000000oci-registry-0.4.5/src/api.rsuse std::iter;
use actix_web::body::SizedStream;
use actix_web::http;
use actix_web::http::header::HeaderName;
use actix_web::rt;
use actix_web::web;
use actix_web::HttpResponse;
use compact_str::CompactString;
use dkregistry::v2::Client;
use futures::stream::StreamExt;
use futures::stream::TryStreamExt;
use once_cell::sync::Lazy;
use prometheus::register_int_counter_vec;
use prometheus::IntCounterVec;
use serde::Deserialize;
use tokio::sync::Mutex;
use tracing::error;
use tracing::warn;
use crate::image::ImageName;
use crate::image::ImageReference;
use crate::storage::Manifest;
use crate::storage::Repository;
use crate::upstream::Clients;
pub mod error;
use error::should_retry_without_namespace;
use error::Error;
pub mod stream;
use stream::DigestCheckedStream;
pub struct RequestConfig {
repo: Repository,
upstream: Mutex<Clients>,
default_ns: CompactString,
check_cache_digest: bool
}
impl RequestConfig {
pub fn new(repo: Repository, upstream: Clients, default_ns: CompactString, check_cache_digest: bool) -> Self {
Self { repo, upstream: Mutex::new(upstream), default_ns, check_cache_digest }
}
}
async fn authenticate_with_upstream(upstream: &mut Client, scope: &str) -> Result<(), dkregistry::errors::Error> {
upstream.authenticate(&[scope]).await?;
Ok(())
}
pub async fn root(config: web::Data<RequestConfig>, qstr: web::Query<ManifestQueryString>) -> Result<&'static str, Error> {
let mut upstream = { config.upstream.lock().await.get(qstr.ns.as_deref().unwrap_or_else(|| config.default_ns.as_ref()))?.client.clone() };
upstream.authenticate(&[]).await?;
Ok("")
}
#[derive(Debug, Deserialize)]
pub struct ManifestRequest {
image: ImageName,
reference: ImageReference
}
impl ManifestRequest {
fn http_path(&self) -> String {
format!("/{}/manifests/{}", self.image, self.reference)
}
fn storage_path(&self, ns: &str) -> String {
match self.image.as_ref().split('/').next() {
Some(part) if part == ns => format!("manifests/{}/{}", self.image, self.reference),
_ => format!("manifests/{}/{}/{}", ns, self.image, self.reference)
}
}
}
#[derive(Debug, Deserialize)]
pub struct ManifestQueryString {
ns: Option<CompactString>
}
fn manifest_response(manifest: Manifest) -> HttpResponse {
let mut response = HttpResponse::Ok();
response.insert_header((http::header::CONTENT_TYPE, manifest.media_type.to_string()));
if let Some(digest) = manifest.digest {
response.insert_header((HeaderName::from_static("docker-content-digest"), digest));
}
response.body(manifest.manifest)
}
pub async fn manifest(req: web::Path<ManifestRequest>, qstr: web::Query<ManifestQueryString>, config: web::Data<RequestConfig>) -> Result<HttpResponse, Error> {
static HIT_COUNTER: Lazy<IntCounterVec> = Lazy::new(|| register_int_counter_vec!("manifest_cache_hits", "Number of manifests read from cache", &["namespace"]).unwrap());
static MISS_COUNTER: Lazy<IntCounterVec> = Lazy::new(|| register_int_counter_vec!("manifest_cache_misses", "Number of manifest requests that went to upstream", &["namespace"]).unwrap());
let (namespace, image) = split_image(qstr.ns.as_deref(), req.image.as_ref(), config.default_ns.as_ref());
let max_age = config.upstream.lock().await.get(namespace)?.manifest_invalidation_time;
let storage_path = req.storage_path(namespace);
match config.repo.read(&storage_path, max_age).await {
Ok(stream) => {
let body = stream.into_inner().try_collect::<web::BytesMut>().await?;
let manifest = serde_json::from_slice(body.as_ref())?;
HIT_COUNTER.with_label_values(&[namespace]).inc();
return Ok(manifest_response(manifest));
},
Err(error) => warn!(path = req.http_path(), storage_path, %error, "Manifest not found in repository; pulling from upstream")
}
MISS_COUNTER.with_label_values(&[namespace]).inc();
let manifest = {
let mut upstream = config.upstream.lock().await.get(namespace)?.clone();
authenticate_with_upstream(&mut upstream.client, &format!("repository:{}:pull", image)).await?;
let reference = req.reference.to_str();
let (manifest, media_type, digest) = match upstream.client.get_raw_manifest_and_metadata(image, reference.as_ref(), Some(namespace)).await {
Ok(v) => v,
Err(e) if should_retry_without_namespace(&e) => upstream.client.get_raw_manifest_and_metadata(image, reference.as_ref(), None).await?,
Err(e) => return Err(e.into())
};
Manifest::new(manifest, media_type, digest)
};
let body = serde_json::to_vec(&manifest).unwrap();
let len = body.len().try_into().unwrap_or(i64::MAX);
if let Err(error) = config
.repo
.write(&storage_path, futures::stream::iter(iter::once(Result::<_, std::io::Error>::Ok(body.into()))), len)
.await
{
error!(%error, "Failed to write manifest to storage");
}
Ok(manifest_response(manifest))
}
#[derive(Debug, Deserialize)]
pub struct BlobRequest {
image: ImageName,
digest: String
}
impl BlobRequest {
fn http_path(&self) -> String {
format!("/{}/blobs/{}", self.image, self.digest)
}
fn storage_path(&self) -> String {
let (method, hash) = self.digest.split_once(':').unwrap_or(("_", &self.digest));
let hash_prefix = hash.get(..2).unwrap_or("_");
let rest_of_hash = hash.get(2..).unwrap_or(hash);
format!("blobs/{method}/{hash_prefix}/{rest_of_hash}")
}
}
pub async fn blob(req: web::Path<BlobRequest>, qstr: web::Query<ManifestQueryString>, config: web::Data<RequestConfig>) -> Result<HttpResponse, Error> {
static HIT_COUNTER: Lazy<IntCounterVec> = Lazy::new(|| register_int_counter_vec!("blob_cache_hits", "Number of blobs read from cache", &["namespace"]).unwrap());
static MISS_COUNTER: Lazy<IntCounterVec> = Lazy::new(|| register_int_counter_vec!("blob_cache_misses", "Number of blob requests that went to upstream", &["namespace"]).unwrap());
let Some(wanted_digest_hex) = req.digest.strip_prefix("sha256:") else {
return Err(Error::InvalidDigest);
};
let wanted_digest = {
let mut buf = [0u8; 256 / 8];
if (hex::decode_to_slice(wanted_digest_hex, &mut buf[..]).is_err()) {
return Err(Error::InvalidDigest);
}
buf
};
let (namespace, image) = split_image(qstr.ns.as_deref(), req.image.as_ref(), config.default_ns.as_ref());
let storage_path = req.storage_path();
let max_age = config.upstream.lock().await.get(namespace)?.blob_invalidation_time;
match config.repo.read(storage_path.as_ref(), max_age).await {
Ok(stream) => match config.check_cache_digest {
true => {
let hash = stream::hash(stream.into_inner()).await?;
if (hash == wanted_digest) {
HIT_COUNTER.with_label_values(&[namespace]).inc();
let stream = config.repo.read(storage_path.as_ref(), max_age).await?;
return Ok(HttpResponse::Ok().body(SizedStream::new(stream.length(), stream.into_inner())));
}
error!(storage_path, "Digest mismatch");
config.repo.delete(storage_path.as_ref()).await?;
},
false => {
HIT_COUNTER.with_label_values(&[namespace]).inc();
let stream = config.repo.read(storage_path.as_ref(), max_age).await?;
return Ok(HttpResponse::Ok().body(SizedStream::new(stream.length(), stream.into_inner())));
}
},
Err(error) => warn!(path = storage_path, %error, "Blob not found in repository; pulling from upstream")
};
MISS_COUNTER.with_label_values(&[namespace]).inc();
let response = {
let mut upstream = config.upstream.lock().await.get(namespace)?.clone();
authenticate_with_upstream(&mut upstream.client, &format!("repository:{}:pull", image)).await?;
match upstream.client.get_blob_response(image, req.digest.as_ref(), Some(namespace)).await {
Ok(v) => v,
Err(e) if should_retry_without_namespace(&e) => upstream.client.get_blob_response(image, req.digest.as_ref(), None).await?,
Err(e) => return Err(e.into())
}
};
let len = response.size().ok_or(Error::MissingContentLength)?;
let (tx, rx) = async_broadcast::broadcast(16);
{
let mut stream = DigestCheckedStream::<_, crate::storage::Error, _>::new(response.stream().err_into::<crate::storage::Error>(), wanted_digest);
rt::spawn(async move {
while let Some(chunk) = stream.next().await {
let chunk = match chunk {
Ok(v) => Ok(v),
Err(error) => {
error!(%error, "Error reading from upstream");
Err(error)
}
};
let is_err = chunk.is_err();
if (tx.broadcast(chunk).await.is_err()) {
error!(path = req.http_path(), "Readers for proxied blob request all closed");
return;
} else if is_err {
return;
}
}
});
}
{
let rx2 = rx.clone();
let config = config.clone();
rt::spawn(async move {
if let Err(error) = config.repo.write(storage_path.as_ref(), rx2, len.try_into().unwrap_or(i64::MAX)).await {
error!(%error, "Failed to write blob to storage");
if let Err(error) = config.repo.delete(storage_path.as_ref()).await {
error!(%error, "Failed to delete failed blob from storage");
}
}
});
}
Ok(HttpResponse::Ok().body(SizedStream::new(len, rx.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)))))
}
#[inline]
pub fn split_image<'a>(ns: Option<&'a str>, image: &'a str, default_ns: &'a str) -> (&'a str, &'a str) {
match ns {
Some(v) => (v, image),
None => match image.split_once('/') {
Some((ns, image)) if image.contains('/') => (ns, image),
Some(_) | None => (default_ns, image)
}
}
}
pub async fn delete_manifest(req: web::Path<ManifestRequest>, qstr: web::Query<ManifestQueryString>, config: web::Data<RequestConfig>) -> Result<&'static str, Error> {
let (namespace, _) = split_image(qstr.ns.as_deref(), req.image.as_ref(), config.default_ns.as_ref());
let storage_path = req.storage_path(namespace);
config.repo.delete(storage_path.as_ref()).await?;
Ok("")
}
pub async fn delete_blob(req: web::Path<BlobRequest>, config: web::Data<RequestConfig>) -> Result<&'static str, Error> {
let storage_path = req.storage_path();
config.repo.delete(storage_path.as_ref()).await?;
Ok("")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn split_image_with_ns() {
let (ns, image) = split_image(Some("docker.io"), "envoyproxy/envoy", "");
assert_eq!(ns, "docker.io");
assert_eq!(image, "envoyproxy/envoy");
let (ns, image) = split_image(Some("docker.io"), "library/busybox", "");
assert_eq!(ns, "docker.io");
assert_eq!(image, "library/busybox");
let (ns, image) = split_image(Some("docker.io"), "grafana/mimirtool", "");
assert_eq!(ns, "docker.io");
assert_eq!(image, "grafana/mimirtool");
let (ns, image) = split_image(Some("gcr.io"), "distroless/static", "");
assert_eq!(ns, "gcr.io");
assert_eq!(image, "distroless/static");
let (ns, image) = split_image(Some("gcr.io"), "flame-public/buildbuddy-app-onprem", "");
assert_eq!(ns, "gcr.io");
assert_eq!(image, "flame-public/buildbuddy-app-onprem");
let (ns, image) = split_image(Some("ghcr.io"), "buildbarn/bb-runner-installer", "");
assert_eq!(ns, "ghcr.io");
assert_eq!(image, "buildbarn/bb-runner-installer");
}
#[test]
fn split_image_without_ns() {
let (ns, image) = split_image(None, "docker.io/envoyproxy/envoy", "");
assert_eq!(ns, "docker.io");
assert_eq!(image, "envoyproxy/envoy");
let (ns, image) = split_image(None, "docker.io/library/busybox", "");
assert_eq!(ns, "docker.io");
assert_eq!(image, "library/busybox");
let (ns, image) = split_image(None, "docker.io/grafana/mimirtool", "");
assert_eq!(ns, "docker.io");
assert_eq!(image, "grafana/mimirtool");
let (ns, image) = split_image(None, "gcr.io/distroless/static", "");
assert_eq!(ns, "gcr.io");
assert_eq!(image, "distroless/static");
let (ns, image) = split_image(None, "gcr.io/flame-public/buildbuddy-app-onprem", "");
assert_eq!(ns, "gcr.io");
assert_eq!(image, "flame-public/buildbuddy-app-onprem");
let (ns, image) = split_image(None, "ghcr.io/buildbarn/bb-runner-installer", "");
assert_eq!(ns, "ghcr.io");
assert_eq!(image, "buildbarn/bb-runner-installer");
}
#[test]
fn split_image_without_ns_fallback() {
let (ns, image) = split_image(None, "envoyproxy/envoy", "docker.io");
assert_eq!(ns, "docker.io");
assert_eq!(image, "envoyproxy/envoy");
let (ns, image) = split_image(None, "library/busybox", "docker.io");
assert_eq!(ns, "docker.io");
assert_eq!(image, "library/busybox");
let (ns, image) = split_image(None, "grafana/mimirtool", "docker.io");
assert_eq!(ns, "docker.io");
assert_eq!(image, "grafana/mimirtool");
}
}
0707010000001D000081A400000000000000000000000166282B01000009FC000000000000000000000000000000000000002400000000oci-registry-0.4.5/src/api/error.rsuse actix_web::body::BoxBody;
use actix_web::http::StatusCode;
use actix_web::HttpResponse;
use actix_web::HttpResponseBuilder;
use dkregistry::errors::Error as Upstream;
use rusoto_core::request::BufferedHttpResponse;
use rusoto_core::RusotoError;
use rusoto_s3::GetObjectError;
use tracing::error;
use crate::api::stream::DigestMismatchError;
use crate::storage::Error as Storage;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Error with storage subsystem: {0}")]
Storage(#[from] Storage),
#[error("Error with upstream registry: {0}")]
Upstream(#[from] Upstream),
#[error("Not found")]
InvalidDigest,
#[error("Missing Content-Length header from upstream")]
MissingContentLength,
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("{0}")]
DataCorrupt(#[from] DigestMismatchError)
}
impl actix_web::ResponseError for Error {
fn status_code(&self) -> StatusCode {
match self {
Self::Storage(e) => match e {
Storage::Io(e) if e.kind() == std::io::ErrorKind::NotFound => StatusCode::NOT_FOUND,
Storage::RusotoGet(e) if matches!(e.as_ref(), &RusotoError::Service(GetObjectError::NoSuchKey(_))) => StatusCode::NOT_FOUND,
Storage::RusotoDelete(e) if matches!(e.as_ref(), &RusotoError::Unknown(BufferedHttpResponse { status: StatusCode::NOT_FOUND, .. })) => StatusCode::NOT_FOUND,
_ => StatusCode::INTERNAL_SERVER_ERROR
},
Self::Upstream(e) => match e {
Upstream::UnexpectedHttpStatus(StatusCode::NOT_FOUND) => StatusCode::NOT_FOUND,
Upstream::UnexpectedHttpStatus(_) => StatusCode::INTERNAL_SERVER_ERROR,
Upstream::Client { status: StatusCode::NOT_FOUND } => StatusCode::NOT_FOUND,
Upstream::Client { .. } => StatusCode::INTERNAL_SERVER_ERROR,
_ => StatusCode::INTERNAL_SERVER_ERROR
},
Self::InvalidDigest => StatusCode::NOT_FOUND,
Self::MissingContentLength => StatusCode::INTERNAL_SERVER_ERROR,
Self::Io(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::Json(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::DataCorrupt(_) => StatusCode::INTERNAL_SERVER_ERROR
}
}
fn error_response(&self) -> HttpResponse<BoxBody> {
let status_code = self.status_code();
error!("{}: {}", status_code.as_u16(), self);
HttpResponseBuilder::new(status_code).body(self.to_string())
}
}
pub fn should_retry_without_namespace(err: &Upstream) -> bool {
matches!(err, dkregistry::errors::Error::Reqwest(_) | dkregistry::errors::Error::UnexpectedHttpStatus(_) | dkregistry::errors::Error::Client { .. })
}
0707010000001E000081A400000000000000000000000166282B0100000C55000000000000000000000000000000000000002500000000oci-registry-0.4.5/src/api/stream.rsuse core::fmt;
use core::marker::PhantomData;
use core::pin::Pin;
use actix_web::web::Bytes;
use futures::stream::Stream;
use futures::stream::StreamExt;
use futures::task::Context;
use futures::task::Poll;
use pin_project::pin_project;
use sha2::Digest;
use sha2::Sha256;
#[pin_project]
pub struct DigestCheckedStream<S, E, IE>
where
S: Stream<Item = Result<Bytes, IE>> + Unpin,
E: std::error::Error + From<IE> + From<DigestMismatchError> + 'static
{
#[pin]
inner: S,
wanted_digest: [u8; 32],
hasher: Option<Sha256>,
_e: PhantomData<E>
}
impl<S, E, IE> Stream for DigestCheckedStream<S, E, IE>
where
S: Stream<Item = Result<Bytes, IE>> + Unpin,
E: std::error::Error + From<IE> + From<DigestMismatchError> + 'static
{
type Item = Result<Bytes, E>;
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let Poll::Ready(chunk) = Pin::new(&mut self.inner).poll_next(ctx) else {
return Poll::Pending;
};
let Some(chunk) = chunk else {
// When the stream has ended, we have one last step - finalize the hash.
// * If self.hasher is None, we've already done that; either the caller has made a
// mistake or we've previously returned a DigestMismatchError.
// * If the hash matches self.wanted_digest, return None to signal the end of the
// stream.
// * If the hash does not match self.wanted_digest, return a DigestMismatchError.
return match std::mem::take(&mut self.hasher) {
None => Poll::Ready(None),
Some(hasher) => {
let result: [u8; 32] = hasher.finalize().into();
match (result == self.wanted_digest) {
true => Poll::Ready(None),
false => {
let error = DigestMismatchError { expected: self.wanted_digest, actual: result };
Poll::Ready(Some(Err(error.into())))
}
}
}
};
};
let Ok(chunk) = chunk else {
return Poll::Ready(Some(chunk.map_err(Into::into)));
};
if let Some(h) = self.hasher.as_mut() {
h.update(&chunk);
}
Poll::Ready(Some(Ok(chunk)))
}
}
impl<S, E, IE> DigestCheckedStream<S, E, IE>
where
S: Stream<Item = Result<Bytes, IE>> + Unpin,
E: std::error::Error + From<IE> + From<DigestMismatchError> + 'static
{
pub fn new(inner: S, wanted_digest: [u8; 32]) -> Self {
Self {
inner,
wanted_digest,
hasher: Some(Sha256::new()),
_e: PhantomData
}
}
}
#[derive(Debug, Clone)]
pub struct DigestMismatchError {
expected: [u8; 32],
actual: [u8; 32]
}
impl fmt::Display for DigestMismatchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Digest '")?;
for byte in self.actual.iter() {
write!(f, "{:x}", byte)?;
}
f.write_str("' did not match expected '")?;
for byte in self.expected.iter() {
write!(f, "{:x}", byte)?;
}
f.write_str("'")
}
}
impl std::error::Error for DigestMismatchError {}
pub async fn hash<S, E>(mut stream: S) -> Result<[u8; 32], E>
where
S: Stream<Item = Result<Bytes, E>> + Unpin,
E: std::error::Error + 'static
{
let mut hasher = Sha256::new();
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
hasher.update(&chunk);
}
Ok(hasher.finalize().into())
}
0707010000001F000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001D00000000oci-registry-0.4.5/src/image07070100000020000081A400000000000000000000000166282B010000084C000000000000000000000000000000000000002000000000oci-registry-0.4.5/src/image.rsuse std::borrow::Cow;
use std::fmt;
use std::str::FromStr;
use compact_str::CompactString;
use lazy_regex::lazy_regex;
use lazy_regex::Lazy;
use lazy_regex::Regex;
use serde_with::DeserializeFromStr;
mod error;
static RE_IMAGE: Lazy<Regex> = lazy_regex!("^[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*$");
static RE_TAG: Lazy<Regex> = lazy_regex!("^[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}$");
fn is_valid_sha256(s: &str) -> bool {
s.len() == 64 && s.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit()) && hex::decode(s).is_ok()
}
#[derive(Debug, DeserializeFromStr)]
pub struct ImageName(CompactString);
impl FromStr for ImageName {
type Err = error::InvalidImageName;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match RE_IMAGE.is_match(input) {
false => Err(error::InvalidImageName(input.to_string())),
true => Ok(ImageName(input.into()))
}
}
}
impl AsRef<str> for ImageName {
#[inline]
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
impl fmt::Display for ImageName {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Debug, DeserializeFromStr)]
pub enum ImageReference {
Tag(CompactString),
Sha256(String)
}
impl FromStr for ImageReference {
type Err = error::InvalidImageReference;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input.strip_prefix("sha256:") {
None => match RE_TAG.is_match(input) {
false => Err(error::InvalidImageReference(input.to_string())),
true => Ok(ImageReference::Tag(input.into()))
},
Some(s) => match is_valid_sha256(s) {
false => Err(error::InvalidImageReference(input.to_string())),
true => Ok(ImageReference::Sha256(s.into()))
}
}
}
}
impl fmt::Display for ImageReference {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Tag(s) => s.fmt(f),
Self::Sha256(s) => write!(f, "sha256:{s}")
}
}
}
impl ImageReference {
pub fn to_str(&self) -> Cow<'_, str> {
match self {
Self::Tag(s) => Cow::Borrowed(s.as_ref()),
Self::Sha256(s) => Cow::Owned(format!("sha256:{s}"))
}
}
}
07070100000021000081A400000000000000000000000166282B01000000ED000000000000000000000000000000000000002600000000oci-registry-0.4.5/src/image/error.rs#[derive(Debug, thiserror::Error)]
#[error("Invalid image name '{0}'")]
pub struct InvalidImageName(pub String);
#[derive(Debug, thiserror::Error)]
#[error("Invalid image reference '{0}'")]
pub struct InvalidImageReference(pub String);
07070100000022000081A400000000000000000000000166282B010000006C000000000000000000000000000000000000001E00000000oci-registry-0.4.5/src/lib.rs#![allow(dead_code)]
#![allow(unused_parens)]
pub mod api;
mod image;
mod storage;
mod upstream;
mod util;
07070100000023000081A400000000000000000000000166282B01000014C9000000000000000000000000000000000000001F00000000oci-registry-0.4.5/src/main.rs#![allow(unused_parens)]
use core::future;
use core::time::Duration;
use std::time::SystemTime;
use actix_web::dev::Service;
use actix_web::http::header::HeaderName;
use actix_web::http::header::HeaderValue;
use actix_web::web;
use actix_web::HttpResponse;
use actix_web_prometheus::PrometheusMetricsBuilder;
use clap::Parser;
use compact_str::CompactString;
use futures::future::FutureExt;
use tokio::sync::oneshot;
use tracing::error;
use tracing::info;
use tracing::warn;
mod api;
mod image;
mod storage;
mod upstream;
mod util;
use storage::StorageConfig;
use upstream::InvalidationConfig;
use upstream::UpstreamConfig;
#[derive(Debug, Parser)]
struct Config {
/// An IP address and port combination to listen on a network socket, or a path prefixed with
/// "unix:" to listen on a Unix domain socket
#[clap(env, long, default_value = "0.0.0.0:80")]
listen: socket_address::Address,
#[clap(env, long, default_value = "docker.io")]
default_namespace: CompactString,
/// If enabled, will validate a blob's SHA256 digest when reading it from cache storage; if the
/// digest doesn't match what was expected based on the request URL, it will be deleted from
/// storage and re-retrieved from upstream. This has an impact on performance, as the entire
/// blob needs to be read from storage twice instead of just once.
#[clap(env, long, default_value_t = false)]
check_cache_digest: bool,
#[clap(flatten)]
upstream: UpstreamConfig,
#[clap(subcommand)]
storage: StorageConfig
}
#[inline]
fn liveness() -> future::Ready<HttpResponse> {
future::ready(HttpResponse::Ok().body(""))
}
#[allow(dead_code)] // TODO: Implement
#[inline]
async fn readiness() -> Result<&'static str, api::error::Error> {
// TODO: Check upstream and storage
Ok("")
}
async fn cleanup(upstream: &InvalidationConfig, repo: &storage::Repository) {
let now = SystemTime::now();
let mut count = match repo.delete_old_blobs(now - upstream.blob).await {
Ok(v) => v,
Err(error) => {
error!(%error, "Error cleaning up blobs");
0
}
};
for (ns, age) in upstream.manifests.iter() {
let ns: &str = ns.as_ref();
match repo.delete_old_manifests(ns, now - *age).await {
Ok(v) => count += v,
Err(error) => error!(%error, namespace = ns, "Error cleaning up manifests")
};
}
if (count > 0) {
warn!(count, "Aged out objects");
} else {
info!(count, "Aged out objects");
}
}
#[actix_web::main]
async fn main() {
let config = Config::parse();
tracing_subscriber::fmt().with_env_filter(tracing_subscriber::EnvFilter::from_default_env()).compact().init();
let repo = config.storage.repository();
let upstream = config.upstream.clients().await.unwrap();
let (shutdown_tx, mut shutdown_rx) = oneshot::channel();
let background = {
let repo = repo.clone();
let upstream = upstream.invalidation_config();
tokio::task::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(300));
loop {
tokio::select! {
_ = interval.tick() => (),
_ = &mut shutdown_rx => break
};
cleanup(&upstream, &repo).await;
}
})
};
let prometheus = PrometheusMetricsBuilder::new("http").endpoint("/metrics").build().unwrap();
let per_request_config = web::Data::new(api::RequestConfig::new(repo, upstream, config.default_namespace, config.check_cache_digest));
let server = actix_web::HttpServer::new(move || {
actix_web::App::new()
.app_data(per_request_config.clone())
.wrap(prometheus.clone())
.service(
web::scope("/v2")
.wrap(actix_web::middleware::Logger::default())
.route("/", web::get().to(api::root))
// /v2/library/telegraf/manifests/1.24-alpine
// /v2/library/redis/manifests/sha256:226cbafc637cd58cf008bf87ec9d1548ad1b672ef4279433495bdff100cdb883
// /v2/docker.io/library/telegraf/manifests/1.24-alpine
// /v2/docker.io/library/redis/manifests/sha256:226cbafc637cd58cf008bf87ec9d1548ad1b672ef4279433495bdff100cdb883
.route("/{image:[^{}]+}/manifests/{reference}", web::head().to(api::manifest))
.route("/{image:[^{}]+}/manifests/{reference}", web::get().to(api::manifest))
// /v2/grafana/grafana/blobs/sha256:6864e61916f58174557076c34e7122753331cf28077edb0f23e1fb5419dd6acd
// /v2/docker.io/grafana/grafana/blobs/sha256:6864e61916f58174557076c34e7122753331cf28077edb0f23e1fb5419dd6acd
.route("/{image:[^{}]+}/blobs/{digest}", web::get().to(api::blob))
.wrap_fn(|req, srv| {
srv.call(req).map(|response| {
response.map(|mut ok| {
ok.headers_mut()
.insert(HeaderName::from_static("docker-distribution-api-version"), HeaderValue::from_static("registry/2.0"));
ok
})
})
})
)
.service(
web::scope("/_admin")
.wrap(actix_web::middleware::Logger::default())
.route("/{image:[^{}]+}/manifests/{reference}", web::delete().to(api::delete_manifest))
.route("/{image:[^{}]+}/blobs/{digest}", web::delete().to(api::delete_blob))
)
.route("/", web::get().to(liveness))
});
match config.listen {
socket_address::Address::Network(addr) => server.shutdown_timeout(10).bind(&addr).unwrap().run().await.unwrap(),
socket_address::Address::UnixSocket(path) => server.shutdown_timeout(10).bind_uds(&path).unwrap().run().await.unwrap()
};
shutdown_tx.send(()).unwrap();
background.await.unwrap();
}
07070100000024000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001F00000000oci-registry-0.4.5/src/storage07070100000025000081A400000000000000000000000166282B0100000D7A000000000000000000000000000000000000002200000000oci-registry-0.4.5/src/storage.rsuse core::time::Duration;
use std::time::SystemTime;
use actix_web::body::SizedStream;
use bytes::Bytes;
use clap::Subcommand;
use compact_str::format_compact;
use dkregistry::mediatypes::MediaTypes;
use futures::stream::BoxStream;
use futures::stream::TryStream;
use futures::stream::TryStreamExt;
use serde::Deserialize;
use serde::Serialize;
mod error;
pub mod filesystem;
pub mod s3;
pub use error::Error;
#[derive(Clone, Debug, Subcommand)]
pub enum StorageConfig {
S3(s3::Config),
Filesystem(filesystem::Config)
}
impl StorageConfig {
pub fn repository(&self) -> Repository {
match self {
Self::S3(config) => Repository::S3(config.repository()),
Self::Filesystem(config) => Repository::Filesystem(config.repository())
}
}
}
#[derive(Clone)]
pub enum Repository {
S3(s3::Repository),
Filesystem(filesystem::Repository)
}
pub struct ReadStream {
length: u64,
inner: BoxStream<'static, Result<Bytes, std::io::Error>>
}
impl ReadStream {
pub fn new(length: u64, inner: BoxStream<'static, Result<Bytes, std::io::Error>>) -> Self {
Self { length, inner }
}
pub fn length(&self) -> u64 {
self.length
}
pub fn into_inner(self) -> BoxStream<'static, Result<Bytes, std::io::Error>> {
self.inner
}
}
impl From<ReadStream> for SizedStream<BoxStream<'static, Result<Bytes, Box<dyn std::error::Error + 'static>>>> {
fn from(stream: ReadStream) -> Self {
SizedStream::new(stream.length, Box::pin(stream.inner.err_into()))
}
}
impl Repository {
pub async fn read(&self, object: &str, invalidation: Duration) -> Result<ReadStream, Error> {
let result = match self {
Self::S3(r) => r.read(object, invalidation).await?,
Self::Filesystem(r) => r.read(object.into(), invalidation).await?
};
Ok(result)
}
pub async fn write<S, E>(&self, object: &str, reader: S, length: i64) -> Result<(), Error>
where
S: TryStream<Ok = Bytes, Error = E> + Unpin + Send + 'static,
E: std::error::Error + From<std::io::Error> + Send + Sync + 'static,
Error: From<E>
{
#[allow(clippy::let_unit_value)] // Because it's likely that we will change the return type eventually, it'll require fewer changes, and it's harmless as-is.
let result = match self {
Self::S3(r) => r.write(object, reader, length).await?,
Self::Filesystem(r) => r.write(object.into(), reader).await?
};
Ok(result)
}
pub async fn delete(&self, object: &str) -> Result<(), Error> {
match self {
Self::S3(r) => r.delete(object).await?,
Self::Filesystem(r) => r.delete(object.as_ref()).await?
};
Ok(())
}
pub async fn delete_old_blobs(&self, older_than: SystemTime) -> Result<usize, Error> {
match self {
Self::S3(r) => r.delete_old_objects(older_than, "blobs/").await,
Self::Filesystem(r) => r.delete_old_files(older_than, "blobs".as_ref()).await
}
}
pub async fn delete_old_manifests(&self, ns: &str, older_than: SystemTime) -> Result<usize, Error> {
let prefix = format_compact!("manifests/{ns}");
let prefix: &str = prefix.as_ref();
match self {
Self::S3(r) => r.delete_old_objects(older_than, prefix).await,
Self::Filesystem(r) => r.delete_old_files(older_than, prefix.as_ref()).await
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Manifest {
pub manifest: Bytes,
pub media_type: MediaTypes,
pub digest: Option<String>
}
impl Manifest {
pub fn new(manifest: Bytes, media_type: MediaTypes, digest: Option<String>) -> Self {
Self { manifest, media_type, digest }
}
}
07070100000026000081A400000000000000000000000166282B01000007F4000000000000000000000000000000000000002800000000oci-registry-0.4.5/src/storage/error.rsuse arcerror::ArcError;
use rusoto_core::RusotoError;
use crate::api::stream::DigestMismatchError;
#[derive(Debug, Clone, thiserror::Error)]
pub enum Error {
#[error("I/O error: {0}")]
Io(ArcError<std::io::Error>),
#[error("Failed to list objects in S3: {0:?}")]
RusotoList(ArcError<RusotoError<rusoto_s3::ListObjectsV2Error>>),
#[error("Failed to get object from S3: {0:?}")]
RusotoGet(ArcError<RusotoError<rusoto_s3::GetObjectError>>),
#[error("Failed to put object into S3: {0:?}")]
RusotoPut(ArcError<RusotoError<rusoto_s3::PutObjectError>>),
#[error("Failed to delete object from S3: {0:?}")]
RusotoDelete(ArcError<RusotoError<rusoto_s3::DeleteObjectError>>),
#[error("Failed to parse datetime: {0}")]
ParseTime(#[from] time::error::Parse),
#[error("Object too old: {0}")]
ObjectTooOld(humantime::Duration),
#[error("Error reading from upstream: {0}")]
Upstream(ArcError<dkregistry::errors::Error>),
#[error("{0}")]
DataCorrupt(#[from] DigestMismatchError)
}
impl From<std::io::Error> for Error {
#[inline]
fn from(inner: std::io::Error) -> Self {
Self::Io(ArcError::from(inner))
}
}
impl From<RusotoError<rusoto_s3::ListObjectsV2Error>> for Error {
#[inline]
fn from(inner: RusotoError<rusoto_s3::ListObjectsV2Error>) -> Self {
Self::RusotoList(ArcError::from(inner))
}
}
impl From<RusotoError<rusoto_s3::GetObjectError>> for Error {
#[inline]
fn from(inner: RusotoError<rusoto_s3::GetObjectError>) -> Self {
Self::RusotoGet(ArcError::from(inner))
}
}
impl From<RusotoError<rusoto_s3::PutObjectError>> for Error {
#[inline]
fn from(inner: RusotoError<rusoto_s3::PutObjectError>) -> Self {
Self::RusotoPut(ArcError::from(inner))
}
}
impl From<RusotoError<rusoto_s3::DeleteObjectError>> for Error {
#[inline]
fn from(inner: RusotoError<rusoto_s3::DeleteObjectError>) -> Self {
Self::RusotoDelete(ArcError::from(inner))
}
}
impl From<dkregistry::errors::Error> for Error {
#[inline]
fn from(inner: dkregistry::errors::Error) -> Self {
Self::Upstream(ArcError::from(inner))
}
}
07070100000027000081A400000000000000000000000166282B0100001205000000000000000000000000000000000000002D00000000oci-registry-0.4.5/src/storage/filesystem.rsuse core::time::Duration;
use std::path::Path;
use std::time::SystemTime;
use actix_web::web::Bytes;
use async_stream::try_stream;
use async_walkdir::WalkDir;
use camino::Utf8Component;
use camino::Utf8Path;
use camino::Utf8PathBuf;
use clap::Parser;
use futures::stream::StreamExt;
use futures::stream::TryStream;
use futures::stream::TryStreamExt;
use tokio::fs::create_dir_all;
use tokio::fs::remove_file;
use tokio::fs::symlink_metadata;
use tokio::fs::File;
use tokio::fs::OpenOptions;
use tokio::io::AsyncBufReadExt;
use tokio::io::AsyncWriteExt;
use tokio::io::BufReader;
use tokio::io::BufWriter;
use tracing::error;
use tracing::info;
use super::ReadStream;
#[derive(Clone, Debug, Parser)]
pub struct Config {
#[clap(env = "FILESYSTEM_ROOT", long)]
root: Utf8PathBuf
}
impl Config {
pub fn repository(&self) -> Repository {
Repository { root: self.root.clone() }
}
}
#[derive(Debug, Clone)]
pub struct Repository {
root: Utf8PathBuf
}
impl Repository {
fn full_path(&self, path: &Utf8Path) -> Utf8PathBuf {
let path = path.components().filter(|c| matches!(c, Utf8Component::ParentDir | Utf8Component::Normal(_))).collect::<Utf8PathBuf>();
self.root.join(path)
}
pub async fn read(&self, object: &Utf8Path, invalidation: Duration) -> Result<ReadStream, super::Error> {
let path = self.full_path(object);
let (age, length) = {
let metadata = symlink_metadata(&path).await?;
(SystemTime::now().duration_since(metadata.modified()?).unwrap_or_default(), metadata.len())
};
if (age > invalidation) {
return Err(super::Error::ObjectTooOld(age.into()));
}
let mut file = BufReader::with_capacity(16384, File::open(path).await?);
Ok(ReadStream::new(
length,
Box::pin(try_stream! {
loop {
let buf = file.fill_buf().await?;
if(buf.is_empty()) {
break;
}
let len = buf.len();
yield Bytes::copy_from_slice(buf);
file.consume(len);
}
})
))
}
pub async fn write<S, E>(&self, object: &Utf8Path, reader: S) -> Result<(), super::Error>
where
S: TryStream<Ok = Bytes, Error = E> + Unpin,
E: std::error::Error + From<std::io::Error> + Send + Sync + 'static,
super::Error: From<E>
{
async fn _write<S, E>(file: &mut BufWriter<File>, mut reader: S) -> Result<(), super::Error>
where
S: TryStream<Ok = Bytes, Error = E> + Unpin,
E: std::error::Error + From<std::io::Error> + Send + Sync + 'static,
super::Error: From<E>
{
while let Some(buf) = reader.try_next().await? {
if (buf.is_empty()) {
break;
}
file.write_all(buf.as_ref()).await.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
}
Ok(())
}
let path = self.full_path(object);
if let Some(parent) = path.parent() {
create_dir_all(parent).await?;
}
let file = OpenOptions::default().create(true).read(false).write(true).truncate(true).open(&path).await?;
let mut file = BufWriter::with_capacity(16384, file);
match _write(&mut file, reader).await {
Ok(_) => Ok(file.flush().await?),
Err(e) => {
self.delete(object.as_ref()).await?;
Err(e)
}
}
}
pub async fn delete(&self, path: &Path) -> Result<(), std::io::Error> {
remove_file(path).await
}
pub async fn delete_old_files(&self, older_than: SystemTime, prefix: &Utf8Path) -> Result<usize, super::Error> {
let mut count = 0;
let root = self.root.join(prefix);
let mut entries = WalkDir::new(root);
let mut first_iteration = true;
while let Some(entry) = entries.next().await {
let entry = match entry {
Ok(v) => v,
// If we get a NotFound error on the first iteration, it only means that we haven't cached anything under this prefix yet
Err(e) if e.kind() == std::io::ErrorKind::NotFound && first_iteration => continue,
Err(error) => {
error!(path = %prefix, %error, "Error walking directory");
continue;
}
};
first_iteration = false;
let path = entry.path();
let metadata = match entry.metadata().await {
Ok(v) => v,
Err(error) => {
error!(path = %path.display(), %error, "Error reading metadata");
continue;
}
};
if (!metadata.is_file()) {
continue;
}
let modified = match metadata.modified() {
Ok(v) => v,
Err(error) => {
error!(path = %path.display(), %error, "Error reading mtime");
continue;
}
};
if (modified < older_than) {
match self.delete(&path).await {
Ok(_) => info!(path = %path.display(), "Aged out"),
Err(error) => {
error!(path = %path.display(), %error, "Error deleting object");
continue;
}
}
count += 1;
}
}
Ok(count)
}
}
07070100000028000081A400000000000000000000000166282B0100001A9A000000000000000000000000000000000000002500000000oci-registry-0.4.5/src/storage/s3.rsuse core::pin::Pin;
use core::time::Duration;
use std::str::FromStr;
use std::time::SystemTime;
use std::vec::IntoIter;
use actix_web::web::Bytes;
use clap::Parser;
use compact_str::CompactString;
use futures::future::BoxFuture;
use futures::future::FutureExt;
use futures::stream::Stream;
use futures::stream::StreamExt;
use futures::stream::TryStream;
use futures::stream::TryStreamExt;
use futures::task::Context;
use futures::task::Poll;
use rusoto_core::request::HttpClient;
use rusoto_core::ByteStream;
use rusoto_core::Region;
use rusoto_core::RusotoError;
use rusoto_credential::StaticProvider;
use rusoto_s3::DeleteObjectError;
use rusoto_s3::DeleteObjectRequest;
use rusoto_s3::GetObjectError;
use rusoto_s3::GetObjectOutput;
use rusoto_s3::GetObjectRequest;
use rusoto_s3::ListObjectsV2Error;
use rusoto_s3::ListObjectsV2Output;
use rusoto_s3::ListObjectsV2Request;
use rusoto_s3::PutObjectRequest;
use rusoto_s3::S3Client;
use rusoto_s3::S3;
use time::format_description::well_known::Rfc2822;
use time::format_description::well_known::Rfc3339;
use time::OffsetDateTime;
use tracing::info;
use super::ReadStream;
#[derive(Clone, Debug, Parser)]
pub struct Config {
#[clap(env = "S3_HOST", long)]
host: Option<String>,
#[clap(env = "S3_ACCESS_KEY", long)]
access_key: CompactString,
#[clap(env = "S3_SECRET_KEY", long)]
secret_key: String,
#[clap(env = "S3_REGION", long, default_value = "us-east-1")]
region: CompactString,
#[clap(env = "S3_BUCKET", long)]
bucket: CompactString
}
impl Config {
pub fn repository(&self) -> Repository {
let region = match self.host.clone() {
Some(s) => Region::Custom { name: self.region.to_string(), endpoint: s },
None => Region::from_str(&self.region).unwrap()
};
let creds = StaticProvider::new(self.access_key.to_string(), self.secret_key.clone(), None, None);
let http = HttpClient::new().unwrap();
Repository {
inner: S3Client::new_with(http, creds, region),
bucket: self.bucket.clone()
}
}
}
struct ListObjectsStream {
client: S3Client,
bucket: CompactString,
current_continuation_token: Option<String>,
current_contents: IntoIter<rusoto_s3::Object>,
current_future: Option<BoxFuture<'static, Result<ListObjectsV2Output, RusotoError<ListObjectsV2Error>>>>
}
impl Stream for ListObjectsStream {
type Item = Result<rusoto_s3::Object, RusotoError<ListObjectsV2Error>>;
#[rustfmt::skip]
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if let Some(obj) = self.current_contents.next() {
return Poll::Ready(Some(Ok(obj)));
}
if let Some(mut future) = self.current_future.take() {
let output = match future.poll_unpin(ctx) {
Poll::Ready(Ok(v)) => v,
Poll::Ready(Err(e)) => return Poll::Ready(Some(Err(e))),
Poll::Pending => {
self.current_future = Some(future);
return Poll::Pending;
}
};
self.current_continuation_token = output.continuation_token;
self.current_contents = match output.contents {
Some(v) => v.into_iter(),
None => vec![].into_iter()
};
ctx.waker().wake_by_ref();
return Poll::Pending;
}
let Some(token) = self.current_continuation_token.take() else {
return Poll::Ready(None);
};
self.current_future = {
let client = Box::pin(self.client.clone());
let bucket = self.bucket.to_string();
Some(Box::pin(async move {
client.list_objects_v2(ListObjectsV2Request{
bucket,
continuation_token: Some(token),
..Default::default()
}).await
}))
};
ctx.waker().wake_by_ref();
Poll::Pending
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self.current_continuation_token.is_some() || self.current_future.is_some() {
true => (self.current_contents.len(), None),
false => (self.current_contents.len(), Some(self.current_contents.len()))
}
}
}
#[derive(Clone)]
pub struct Repository {
inner: S3Client,
bucket: CompactString
}
impl Repository {
async fn list_objects(&self, prefix: &str) -> Result<ListObjectsStream, RusotoError<ListObjectsV2Error>> {
let req = ListObjectsV2Request {
bucket: self.bucket.to_string(),
prefix: Some(prefix.into()),
..Default::default()
};
let result = self.inner.list_objects_v2(req).await?;
Ok(ListObjectsStream {
client: self.inner.clone(),
bucket: self.bucket.clone(),
current_continuation_token: result.continuation_token,
current_contents: result.contents.unwrap_or_default().into_iter(),
current_future: None
})
}
async fn get_object(&self, object: &str) -> Result<GetObjectOutput, RusotoError<GetObjectError>> {
let req = GetObjectRequest {
bucket: self.bucket.to_string(),
key: object.into(),
..Default::default()
};
self.inner.get_object(req).await
}
pub async fn read(&self, object: &str, invalidation: Duration) -> Result<ReadStream, super::Error> {
let obj = self.get_object(object).await?;
let time = obj.last_modified.map(|s| OffsetDateTime::parse(&s, &Rfc2822)).transpose()?.unwrap_or(OffsetDateTime::UNIX_EPOCH);
let age = Duration::try_from(SystemTime::now() - time).unwrap_or_default();
if (age > invalidation) {
return Err(super::Error::ObjectTooOld(age.into()));
}
Ok(ReadStream::new(obj.content_length.unwrap().try_into().unwrap_or_default(), Box::pin(obj.body.unwrap())))
}
pub async fn write<S, E>(&self, object: &str, reader: S, length: i64) -> Result<(), super::Error>
where
S: TryStream<Ok = Bytes, Error = E> + Unpin + Send + 'static,
E: std::error::Error + Send + Sync + 'static,
super::Error: From<E>
{
let req = PutObjectRequest {
bucket: self.bucket.to_string(),
key: object.into(),
content_length: Some(length),
body: Some(ByteStream::new(reader.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)))),
..Default::default()
};
if let Err(e) = self.inner.put_object(req).await {
self.delete(object).await?;
return Err(e.into());
}
Ok(())
}
pub async fn delete(&self, object: &str) -> Result<(), RusotoError<DeleteObjectError>> {
let req = DeleteObjectRequest {
bucket: self.bucket.to_string(),
key: object.to_owned(),
..Default::default()
};
self.inner.delete_object(req).await?;
Ok(())
}
pub async fn delete_old_objects(&self, older_than: SystemTime, prefix: &str) -> Result<usize, super::Error> {
let mut count = 0;
let mut stream = self.list_objects(prefix).await?;
while let Some(obj) = stream.next().await {
let obj = obj?;
let Some(key) = obj.key else {
continue;
};
let modified = obj.last_modified.and_then(|s| OffsetDateTime::parse(&s, &Rfc3339).ok()).unwrap_or(OffsetDateTime::UNIX_EPOCH);
if (modified < older_than) {
match self.delete(key.as_ref()).await {
Ok(_) => info!(object = key, "Aged out"),
Err(_) => continue
};
count += 1;
}
}
Ok(count)
}
}
07070100000029000081A400000000000000000000000166282B0100001CB2000000000000000000000000000000000000002300000000oci-registry-0.4.5/src/upstream.rsuse std::collections::HashMap;
use camino::Utf8PathBuf;
use clap::Parser;
use compact_str::CompactString;
use dkregistry::errors::Error;
use dkregistry::v2::Client as InnerClient;
use humantime::Duration;
use serde::Deserialize;
use serde_with::serde_as;
use serde_with::DisplayFromStr;
use tokio::fs::read_to_string;
use tracing::info;
use tracing::warn;
use crate::util::SecretString;
#[derive(Clone, Debug)]
pub struct Client {
pub client: InnerClient,
pub manifest_invalidation_time: core::time::Duration,
pub blob_invalidation_time: core::time::Duration
}
pub struct Clients(HashMap<CompactString, Client>);
impl Clients {
pub fn get<'a>(&'a mut self, key: &str) -> Result<&'a mut Client, Error> {
if (!self.0.contains_key(key)) {
warn!(namespace = key, "Unknown namespace passed; configuring with default settings");
self.insert(key.into(), SingleUpstreamConfig::new(key.into()))?;
}
Ok(self.0.get_mut(key).unwrap())
}
fn insert(&mut self, key: CompactString, config: SingleUpstreamConfig) -> Result<(), Error> {
self.0.insert(key, config.try_into()?);
Ok(())
}
pub fn invalidation_config(&self) -> InvalidationConfig {
let mut config = InvalidationConfig {
blob: core::time::Duration::from_secs(10),
manifests: HashMap::with_capacity(self.0.len())
};
for (ns, client) in self.0.iter() {
if (ns.is_empty()) {
continue;
}
config.manifests.insert(ns.clone(), client.manifest_invalidation_time);
if (client.blob_invalidation_time > config.blob) {
config.blob = client.blob_invalidation_time;
}
}
config
}
}
impl FromIterator<(CompactString, Client)> for Clients {
fn from_iter<T: IntoIterator<Item = (CompactString, Client)>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
#[derive(Clone, Debug)]
pub struct InvalidationConfig {
pub blob: core::time::Duration,
pub manifests: HashMap<CompactString, core::time::Duration>
}
const fn truth() -> bool {
true
}
fn default_manifest_invalidation_time() -> Duration {
core::time::Duration::from_secs(14 * 86400).into()
}
fn default_blob_invalidation_time() -> Duration {
core::time::Duration::from_secs(14 * 86400).into()
}
#[serde_as]
#[derive(Clone, Debug, Deserialize)]
pub struct SingleUpstreamConfig {
namespace: CompactString,
host: CompactString,
#[serde(default = "truth")]
tls: bool,
#[serde(default)]
accept_invalid_certs: bool,
#[serde(default)]
user_agent: Option<arcstr::ArcStr>,
#[serde(default)]
username: Option<SecretString>,
#[serde(default)]
password: Option<SecretString>,
#[serde(default = "default_manifest_invalidation_time")]
#[serde_as(as = "DisplayFromStr")]
manifest_invalidation_time: Duration,
#[serde(default = "default_blob_invalidation_time")]
#[serde_as(as = "DisplayFromStr")]
blob_invalidation_time: Duration
}
impl SingleUpstreamConfig {
fn new(namespace: CompactString) -> Self {
Self::with_host(namespace.clone(), namespace)
}
fn with_host(namespace: CompactString, host: CompactString) -> Self {
Self {
namespace,
host,
tls: true,
accept_invalid_certs: false,
user_agent: None,
username: None,
password: None,
manifest_invalidation_time: default_manifest_invalidation_time(),
blob_invalidation_time: default_blob_invalidation_time()
}
}
}
impl TryFrom<SingleUpstreamConfig> for Client {
type Error = Error;
fn try_from(config: SingleUpstreamConfig) -> Result<Self, Self::Error> {
let client = InnerClient::configure()
.registry(&config.host)
.insecure_registry(!config.tls)
.accept_invalid_certs(config.accept_invalid_certs)
.user_agent(config.user_agent)
.username(config.username.map(|s| s.into_inner()))
.password(config.password.map(|s| s.into_inner()))
.build()?;
Ok(Self {
client,
manifest_invalidation_time: config.manifest_invalidation_time.into(),
blob_invalidation_time: config.blob_invalidation_time.into()
})
}
}
#[derive(Debug, Parser)]
pub struct UpstreamConfig {
#[clap(env, long, default_value = "docker.io")]
/// For requests made without a namespace (I'm looking at you, Docker), this namespace will be
/// used.
default_upstream_namespace: CompactString,
#[clap(env, long)]
/// If not passed, will default to a configuration that works for Docker Hub. If a client
/// passes in a `ns` parameter that isn't found in the configuration, the namespace will be
/// treated as an upstream hostname, and we will try to connect with TLS enabled, requiring
/// valid certs, and with no user-agent/credentials.
upstream_config_file: Option<Utf8PathBuf>,
#[clap(env, long, default_value = "{}")]
/// For security reasons, upstream registry credentials can be passed this way instead of
/// storing them in a config file - this is expected in JSON format, as a map from namespace
/// to credentials.
///
/// Example: `{"docker.io": {"username": "foo", "password": "bar"}, "namespace2": {"username":
/// {"aaa", "pasword": "bbb"}}`
upstream_credentials: String
}
#[derive(Debug, Deserialize)]
pub struct CredentialsOverride<'a> {
username: &'a str,
password: &'a str
}
impl UpstreamConfig {
pub async fn clients(&self) -> Result<Clients, Error> {
let mut upstream_credentials: HashMap<&str, CredentialsOverride<'_>> = serde_json::from_str(self.upstream_credentials.as_ref()).unwrap();
let mut clients = match self.upstream_config_file.as_ref() {
Some(file) => {
let upstream_config = read_to_string(file).await.unwrap();
let upstream_config: Vec<SingleUpstreamConfig> = serde_yaml::from_str(&upstream_config).unwrap();
upstream_config
.into_iter()
.map(|conf| {
info!(config = ?conf, "Parsed upstream config");
conf
})
.map(|mut conf| match upstream_credentials.remove::<str>(conf.namespace.as_ref()) {
Some(cred) => {
if (conf.username.is_some() || conf.password.is_some()) {
let namespace: &str = conf.namespace.as_ref();
warn!(namespace, "Found namespace in UPSTREAM_CREDENTIALS override, and it already has credentials set in the config file");
}
conf.username = Some(cred.username.into());
conf.password = Some(cred.password.into());
conf
},
None => conf
})
.map(|conf| Ok::<_, Error>((conf.namespace.clone(), conf.try_into()?)))
.collect::<Result<Clients, _>>()?
},
None => {
let (username, password) = match upstream_credentials.remove("docker.io") {
Some(creds) => (Some(creds.username.into()), Some(creds.password.into())),
None => (None, None)
};
#[rustfmt::skip]
let client = SingleUpstreamConfig{
namespace: "docker.io".into(),
host: "registry-1.docker.io".into(),
tls: true,
accept_invalid_certs: false,
user_agent: None,
username,
password,
manifest_invalidation_time: default_manifest_invalidation_time(),
blob_invalidation_time: default_blob_invalidation_time()
}.try_into()?;
let mut map = HashMap::with_capacity(1);
map.insert("docker.io".into(), client);
Clients(map)
}
};
for (namespace, _) in upstream_credentials {
warn!(namespace, "Namespace found in UPSTREAM_CREDENTIALS, but not in upstream config file; will be ignored.");
}
let default_client = clients.get(&self.default_upstream_namespace)?.clone();
clients.0.insert("".into(), default_client);
Ok(clients)
}
}
0707010000002A000081A400000000000000000000000166282B0100000389000000000000000000000000000000000000001F00000000oci-registry-0.4.5/src/util.rsuse core::convert::Infallible;
use core::fmt;
use core::str::FromStr;
use compact_str::CompactString;
use serde::Deserialize;
use serde::Deserializer;
#[derive(Clone)]
pub(crate) struct SecretString(CompactString);
impl FromStr for SecretString {
type Err = Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(s.into())
}
}
impl From<&str> for SecretString {
#[inline]
fn from(s: &str) -> Self {
Self(s.into())
}
}
impl fmt::Debug for SecretString {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("\"REDACTED\"")
}
}
impl<'de> Deserialize<'de> for SecretString {
#[inline]
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = CompactString::deserialize(deserializer)?;
Ok(Self(s))
}
}
impl SecretString {
#[inline]
pub(crate) fn into_inner(self) -> CompactString {
self.0
}
}
0707010000002B000081ED00000000000000000000000166282B01000005CA000000000000000000000000000000000000001B00000000oci-registry-0.4.5/test.sh#!/bin/bash
# Expects oci-registry to be listening on localhost:8080, for example:
# RUST_LOG=info,actix-web=debug cargo run -- --listen 0.0.0.0:8080 filesystem --root /tmp/oci-mirror
set -eu
test() {
echo "--- Testing $1/$2"
rm -rf /tmp/oci-mirror
# containerd
url="localhost:8080/v2/$2?ns=$1"
curl -s -o /dev/null -w " %{http_code}: $url\n" "$url"
rm -rf /tmp/oci-mirror
# cri-o
url="localhost:8080/v2/$1/$2"
curl -s -o /dev/null -w " %{http_code}: $url\n" "$url"
rm -rf /tmp/oci-mirror
# Special Docker Hub case falling back to default_ns
if [ "$1" == "docker.io" ]; then
url="localhost:8080/v2/$2"
curl -s -o /dev/null -w " %{http_code}: $url\n" "$url"
fi
}
test 'docker.io' 'envoyproxy/envoy/manifests/v1.26.2'
test 'docker.io' 'library/busybox/manifests/latest'
test 'docker.io' 'grafana/mimirtool/blobs/sha256:31e352740f534f9ad170f75378a84fe453d6156e40700b882d737a8f4a6988a3'
test 'gcr.io' 'distroless/static/manifests/latest'
test 'gcr.io' 'distroless/static/blobs/sha256:fe5ca62666f04366c8e7f605aa82997d71320183e99962fa76b3209fdfbb8b58'
test 'gcr.io' 'flame-public/buildbuddy-app-onprem/manifests/sha256:68932b6227b4c16d6bbc08997620284ef71f7b10ee9b9dc47b631ae92f31a6a3'
test 'ghcr.io' 'buildbarn/bb-runner-installer/manifests/sha256:beb72a39662a613a889f17e7a15254f7e03849e4f7000f399ea7bdabe4a25f79'
test 'ghcr.io' 'buildbarn/bb-runner-installer/blobs/sha256:e2334dd9fee4b77e48a8f2d793904118a3acf26f1f2e72a3d79c6cae993e07f0'
0707010000002C000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001C00000000oci-registry-0.4.5/testdata0707010000002D000081A400000000000000000000000166282B01000005A5000000000000000000000000000000000000002700000000oci-registry-0.4.5/testdata/images.txt# ns repository tag
docker.io tarampampam/webhook-tester 0.4.2
docker.io stpaquet/alpinemailcatcher latest
docker.io stedolan/jq latest
docker.io sig9/snmptrapd latest
docker.io rabbitmqoperator/cluster-operator 2.0.0
docker.io prom/pushgateway v1.2.0
docker.io metrics-server/metrics-server v0.6.1
docker.io metallb/speaker latest
docker.io metallb/controller latest
docker.io library/telegraf 1.24-alpine
docker.io library/redis 6.2.6
docker.io library/rabbitmq 3.10.2
docker.io library/kong 2.8
docker.io library/busybox latest
docker.io library/busybox 1.31.1
docker.io kubernetesui/metrics-scraper latest
docker.io kubernetesui/dashboard latest
docker.io kong/kubernetes-ingress-controller 2.3.1
docker.io kiwigrid/k8s-sidecar 1.15.6
docker.io k8s-minikube/minikube-ingress-dns latest
docker.io jetstack/cert-manager-webhook v1.8.0
docker.io jetstack/cert-manager-controller v1.8.0
docker.io jetstack/cert-manager-cainjector v1.8.0
docker.io ingress-nginx/kube-webhook-certgen latest
docker.io ingress-nginx/controller latest
docker.io grafana/promtail 2.6.1
docker.io grafana/loki 2.6.1
docker.io grafana/grafana 9.2.0
docker.io grafana/grafana 8.3.5
docker.io gospatial/tegola v0.13.0
docker.io external-secrets/external-secrets v0.5.1
docker.io curlimages/curl 7.85.0
docker.io bitnami/postgresql 14.5.0-debian-11-r24
docker.io bitnami/keycloak 19.0.3-debian-11-r3
docker.io bitnami/influxdb 2.4.0-debian-11-r11
0707010000002E000081A400000000000000000000000166282B01000000BF000000000000000000000000000000000000002200000000oci-registry-0.4.5/testdata/s3cfg[default]
access_key = F504CLZ37ECLH011V4XB
secret_key = Btj2sAMtCs7GFpkmrKuMojvSdivXWt8EXy5DDZJ5
host_base = 192.168.1.200:7480
host_bucket = 192.168.1.200:7480/%(bucket)
use_https = False
0707010000002F000081A400000000000000000000000166282B01000001E4000000000000000000000000000000000000002A00000000oci-registry-0.4.5/testdata/upstream.yaml- namespace: docker.io
host: 10.254.20.0
tls: false
accept_invalid_certs: false
user_agent: null
username: null
password: null
manifest_invalidation_time: 14d
blob_invalidation_time: 14d
- namespace: quay.io
host: 10.254.20.0
tls: false
- namespace: gcr.io
host: 10.254.20.0
tls: false
- namespace: ghcr.io
host: 10.254.20.0
tls: false
- namespace: k8s.gcr.io
host: 10.254.20.0
tls: false
- namespace: registry.k8s.io
host: 10.254.20.0
tls: false
07070100000030000041ED00000000000000000000000266282B0100000000000000000000000000000000000000000000001900000000oci-registry-0.4.5/tools07070100000031000081ED00000000000000000000000166282B010000029E000000000000000000000000000000000000003500000000oci-registry-0.4.5/tools/generate-filesystem-profile#!/bin/bash
DIR="$(cd "$(dirname "${0}")"; pwd)"
mkdir -pv test
rm -Rf test/*
RUST_LOG=info,actix-web=debug
RUST_BACKTRACE=1
"./target/x86_64-unknown-linux-gnu/release/oci-registry${1}" \
--listen 0.0.0.0:16385 \
--upstream-config-file=testdata/upstream.yaml \
filesystem \
--root=test \
| sed 's/^/[fs] /' &
pid="$!"
sleep 0.1
while true; do
echo | ncat localhost 16385
sleep 0.1
done &
loop_pid="$!"
"${DIR}/make-test-requests" http://localhost:16385 | sed 's/^/[fs] /'
sleep 2
echo '[fs] done requests'
ps -ef | grep "oci-registry${1}" | grep -- '0\.0\.0\.0:16385' | awk '{print $2}' | xargs kill
echo '[fs] killed oci-registry'
kill "$loop_pid"
sleep 0.5
07070100000032000081ED00000000000000000000000166282B01000000B4000000000000000000000000000000000000002B00000000oci-registry-0.4.5/tools/generate-profiles#!/bin/sh
DIR="$(cd "$(dirname "${0}")"; pwd)"
"${DIR}/generate-filesystem-profile" "$1" &
pid_fs="$!"
"${DIR}/generate-s3-profile" "$1" &
pid_s3="$!"
wait "$pid_fs" "$pid_s3"
07070100000033000081ED00000000000000000000000166282B0100000325000000000000000000000000000000000000002D00000000oci-registry-0.4.5/tools/generate-s3-profile#!/bin/bash
DIR="$(cd "$(dirname "${0}")"; pwd)"
s3cmd rm -rf s3://oci-registry-test
RUST_LOG=info,actix-web=debug
RUST_BACKTRACE=1
"./target/x86_64-unknown-linux-gnu/release/oci-registry${1}" \
--listen 0.0.0.0:16384 \
--upstream-config-file=testdata/upstream.yaml \
s3 \
--host=http://192.168.1.200:7480 \
--access-key=F504CLZ37ECLH011V4XB \
--secret-key=Btj2sAMtCs7GFpkmrKuMojvSdivXWt8EXy5DDZJ5 \
--bucket=oci-registry-test \
| sed 's/^/[s3] /' &
sleep 0.1
while true; do
echo | ncat localhost 16384
sleep 0.1
done &
loop_pid="$!"
"${DIR}/make-test-requests" http://localhost:16384 | sed 's/^/[s3] /'
sleep 2
echo '[s3] done requests'
ps -ef | grep "oci-registry${1}" | grep -- '0\.0\.0\.0:16384' | awk '{print $2}' | xargs kill
echo '[s3] killed oci-registry'
kill "$loop_pid"
sleep 0.5
07070100000034000081ED00000000000000000000000166282B0100000387000000000000000000000000000000000000002C00000000oci-registry-0.4.5/tools/make-test-requests#!/bin/sh
(
for i in {0..200}; do
echo 'GET /'
sleep 0.1
done
for i in {0..3}; do
COUNT=0;
cat "$(cd "$(dirname "${0}")"; pwd)/../testdata/images.txt" | grep -v '^#' | while read ns repo tag; do
manifest_hash="$(curl -svI "$1/v2/$repo/manifests/$tag?ns=$ns" 2>&1 | grep docker-content-digest: | head -n1 | cut -d: -f2- | sed -e 's/^\s\+//' -e 's/\s\+$//')";
curl -s "$1/v2/$repo/manifests/$manifest_hash?ns=$ns" | jq -r '.manifests[].digest' | while read manifest_hash; do
curl -s "$1/v2/$repo/manifests/$manifest_hash?ns=$ns" | jq -r '.config.digest, .layers[].digest' | while read blob_hash; do
echo "GET /v2/$repo/blobs/$blob_hash?ns=$ns";
done &
echo 'GET /';
done &
echo 'GET /';
done
for i in {0..500}; do
echo 'GET /'
sleep 0.1
done
done
) | xargs -n2 -P40 bash -c 'curl -o /dev/null -X "${1}" "'"${1}"'${2}" &>/dev/null; echo $? $@' argv0
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!380 blocks