Compare commits

...

203 Commits

Author SHA1 Message Date
Miloslav Trmač
5c119083fe
Merge pull request #2616 from giuseppe/add-cap-sys-admin-needed-caps
unshare: Add CAP_SYS_ADMIN to needed capabilities
2025-05-30 20:57:26 +02:00
Giuseppe Scrivano
50f414a7cf
unshare: Add CAP_SYS_ADMIN to needed capabilities
Some container storage operations (e.g., mounting the home directory
for containers/storage) require CAP_SYS_ADMIN.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2025-05-30 15:15:44 +02:00
Miloslav Trmač
dc88f3211b
Merge pull request #2605 from cgwalters/manpage-proxy
docs: Add a manpage for experimental-image-proxy
2025-05-26 19:08:29 +02:00
Colin Walters
a5cbf05259 docs: Add a manpage for experimental-image-proxy
I'm thinking about making it un-experimental. Having docs
is a step towards that.

Co-authored-by: Gemini Code Assist (which basically got this right)
Co-authored-by: Miloslav Trmač <mitr@redhat.com>
Signed-off-by: Colin Walters <walters@verbum.org>
2025-05-22 20:31:55 -04:00
Miloslav Trmač
c3e66b5876
Merge pull request #2604 from TomSweeneyRedHat/dev/tsweeney/bumpcommon_v0.60
Bump to c/common 0.63.0, c/image 5.35.0, Skopeo to v1.19.0, v1.20.0-dev
2025-05-22 18:41:40 +02:00
tomsweeneyredhat
aaba5370de Bump to v1.20.0-dev
Bump to the next dev version v1.20.0-dev

Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
2025-05-22 09:55:59 -04:00
tomsweeneyredhat
7aa78df96b Bump to v1.19.0
Bump to v1.19.0 to align with the Podman v5.5 release

Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
2025-05-22 09:55:50 -04:00
Miloslav Trmač
37b0289f3b
Merge pull request #2608 from containers/renovate/github.com-containers-common-0.x
fix(deps): update module github.com/containers/common to v0.63.0
2025-05-21 00:00:56 +02:00
renovate[bot]
64e5ebe20e
fix(deps): update module github.com/containers/common to v0.63.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-20 21:00:14 +00:00
Miloslav Trmač
8335d5aa6e
Merge pull request #2607 from containers/renovate/github.com-containers-image-v5-5.x
fix(deps): update module github.com/containers/image/v5 to v5.35.0
2025-05-20 22:57:20 +02:00
renovate[bot]
ec3516ec89 fix(deps): update module github.com/containers/image/v5 to v5.35.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-05-20 21:48:36 +02:00
Miloslav Trmač
d0d0b7099e Disable Packit builds on ELN
We need Go 1.23.3, which is not yet available there.

Compare https://github.com/containers/podman/pull/25706 .

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-05-20 21:48:36 +02:00
Miloslav Trmač
802f85645c
Merge pull request #2606 from lsm5/packit-post-f40
[skip-ci] Packit: set fedora-all after F40 EOL
2025-05-20 18:16:28 +02:00
Lokesh Mandvekar
9ddfd54926
[skip-ci] Packit: set fedora-all after F40 EOL
F40 is now EOL and all current Fedora releases have Go 1.23. So, we're
safe to re-enable fedora-all.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-05-19 12:22:03 -04:00
Miloslav Trmač
4e4bb0e9d7
Merge pull request #2598 from lsm5/openssf-passing
[CI:DOCS] README.md: Add openssf passing badge
2025-05-19 18:17:45 +02:00
Lokesh Mandvekar
ffad97c2ff
[CI:DOCS] README.md: Add openssf passing badge
Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-05-19 11:54:20 -04:00
Miloslav Trmač
39445ea592
Merge pull request #2601 from cgwalters/get-raw-blob
proxy: Add GetRawBlob
2025-05-16 20:53:08 +02:00
Colin Walters
6ecc6c334f proxy: Move defer() higher up
Pre-existing problem noticed in review.

Signed-off-by: Colin Walters <walters@verbum.org>
2025-05-16 14:14:52 -04:00
Colin Walters
983e77d85f proxy: Add GetRawBlob
The original model the idea here is the proxy centralizes
verification of things like digest. However in practice,
this causes reading to be seriously awkward; ref
https://github.com/containers/containers-image-proxy-rs/issues/79
(Basically `FinishPipe` blocks the metadata channel)

Also, I have a project to implement a registry frontend to
`containers-storage:` and a core problem with `GetBlob` right
now is it *requires* the blob size up front even though the
underlying Go logic doesn't.

Moving to a "raw" interface solves that too. In this new
raw API, we return two file descriptors, one for the data
and one for the error channel, which contains a JSON
serialization of an error.

For the error type we reuse the existing "is error retryable"
and expose that back to the client.

We also (backwards compatibly) add this new error code
for the existing APIs.

Signed-off-by: Colin Walters <walters@verbum.org>
2025-05-16 14:14:52 -04:00
Miloslav Trmač
a477063650
Merge pull request #2596 from lsm5/badges
[CI:DOCS] README.md: Add badges
2025-05-09 14:21:47 +02:00
Lokesh Mandvekar
faa6f8a008 [CI:DOCS] README.md: Add badges
Add badges for License, Latest Release and Go Report Card.
Copied and modified from podman.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-05-08 15:42:39 +05:30
Miloslav Trmač
1942cd2ba7
Merge pull request #2597 from lsm5/communication
[CI:DOCS] CONTRIBUTING.md: Update communication channels
2025-05-07 16:56:21 +02:00
Lokesh Mandvekar
c228b1dba4
[CI:DOCS] CONTRIBUTING.md: Update communication channels
Fixes: #2592

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-05-07 19:04:04 +05:30
Miloslav Trmač
6c3096231c
Merge pull request #2593 from containers/renovate/golang.org-x-term-0.x
fix(deps): update module golang.org/x/term to v0.32.0
2025-05-06 15:26:09 +02:00
renovate[bot]
f8432950fa
fix(deps): update module golang.org/x/term to v0.32.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-06 00:11:08 +00:00
Miloslav Trmač
7ef7c49749
Merge pull request #2591 from containers/renovate/golangci-golangci-lint-2.x
chore(deps): update dependency golangci/golangci-lint to v2.1.6
2025-05-05 18:27:14 +02:00
renovate[bot]
2bd609a0dd
chore(deps): update dependency golangci/golangci-lint to v2.1.6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-04 17:58:13 +00:00
Miloslav Trmač
0f95b2bff9
Merge pull request #2588 from containers/renovate/golangci-golangci-lint-2.x
chore(deps): update dependency golangci/golangci-lint to v2.1.5
2025-04-30 11:48:41 +02:00
renovate[bot]
159095c102
chore(deps): update dependency golangci/golangci-lint to v2.1.5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 19:31:52 +00:00
Miloslav Trmač
4d32babb91
Merge pull request #2587 from containers/renovate/major-ci-vm-image
chore(deps): update dependency containers/automation_images to v20250422
2025-04-28 21:31:21 +02:00
renovate[bot]
eff578f537
chore(deps): update dependency containers/automation_images to v20250422
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 11:50:07 +00:00
Miloslav Trmač
bb26ea90f9
Merge pull request #2583 from containers/renovate/go-golang.org-x-net-vulnerability
chore(deps): update module golang.org/x/net to v0.38.0 [security]
2025-04-17 21:09:40 +02:00
renovate[bot]
4c55fce106
chore(deps): update module golang.org/x/net to v0.38.0 [security]
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-17 15:12:35 +00:00
Miloslav Trmač
ee84e9ae0a
Merge pull request #2581 from mtrmac/btrfs_noversion
Stop setting unused build tags
2025-04-17 17:11:30 +02:00
Miloslav Trmač
5cf5a11e04 Stop setting libdm_no_deferred_remove
No code is consuming this build tag, and it should have
been removed in 8d04b4a9f6 .

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-04-16 18:52:39 +02:00
Miloslav Trmač
47bf2b4ef7 Stop setting btrfs_noversion
c/storage no longer uses this tag after
https://github.com/containers/storage/pull/2308 .

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-04-16 18:52:39 +02:00
Miloslav Trmač
320a3e0775 Don't require BUILDTAGS to be non-empty
This removes a safety mechanism, but it's better than
inventing a dummy tag value (both here and in c/image).

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-04-16 18:52:39 +02:00
Miloslav Trmač
9bf0c3bf7c
Merge pull request #2580 from containers/renovate/github.com-containers-storage-1.x
fix(deps): update module github.com/containers/storage to v1.58.0
2025-04-16 18:43:39 +02:00
renovate[bot]
ed34be71c6
fix(deps): update module github.com/containers/storage to v1.58.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-16 15:55:29 +00:00
Miloslav Trmač
32b8827d78
Merge pull request #2579 from containers/renovate/golangci-golangci-lint-2.x
chore(deps): update dependency golangci/golangci-lint to v2.1.2
2025-04-15 18:14:40 +02:00
renovate[bot]
3755a3db63
chore(deps): update dependency golangci/golangci-lint to v2.1.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 15:45:49 +00:00
Miloslav Trmač
44877b3af2
Merge pull request #2565 from kolyshkin/lint-tests
Add golangci-lint run --tests=false, fix found issues
2025-04-14 13:50:12 +02:00
Kir Kolyshkin
f4d30802b2 Makefile: add linting with --tests=false
Sometimes running golangci-lint with --tests=false helps to uncover some
unused code which was not removed because it has unit tests. Since
everything is already cached, this additional run doesn't take much
time.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-14 12:29:02 +02:00
Kir Kolyshkin
d66183b129 Remove hack/validate-lint.sh wrapper
Before commit d4bd787e this script used to contain some logic,
but now it's just a wrapper that does nothing useful and stands in the
way. Remove it, and call golangci-lint directly.

This slightly changes the way the linting is done, because BUILDTAGS
was empty before, and now they it contains libsubid.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-14 12:29:02 +02:00
Kir Kolyshkin
b74989dfbc integration: add unix tag to non-windows tests
These tests can't be compiled on Windows, so add unix build tag.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-14 12:29:02 +02:00
Kir Kolyshkin
25481e1a88 integration: add _test suffix to files
Some files in integration did not have _test, resulting in lots of
complains when running golangci-lint with --tests=false.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-14 12:29:02 +02:00
Miloslav Trmač
990ac07ff5
Merge pull request #2578 from containers/renovate/golangci-golangci-lint-2.x
chore(deps): update dependency golangci/golangci-lint to v2.1.1
2025-04-14 12:28:46 +02:00
renovate[bot]
53a1b69591
chore(deps): update dependency golangci/golangci-lint to v2.1.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 19:02:44 +00:00
Paul Holzinger
c5ccf21893
Merge pull request #2574 from Luap99/github
.github: check_cirrus_cron work around github bug
2025-04-11 19:33:32 +02:00
Paul Holzinger
f9e03e6c04
.github: check_cirrus_cron work around github bug
So I wondered why our email workflow only reported things for podman...

It seems the secrets: inherit is broken and no longer working, I see all
jobs on all repos failing with:

Error when evaluating 'secrets'. .github/workflows/check_cirrus_cron.yml (Line: 19, Col: 11): Secret SECRET_CIRRUS_API_KEY is required, but not provided while calling.

This makes no sense to me I doubled checked the names, nothing changed
on our side and it is consistent for all projects. Interestingly this
same thing passed on March 10 and 11 (on all repos) but failed before
and after this as well.

Per[1] we are not alone, anyway let's try to get this working again even
if it means more duplication.

[1] actions/runner#2709

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2025-04-11 19:03:55 +02:00
Lokesh Mandvekar
b39bf85a1a GHA: remove .github/labeler.yaml
This was added earlier as part of PR label-based triggering of Packit
jobs. But we decided not to go ahead with that approach, thus keeping
only a single set of tests. This file should've been removed during the
revert, but better late than never.

Ref: https://github.com/containers/skopeo/pull/2558

FWIW, this yaml file doesn't work by itself without the corresponding
GHA which was never included. So, this yaml config was pretty much a NOP
anyway.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-04-11 16:35:18 +05:30
Miloslav Trmač
a6ff545f30
Merge pull request #2566 from kolyshkin/golang-yml
.golangci.yml: simplify
2025-04-10 19:34:53 +02:00
Kir Kolyshkin
4920d7f172 .golangci.yml: simplify
Remove some unused exclusions, document the used ones.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-09 14:38:16 -07:00
Paul Holzinger
c7dca2e3ac
Merge pull request #2570 from mheon/add_governance_and_owners
Add MAINTAINERS.md and Governance, update OWNERS
2025-04-09 21:26:55 +02:00
Matt Heon
5b135b92a8 Add MAINTAINERS.md and Governance, update OWNERS
Many of the people in OWNERS no longer contribute to the project,
so clean the file and restrict to those who are still active.
Alongside this, add our core maintainers who have merge authority
on all repos.

Governance is a simple link to the Podman governance model, and
MAINTAINERS.md mirrors the new OWNERS.

Signed-off-by: Matt Heon <mheon@redhat.com>
2025-04-09 15:06:26 -04:00
Miloslav Trmač
119816b17c
Merge pull request #2569 from containers/renovate/golang.org-x-term-0.x
fix(deps): update module golang.org/x/term to v0.31.0
2025-04-07 20:26:59 +02:00
renovate[bot]
f5c34db79d
fix(deps): update module golang.org/x/term to v0.31.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-06 02:28:30 +00:00
Miloslav Trmač
ddc2848b66
Merge pull request #2562 from luozexuan/main
chore: fix some function names in comment
2025-03-31 16:48:10 +02:00
luozexuan
b6b6415286 chore: fix some function names in comment
Signed-off-by: luozexuan <fetchcode@139.com>
2025-03-30 16:19:50 +08:00
Miloslav Trmač
610f30db60
Merge pull request #2560 from containers/renovate/github.com-containers-common-0.x
fix(deps): update module github.com/containers/common to v0.62.3
2025-03-28 19:52:59 +01:00
renovate[bot]
f7ab0ed03a
fix(deps): update module github.com/containers/common to v0.62.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-28 00:13:32 +00:00
Miloslav Trmač
ecdf380b0c
Merge pull request #2557 from containers/renovate/golangci-golangci-lint-2.x
chore(deps): update dependency golangci/golangci-lint to v2.0.2
2025-03-25 23:54:03 +01:00
renovate[bot]
0e68f7bebd
chore(deps): update dependency golangci/golangci-lint to v2.0.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 22:32:06 +00:00
Miloslav Trmač
c6d7c5916a
Merge pull request #2558 from lsm5/single-set-tmt
[skip-ci] TMT: keep PR-label independent tests
2025-03-25 23:31:34 +01:00
Lokesh Mandvekar
edfeb73504
[skip-ci] TMT: keep PR-label independent tests
Switch to keeping TMT tests independent of PR labels for now.

In order to keep PR-label dependent tests, Packit UI would need
improvement making it clear that some tests are not meant to run,
perhaps also changing the status to `ignore` or `neutral`.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-03-25 16:05:05 +05:30
Miloslav Trmač
f37a82cddf
Merge pull request #2556 from containers/renovate/golangci-golangci-lint-2.x
chore(deps): update dependency golangci/golangci-lint to v2
2025-03-24 20:09:11 +01:00
renovate[bot]
ba2f8b7ace chore(deps): update dependency golangci/golangci-lint to v2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-24 19:42:38 +01:00
Miloslav Trmač
11fc49b491 Rely on golangci-lint exit code instead of expecting empty output
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-24 19:36:22 +01:00
Miloslav Trmač
b78fa41e42 Satisfy staticcheck
> QF1008: could remove embedded field "dockerImageOptions" from selector (staticcheck)

Should not change behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-24 19:29:24 +01:00
Miloslav Trmač
e8d9f916e0
Merge pull request #2555 from containers/renovate/major-ci-vm-image
chore(deps): update dependency containers/automation_images to v20250324
2025-03-24 18:16:13 +01:00
renovate[bot]
da1bf9f7e3
chore(deps): update dependency containers/automation_images to v20250324
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 14:36:01 +00:00
Colin Walters
5b0b0d3954
Merge pull request #2554 from cgwalters/layer-info-extended
proxy: Add GetLayerInfoPiped
2025-03-24 10:35:27 -04:00
Colin Walters
5b30cfe29c
Merge branch 'main' into layer-info-extended 2025-03-21 17:56:01 -04:00
Miloslav Trmač
d62cbd6178
Merge pull request #2551 from mtrmac/go1.23
Update to benefit from Go 1.23
2025-03-21 22:12:24 +01:00
Miloslav Trmač
7983f20adb Remove obsolete build tag syntax
per (go fix ./...).

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-21 21:00:49 +01:00
Miloslav Trmač
8d000f4522 Use the new maps.Keys and slices.Sorted
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-21 21:00:39 +01:00
Miloslav Trmač
1f49b2c0c0 Use slices.Backward
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-21 21:00:31 +01:00
Tom Sweeney
f745bb46bc
Merge pull request #2552 from mtrmac/old-deps
Update old indirect dependencies
2025-03-21 15:55:48 -04:00
Colin Walters
a31470d7a4 proxy: Add GetLayerInfoPiped
I was experimenting with images with lots of layers (> 200) and
this invocation was incorrectly adding the entire response
into what was intended as the metadata plane.

`GetManifest` and `GetConfig` (even those are relatively small)
still always return their data over a pipe, same as blobs.

Add a new `GetLayerInfoPiped` that does the same so we
can easily get this information for images with a lot of layers.

Signed-off-by: Colin Walters <walters@verbum.org>
2025-03-21 15:05:59 -04:00
Miloslav Trmač
ec21960402 Update github.com/hashicorp/go-multierror
This updates from a release to a commit, but the release
is very old, and we get to remove a technically-obsolete dependency.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-21 18:18:22 +01:00
Miloslav Trmač
1a38d97653 Update github.com/dsnet/compress
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-21 18:18:15 +01:00
Miloslav Trmač
115f3727e8
Merge pull request #2524 from yedayak/transport-completions
Transport completions
2025-03-21 18:12:25 +01:00
Yedaya Katsman
49569bcf69 Complete paths for some transports
Transports that reference a file or directory are completed.

Signed-off-by: Yedaya Katsman <yedaya.ka@gmail.com>
2025-03-21 17:31:07 +02:00
Yedaya Katsman
e7e09255b4 Don't complete a space after '<transport>:'
Signed-off-by: Yedaya Katsman <yedaya.ka@gmail.com>
2025-03-21 17:31:06 +02:00
Tom Sweeney
dd71592115
Merge pull request #2527 from mtrmac/enforce-digests
Enforce manifest and blob digests in (skopeo inspect) and (skopeo layers)
2025-03-21 10:04:32 -04:00
Miloslav Trmač
9c0f31dcce In (skopeo inspect), validate the manifest against a digest reference
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-19 19:11:50 +01:00
Miloslav Trmač
9fda7e7304 In (skopeo layers), validate the blob against the expected digest
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-19 19:11:41 +01:00
Miloslav Trmač
a0799484c8 Always close the blob we are reading from a registry
== the HTTP response body.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-19 19:11:30 +01:00
Miloslav Trmač
603d37c588
Merge pull request #2553 from containers/renovate/golang.org-x-term-0.x
fix(deps): update module golang.org/x/term to v0.30.0
2025-03-19 18:56:50 +01:00
renovate[bot]
a51828764c
fix(deps): update module golang.org/x/term to v0.30.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-19 17:13:06 +00:00
Miloslav Trmač
cb7a78c860
Merge pull request #2550 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.64.8
2025-03-19 18:12:01 +01:00
renovate[bot]
b8637922e2
chore(deps): update dependency golangci/golangci-lint to v1.64.8
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-19 16:22:09 +00:00
Miloslav Trmač
48abc39c54
Merge pull request #2545 from giuseppe/add-roadmap
ROADMAP: new file
2025-03-19 17:21:08 +01:00
Giuseppe Scrivano
56ccf09c68
ROADMAP: new file
Closes: https://issues.redhat.com/browse/RUN-2450

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2025-03-19 09:03:05 +01:00
Miloslav Trmač
ceabd93f4a
Merge pull request #2548 from containers/renovate/go-golang.org-x-net-vulnerability
chore(deps): update module golang.org/x/net to v0.36.0 [security]
2025-03-18 20:25:56 +01:00
renovate[bot]
03fa889da5
chore(deps): update module golang.org/x/net to v0.36.0 [security]
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-18 18:51:45 +00:00
Miloslav Trmač
c87f3aeaac
Merge pull request #2547 from mtrmac/go1.23-minimal
Update to Go 1.23
2025-03-18 19:50:26 +01:00
Miloslav Trmač
15132e6c1e Update to Go 1.23
... and stop testing on Fedora 40 because it is not available there.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-03-12 19:59:00 +01:00
Miloslav Trmač
e7fe80b5df
Merge pull request #2546 from containers/renovate/github.com-containers-common-0.x
fix(deps): update module github.com/containers/common to v0.62.2
2025-03-12 19:57:25 +01:00
renovate[bot]
4080a631b1
fix(deps): update module github.com/containers/common to v0.62.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-12 18:28:09 +00:00
Miloslav Trmač
b88f8eccaa
Merge pull request #2544 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.64.7
2025-03-12 19:27:09 +01:00
renovate[bot]
cc743c3c0f
chore(deps): update dependency golangci/golangci-lint to v1.64.7
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-12 03:32:48 +00:00
Miloslav Trmač
a88629df99
Merge pull request #2540 from containers/renovate/github.com-containers-image-v5-5.x
fix(deps): update module github.com/containers/image/v5 to v5.34.2
2025-03-11 17:53:37 +01:00
renovate[bot]
91c6aa613d
fix(deps): update module github.com/containers/image/v5 to v5.34.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-11 03:01:17 +00:00
Miloslav Trmač
9d3331be7b
Merge pull request #2538 from containers/renovate/github.com-containers-storage-1.x
fix(deps): update module github.com/containers/storage to v1.57.2
2025-03-07 19:41:07 +01:00
renovate[bot]
d00ea33dfa
fix(deps): update module github.com/containers/storage to v1.57.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 18:13:27 +00:00
Miloslav Trmač
0f5d87a9c0
Merge pull request #2539 from Luap99/cirrus-rerun
.github: remove cirrus rerun action
2025-03-07 19:12:21 +01:00
Paul Holzinger
7bd0dc216f
.github: remove cirrus rerun action
As pointed out in buildah[1] the action is broken in bad ways where it can
trigger 1000+ rerun wasting our cloud resources.

Get rid of it for now until we find something better or can properly
identify and fix the root cause.

[1] https://github.com/containers/buildah/issues/6035

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2025-03-07 17:44:02 +01:00
Miloslav Trmač
5d0807795d
Merge pull request #2535 from containers/renovate/github.com-opencontainers-image-spec-1.x
fix(deps): update module github.com/opencontainers/image-spec to v1.1.1
2025-03-04 20:02:26 +01:00
renovate[bot]
547141ce57
fix(deps): update module github.com/opencontainers/image-spec to v1.1.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 17:44:25 +00:00
Miloslav Trmač
1de2d3bad9
Merge pull request #2530 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.64.6
2025-03-04 18:43:27 +01:00
renovate[bot]
a185498c73
chore(deps): update dependency golangci/golangci-lint to v1.64.6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 00:36:00 +00:00
Miloslav Trmač
070f2bcfaf
Merge pull request #2533 from containers/renovate/go-github.com-go-jose-go-jose-v4-vulnerability
chore(deps): update module github.com/go-jose/go-jose/v4 to v4.0.5 [security]
2025-03-04 01:35:28 +01:00
renovate[bot]
fad5a31a42
chore(deps): update module github.com/go-jose/go-jose/v4 to v4.0.5 [security]
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 23:57:23 +00:00
Miloslav Trmač
41e4b1b7ac
Merge pull request #2532 from containers/renovate/go-github.com-go-jose-go-jose-v3-vulnerability
chore(deps): update module github.com/go-jose/go-jose/v3 to v3.0.4 [security]
2025-03-04 00:56:15 +01:00
renovate[bot]
5744b9b49d
chore(deps): update module github.com/go-jose/go-jose/v3 to v3.0.4 [security]
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 23:24:57 +00:00
Miloslav Trmač
e9340fbc69
Merge pull request #2534 from containers/renovate/github.com-containers-common-0.x
fix(deps): update module github.com/containers/common to v0.62.1
2025-03-04 00:23:55 +01:00
renovate[bot]
934ea727a4
fix(deps): update module github.com/containers/common to v0.62.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 22:51:38 +00:00
Miloslav Trmač
22ab1a3717
Merge pull request #2528 from containers/renovate/github.com-containers-image-v5-5.x
fix(deps): update module github.com/containers/image/v5 to v5.34.1
2025-03-03 23:49:59 +01:00
renovate[bot]
8a44fe6c8b
fix(deps): update module github.com/containers/image/v5 to v5.34.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-28 22:12:18 +00:00
Miloslav Trmač
2d79fec20c
Merge pull request #2523 from containers/renovate/github.com-spf13-cobra-1.x
fix(deps): update module github.com/spf13/cobra to v1.9.1
2025-02-18 13:46:06 +01:00
Miloslav Trmač
c7aaed7397 Update for cobra API change
This is not _really_ necessary, but let's be consistent
with cobra's style.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-02-17 19:26:53 +01:00
renovate[bot]
9d73060a2e
fix(deps): update module github.com/spf13/cobra to v1.9.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 01:36:56 +00:00
Miloslav Trmač
0283441cf1
Merge pull request #2521 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.64.5
2025-02-14 00:36:38 +01:00
renovate[bot]
5c968d67b8
chore(deps): update dependency golangci/golangci-lint to v1.64.5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-13 23:07:12 +00:00
Miloslav Trmač
690b1ef3e3
Merge pull request #2518 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.64.4
2025-02-13 02:29:15 +01:00
renovate[bot]
841a1b61ae
chore(deps): update dependency golangci/golangci-lint to v1.64.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 23:03:11 +00:00
Miloslav Trmač
8c78c03347
Merge pull request #2517 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.64.3
2025-02-13 00:02:39 +01:00
renovate[bot]
8c2eff1dae
chore(deps): update dependency golangci/golangci-lint to v1.64.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 21:34:46 +00:00
Miloslav Trmač
a5916e63cc
Merge pull request #1960 from lsm5/packit-gating-tests
[skip-ci] Packit/TMT: Run gating tests
2025-02-12 22:34:10 +01:00
Lokesh Mandvekar
f88186e688 [skip-ci] Packit/TMT: Run system tests
This commit enables TMT jobs triggered by Packit to run system tests.

2 set of jobs `dev` and `release` have been added. `dev` jobs are meant
to run on main PRs with additional package updates fetched from
podman-next copr while `release` jobs are meant to run on release-
branch PRs using only the dependencies present in the official distro.

Packit checks PR labels (see previous commit) to filter out
the jobs that get run.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-02-12 21:51:18 +01:00
Lokesh Mandvekar
ff462b3dad PR Labels: apply release label to release- branch PRs
This will be useful in the followup commit that enables TMT test jobs on
PRs.

PRs on `main` branch should be tested with bleeding-edge dependencies
from the podman-next COPR while PRs on `release` branches should be
tested only with the official distro packages. Packit will run/skip the
relevant set of tests based on this label.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-02-12 21:51:18 +01:00
Miloslav Trmač
a3ffb772e1
Merge pull request #2515 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.64.2
2025-02-12 21:25:31 +01:00
renovate[bot]
8c20592d78
chore(deps): update dependency golangci/golangci-lint to v1.64.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 18:31:29 +00:00
Miloslav Trmač
44d0f7103a
Merge pull request #2516 from TomSweeneyRedHat/dev/tsweeney/v1.18.0
Bump Skopeo to v1.18.0, then to v1.19.0-dev
2025-02-12 19:30:57 +01:00
tomsweeneyredhat
20746ae273 Bump Skopeo to v1.19.0-dev
Bumping to the next dev version on the main branch.

Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
2025-02-12 11:29:36 -05:00
tomsweeneyredhat
64361bde06 Bump Skopeo to v1.18.0
As the title says, bumping to v1.18.0 to go out
with Podman v5.4.

Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
2025-02-12 11:27:38 -05:00
Miloslav Trmač
955233070b
Merge pull request #2513 from mheon/cncf_code_of_conduct
Switch to the CNCF Code of Conduct
2025-02-10 21:41:40 +01:00
Matt Heon
bd1ac4668f Switch to the CNCF Code of Conduct
As part of the CNCF Sandbox, we are replacing our existing COC
with the standard CNCF version.

Signed-off-by: Matt Heon <mheon@redhat.com>
2025-02-10 14:45:44 -05:00
Miloslav Trmač
2b3701b7be
Merge pull request #2511 from containers/renovate/golang.org-x-term-0.x
fix(deps): update module golang.org/x/term to v0.29.0
2025-02-05 22:30:13 +01:00
renovate[bot]
59ec554738
fix(deps): update module golang.org/x/term to v0.29.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 20:51:14 +00:00
Miloslav Trmač
83d0e76b83
Merge pull request #2509 from containers/renovate/github.com-containers-common-0.x
fix(deps): update module github.com/containers/common to v0.62.0
2025-02-04 21:50:04 +01:00
renovate[bot]
04d65888a3
fix(deps): update module github.com/containers/common to v0.62.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 22:39:58 +00:00
Miloslav Trmač
958d586c45
Merge pull request #2510 from containers/renovate/major-ci-vm-image
chore(deps): update dependency containers/automation_images to v20250131
2025-02-03 23:38:57 +01:00
renovate[bot]
137a912c55
chore(deps): update dependency containers/automation_images to v20250131
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 17:49:21 +00:00
Miloslav Trmač
dbf619c027
Merge pull request #2505 from containers/renovate/github.com-spf13-pflag-1.x
fix(deps): update module github.com/spf13/pflag to v1.0.6
2025-02-03 18:48:12 +01:00
renovate[bot]
52895bc6cd
fix(deps): update module github.com/spf13/pflag to v1.0.6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 16:56:18 +00:00
Miloslav Trmač
d18677e479
Merge pull request #2508 from containers/renovate/github.com-containers-image-v5-5.x
fix(deps): update module github.com/containers/image/v5 to v5.34.0
2025-02-03 17:55:16 +01:00
renovate[bot]
b78a415987 fix(deps): update module github.com/containers/image/v5 to v5.34.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-01-31 21:34:59 +01:00
Miloslav Trmač
0eb4ad2f54
Merge pull request #2501 from lsm5/rpm-go-macro-cleanup
RPM: cleanup gobuild macro for CentOS Stream
2025-01-31 21:06:48 +01:00
Lokesh Mandvekar
5eba061489 RPM: include check section to silence rpmlint
We're not running any tests in the check section.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-01-31 20:20:44 +01:00
Lokesh Mandvekar
9764c99dbd RPM: cleanup gobuild macro for CentOS Stream
The default gobuild macro on CentOS Stream now accounts for `BUILDTAGS`,
so we don't need to redefine the macro in rpm spec.

The `libtrust_openssl` has been set in the spec for RHEL
environments.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2025-01-31 20:20:44 +01:00
Miloslav Trmač
54d235403a
Merge pull request #2507 from containers/renovate/github.com-containers-storage-1.x
fix(deps): update module github.com/containers/storage to v1.57.1
2025-01-31 18:06:20 +01:00
renovate[bot]
a81cb65fac
fix(deps): update module github.com/containers/storage to v1.57.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 01:17:48 +00:00
Miloslav Trmač
7d6169d219
Merge pull request #2506 from containers/renovate/github.com-containers-storage-1.x
fix(deps): update module github.com/containers/storage to v1.57.0
2025-01-30 20:14:44 +01:00
renovate[bot]
85fa4dff42
fix(deps): update module github.com/containers/storage to v1.57.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 18:12:33 +00:00
Miloslav Trmač
8380f284c7
Merge pull request #2500 from adambkaplan/add-retry-delay
feat: Add `--retry-delay` Option
2025-01-16 23:17:22 +01:00
Adam Kaplan
ed0efc6932 feat: Add --retry-delay Option
- Add option to set a fixed delay between retries.
- Clarify that if delay is unset, skopeo uses an exponential delay for
  retries.

Fixes #2476

Signed-off-by: Adam Kaplan <adam.kaplan@redhat.com>
2025-01-16 22:39:25 +01:00
Miloslav Trmač
3315da48b5
Merge pull request #2498 from containers/renovate/github.com-containers-common-0.x
fix(deps): update module github.com/containers/common to v0.61.1
2025-01-16 21:37:18 +01:00
renovate[bot]
ab53f64473
fix(deps): update module github.com/containers/common to v0.61.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-16 19:43:51 +00:00
Miloslav Trmač
c737e5daea
Merge pull request #2495 from containers/renovate/github.com-containers-image-v5-5.x
fix(deps): update module github.com/containers/image/v5 to v5.33.1
2025-01-16 20:43:05 +01:00
renovate[bot]
653db36664
fix(deps): update module github.com/containers/image/v5 to v5.33.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-16 01:52:10 +00:00
Miloslav Trmač
0633de6350
Merge pull request #2494 from containers/renovate/github.com-containers-storage-1.x
fix(deps): update module github.com/containers/storage to v1.56.1
2025-01-15 16:40:39 +01:00
renovate[bot]
6483de4894
fix(deps): update module github.com/containers/storage to v1.56.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 23:42:40 +00:00
Miloslav Trmač
3d2c80f58f
Merge pull request #2493 from Luap99/test-registry
systemtest: update quay.io registry image
2025-01-13 17:06:13 +01:00
Paul Holzinger
b5a13bccfd systemtest: update quay.io registry image
The "2" tag is very old and not a multi arch manifest. As such testing
on aarch64 failed because it pulled and x86_64 image instead. This was
found in downstream RHEL testing.

The "2.8.2" is multi arch and used in podman testing were we
successfully run aarch64 based testing.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2025-01-11 20:56:39 +01:00
renovate[bot]
eae9e8862c
chore(deps): update dependency containers/automation_images to v20250107 (#2488)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 07:22:06 -05:00
Miloslav Trmač
392aa3f70f
Merge pull request #2487 from containers/renovate/golang.org-x-term-0.x
fix(deps): update module golang.org/x/term to v0.28.0
2025-01-06 15:58:43 +01:00
renovate[bot]
b68afb1a73
fix(deps): update module golang.org/x/term to v0.28.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-05 04:55:13 +00:00
Miloslav Trmač
0eb0ac3707
Merge pull request #2486 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.63.4
2025-01-04 14:59:31 +01:00
renovate[bot]
2a47dff7e1
chore(deps): update dependency golangci/golangci-lint to v1.63.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-03 21:25:55 +00:00
Miloslav Trmač
631555fc83
Merge pull request #2485 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.63.3
2025-01-03 16:18:46 +01:00
renovate[bot]
83efeea4f3
chore(deps): update dependency golangci/golangci-lint to v1.63.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 23:34:23 +00:00
Miloslav Trmač
da5c8d6e7b
Merge pull request #2483 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.63.2
2025-01-02 15:55:47 +01:00
renovate[bot]
deda96636b
chore(deps): update dependency golangci/golangci-lint to v1.63.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 14:06:16 +00:00
Miloslav Trmač
17ea741413
Merge pull request #2482 from containers/renovate/golang.org-x-exp-digest
fix(deps): update golang.org/x/exp digest to b2144cd
2025-01-02 15:05:42 +01:00
renovate[bot]
fb777d3906
fix(deps): update golang.org/x/exp digest to b2144cd
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-01 01:28:27 +00:00
Miloslav Trmač
bf5987896a
Merge pull request #2478 from containers/renovate/go-golang.org-x-net-vulnerability
chore(deps): update module golang.org/x/net to v0.33.0 [security]
2024-12-23 11:09:32 +01:00
renovate[bot]
568d5d1c6f
chore(deps): update module golang.org/x/net to v0.33.0 [security]
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-22 19:13:46 +00:00
Miloslav Trmač
f333a897f6
Merge pull request #2475 from containers/renovate/github.com-containers-ocicrypt-1.x
fix(deps): update module github.com/containers/ocicrypt to v1.2.1
2024-12-17 16:39:20 +01:00
renovate[bot]
1866ecbda2
fix(deps): update module github.com/containers/ocicrypt to v1.2.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 18:06:00 +00:00
Miloslav Trmač
f7801f77cc
Merge pull request #2471 from containers/renovate/golang.org-x-term-0.x
fix(deps): update module golang.org/x/term to v0.27.0
2024-12-04 21:13:01 +01:00
renovate[bot]
b116c5bdce
fix(deps): update module golang.org/x/term to v0.27.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-04 18:13:02 +00:00
Colin Walters
e288827449
Merge pull request #2469 from mtrmac/error-with-usage
Fix handling of errorShouldDisplayUsage
2024-12-03 14:31:04 -05:00
Miloslav Trmač
27baed919d Fix handling of errorShouldDisplayUsage
- Exit with a non-zero exit code
- Actually report the error we detected
- Write usage to stderr

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-12-02 20:45:28 +01:00
Miloslav Trmač
4863e05f5f
Merge pull request #2467 from containers/renovate/golang.org-x-exp-digest
fix(deps): update golang.org/x/exp digest to 2d47ceb
2024-12-02 20:44:57 +01:00
renovate[bot]
a71a8b4c48
fix(deps): update golang.org/x/exp digest to 2d47ceb
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-01 10:52:22 +00:00
Lokesh Mandvekar
4541d649a6 Packit: remove rhel (epel) jobs
RHEL targets are often out of date with respect to golang and other
important dependencies leading to frequent failures. CentOS Stream moves
faster and helps to ensure whatever eventually enters RHEL has been
tested upstream at some point.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2024-11-29 16:05:21 +05:30
Lokesh Mandvekar
96f3804385 Packit: switch fedora copr targets to fedora-all
Fedora-39 is now EOL, so fedora-all will not include it anymore.

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2024-11-29 16:05:21 +05:30
Miloslav Trmač
be26f2eb2f
Merge pull request #2464 from containers/renovate/github.com-stretchr-testify-1.x
fix(deps): update module github.com/stretchr/testify to v1.10.0
2024-11-25 20:26:51 +01:00
renovate[bot]
e9755957df
fix(deps): update module github.com/stretchr/testify to v1.10.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-25 18:46:39 +00:00
Miloslav Trmač
74488c4b86
Merge pull request #2465 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.62.2
2024-11-25 19:45:29 +01:00
renovate[bot]
2a3c8ee5b1
chore(deps): update dependency golangci/golangci-lint to v1.62.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-25 17:53:08 +00:00
Tom Sweeney
87f199fbaf
Merge pull request #2442 from mtrmac/error-change
Update an expected error message
2024-11-20 18:37:49 -05:00
Miloslav Trmač
f423f01d1b Update an expected error message
https://github.com/containers/image/pull/2595 will change it.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-11-20 16:18:20 +01:00
Miloslav Trmač
c5eaf49918
Merge pull request #2462 from containers/renovate/github.com-masterminds-semver-v3-3.x
fix(deps): update module github.com/masterminds/semver/v3 to v3.3.1
2024-11-20 15:50:53 +01:00
renovate[bot]
186e9b4f0b
fix(deps): update module github.com/masterminds/semver/v3 to v3.3.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-19 22:54:13 +00:00
Miloslav Trmač
8896960688
Merge pull request #2454 from containers/renovate/golangci-golangci-lint-1.x
chore(deps): update dependency golangci/golangci-lint to v1.62.0
2024-11-14 22:13:56 +01:00
renovate[bot]
f818827f6d
chore(deps): update dependency golangci/golangci-lint to v1.62.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 20:53:06 +00:00
Miloslav Trmač
0c25d2c9fb
Merge pull request #2457 from containers/renovate/github.com-moby-sys-capability-0.x
fix(deps): update module github.com/moby/sys/capability to v0.4.0
2024-11-14 21:52:47 +01:00
renovate[bot]
bae8ccd7fb
fix(deps): update module github.com/moby/sys/capability to v0.4.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-13 16:26:44 +00:00
Paul Holzinger
181429435e
Merge pull request #2458 from TomSweeneyRedHat/dev/tsweeney/v1.17.0
Bump Skopeo to v1.17.0, c/common v0.61.0, c/image v5.33.0, c/storage v1.56.0
2024-11-13 17:25:52 +01:00
tomsweeneyredhat
293ac065b7 Bump to c/Skopeo v1.18.0-dev
Bumping to the next dev version on the main branch.

Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
2024-11-12 18:02:04 -05:00
987 changed files with 53516 additions and 36086 deletions

View File

@ -21,7 +21,7 @@ env:
SCRIPT_BASE: "./contrib/cirrus"
# Google-cloud VM Images
IMAGE_SUFFIX: "c20241107t210000z-f41f40d13"
IMAGE_SUFFIX: "c20250422t130822z-f42f41d13"
FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}"
# Container FQIN's
@ -62,7 +62,7 @@ doccheck_task:
cpu: 4
memory: 8
env:
BUILDTAGS: &withopengpg 'btrfs_noversion libdm_no_deferred_remove containers_image_openpgp'
BUILDTAGS: &withopengpg 'containers_image_openpgp'
script: |
# TODO: Can't use 'runner.sh setup' inside container. However,
# removing the pre-installed package is the only necessary step
@ -194,7 +194,7 @@ test_skopeo_task:
matrix:
- name: "Skopeo Test" # N/B: Name ref. by hack/get_fqin.sh
env:
BUILDTAGS: 'btrfs_noversion libdm_no_deferred_remove'
BUILDTAGS: ''
- name: "Skopeo Test w/ opengpg"
env:
BUILDTAGS: *withopengpg

1
.fmf/version Normal file
View File

@ -0,0 +1 @@
1

View File

@ -17,4 +17,9 @@ jobs:
# Ref: https://docs.github.com/en/actions/using-workflows/reusing-workflows
call_cron_failures:
uses: containers/podman/.github/workflows/check_cirrus_cron.yml@main
secrets: inherit
secrets:
SECRET_CIRRUS_API_KEY: ${{secrets.SECRET_CIRRUS_API_KEY}}
ACTION_MAIL_SERVER: ${{secrets.ACTION_MAIL_SERVER}}
ACTION_MAIL_USERNAME: ${{secrets.ACTION_MAIL_USERNAME}}
ACTION_MAIL_PASSWORD: ${{secrets.ACTION_MAIL_PASSWORD}}
ACTION_MAIL_SENDER: ${{secrets.ACTION_MAIL_SENDER}}

View File

@ -1,19 +0,0 @@
---
# See also: https://github.com/containers/podman/blob/main/.github/workflows/rerun_cirrus_cron.yml
on:
# Note: This only applies to the default branch.
schedule:
# N/B: This should correspond to a period slightly after
# the last job finishes running. See job defs. at:
# https://cirrus-ci.com/settings/repository/6706677464432640
- cron: '01 01 * * 1-5'
# Debug: Allow triggering job manually in github-actions WebUI
workflow_dispatch: {}
jobs:
# Ref: https://docs.github.com/en/actions/using-workflows/reusing-workflows
call_cron_rerun:
uses: containers/podman/.github/workflows/rerun_cirrus_cron.yml@main
secrets: inherit

View File

@ -1,3 +1,13 @@
---
run:
timeout: 5m
version: "2"
linters:
settings:
staticcheck:
checks:
# Compared to golangci-lint v2.0.2 defaults, we dont exclude
# ST1003, ST1016, ST1020, ST1021, ST1022 as we don't hit those.
- all
- -ST1000 # Incorrect or missing package comment.
- -ST1005 # Incorrectly formatted error string.
exclusions:
presets:
- std-error-handling

View File

@ -9,6 +9,27 @@
downstream_package_name: skopeo
upstream_tag_template: v{version}
# These files get synced from upstream to downstream (Fedora / CentOS Stream) on every
# propose-downstream job. This is done so tests maintained upstream can be run
# downstream in Zuul CI and Bodhi.
# Ref: https://packit.dev/docs/configuration#files_to_sync
files_to_sync:
- src: rpm/gating.yaml
dest: gating.yaml
delete: true
- src: plans/
dest: plans/
delete: true
mkpath: true
- src: systemtest/tmt/
dest: test/tmt/
delete: true
mkpath: true
- src: .fmf/
dest: .fmf/
delete: true
- .packit.yaml
packages:
skopeo-fedora:
pkg_tool: fedpkg
@ -16,8 +37,6 @@ packages:
skopeo-centos:
pkg_tool: centpkg
specfile_path: rpm/skopeo.spec
skopeo-rhel:
specfile_path: rpm/skopeo.spec
skopeo-eln:
specfile_path: rpm/skopeo.spec
@ -31,19 +50,14 @@ jobs:
notifications: &copr_build_failure_notification
failure_comment:
message: "Ephemeral COPR build failed. @containers/packit-build please check."
targets:
- fedora-development-x86_64
- fedora-development-aarch64
- fedora-latest-x86_64
- fedora-latest-aarch64
- fedora-latest-stable-x86_64
- fedora-latest-stable-aarch64
- fedora-40-x86_64
- fedora-40-aarch64
targets: &fedora_copr_targets
- fedora-all-x86_64
- fedora-all-aarch64
enable_net: true
# Ignore until golang is updated in distro buildroot to go 1.23.3+
- job: copr_build
trigger: pull_request
trigger: ignore
packages: [skopeo-eln]
notifications: *copr_build_failure_notification
targets:
@ -55,27 +69,18 @@ jobs:
- "https://kojipkgs.fedoraproject.org/repos/eln-build/latest/aarch64/"
enable_net: true
# Ignore until golang is updated in distro buildroot to go 1.23.3+
- job: copr_build
trigger: pull_request
trigger: ignore
packages: [skopeo-centos]
notifications: *copr_build_failure_notification
targets:
targets: &centos_copr_targets
- centos-stream-9-x86_64
- centos-stream-9-aarch64
- centos-stream-10-x86_64
- centos-stream-10-aarch64
enable_net: true
# Disabled until there is go 1.22 in epel-9
# - job: copr_build
# trigger: pull_request
# packages: [skopeo-rhel]
# notifications: *copr_build_failure_notification
# targets:
# - epel-9-x86_64
# - epel-9-aarch64
# enable_net: true
# Run on commit to main branch
- job: copr_build
trigger: commit
@ -88,6 +93,33 @@ jobs:
project: podman-next
enable_net: true
# Tests on Fedora for main branch
- job: tests
trigger: pull_request
packages: [skopeo-fedora]
notifications: &test_failure_notification
failure_comment:
message: "Tests failed. @containers/packit-build please check."
targets: *fedora_copr_targets
tf_extra_params:
environments:
- artifacts:
- type: repository-file
id: https://copr.fedorainfracloud.org/coprs/rhcontainerbot/podman-next/repo/fedora-$releasever/rhcontainerbot-podman-next-fedora-$releasever.repo
# Tests on CentOS Stream for main branch
# Ignore until golang is updated in distro buildroot to go 1.23.3+
- job: tests
trigger: ignore
packages: [skopeo-centos]
notifications: *test_failure_notification
targets: *centos_copr_targets
tf_extra_params:
environments:
- artifacts:
- type: repository-file
id: https://copr.fedorainfracloud.org/coprs/rhcontainerbot/podman-next/repo/centos-stream-$releasever/rhcontainerbot-podman-next-centos-stream-$releasever.repo
# Sync to Fedora
- job: propose_downstream
trigger: release

View File

@ -1,3 +1,3 @@
## The skopeo Project Community Code of Conduct
The skopeo project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md).
The skopeo project, as part of Podman Container Tools, follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).

View File

@ -149,8 +149,12 @@ When new PRs for [containers/image](https://github.com/containers/image) break `
## Communications
For general questions, or discussions, please use the
IRC channel on `irc.libera.chat` called `#container-projects`
that has been setup.
[#podman](https://app.slack.com/client/T08PSQ7BQ/C08MXJLCFCN) channel on the [CNCF
Slack](https://cloud-native.slack.com).
For development related discussions, please use the
[#podman-dev](https://app.slack.com/client/T08PSQ7BQ/C08NTKCDC1W) channel on the CNCF
Slack.
For discussions around issues/bugs and features, you can use the github
[issues](https://github.com/containers/skopeo/issues)

3
GOVERNANCE.md Normal file
View File

@ -0,0 +1,3 @@
## The Skopeo Project Community Governance
The Skopeo project, as part of Podman Container Tools, follows the [Podman Project Governance](https://github.com/containers/podman/blob/main/GOVERNANCE.md).

29
MAINTAINERS.md Normal file
View File

@ -0,0 +1,29 @@
# Skopeo Maintainers
[GOVERNANCE.md](https://github.com/containers/podman/blob/main/GOVERNANCE.md)
describes the project's governance and the Project Roles used below.
## Maintainers
| Maintainer | GitHub ID | Project Roles | Affiliation |
|-------------------|----------------------------------------------------------|----------------------------------|----------------------------------------------|
| Brent Baude | [baude](https://github.com/baude) | Core Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Nalin Dahyabhai | [nalind](https://github.com/nalind) | Core Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Matthew Heon | [mheon](https://github.com/mheon) | Core Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Paul Holzinger | [Luap99](https://github.com/Luap99) | Core Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Giuseppe Scrivano | [giuseppe](https://github.com/giuseppe) | Core Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Miloslav Trmač | [mtrmac](https://github.com/mtrmac) | Core Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Neil Smith | [Neil-Smith](https://github.com/Neil-Smith) | Community Manager | [Red Hat](https://github.com/RedHatOfficial) |
| Tom Sweeney | [TomSweeneyRedHat](https://github.com/TomSweeneyRedHat/) | Maintainer and Community Manager | [Red Hat](https://github.com/RedHatOfficial) |
| Lokesh Mandvekar | [lsm5](https://github.com/lsm5) | Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Dan Walsh | [rhatdan](https://github.com/rhatdan) | Maintainer | [Red Hat](https://github.com/RedHatOfficial) |
| Ashley Cui | [ashley-cui](https://github.com/ashley-cui) | Reviewer | [Red Hat](https://github.com/RedHatOfficial) |
| Valentin Rothberg | [vrothberg](https://github.com/vrothberg) | Reviewer | [Red Hat](https://github.com/RedHatOfficial) |
## Alumni
None at present
## Credits
The structure of this document was based off of the equivalent one in the [CRI-O Project](https://github.com/cri-o/cri-o/blob/main/MAINTAINERS.md).

View File

@ -27,7 +27,7 @@ GOARCH ?= $(shell go env GOARCH)
# N/B: This value is managed by Renovate, manual changes are
# possible, as long as they don't disturb the formatting
# (i.e. DO NOT ADD A 'v' prefix!)
GOLANGCI_LINT_VERSION := 1.61.0
GOLANGCI_LINT_VERSION := 2.1.6
ifeq ($(GOBIN),)
GOBIN := $(GOPATH)/bin
@ -90,7 +90,7 @@ SKOPEO_LDFLAGS := -ldflags '-X main.gitCommit=${GIT_COMMIT} $(EXTRA_LDFLAGS)'
MANPAGES_MD = $(wildcard docs/*.md)
MANPAGES ?= $(MANPAGES_MD:%.md=%)
BTRFS_BUILD_TAG = $(shell hack/btrfs_tag.sh) $(shell hack/btrfs_installed_tag.sh)
BTRFS_BUILD_TAG = $(shell hack/btrfs_installed_tag.sh)
LIBSUBID_BUILD_TAG = $(shell hack/libsubid_tag.sh)
LOCAL_BUILD_TAGS = $(BTRFS_BUILD_TAG) $(LIBSUBID_BUILD_TAG)
BUILDTAGS += $(LOCAL_BUILD_TAGS)
@ -237,7 +237,11 @@ test-all-local: validate-local validate-docs test-unit-local
validate-local:
hack/validate-git-marks.sh
hack/validate-gofmt.sh
GOBIN=$(GOBIN) hack/validate-lint.sh
$(GOBIN)/golangci-lint run --build-tags "${BUILDTAGS}"
# An extra run with --tests=false allows detecting code unused outside of tests;
# ideally the linter should be able to find this automatically.
# Since everything is already cached, this additional run doesn't take much time.
$(GOBIN)/golangci-lint run --build-tags "${BUILDTAGS}" --tests=false
BUILDTAGS="${BUILDTAGS}" hack/validate-vet.sh
# This invokes bin/skopeo, hence cannot be run as part of validate-local

17
OWNERS
View File

@ -1,17 +1,22 @@
approvers:
- mtrmac
- baude
- giuseppe
- lsm5
- TomSweeneyRedHat
- Luap99
- mheon
- mtrmac
- nalind
- rhatdan
- vrothberg
- TomSweeneyRedHat
reviewers:
- ashley-cui
- baude
- giuseppe
- containers/image-maintainers
- lsm5
- Luap99
- mheon
- mtrmac
- QiWang19
- nalind
- rhatdan
- runcom
- TomSweeneyRedHat
- vrothberg

View File

@ -3,6 +3,10 @@
</p>
----
![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/containers/skopeo)
[![Go Report Card](https://goreportcard.com/badge/github.com/containers/skopeo)](https://goreportcard.com/report/github.com/containers/skopeo)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/10516/badge)](https://www.bestpractices.dev/projects/10516)
`skopeo` is a command line utility that performs various operations on container images and image repositories.

12
ROADMAP.md Normal file
View File

@ -0,0 +1,12 @@
# Skopeo Roadmap
Skopeo intends to mostly continue to be a very thin CLI wrapper over the [https://github.com/containers/image](containers/image) library, with most features being added there, not to this repo. A typical new Skopeo feature would only add a CLI for a recent containers/image feature.
## Future feature focus (most of the work must be done in the containers/image library)
* OCI artifact support.
* Integration of composefs.
* Partial pull support (zstd:chunked).
* Performance and stability improvements.
* Reductions to the size of the Skopeo binary.
* `skopeo sync` exists, and bugs in it should be fixed, but we dont have much of an ambition to compete with much larger projects like [https://github.com/openshift/oc-mirror](oc-mirror).

View File

@ -1,15 +1,52 @@
package main
import (
"github.com/containers/image/v5/directory"
"github.com/containers/image/v5/docker"
dockerArchive "github.com/containers/image/v5/docker/archive"
ociArchive "github.com/containers/image/v5/oci/archive"
oci "github.com/containers/image/v5/oci/layout"
"github.com/containers/image/v5/sif"
"github.com/containers/image/v5/tarball"
"github.com/containers/image/v5/transports"
"github.com/spf13/cobra"
"strings"
)
// autocompleteSupportedTransports list all supported transports with the colon suffix.
func autocompleteSupportedTransports(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
func autocompleteImageNames(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
transport, details, haveTransport := strings.Cut(toComplete, ":")
if !haveTransport {
transports := supportedTransportSuggestions()
return transports, cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
}
switch transport {
case ociArchive.Transport.Name(), dockerArchive.Transport.Name():
// Can have [:{*reference|@source-index}]
// FIXME: `oci-archive:/path/to/a.oci:<TAB>` completes paths
return nil, cobra.ShellCompDirectiveNoSpace
case sif.Transport.Name():
return nil, cobra.ShellCompDirectiveDefault
// Both directory and oci should have ShellCompDirectiveFilterDirs to complete only directories, but it doesn't currently work in bash: https://github.com/spf13/cobra/issues/2242
case oci.Transport.Name():
// Can have '[:{reference|@source-index}]'
// FIXME: `oci:/path/to/dir/:<TAB>` completes paths
return nil, cobra.ShellCompDirectiveDefault | cobra.ShellCompDirectiveNoSpace
case directory.Transport.Name():
return nil, cobra.ShellCompDirectiveDefault
case docker.Transport.Name():
if details == "" {
return []cobra.Completion{transport + "://"}, cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
}
}
return nil, cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
}
// supportedTransportSuggestions list all supported transports with the colon suffix.
func supportedTransportSuggestions() []string {
tps := transports.ListNames()
suggestions := make([]string, 0, len(tps))
suggestions := make([]cobra.Completion, 0, len(tps))
for _, tp := range tps {
// ListNames is generally expected to filter out deprecated transports.
// tarball: is not deprecated, but it is only usable from a Go caller (using tarball.ConfigUpdater),
@ -18,5 +55,5 @@ func autocompleteSupportedTransports(cmd *cobra.Command, args []string, toComple
suggestions = append(suggestions, tp+":")
}
}
return suggestions, cobra.ShellCompDirectiveNoFileComp
return suggestions
}

View File

@ -71,7 +71,7 @@ See skopeo(1) section "IMAGE NAMES" for the expected format
`, strings.Join(transports.ListNames(), ", ")),
RunE: commandAction(opts.run),
Example: `skopeo copy docker://quay.io/skopeo/stable:latest docker://registry.example.com/skopeo:latest`,
ValidArgsFunction: autocompleteSupportedTransports,
ValidArgsFunction: autocompleteImageNames,
}
adjustUsage(cmd)
flags := cmd.Flags()

18
cmd/skopeo/copy_test.go Normal file
View File

@ -0,0 +1,18 @@
package main
import "testing"
func TestCopy(t *testing.T) {
// Invalid command-line arguments
for _, args := range [][]string{
{},
{"a1"},
{"a1", "a2", "a3"},
} {
out, err := runSkopeo(append([]string{"--insecure-policy", "copy"}, args...)...)
assertTestFailed(t, out, err, "Exactly two arguments expected")
}
// FIXME: Much more test coverage
// Actual feature tests exist in integration and systemtest
}

View File

@ -37,7 +37,7 @@ See skopeo(1) section "IMAGE NAMES" for the expected format
`, strings.Join(transports.ListNames(), ", ")),
RunE: commandAction(opts.run),
Example: `skopeo delete docker://registry.example.com/example/pause:latest`,
ValidArgsFunction: autocompleteSupportedTransports,
ValidArgsFunction: autocompleteImageNames,
}
adjustUsage(cmd)
flags := cmd.Flags()

View File

@ -53,7 +53,7 @@ See skopeo(1) section "IMAGE NAMES" for the expected format
Example: `skopeo inspect docker://registry.fedoraproject.org/fedora
skopeo inspect --config docker://docker.io/alpine
skopeo inspect --format "Name: {{.Name}} Digest: {{.Digest}}" docker://registry.access.redhat.com/ubi8`,
ValidArgsFunction: autocompleteSupportedTransports,
ValidArgsFunction: autocompleteImageNames,
}
adjustUsage(cmd)
flags := cmd.Flags()
@ -106,8 +106,9 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
}
}()
unparsedInstance := image.UnparsedInstance(src, nil)
if err := retry.IfNecessary(ctx, func() error {
rawManifest, _, err = src.GetManifest(ctx, nil)
rawManifest, _, err = unparsedInstance.Manifest(ctx)
return err
}, opts.retryOpts); err != nil {
return fmt.Errorf("Error retrieving manifest for image: %w", err)
@ -122,7 +123,7 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
return nil
}
img, err := image.FromUnparsedImage(ctx, sys, image.UnparsedInstance(src, nil))
img, err := image.FromUnparsedImage(ctx, sys, unparsedInstance)
if err != nil {
return fmt.Errorf("Error parsing manifest for image: %w", err)
}

View File

@ -151,12 +151,22 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) {
}, opts.retryOpts); err != nil {
return err
}
if _, err := dest.PutBlob(ctx, r, types.BlobInfo{Digest: bd.digest, Size: blobSize}, cache, bd.isConfig); err != nil {
if closeErr := r.Close(); closeErr != nil {
return fmt.Errorf("%w (close error: %v)", err, closeErr)
defer func() {
if err := r.Close(); err != nil {
retErr = noteCloseFailure(retErr, fmt.Sprintf("closing blob %q", bd.digest.String()), err)
}
}()
verifier := bd.digest.Verifier()
tr := io.TeeReader(r, verifier)
if _, err := dest.PutBlob(ctx, tr, types.BlobInfo{Digest: bd.digest, Size: blobSize}, cache, bd.isConfig); err != nil {
return err
}
if _, err := io.Copy(io.Discard, tr); err != nil { // Ensure we process all of tr, so that we can validate the digest.
return err
}
if !verifier.Verified() {
return fmt.Errorf("corrupt blob %q", bd.digest.String())
}
}
var manifest []byte

View File

@ -6,7 +6,8 @@ import (
"errors"
"fmt"
"io"
"sort"
"maps"
"slices"
"strings"
"github.com/containers/common/pkg/retry"
@ -16,7 +17,6 @@ import (
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/spf13/cobra"
"golang.org/x/exp/maps"
)
// tagListOutput is the output format of (skopeo list-tags), primarily so that we can format it with a simple json.MarshalIndent.
@ -38,8 +38,7 @@ var transportHandlers = map[string]func(ctx context.Context, sys *types.SystemCo
// supportedTransports returns all the supported transports
func supportedTransports(joinStr string) string {
res := maps.Keys(transportHandlers)
sort.Strings(res)
res := slices.Sorted(maps.Keys(transportHandlers))
return strings.Join(res, joinStr)
}

View File

@ -54,3 +54,17 @@ func TestDockerRepositoryReferenceParserDrift(t *testing.T) {
}
}
}
func TestListTags(t *testing.T) {
// Invalid command-line arguments
for _, args := range [][]string{
{},
{"a1", "a2"},
} {
out, err := runSkopeo(append([]string{"list-tags"}, args...)...)
assertTestFailed(t, out, err, "Exactly one non-option argument expected")
}
// FIXME: Much more test coverage
// Actual feature tests exist in systemtest
}

View File

@ -1,62 +1,11 @@
//go:build !windows
// +build !windows
package main
/*
This code is currently only intended to be used by ostree
to fetch content via containers. The API is subject
to change. A goal however is to stabilize the API
eventually as a full out-of-process interface to the
core containers/image library functionality.
To use this command, in a parent process create a
`socketpair()` of type `SOCK_SEQPACKET`. Fork
off this command, and pass one half of the socket
pair to the child. Providing it on stdin (fd 0)
is the expected default.
The protocol is JSON for the control layer,
and a read side of a `pipe()` passed for large data.
Base JSON protocol:
request: { method: "MethodName": args: [arguments] }
reply: { success: bool, value: JSVAL, pipeid: number, error: string }
For any non-metadata i.e. payload data from `GetManifest`
and `GetBlob` the server will pass back the read half of a `pipe(2)` via FD passing,
along with a `pipeid` integer.
The expected flow looks like this:
- Initialize
And validate the returned protocol version versus
what your client supports.
- OpenImage docker://quay.io/someorg/example:latest
(returns an imageid)
- GetManifest imageid (and associated <pipeid>)
(Streaming read data from pipe)
- FinishPipe <pipeid>
- GetBlob imageid sha256:...
(Streaming read data from pipe)
- FinishPipe <pipeid>
- GetBlob imageid sha256:...
(Streaming read data from pipe)
- FinishPipe <pipeid>
- CloseImage imageid
You may interleave invocations of these methods, e.g. one
can also invoke `OpenImage` multiple times, as well as
starting multiple GetBlob requests before calling `FinishPipe`
on them. The server will stream data into the pipefd
until `FinishPipe` is invoked.
Note that the pipe will not be closed by the server until
the client has invoked `FinishPipe`. This is to ensure
that the client checks for errors. For example, `GetBlob`
performs digest (e.g. sha256) verification and this must
be checked after all data has been written.
This command is still experimental. Documentation
is available in
docs-experimental/skopeo-experimental-image-proxy.1.md
*/
import (
@ -71,6 +20,7 @@ import (
"sync"
"syscall"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/image"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/blobinfocache"
@ -87,13 +37,8 @@ import (
// The first version of the protocol has major version 0.2 to signify a
// departure from the original code which used HTTP.
//
// 0.2.1: Initial version
// 0.2.2: Added support for fetching image configuration as OCI
// 0.2.3: Added GetFullConfig
// 0.2.4: Added OpenImageOptional
// 0.2.5: Added LayerInfoJSON
// 0.2.6: Policy Verification before pulling OCI
const protocolVersion = "0.2.6"
// When bumping this, please also update the man page.
const protocolVersion = "0.2.8"
// maxMsgSize is the current limit on a packet size.
// Note that all non-metadata (i.e. payload data) is sent over a pipe.
@ -116,6 +61,23 @@ type request struct {
Args []any `json:"args"`
}
type proxyErrorCode string
const (
// proxyErrPipe means we got EPIPE writing to a pipe owned by the client
proxyErrPipe proxyErrorCode = "EPIPE"
// proxyErrRetryable can be used by clients to automatically retry operations
proxyErrRetryable proxyErrorCode = "retryable"
// All other errors
proxyErrOther proxyErrorCode = "other"
)
// proxyError is serialized over the errfd channel for GetRawBlob
type proxyError struct {
Code proxyErrorCode `json:"code"`
Message string `json:"message"`
}
// reply is serialized to JSON as the return value from a function call.
type reply struct {
// Success is true if and only if the call succeeded.
@ -124,6 +86,8 @@ type reply struct {
Value any `json:"value"`
// PipeID is an index into open pipes, and should be passed to FinishPipe
PipeID uint32 `json:"pipeid"`
// ErrorCode will be non-empty if error is set (new in 0.2.8)
ErrorCode proxyErrorCode `json:"error_code"`
// Error should be non-empty if Success == false
Error string `json:"error"`
}
@ -132,8 +96,11 @@ type reply struct {
type replyBuf struct {
// value will be converted to a reply Value
value any
// fd is the read half of a pipe, passed back to the client
// fd is the read half of a pipe, passed back to the client for additional data
fd *os.File
// errfd will be a serialization of error state. This is optional and is currently
// only used by GetRawBlob.
errfd *os.File
// pipeid will be provided to the client as PipeID, an index into our open pipes
pipeid uint32
}
@ -182,6 +149,30 @@ type convertedLayerInfo struct {
MediaType string `json:"media_type"`
}
// mapProxyErrorCode turns an error into a known string value.
func mapProxyErrorCode(err error) proxyErrorCode {
switch {
case err == nil:
return ""
case errors.Is(err, syscall.EPIPE):
return proxyErrPipe
case retry.IsErrorRetryable(err):
return proxyErrRetryable
default:
return proxyErrOther
}
}
// newProxyError creates a serializable structure for
// the client containing a mapped error code based
// on the error type, plus its value as a string.
func newProxyError(err error) proxyError {
return proxyError{
Code: mapProxyErrorCode(err),
Message: fmt.Sprintf("%v", err),
}
}
// Initialize performs one-time initialization, and returns the protocol version
func (h *proxyHandler) Initialize(args []any) (replyBuf, error) {
h.lock.Lock()
@ -277,7 +268,7 @@ func (h *proxyHandler) openImageImpl(args []any, allowNotFound bool) (retReplyBu
return ret, nil
}
// OpenImage accepts a string image reference i.e. TRANSPORT:REF - like `skopeo copy`.
// OpenImageOptional accepts a string image reference i.e. TRANSPORT:REF - like `skopeo copy`.
// The return value is an opaque integer handle. If the image does not exist, zero
// is returned.
func (h *proxyHandler) OpenImageOptional(args []any) (replyBuf, error) {
@ -617,11 +608,97 @@ func (h *proxyHandler) GetBlob(args []any) (replyBuf, error) {
return ret, nil
}
// GetRawBlob can be viewed as a more general purpose successor
// to GetBlob. First, it does not verify the digest, which in
// some cases is unnecessary as the client would prefer to do it.
//
// It also does not use the "FinishPipe" API call, but instead
// returns *two* file descriptors, one for errors and one for data.
//
// On (initial) success, the return value provided to the client is the size of the blob.
func (h *proxyHandler) GetRawBlob(args []any) (replyBuf, error) {
h.lock.Lock()
defer h.lock.Unlock()
var ret replyBuf
if h.sysctx == nil {
return ret, fmt.Errorf("client error: must invoke Initialize")
}
if len(args) != 2 {
return ret, fmt.Errorf("found %d args, expecting (imgid, digest)", len(args))
}
imgref, err := h.parseImageFromID(args[0])
if err != nil {
return ret, err
}
digestStr, ok := args[1].(string)
if !ok {
return ret, fmt.Errorf("expecting string blobid")
}
ctx := context.TODO()
d, err := digest.Parse(digestStr)
if err != nil {
return ret, err
}
blobr, blobSize, err := imgref.src.GetBlob(ctx, types.BlobInfo{Digest: d, Size: int64(-1)}, h.cache)
if err != nil {
return ret, err
}
// Note this doesn't call allocPipe; we're not using the FinishPipe infrastructure.
piper, pipew, err := os.Pipe()
if err != nil {
blobr.Close()
return ret, err
}
errpipeR, errpipeW, err := os.Pipe()
if err != nil {
piper.Close()
pipew.Close()
blobr.Close()
return ret, err
}
// Asynchronous worker doing a copy
go func() {
// We own the read from registry, and write pipe objects
defer blobr.Close()
defer pipew.Close()
defer errpipeW.Close()
logrus.Debugf("Copying blob to client: %d bytes", blobSize)
_, err := io.Copy(pipew, blobr)
// Handle errors here by serializing a JSON error back over
// the error channel. In either case, both file descriptors
// will be closed, signaling the completion of the operation.
if err != nil {
logrus.Debugf("Sending error to client: %v", err)
serializedErr := newProxyError(err)
buf, err := json.Marshal(serializedErr)
if err != nil {
// Should never happen
panic(err)
}
_, writeErr := errpipeW.Write(buf)
if writeErr != nil && !errors.Is(err, syscall.EPIPE) {
logrus.Debugf("Writing to client: %v", err)
}
}
logrus.Debugf("Completed GetRawBlob operation")
}()
ret.value = blobSize
ret.fd = piper
ret.errfd = errpipeR
return ret, nil
}
// GetLayerInfo returns data about the layers of an image, useful for reading the layer contents.
//
// This needs to be called since the data returned by GetManifest() does not allow to correctly
// calling GetBlob() for the containers-storage: transport (which doesnt store the original compressed
// representations referenced in the manifest).
// This is the same as GetLayerInfoPiped, but returns its contents inline. This is subject to
// failure for large images (because we use SOCK_SEQPACKET which has a maximum buffer size)
// and is hence only retained for backwards compatibility. Callers are expected to use
// the semver to know whether they can call the new API.
func (h *proxyHandler) GetLayerInfo(args []any) (replyBuf, error) {
h.lock.Lock()
defer h.lock.Unlock()
@ -667,6 +744,59 @@ func (h *proxyHandler) GetLayerInfo(args []any) (replyBuf, error) {
return ret, nil
}
// GetLayerInfoPiped returns data about the layers of an image, useful for reading the layer contents.
//
// This needs to be called since the data returned by GetManifest() does not allow to correctly
// calling GetBlob() for the containers-storage: transport (which doesnt store the original compressed
// representations referenced in the manifest).
func (h *proxyHandler) GetLayerInfoPiped(args []any) (replyBuf, error) {
h.lock.Lock()
defer h.lock.Unlock()
var ret replyBuf
if h.sysctx == nil {
return ret, fmt.Errorf("client error: must invoke Initialize")
}
if len(args) != 1 {
return ret, fmt.Errorf("found %d args, expecting (imgid)", len(args))
}
imgref, err := h.parseImageFromID(args[0])
if err != nil {
return ret, err
}
ctx := context.TODO()
err = h.cacheTargetManifest(imgref)
if err != nil {
return ret, err
}
img := imgref.cachedimg
layerInfos, err := img.LayerInfosForCopy(ctx)
if err != nil {
return ret, err
}
if layerInfos == nil {
layerInfos = img.LayerInfos()
}
layers := make([]convertedLayerInfo, 0, len(layerInfos))
for _, layer := range layerInfos {
layers = append(layers, convertedLayerInfo{layer.Digest, layer.Size, layer.MediaType})
}
serialized, err := json.Marshal(&layers)
if err != nil {
return ret, err
}
return h.returnBytes(nil, serialized)
}
// FinishPipe waits for the worker goroutine to finish, and closes the write side of the pipe.
func (h *proxyHandler) FinishPipe(args []any) (replyBuf, error) {
h.lock.Lock()
@ -709,30 +839,37 @@ func (h *proxyHandler) close() {
// send writes a reply buffer to the socket
func (buf replyBuf) send(conn *net.UnixConn, err error) error {
logrus.Debugf("Sending reply: err=%v value=%v pipeid=%v", err, buf.value, buf.pipeid)
logrus.Debugf("Sending reply: err=%v value=%v pipeid=%v datafd=%v errfd=%v", err, buf.value, buf.pipeid, buf.fd, buf.errfd)
// We took ownership of these FDs, so close when we're done sending them or on error
defer func() {
if buf.fd != nil {
buf.fd.Close()
}
if buf.errfd != nil {
buf.errfd.Close()
}
}()
replyToSerialize := reply{
Success: err == nil,
Value: buf.value,
PipeID: buf.pipeid,
}
if err != nil {
replyToSerialize.ErrorCode = mapProxyErrorCode(err)
replyToSerialize.Error = err.Error()
}
serializedReply, err := json.Marshal(&replyToSerialize)
if err != nil {
return err
}
// We took ownership of the FD - close it when we're done.
defer func() {
if buf.fd != nil {
buf.fd.Close()
}
}()
// Copy the FD number to the socket ancillary buffer
// Copy the FD number(s) to the socket ancillary buffer
fds := make([]int, 0)
if buf.fd != nil {
fds = append(fds, int(buf.fd.Fd()))
}
if buf.errfd != nil {
fds = append(fds, int(buf.errfd.Fd()))
}
oob := syscall.UnixRights(fds...)
n, oobn, err := conn.WriteMsgUnix(serializedReply, oob, nil)
if err != nil {
@ -804,8 +941,12 @@ func (h *proxyHandler) processRequest(readBytes []byte) (rb replyBuf, terminate
rb, err = h.GetFullConfig(req.Args)
case "GetBlob":
rb, err = h.GetBlob(req.Args)
case "GetRawBlob":
rb, err = h.GetRawBlob(req.Args)
case "GetLayerInfo":
rb, err = h.GetLayerInfo(req.Args)
case "GetLayerInfoPiped":
rb, err = h.GetLayerInfoPiped(req.Args)
case "FinishPipe":
rb, err = h.FinishPipe(req.Args)
case "Shutdown":

View File

@ -1,5 +1,4 @@
//go:build windows
// +build windows
package main

View File

@ -44,3 +44,18 @@ func TestTLSVerifyConfig(t *testing.T) {
err := yaml.Unmarshal([]byte(`tls-verify: "not a valid bool"`), &config)
assert.Error(t, err)
}
func TestSync(t *testing.T) {
// Invalid command-line arguments
for _, args := range [][]string{
{},
{"a1"},
{"a1", "a2", "a3"},
} {
out, err := runSkopeo(append([]string{"sync"}, args...)...)
assertTestFailed(t, out, err, "Exactly two arguments expected")
}
// FIXME: Much more test coverage
// Actual feature tests exist in integration and systemtest
}

View File

@ -1,5 +1,4 @@
//go:build !linux
// +build !linux
package main

View File

@ -16,6 +16,7 @@ var neededCapabilities = []capability.Cap{
capability.CAP_FSETID,
capability.CAP_MKNOD,
capability.CAP_SETFCAP,
capability.CAP_SYS_ADMIN,
}
func maybeReexec() error {

View File

@ -7,6 +7,7 @@ import (
"io"
"os"
"strings"
"time"
commonFlag "github.com/containers/common/pkg/flag"
"github.com/containers/common/pkg/retry"
@ -26,7 +27,7 @@ import (
"golang.org/x/term"
)
// errorShouldDisplayUsage is a subtype of error used by command handlers to indicate that cli.ShowSubcommandHelp should be called.
// errorShouldDisplayUsage is a subtype of error used by command handlers to indicate that the commands help should be included.
type errorShouldDisplayUsage struct {
error
}
@ -62,7 +63,8 @@ func commandAction(handler func(args []string, stdout io.Writer) error) func(cmd
err := handler(args, c.OutOrStdout())
var shouldDisplayUsage errorShouldDisplayUsage
if errors.As(err, &shouldDisplayUsage) {
return c.Help()
c.SetOut(c.ErrOrStderr()) // This mutates c, but we are failing anyway.
_ = c.Help() // Even if this failed, we prefer to report the original error
}
return err
}
@ -183,6 +185,7 @@ func retryFlags() (pflag.FlagSet, *retry.Options) {
opts := retry.Options{}
fs := pflag.FlagSet{}
fs.IntVar(&opts.MaxRetry, "retry-times", 0, "the number of times to possibly retry")
fs.DurationVar(&opts.Delay, "retry-delay", 0*time.Second, "Fixed delay between retries. If not set, retry uses an exponential backoff delay.")
return fs, &opts
}
@ -197,8 +200,8 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) {
ctx.AuthFilePath = opts.shared.authFilePath
ctx.DockerDaemonHost = opts.dockerDaemonHost
ctx.DockerDaemonCertPath = opts.dockerCertPath
if opts.dockerImageOptions.authFilePath.Present() {
ctx.AuthFilePath = opts.dockerImageOptions.authFilePath.Value()
if opts.authFilePath.Present() {
ctx.AuthFilePath = opts.authFilePath.Value()
}
if opts.deprecatedTLSVerify != nil && opts.deprecatedTLSVerify.tlsVerify.Present() {
// If both this deprecated option and a non-deprecated option is present, we use the latter value.

View File

@ -128,7 +128,7 @@ _run_system() {
make test-system-local BUILDTAGS="$BUILDTAGS"
}
req_env_vars SKOPEO_PATH BUILDTAGS
req_env_vars SKOPEO_PATH
handler="_run_${1}"
if [ "$(type -t $handler)" != "function" ]; then

View File

@ -0,0 +1,158 @@
% skopeo-experimental-image-proxy(1)
# NAME
skopeo-experimental-image-proxy - API server for fetching container images (EXPERIMENTAL)
# SYNOPSIS
**skopeo experimental-image-proxy** [*options*]
# DESCRIPTION
**EXPERIMENTAL COMMAND**: This command is experimental, and its API is subject to change. It is currently hidden from the main help output and not supported on Windows.
`skopeo experimental-image-proxy` exposes core container image fetching APIs via custom JSON+fd-passing protocol. This provides a lightweight way to fetch container image content (manifests and blobs). This command is primarily intended for programs that want to operate on a storage type that skopeo doesn't natively handle. For example, the bootc project currently has a custom ostree-based container storage backend.
The client process that invokes `skopeo experimental-image-proxy` is responsible for creating a socket pair and passing one of the file descriptors to the proxy. By default, the proxy expects this file descriptor to be its standard input (fd 0), but a different fd can be specified using the **--sockfd** option.
**Protocol Overview**
The protocol requires a `socketpair(2)` of type `SOCK_SEQPACKET`, over which a single JSON message is sent per packet. Large data payloads, such as image manifests and blobs, are transferred over separate pipes (`pipe(2)`), with the read-ends of these pipes passed to the client via file descriptor (FD) passing.
* **Request Format**: A JSON object: `{ "method": "MethodName", "args": [arguments] }`
* **Reply Format**: A JSON object: `{ "success": boolean, "value": JSONValue, "pipeid": number, "error_code": string, "error": string }`
* `success`: `true` if the call succeeded, `false` otherwise.
* `value`: The return value of the method, if any.
* `pipeid`: An integer identifying a pipe for data transfer. This ID is used with the `FinishPipe` method.
* `error_code`: A string indicating the type of error if `success` is `false` (e.g., "EPIPE", "retryable", "other"). (Introduced in protocol version 0.2.8)
* `error`: A string describing the error if `success` is `false`.
The current protocol version is `0.2.8`.
**Supported Protocol Methods**
The server supports the following methods:
* **Initialize**: Initializes the proxy. This method must be called before any other method.
* Args: `[]` (empty array)
* Returns: `string` (the protocol version, e.g., "0.2.8")
* **OpenImage**: Opens an image reference (e.g., `docker://quay.io/example/image:latest`).
* Args: `[string imageName]`
* Returns: `uint64` (an opaque image ID to be used in subsequent calls)
* **OpenImageOptional**: Similar to `OpenImage`, but if the image is not found, it returns `0` (a sentinel image ID) instead of an error.
* Args: `[string imageName]`
* Returns: `uint64` (opaque image ID, or `0` if the image is not found)
* **CloseImage**: Closes a previously opened image, releasing associated resources.
* Args: `[uint64 imageID]`
* Returns: `null`
* **GetManifest**: Retrieves the image manifest. If the image is a manifest list, it is resolved to an image matching the proxy's current OS and architecture. The manifest is converted to OCI format if it isn't already. The `value` field in the reply contains the original digest of the manifest (if the image is a manifest list, this is the digest of the list, not the per-platform instance). The manifest content is streamed over a pipe.
* Args: `[uint64 imageID]`
* Returns: `string` (manifest digest in `value`), manifest data via pipe.
* **GetFullConfig**: Retrieves the full image configuration, conforming to the OCI Image Format Specification. Configuration data is streamed over a pipe.
* Args: `[uint64 imageID]`
* Returns: `null`, configuration data via pipe.
* **GetBlob**: Fetches an image blob (e.g., a layer) by its digest and expected size. The proxy performs digest verification on the blob data. The `value` field in the reply contains the blob size. Blob data is streamed over a pipe.
* Args: `[uint64 imageID, string digest, uint64 size]`
* Returns: `int64` (blob size in `value`, `-1` if unknown), blob data via pipe.
* **GetRawBlob**: Fetches an image blob by its digest. Unlike `GetBlob`, this method does not perform server-side digest verification. It returns two file descriptors to the client: one for the blob data and another for reporting errors that occur during the streaming. This method does not use the `FinishPipe` mechanism. The `value` field in the reply contains the blob size. (Introduced in protocol version 0.2.8)
* Args: `[uint64 imageID, string digest]`
* Returns: `int64` (blob size in `value`, `-1` if unknown), and *two* file descriptors: one for the blob data, one for errors. The error is a `ProxyError` type, see below.
* **GetLayerInfoPiped**: Retrieves information about image layers. This replaces `GetLayerInfo`. Layer information data is streamed over a pipe, which makes it more reliable for images with many layers that would exceed message size limits with `GetLayerInfo`. The returned data is a JSON array of `{digest: string, size: int64, media_type: string}`. (Introduced in protocol version 0.2.7)
* Args: `[uint64 imageID]`
* Returns: `null`, layer information data via pipe.
* **FinishPipe**: Signals that the client has finished reading all data from a pipe associated with a `pipeid` (obtained from methods like `GetManifest` or `GetBlob`). This allows the server to close its end of the pipe and report any pending errors (e.g., digest verification failure for `GetBlob`). This method **must** be called by the client after consuming data from a pipe, except for pipes from `GetRawBlob`.
* Args: `[uint32 pipeID]`
* Returns: `null`
* **Shutdown**: Instructs the proxy server to terminate gracefully.
* Args: `[]` (empty array)
* Returns: `null`
The following methods are deprecated:
* **GetConfig**: (deprecated) Retrieves the container runtime configuration part of the image (the OCI `config` field). **Note**: This method returns only a part of the full image configuration due to a historical oversight. Use `GetFullConfig` for the complete image configuration. Configuration data is streamed over a pipe.
* Args: `[uint64 imageID]`
* Returns: `null`, configuration data via pipe.
* **GetLayerInfo**: (deprecated) Retrieves an array of objects, each describing an image layer (digest, size, mediaType). **Note**: This method returns data inline and may fail for images with many layers due to message size limits. Use `GetLayerInfoPiped` for a more robust solution.
* Args: `[uint64 imageID]`
* Returns: `array` of `{digest: string, size: int64, media_type: string}`.
**Data Transfer for Pipes**
When a method returns a `pipeid`, the server also passes the read-end of a pipe via file descriptor (FD) passing. The client reads the data (e.g., manifest content, blob content) from this FD. After successfully reading all data, the client **must** call `FinishPipe` with the corresponding `pipeid`. This signals to the server that the transfer is complete, allows the server to clean up resources, and enables the client to check for any errors that might have occurred during the data streaming process (e.g., a digest mismatch during `GetBlob`). The `GetRawBlob` method is an exception; it uses a dedicated error pipe instead of the `FinishPipe` mechanism.
**ProxyError**
`GetBlobRaw` returns a JSON object of the following form in the error pipe where:
```
{
"code": "EPIPE" | "retryable" | "other",
"message": "error message"
}
```
- EPIPE: The client closed the pipe before reading all data.
- retryable: The operation failed but might succeed if retried.
- other: A generic error occurred.
# OPTIONS
**--sockfd**=*fd*
Serve on the opened socket passed as file descriptor *fd*. Defaults to 0 (standard input).
The command also supports common skopeo options for interacting with image registries and local storage. These include:
**--authfile**=*path*
Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `skopeo login`.
If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
**--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
**--creds** _username[:password]_
Username and password for accessing the registry.
**--daemon-host** _host_
Use docker daemon host at _host_ (`docker-daemon:` transport only)
**--no-creds**
Access the registry anonymously.
**--password**=*password*
Password for accessing the registry. Use with **--username**.
**--registry-token**=*token*
Provide a Bearer *token* for accessing the registry.
**--shared-blob-dir** _directory_
Directory to use to share blobs across OCI repositories.
**--tls-verify**=_bool_
Require HTTPS and verify certificates when talking to the container registry or daemon. Default to registry.conf setting.
**--username**=*username*
Username for accessing the registry. Use with **--password**.
# REFERENCE CLIENT LIBRARIES
- Rust: The [containers-image-proxy-rs project](https://github.com/containers/containers-image-proxy-rs) serves
as the reference Rust client.
# PROTOCOL HISTORY
- 0.2.1: Initial version
- 0.2.2: Added support for fetching image configuration as OCI
- 0.2.3: Added GetFullConfig
- 0.2.4: Added OpenImageOptional
- 0.2.5: Added LayerInfoJSON
- 0.2.6: Policy Verification before pulling OCI
- 0.2.7: Added GetLayerInfoPiped
- 0.2.8: Added GetRawBlob and error_code to replies
## SEE ALSO
skopeo(1), containers-auth.json(5)

View File

@ -204,7 +204,11 @@ Precompute digests to ensure layers are not uploaded that already exist on the d
**--retry-times**
The number of times to retry. Retry wait time will be exponentially increased based on the number of failed attempts.
The number of times to retry.
**--retry-delay**
Fixed delay between retries. If not set (or set to 0s), retry wait time will be exponentially increased based on the number of failed attempts.
**--src-username**

View File

@ -66,7 +66,11 @@ Bearer token for accessing the registry.
**--retry-times**
The number of times to retry. Retry wait time will be exponentially increased based on the number of failed attempts.
The number of times to retry.
**--retry-delay**
Fixed delay between retries. If not set (or set to 0s), retry wait time will be exponentially increased based on the number of failed attempts.
**--shared-blob-dir** _directory_

View File

@ -65,7 +65,11 @@ Registry token for accessing the registry.
**--retry-times**
The number of times to retry; retry wait time will be exponentially increased based on the number of failed attempts.
The number of times to retry.
**--retry-delay**
Fixed delay between retries. If not set (or set to 0s), retry wait time will be exponentially increased based on the number of failed attempts.
**--shared-blob-dir** _directory_

View File

@ -39,7 +39,11 @@ Bearer token for accessing the registry.
**--retry-times**
The number of times to retry. Retry wait time will be exponentially increased based on the number of failed attempts.
The number of times to retry.
**--retry-delay**
Fixed delay between retries. If not set (or set to 0s), retry wait time will be exponentially increased based on the number of failed attempts.
**--tls-verify**=_bool_

View File

@ -123,7 +123,13 @@ The passphare to use when signing with `--sign-by` or `--sign-by-sigstore-privat
**--dest-registry-token** _Bearer token_ for accessing the destination registry.
**--retry-times** the number of times to retry, retry wait time will be exponentially increased based on the number of failed attempts.
**--retry-times**
The number of times to retry.
**--retry-delay**
Fixed delay between retries. If not set (or set to 0s), retry wait time will be exponentially increased based on the number of failed attempts.
**--keep-going**
If any errors occur during copying of images, those errors are logged and the process continues syncing rest of the images and finally fails at the end.

128
go.mod
View File

@ -1,139 +1,137 @@
module github.com/containers/skopeo
// Minimum required golang version
go 1.22.6
go 1.23.3
// Warning: Ensure the "go" and "toolchain" versions match exactly to prevent unwanted auto-updates
require (
github.com/Masterminds/semver/v3 v3.3.0
github.com/containers/common v0.61.0
github.com/containers/image/v5 v5.33.0
github.com/containers/ocicrypt v1.2.0
github.com/containers/storage v1.56.0
github.com/Masterminds/semver/v3 v3.3.1
github.com/containers/common v0.63.0
github.com/containers/image/v5 v5.35.0
github.com/containers/ocicrypt v1.2.1
github.com/containers/storage v1.58.0
github.com/docker/distribution v2.8.3+incompatible
github.com/moby/sys/capability v0.3.0
github.com/moby/sys/capability v0.4.0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0
github.com/opencontainers/image-spec v1.1.1
github.com/opencontainers/image-tools v1.0.0-rc3
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
golang.org/x/term v0.26.0
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
golang.org/x/term v0.32.0
gopkg.in/yaml.v3 v3.0.1
)
require (
dario.cat/mergo v1.0.1 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.12.9 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/containerd/cgroups/v3 v3.0.3 // indirect
github.com/containerd/errdefs v0.3.0 // indirect
github.com/containerd/cgroups/v3 v3.0.5 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
github.com/containerd/typeurl/v2 v2.2.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
github.com/coreos/go-oidc/v3 v3.11.0 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
github.com/coreos/go-oidc/v3 v3.13.0 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/docker v27.3.1+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.2 // indirect
github.com/docker/docker v28.0.4+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
github.com/go-openapi/errors v0.22.1 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/loads v0.22.0 // indirect
github.com/go-openapi/runtime v0.28.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/strfmt v0.23.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-containerregistry v0.20.2 // indirect
github.com/google/go-containerregistry v0.20.3 // indirect
github.com/google/go-intervals v0.0.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-multierror v1.1.2-0.20250313123807-1ee6e1a1957a // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-sqlite3 v1.14.24 // indirect
github.com/mattn/go-sqlite3 v1.14.27 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect
github.com/moby/sys/user v0.3.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/opencontainers/selinux v1.11.1 // indirect
github.com/opencontainers/runtime-spec v1.2.1 // indirect
github.com/opencontainers/selinux v1.12.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/proglottis/gpgme v0.1.3 // indirect
github.com/proglottis/gpgme v0.1.4 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/sigstore/fulcio v1.6.4 // indirect
github.com/sigstore/rekor v1.3.6 // indirect
github.com/sigstore/sigstore v1.8.9 // indirect
github.com/sigstore/fulcio v1.6.6 // indirect
github.com/sigstore/protobuf-specs v0.4.1 // indirect
github.com/sigstore/rekor v1.3.10 // indirect
github.com/sigstore/sigstore v1.9.3 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/smallstep/pkcs7 v0.1.1 // indirect
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect
github.com/sylabs/sif/v2 v2.19.1 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/sylabs/sif/v2 v2.21.1 // indirect
github.com/tchap/go-patricia/v2 v2.3.2 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/vbatts/tar-split v0.11.6 // indirect
github.com/vbauerster/mpb/v8 v8.8.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/vbatts/tar-split v0.12.1 // indirect
github.com/vbauerster/mpb/v8 v8.9.3 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/grpc v1.67.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/oauth2 v0.29.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.24.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
google.golang.org/grpc v1.71.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
)

360
go.sum
View File

@ -6,10 +6,10 @@ github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dY
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
@ -29,57 +29,57 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU=
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso=
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g=
github.com/containers/common v0.61.0 h1:j/84PTqZIKKYy42OEJsZmjZ4g4Kq2ERuC3tqp2yWdh4=
github.com/containers/common v0.61.0/go.mod h1:NGRISq2vTFPSbhNqj6MLwyes4tWSlCnqbJg7R77B8xc=
github.com/containers/image/v5 v5.33.0 h1:6oPEFwTurf7pDTGw7TghqGs8K0+OvPtY/UyzU0B2DfE=
github.com/containers/image/v5 v5.33.0/go.mod h1:T7HpASmvnp2H1u4cyckMvCzLuYgpD18dSmabSw0AcHk=
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/containers/common v0.63.0 h1:ox6vgUYX5TSvt4W+bE36sYBVz/aXMAfRGVAgvknSjBg=
github.com/containers/common v0.63.0/go.mod h1:+3GCotSqNdIqM3sPs152VvW7m5+Mg8Kk+PExT3G9hZw=
github.com/containers/image/v5 v5.35.0 h1:T1OeyWp3GjObt47bchwD9cqiaAm/u4O4R9hIWdrdrP8=
github.com/containers/image/v5 v5.35.0/go.mod h1:8vTsgb+1gKcBL7cnjyNOInhJQfTUQjJoO2WWkKDoebM=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM=
github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U=
github.com/containers/storage v1.56.0 h1:DZ9KSkj6M2tvj/4bBoaJu3QDHRl35BwsZ4kmLJS97ZI=
github.com/containers/storage v1.56.0/go.mod h1:c6WKowcAlED/DkWGNuL9bvGYqIWCVy7isRMdCSKWNjk=
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM=
github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=
github.com/containers/storage v1.58.0 h1:Q7SyyCCjqgT3wYNgRNIL8o/wUS92heIj2/cc8Sewvcc=
github.com/containers/storage v1.58.0/go.mod h1:w7Jl6oG+OpeLGLzlLyOZPkmUso40kjpzgrHUk5tyBlo=
github.com/coreos/go-oidc/v3 v3.13.0 h1:M66zd0pcc5VxvBNM4pB331Wrsanby+QomQYjN8HamW8=
github.com/coreos/go-oidc/v3 v3.13.0/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q=
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ=
github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v28.0.4+incompatible h1:pBJSJeNd9QeIWPjRcV91RVJihd/TXB77q1ef64XEu4A=
github.com/docker/cli v28.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI=
github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok=
github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -89,10 +89,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@ -100,8 +98,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU=
github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
@ -114,8 +112,8 @@ github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9Z
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA=
@ -128,8 +126,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -149,33 +147,30 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo=
github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM=
github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-multierror v1.1.2-0.20250313123807-1ee6e1a1957a h1:zTI4FFCOXw14aUC78fxMh4tS7jJI7Fm51sH4smjl+Fc=
github.com/hashicorp/go-multierror v1.1.2-0.20250313123807-1ee6e1a1957a/go.mod h1:RYOtqYU2MvOrqUMooJlQoFFuqR6sazGdm1ubZTL++r8=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@ -189,8 +184,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@ -200,16 +195,16 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2TSgRbAhD7yjZzTQmcN25sDRPEeinR51yQ=
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.27 h1:drZCnuvf37yPfs95E5jd9s3XhdVWLal+6BOK6qrv6IU=
github.com/mattn/go-sqlite3 v1.14.27/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
@ -218,14 +213,14 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -237,20 +232,20 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/image-tools v1.0.0-rc3 h1:ZR837lBIxq6mmwEqfYrbLMuf75eBSHhccVHy6lsBeM4=
github.com/opencontainers/image-tools v1.0.0-rc3/go.mod h1:A9btVpZLzttF4iFaKNychhPyrhfOjJ1OF5KrA8GcLj4=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8=
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqwnHagNDPGOlts35QkhAZ8by3DR7nMih7M=
@ -260,49 +255,57 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/proglottis/gpgme v0.1.3 h1:Crxx0oz4LKB3QXc5Ea0J19K/3ICfy3ftr5exgUK1AU0=
github.com/proglottis/gpgme v0.1.3/go.mod h1:fPbW/EZ0LvwQtH8Hy7eixhp1eF3G39dtx7GUN+0Gmy0=
github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/proglottis/gpgme v0.1.4 h1:3nE7YNA70o2aLjcg63tXMOhPD7bplfE5CBdV+hLAm2M=
github.com/proglottis/gpgme v0.1.4/go.mod h1:5LoXMgpE4bttgwwdv9bLs/vwqv3qV7F4glEEZ7mRKrM=
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVhoNcY=
github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY=
github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA=
github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc=
github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw=
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sigstore/fulcio v1.6.4 h1:d86obfxUAG3Y6CYwOx1pdwCZwKmROB6w6927pKOVIRY=
github.com/sigstore/fulcio v1.6.4/go.mod h1:Y6bn3i3KGhXpaHsAtYP3Z4Np0+VzCo1fLv8Ci6mbPDs=
github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8=
github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc=
github.com/sigstore/sigstore v1.8.9 h1:NiUZIVWywgYuVTxXmRoTT4O4QAGiTEKup4N1wdxFadk=
github.com/sigstore/sigstore v1.8.9/go.mod h1:d9ZAbNDs8JJfxJrYmulaTazU3Pwr8uLL9+mii4BNR3w=
github.com/sigstore/fulcio v1.6.6 h1:XaMYX6TNT+8n7Npe8D94nyZ7/ERjEsNGFC+REdi/wzw=
github.com/sigstore/fulcio v1.6.6/go.mod h1:BhQ22lwaebDgIxVBEYOOqLRcN5+xOV+C9bh/GUXRhOk=
github.com/sigstore/protobuf-specs v0.4.1 h1:5SsMqZbdkcO/DNHudaxuCUEjj6x29tS2Xby1BxGU7Zc=
github.com/sigstore/protobuf-specs v0.4.1/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc=
github.com/sigstore/rekor v1.3.10 h1:/mSvRo4MZ/59ECIlARhyykAlQlkmeAQpvBPlmJtZOCU=
github.com/sigstore/rekor v1.3.10/go.mod h1:JvryKJ40O0XA48MdzYUPu0y4fyvqt0C4iSY7ri9iu3A=
github.com/sigstore/sigstore v1.9.3 h1:y2qlTj+vh+Or3ictKuR3JUFawZPdDxAjrWkeFhon0OQ=
github.com/sigstore/sigstore v1.9.3/go.mod h1:VwYkiw0G0dRtwL25KSs04hCyVFF6CYMd/qvNeYrl7EQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU=
github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw=
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -313,28 +316,21 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/sylabs/sif/v2 v2.19.1 h1:1eeMmFc8elqJe60ZiWwXgL3gMheb0IP4GmNZ4q0IEA0=
github.com/sylabs/sif/v2 v2.19.1/go.mod h1:U1SUhvl8X1JIxAylC0DYz1fa/Xba6EMZD1dGPGBH83E=
github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes=
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/sylabs/sif/v2 v2.21.1 h1:GZ0b5//AFAqJEChd8wHV/uSKx/l1iuGYwjR8nx+4wPI=
github.com/sylabs/sif/v2 v2.21.1/go.mod h1:YoqEGQnb5x/ItV653bawXHZJOXQaEWpGwHsSD3YePJI=
github.com/tchap/go-patricia/v2 v2.3.2 h1:xTHFutuitO2zqKAQ5rCROYgUb7Or/+IC3fts9/Yc7nM=
github.com/tchap/go-patricia/v2 v2.3.2/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0=
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs=
github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI=
github.com/vbauerster/mpb/v8 v8.8.3 h1:dTOByGoqwaTJYPubhVz3lO5O6MK553XVgUo33LdnNsQ=
github.com/vbauerster/mpb/v8 v8.8.3/go.mod h1:JfCCrtcMsJwP6ZwMn9e5LMnNyp3TVNpUWWkN+nd4EWk=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
github.com/vbauerster/mpb/v8 v8.9.3 h1:PnMeF+sMvYv9u23l6DO6Q3+Mdj408mjLRXIzmUmU2Z8=
github.com/vbauerster/mpb/v8 v8.9.3/go.mod h1:hxS8Hz4C6ijnppDSIX6LjG8FYJSoPo9iIOcE53Zik0c=
github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
@ -350,38 +346,43 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@ -389,8 +390,11 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -404,11 +408,14 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -416,8 +423,12 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -429,26 +440,36 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -459,8 +480,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -470,18 +493,17 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c h1:TYOEhrQMrNDTAd2rX9m+WgGr8Ku6YNuj1D7OX6rWSok=
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -491,17 +513,15 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
${CPP:-${CC:-cc} -E} ${CPPFLAGS} - > /dev/null 2> /dev/null << EOF
#include <btrfs/version.h>
EOF
if test $? -ne 0 ; then
echo btrfs_noversion
fi

View File

@ -1,16 +0,0 @@
#!/bin/bash
errors=$($GOBIN/golangci-lint run --build-tags "${BUILDTAGS}" 2>&1)
if [ -z "$errors" ]; then
echo 'Congratulations! All Go source files have been linted.'
else
{
echo "Errors from golangci-lint:"
echo "$errors"
echo
echo 'Please fix the above errors. You can test via "golangci-lint" and commit the result.'
echo
} >&2
exit 1
fi

View File

@ -139,7 +139,7 @@ located at [https://github.com/containers/image_build/tree/main/skopeo](https://
Otherwise, read on for building and installing it from source:
To build the `skopeo` binary you need at least Go 1.22.
To build the `skopeo` binary you need at least Go 1.23.
There are two ways to build skopeo: in a container, or locally without a
container. Choose the one which better matches your needs and environment.

View File

@ -1,5 +1,4 @@
//go:build openshift_shell
// +build openshift_shell
package main

View File

@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"path/filepath"
"slices"
"strings"
"testing"
"time"
@ -153,7 +154,7 @@ func (cluster *openshiftCluster) prepareRegistryConfig(t *testing.T) {
require.Equal(t, "", string(out))
}
// startRegistry starts the OpenShift registry with configPart on port, waits for it to be ready, and returns the process object, or terminates on failure.
// startRegistryProcess starts the OpenShift registry with configPart on port, waits for it to be ready, and returns the process object, or terminates on failure.
func (cluster *openshiftCluster) startRegistryProcess(t *testing.T, port uint16, configPath string) *exec.Cmd {
cmd := cluster.clusterCmd(map[string]string{
"KUBECONFIG": "openshift.local.registry/openshift-registry.kubeconfig",
@ -253,10 +254,10 @@ func (cluster *openshiftCluster) relaxImageSignerPermissions(t *testing.T) {
// tearDown stops the cluster services and deletes (only some!) of the state.
func (cluster *openshiftCluster) tearDown(t *testing.T) {
for i := len(cluster.processes) - 1; i >= 0; i-- {
for _, process := range slices.Backward(cluster.processes) {
// Its undocumented what Kill() returns if the process has terminated,
// so we couldnt check just for that. This is running in a container anyway…
_ = cluster.processes[i].Process.Kill()
_ = process.Process.Kill()
}
if cluster.dockerDir != "" {
err := os.RemoveAll(cluster.dockerDir)

View File

@ -1,5 +1,4 @@
//go:build !linux
// +build !linux
//go:build unix && !linux
package main

View File

@ -1,3 +1,5 @@
//go:build unix
package main
import (
@ -8,6 +10,7 @@ import (
"os"
"os/exec"
"strings"
"sync"
"syscall"
"testing"
"time"
@ -58,8 +61,9 @@ type proxy struct {
type pipefd struct {
// id is the remote identifier "pipeid"
id uint
fd *os.File
id uint
datafd *os.File
errfd *os.File
}
func (p *proxy) call(method string, args []any) (rval any, fd *pipefd, err error) {
@ -97,26 +101,41 @@ func (p *proxy) call(method string, args []any) (rval any, fd *pipefd, err error
return
}
var scms []syscall.SocketControlMessage
scms, err = syscall.ParseSocketControlMessage(oob[:oobn])
if err != nil {
err = fmt.Errorf("failed to parse control message: %w", err)
return
}
if reply.PipeID > 0 {
var scms []syscall.SocketControlMessage
scms, err = syscall.ParseSocketControlMessage(oob[:oobn])
if err != nil {
err = fmt.Errorf("failed to parse control message: %w", err)
return
}
if len(scms) != 1 {
err = fmt.Errorf("Expected 1 received fd, found %d", len(scms))
err = fmt.Errorf("Expected 1 socket control message, found %d", len(scms))
return
}
}
if len(scms) > 2 {
err = fmt.Errorf("Expected 1 or 2 socket control message, found %d", len(scms))
return
}
if len(scms) != 0 {
var fds []int
fds, err = syscall.ParseUnixRights(&scms[0])
if err != nil {
err = fmt.Errorf("failed to parse unix rights: %w", err)
return
}
if len(fds) < 1 || len(fds) > 2 {
err = fmt.Errorf("expected 1 or 2 fds, found %d", len(fds))
return
}
var errfd *os.File
if len(fds) == 2 {
errfd = os.NewFile(uintptr(fds[1]), "errfd")
}
fd = &pipefd{
fd: os.NewFile(uintptr(fds[0]), "replyfd"),
id: uint(reply.PipeID),
datafd: os.NewFile(uintptr(fds[0]), "replyfd"),
id: uint(reply.PipeID),
errfd: errfd,
}
}
@ -149,7 +168,7 @@ func (p *proxy) callReadAllBytes(method string, args []any) (rval any, buf []byt
}
fetchchan := make(chan byteFetch)
go func() {
manifestBytes, err := io.ReadAll(fd.fd)
manifestBytes, err := io.ReadAll(fd.datafd)
fetchchan <- byteFetch{
content: manifestBytes,
err: err,
@ -173,6 +192,80 @@ func (p *proxy) callReadAllBytes(method string, args []any) (rval any, buf []byt
return
}
type proxyError struct {
Code string `json:"code"`
Message string `json:"message"`
}
func (p *proxy) callGetRawBlob(args []any) (rval any, buf []byte, err error) {
var fd *pipefd
rval, fd, err = p.call("GetRawBlob", args)
if err != nil {
return
}
if fd == nil {
err = fmt.Errorf("Expected fds from method GetRawBlob")
return
}
if fd.errfd == nil {
err = fmt.Errorf("Expected errfd from method GetRawBlob")
return
}
var wg sync.WaitGroup
fetchchan := make(chan byteFetch, 1)
errchan := make(chan proxyError, 1)
wg.Add(1)
go func() {
defer wg.Done()
defer close(fetchchan)
defer fd.datafd.Close()
buf, err := io.ReadAll(fd.datafd)
fetchchan <- byteFetch{
content: buf,
err: err,
}
}()
wg.Add(1)
go func() {
defer wg.Done()
defer fd.errfd.Close()
defer close(errchan)
buf, err := io.ReadAll(fd.errfd)
var proxyErr proxyError
if err != nil {
proxyErr.Code = "read-from-proxy"
proxyErr.Message = err.Error()
errchan <- proxyErr
return
}
// No error, leave code+message unset
if len(buf) == 0 {
return
}
unmarshalErr := json.Unmarshal(buf, &proxyErr)
// Shouldn't happen
if unmarshalErr != nil {
panic(unmarshalErr)
}
errchan <- proxyErr
}()
wg.Wait()
errMsg := <-errchan
if errMsg.Code != "" {
return nil, nil, fmt.Errorf("(%s) %s", errMsg.Code, errMsg.Message)
}
fetchRes := <-fetchchan
err = fetchRes.err
if err != nil {
return
}
buf = fetchRes.content
return
}
func newProxy() (*proxy, error) {
fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET, 0)
if err != nil {
@ -229,7 +322,8 @@ type byteFetch struct {
err error
}
func runTestGetManifestAndConfig(p *proxy, img string) error {
// This exercises all the metadata fetching APIs.
func runTestMetadataAPIs(p *proxy, img string) error {
v, err := p.callNoFd("OpenImage", []any{img})
if err != nil {
return err
@ -291,6 +385,19 @@ func runTestGetManifestAndConfig(p *proxy, img string) error {
return fmt.Errorf("No CMD or ENTRYPOINT set")
}
_, layerInfoBytes, err := p.callReadAllBytes("GetLayerInfoPiped", []any{imgid})
if err != nil {
return err
}
var layerInfoBytesData []interface{}
err = json.Unmarshal(layerInfoBytes, &layerInfoBytesData)
if err != nil {
return err
}
if len(layerInfoBytesData) == 0 {
return fmt.Errorf("expected layer info data")
}
// Also test this legacy interface
_, ctrconfigBytes, err := p.callReadAllBytes("GetConfig", []any{imgid})
if err != nil {
@ -332,18 +439,57 @@ func runTestOpenImageOptionalNotFound(p *proxy, img string) error {
return nil
}
func (s *proxySuite) TestProxy() {
func runTestGetBlob(p *proxy, img string) error {
imgid, err := p.callNoFd("OpenImage", []any{img})
if err != nil {
return err
}
_, manifestBytes, err := p.callReadAllBytes("GetManifest", []any{imgid})
if err != nil {
return err
}
mfest, err := manifest.OCI1FromManifest(manifestBytes)
if err != nil {
return err
}
for _, layer := range mfest.Layers {
_, blobBytes, err := p.callGetRawBlob([]any{imgid, layer.Digest})
if err != nil {
return err
}
if len(blobBytes) != int(layer.Size) {
panic(fmt.Sprintf("Expected %d bytes, got %d", layer.Size, len(blobBytes)))
}
}
// echo "not a valid layer" | sha256sum
invalidDigest := "sha256:21a9aab5a3494674d2b4d8e7381c236a799384dd10545531014606cf652c119f"
_, blobBytes, err := p.callGetRawBlob([]any{imgid, invalidDigest})
if err == nil {
panic("Expected error fetching invalid blob")
}
if blobBytes != nil {
panic("Expected no bytes fetching invalid blob")
}
return nil
}
func (s *proxySuite) TestProxyMetadata() {
t := s.T()
p, err := newProxy()
require.NoError(t, err)
err = runTestGetManifestAndConfig(p, knownNotManifestListedImageX8664)
err = runTestMetadataAPIs(p, knownNotManifestListedImageX8664)
if err != nil {
err = fmt.Errorf("Testing image %s: %v", knownNotManifestListedImageX8664, err)
}
assert.NoError(t, err)
err = runTestGetManifestAndConfig(p, knownListImage)
err = runTestMetadataAPIs(p, knownListImage)
if err != nil {
err = fmt.Errorf("Testing image %s: %v", knownListImage, err)
}
@ -355,3 +501,15 @@ func (s *proxySuite) TestProxy() {
}
assert.NoError(t, err)
}
func (s *proxySuite) TestProxyGetBlob() {
t := s.T()
p, err := newProxy()
require.NoError(t, err)
err = runTestGetBlob(p, knownListImage)
if err != nil {
err = fmt.Errorf("Testing GetBLob for %s: %v", knownListImage, err)
}
assert.NoError(t, err)
}

20
plans/main.fmf Normal file
View File

@ -0,0 +1,20 @@
discover:
how: fmf
execute:
how: tmt
prepare:
- when: distro == centos-stream or distro == rhel
how: shell
script: |
dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-$(rpm --eval '%{?rhel}').noarch.rpm
dnf -y config-manager --set-enabled epel
order: 10
- when: initiator == packit
how: shell
script: |
COPR_REPO_FILE="/etc/yum.repos.d/*podman-next*.repo"
if compgen -G $COPR_REPO_FILE > /dev/null; then
sed -i -n '/^priority=/!p;$apriority=1' $COPR_REPO_FILE
fi
dnf -y upgrade --allowerasing
order: 20

16
rpm/gating.yaml Normal file
View File

@ -0,0 +1,16 @@
--- !Policy
product_versions:
- fedora-*
decision_context:
- bodhi_update_push_stable
- bodhi_update_push_testing
subject_type: koji_build
rules:
- !PassingTestCaseRule {test_case_name: fedora-ci.koji-build.tier0.functional}
--- !Policy
product_versions:
- rhel-*
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

View File

@ -7,15 +7,6 @@
%global debug_package %{nil}
%endif
# RHEL's default %%gobuild macro doesn't account for the BUILDTAGS variable, so we
# set it separately here and do not depend on RHEL's go-[s]rpm-macros package
# until that's fixed.
# c9s bz: https://bugzilla.redhat.com/show_bug.cgi?id=2227328
# c8s bz: https://bugzilla.redhat.com/show_bug.cgi?id=2227331
%if %{defined rhel}
%define gobuild(o:) go build -buildmode pie -compiler gc -tags="rpm_crashtraceback libtrust_openssl ${BUILDTAGS:-}" -ldflags "-linkmode=external -compressdwarf=false ${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '%__global_ldflags'" -a -v -x %{?**};
%endif
%global gomodulesmode GO111MODULE=on
# No btrfs on RHEL
@ -23,10 +14,15 @@
%define build_with_btrfs 1
%endif
%if %{defined rhel}
%define fips 1
%endif
# Only used in official koji builds
# Copr builds set a separate epoch for all environments
%if %{defined fedora}
%define conditional_epoch 1
%define fakeroot 1
%else
%define conditional_epoch 2
%endif
@ -77,12 +73,14 @@ Requires: containers-common >= 4:1-21
Command line utility to inspect images and repositories directly on Docker
registries without the need to pull them
# NOTE: The tests subpackage is only intended for testing and will not be supported
# for end-users and/or customers.
%package tests
Summary: Tests for %{name}
Requires: %{name} = %{epoch}:%{version}-%{release}
%if %{defined fedora}
Requires: bats
%if %{defined fakeroot}
Requires: fakeroot
%endif
Requires: gnupg
@ -122,9 +120,13 @@ export CGO_CFLAGS="$CGO_CFLAGS -m64 -mtune=generic -fcf-protection=full"
BASEBUILDTAGS="$(hack/libsubid_tag.sh)"
%if %{defined build_with_btrfs}
export BUILDTAGS="$BASEBUILDTAGS $(hack/btrfs_tag.sh) $(hack/btrfs_installed_tag.sh)"
export BUILDTAGS="$BASEBUILDTAGS $(hack/btrfs_installed_tag.sh)"
%else
export BUILDTAGS="$BASEBUILDTAGS btrfs_noversion exclude_graphdriver_btrfs"
export BUILDTAGS="$BASEBUILDTAGS exclude_graphdriver_btrfs"
%endif
%if %{defined fips}
export BUILDTAGS="$BUILDTAGS libtrust_openssl"
%endif
# unset LDFLAGS earlier set from set_build_flags
@ -146,6 +148,10 @@ cp -pav systemtest/* %{buildroot}/%{_datadir}/%{name}/test/system/
#define license tag if not already defined
%{!?_licensedir:%global license %doc}
# Include this to silence rpmlint.
# Especially annoying if you use syntastic vim plugin.
%check
%files
%license LICENSE
%doc README.md

View File

@ -132,7 +132,7 @@ END_EXPECT
@test "inspect: image unknown" {
# non existing image
run_skopeo 2 inspect containers-storage:non-existing-tag
expect_output --substring "identifier is not an image" \
expect_output --substring "does not resolve to an image ID" \
"skopeo inspect containers-storage:010101010101"
}

View File

@ -10,7 +10,7 @@ SKOPEO_BINARY=${SKOPEO_BINARY:-${TEST_SOURCE_DIR}/../bin/skopeo}
SKOPEO_TIMEOUT=${SKOPEO_TIMEOUT:-300}
# Default image to run as a local registry
REGISTRY_FQIN=${SKOPEO_TEST_REGISTRY_FQIN:-quay.io/libpod/registry:2}
REGISTRY_FQIN=${SKOPEO_TEST_REGISTRY_FQIN:-quay.io/libpod/registry:2.8.2}
###############################################################################
# BEGIN setup/teardown

10
systemtest/tmt/main.fmf Normal file
View File

@ -0,0 +1,10 @@
require:
- bats
- skopeo-tests
environment:
SKOPEO_BINARY: /usr/bin/skopeo
summary: System test
test: bash ./test.sh
duration: 60m

13
systemtest/tmt/test.sh Normal file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -exo pipefail
uname -r
rpm -q \
bats \
containers-common \
skopeo \
skopeo-tests \
bats /usr/share/skopeo/test/system

View File

@ -3,7 +3,7 @@ reflection interface similar to Go's standard library `json` and `xml` packages.
Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0).
Documentation: https://godocs.io/github.com/BurntSushi/toml
Documentation: https://pkg.go.dev/github.com/BurntSushi/toml
See the [releases page](https://github.com/BurntSushi/toml/releases) for a
changelog; this information is also in the git tag annotations (e.g. `git show

View File

@ -196,6 +196,19 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v any) error {
return md.unify(primValue.undecoded, rvalue(v))
}
// markDecodedRecursive is a helper to mark any key under the given tmap as
// decoded, recursing as needed
func markDecodedRecursive(md *MetaData, tmap map[string]any) {
for key := range tmap {
md.decoded[md.context.add(key).String()] = struct{}{}
if tmap, ok := tmap[key].(map[string]any); ok {
md.context = append(md.context, key)
markDecodedRecursive(md, tmap)
md.context = md.context[0 : len(md.context)-1]
}
}
}
// unify performs a sort of type unification based on the structure of `rv`,
// which is the client representation.
//
@ -222,6 +235,16 @@ func (md *MetaData) unify(data any, rv reflect.Value) error {
if err != nil {
return md.parseErr(err)
}
// Assume the Unmarshaler decoded everything, so mark all keys under
// this table as decoded.
if tmap, ok := data.(map[string]any); ok {
markDecodedRecursive(md, tmap)
}
if aot, ok := data.([]map[string]any); ok {
for _, tmap := range aot {
markDecodedRecursive(md, tmap)
}
}
return nil
}
if v, ok := rvi.(encoding.TextUnmarshaler); ok {
@ -540,12 +563,14 @@ func (md *MetaData) badtype(dst string, data any) error {
func (md *MetaData) parseErr(err error) error {
k := md.context.String()
d := string(md.data)
return ParseError{
LastKey: k,
Position: md.keyInfo[k].pos,
Line: md.keyInfo[k].pos.Line,
Message: err.Error(),
err: err,
input: string(md.data),
LastKey: k,
Position: md.keyInfo[k].pos.withCol(d),
Line: md.keyInfo[k].pos.Line,
input: d,
}
}

View File

@ -402,31 +402,30 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
// Sort keys so that we have deterministic output. And write keys directly
// underneath this key first, before writing sub-structs or sub-maps.
var mapKeysDirect, mapKeysSub []string
var mapKeysDirect, mapKeysSub []reflect.Value
for _, mapKey := range rv.MapKeys() {
k := mapKey.String()
if typeIsTable(tomlTypeOfGo(eindirect(rv.MapIndex(mapKey)))) {
mapKeysSub = append(mapKeysSub, k)
mapKeysSub = append(mapKeysSub, mapKey)
} else {
mapKeysDirect = append(mapKeysDirect, k)
mapKeysDirect = append(mapKeysDirect, mapKey)
}
}
var writeMapKeys = func(mapKeys []string, trailC bool) {
sort.Strings(mapKeys)
writeMapKeys := func(mapKeys []reflect.Value, trailC bool) {
sort.Slice(mapKeys, func(i, j int) bool { return mapKeys[i].String() < mapKeys[j].String() })
for i, mapKey := range mapKeys {
val := eindirect(rv.MapIndex(reflect.ValueOf(mapKey)))
val := eindirect(rv.MapIndex(mapKey))
if isNil(val) {
continue
}
if inline {
enc.writeKeyValue(Key{mapKey}, val, true)
enc.writeKeyValue(Key{mapKey.String()}, val, true)
if trailC || i != len(mapKeys)-1 {
enc.wf(", ")
}
} else {
enc.encode(key.add(mapKey), val)
enc.encode(key.add(mapKey.String()), val)
}
}
}
@ -441,8 +440,6 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
}
}
const is32Bit = (32 << (^uint(0) >> 63)) == 32
func pointerTo(t reflect.Type) reflect.Type {
if t.Kind() == reflect.Ptr {
return pointerTo(t.Elem())
@ -477,15 +474,14 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
frv := eindirect(rv.Field(i))
if is32Bit {
// Copy so it works correct on 32bit archs; not clear why this
// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
// This also works fine on 64bit, but 32bit archs are somewhat
// rare and this is a wee bit faster.
copyStart := make([]int, len(start))
copy(copyStart, start)
start = copyStart
}
// Need to make a copy because ... ehm, I don't know why... I guess
// allocating a new array can cause it to fail(?)
//
// Done for: https://github.com/BurntSushi/toml/issues/430
// Previously only on 32bit for: https://github.com/BurntSushi/toml/issues/314
copyStart := make([]int, len(start))
copy(copyStart, start)
start = copyStart
// Treat anonymous struct fields with tag names as though they are
// not anonymous, like encoding/json does.
@ -507,7 +503,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
}
addFields(rt, rv, nil)
writeFields := func(fields [][]int) {
writeFields := func(fields [][]int, totalFields int) {
for _, fieldIndex := range fields {
fieldType := rt.FieldByIndex(fieldIndex)
fieldVal := rv.FieldByIndex(fieldIndex)
@ -537,7 +533,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
if inline {
enc.writeKeyValue(Key{keyName}, fieldVal, true)
if fieldIndex[0] != len(fields)-1 {
if fieldIndex[0] != totalFields-1 {
enc.wf(", ")
}
} else {
@ -549,8 +545,10 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
if inline {
enc.wf("{")
}
writeFields(fieldsDirect)
writeFields(fieldsSub)
l := len(fieldsDirect) + len(fieldsSub)
writeFields(fieldsDirect, l)
writeFields(fieldsSub, l)
if inline {
enc.wf("}")
}

View File

@ -67,21 +67,36 @@ type ParseError struct {
// Position of an error.
type Position struct {
Line int // Line number, starting at 1.
Col int // Error column, starting at 1.
Start int // Start of error, as byte offset starting at 0.
Len int // Lenght in bytes.
Len int // Length of the error in bytes.
}
func (p Position) withCol(tomlFile string) Position {
var (
pos int
lines = strings.Split(tomlFile, "\n")
)
for i := range lines {
ll := len(lines[i]) + 1 // +1 for the removed newline
if pos+ll >= p.Start {
p.Col = p.Start - pos + 1
if p.Col < 1 { // Should never happen, but just in case.
p.Col = 1
}
break
}
pos += ll
}
return p
}
func (pe ParseError) Error() string {
msg := pe.Message
if msg == "" { // Error from errorf()
msg = pe.err.Error()
}
if pe.LastKey == "" {
return fmt.Sprintf("toml: line %d: %s", pe.Position.Line, msg)
return fmt.Sprintf("toml: line %d: %s", pe.Position.Line, pe.Message)
}
return fmt.Sprintf("toml: line %d (last key %q): %s",
pe.Position.Line, pe.LastKey, msg)
pe.Position.Line, pe.LastKey, pe.Message)
}
// ErrorWithPosition returns the error with detailed location context.
@ -92,26 +107,19 @@ func (pe ParseError) ErrorWithPosition() string {
return pe.Error()
}
var (
lines = strings.Split(pe.input, "\n")
col = pe.column(lines)
b = new(strings.Builder)
)
msg := pe.Message
if msg == "" {
msg = pe.err.Error()
}
// TODO: don't show control characters as literals? This may not show up
// well everywhere.
var (
lines = strings.Split(pe.input, "\n")
b = new(strings.Builder)
)
if pe.Position.Len == 1 {
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d:\n\n",
msg, pe.Position.Line, col+1)
pe.Message, pe.Position.Line, pe.Position.Col)
} else {
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d-%d:\n\n",
msg, pe.Position.Line, col, col+pe.Position.Len)
pe.Message, pe.Position.Line, pe.Position.Col, pe.Position.Col+pe.Position.Len-1)
}
if pe.Position.Line > 2 {
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, expandTab(lines[pe.Position.Line-3]))
@ -129,7 +137,7 @@ func (pe ParseError) ErrorWithPosition() string {
diff := len(expanded) - len(lines[pe.Position.Line-1])
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, expanded)
fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col+diff), strings.Repeat("^", pe.Position.Len))
fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", pe.Position.Col-1+diff), strings.Repeat("^", pe.Position.Len))
return b.String()
}
@ -151,23 +159,6 @@ func (pe ParseError) ErrorWithUsage() string {
return m
}
func (pe ParseError) column(lines []string) int {
var pos, col int
for i := range lines {
ll := len(lines[i]) + 1 // +1 for the removed newline
if pos+ll >= pe.Position.Start {
col = pe.Position.Start - pos
if col < 0 { // Should never happen, but just in case.
col = 0
}
break
}
pos += ll
}
return col
}
func expandTab(s string) string {
var (
b strings.Builder

View File

@ -275,7 +275,9 @@ func (lx *lexer) errorPos(start, length int, err error) stateFn {
func (lx *lexer) errorf(format string, values ...any) stateFn {
if lx.atEOF {
pos := lx.getPos()
pos.Line--
if lx.pos >= 1 && lx.input[lx.pos-1] == '\n' {
pos.Line--
}
pos.Len = 1
pos.Start = lx.pos - 1
lx.items <- item{typ: itemError, pos: pos, err: fmt.Errorf(format, values...)}
@ -492,6 +494,9 @@ func lexKeyEnd(lx *lexer) stateFn {
lx.emit(itemKeyEnd)
return lexSkip(lx, lexValue)
default:
if r == '\n' {
return lx.errorPrevLine(fmt.Errorf("expected '.' or '=', but got %q instead", r))
}
return lx.errorf("expected '.' or '=', but got %q instead", r)
}
}
@ -560,6 +565,9 @@ func lexValue(lx *lexer) stateFn {
if r == eof {
return lx.errorf("unexpected EOF; expected value")
}
if r == '\n' {
return lx.errorPrevLine(fmt.Errorf("expected value but found %q instead", r))
}
return lx.errorf("expected value but found %q instead", r)
}
@ -1111,7 +1119,7 @@ func lexBaseNumberOrDate(lx *lexer) stateFn {
case 'x':
r = lx.peek()
if !isHex(r) {
lx.errorf("not a hexidecimal number: '%s%c'", lx.current(), r)
lx.errorf("not a hexadecimal number: '%s%c'", lx.current(), r)
}
return lexHexInteger
}
@ -1259,23 +1267,6 @@ func isBinary(r rune) bool { return r == '0' || r == '1' }
func isOctal(r rune) bool { return r >= '0' && r <= '7' }
func isHex(r rune) bool { return (r >= '0' && r <= '9') || (r|0x20 >= 'a' && r|0x20 <= 'f') }
func isBareKeyChar(r rune, tomlNext bool) bool {
if tomlNext {
return (r >= 'A' && r <= 'Z') ||
(r >= 'a' && r <= 'z') ||
(r >= '0' && r <= '9') ||
r == '_' || r == '-' ||
r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) ||
(r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) ||
(r >= 0x037f && r <= 0x1fff) ||
(r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) ||
(r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) ||
(r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) ||
(r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) ||
(r >= 0x10000 && r <= 0xeffff)
}
return (r >= 'A' && r <= 'Z') ||
(r >= 'a' && r <= 'z') ||
(r >= '0' && r <= '9') ||
r == '_' || r == '-'
return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') ||
(r >= '0' && r <= '9') || r == '_' || r == '-'
}

View File

@ -135,9 +135,6 @@ func (k Key) maybeQuoted(i int) string {
// Like append(), but only increase the cap by 1.
func (k Key) add(piece string) Key {
if cap(k) > len(k) {
return append(k, piece)
}
newKey := make(Key, len(k)+1)
copy(newKey, k)
newKey[len(k)] = piece

View File

@ -50,7 +50,6 @@ func parse(data string) (p *parser, err error) {
// it anyway.
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16
data = data[2:]
//lint:ignore S1017 https://github.com/dominikh/go-tools/issues/1447
} else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8
data = data[3:]
}
@ -65,7 +64,7 @@ func parse(data string) (p *parser, err error) {
if i := strings.IndexRune(data[:ex], 0); i > -1 {
return nil, ParseError{
Message: "files cannot contain NULL bytes; probably using UTF-16; TOML files must be UTF-8",
Position: Position{Line: 1, Start: i, Len: 1},
Position: Position{Line: 1, Col: 1, Start: i, Len: 1},
Line: 1,
input: data,
}
@ -92,8 +91,9 @@ func parse(data string) (p *parser, err error) {
func (p *parser) panicErr(it item, err error) {
panic(ParseError{
Message: err.Error(),
err: err,
Position: it.pos,
Position: it.pos.withCol(p.lx.input),
Line: it.pos.Len,
LastKey: p.current(),
})
@ -102,7 +102,7 @@ func (p *parser) panicErr(it item, err error) {
func (p *parser) panicItemf(it item, format string, v ...any) {
panic(ParseError{
Message: fmt.Sprintf(format, v...),
Position: it.pos,
Position: it.pos.withCol(p.lx.input),
Line: it.pos.Len,
LastKey: p.current(),
})
@ -111,7 +111,7 @@ func (p *parser) panicItemf(it item, format string, v ...any) {
func (p *parser) panicf(format string, v ...any) {
panic(ParseError{
Message: fmt.Sprintf(format, v...),
Position: p.pos,
Position: p.pos.withCol(p.lx.input),
Line: p.pos.Line,
LastKey: p.current(),
})
@ -123,10 +123,11 @@ func (p *parser) next() item {
if it.typ == itemError {
if it.err != nil {
panic(ParseError{
Position: it.pos,
Message: it.err.Error(),
err: it.err,
Position: it.pos.withCol(p.lx.input),
Line: it.pos.Line,
LastKey: p.current(),
err: it.err,
})
}
@ -527,7 +528,7 @@ func numUnderscoresOK(s string) bool {
}
}
// isHexis a superset of all the permissable characters surrounding an
// isHex is a superset of all the permissible characters surrounding an
// underscore.
accept = isHex(r)
}

View File

@ -39,9 +39,11 @@ var (
)
// semVerRegex is the regular expression used to parse a semantic version.
const semVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
// This is not the official regex from the semver spec. It has been modified to allow for loose handling
// where versions like 2.1 are detected.
const semVerRegex string = `v?(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:\.(0|[1-9]\d*))?` +
`(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?` +
`(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?`
// Version represents a single semantic version.
type Version struct {
@ -146,8 +148,8 @@ func NewVersion(v string) (*Version, error) {
}
sv := &Version{
metadata: m[8],
pre: m[5],
metadata: m[5],
pre: m[4],
original: v,
}
@ -158,7 +160,7 @@ func NewVersion(v string) (*Version, error) {
}
if m[2] != "" {
sv.minor, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 64)
sv.minor, err = strconv.ParseUint(m[2], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
@ -167,7 +169,7 @@ func NewVersion(v string) (*Version, error) {
}
if m[3] != "" {
sv.patch, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 64)
sv.patch, err = strconv.ParseUint(m[3], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
@ -612,7 +614,9 @@ func containsOnly(s string, comp string) bool {
func validatePrerelease(p string) error {
eparts := strings.Split(p, ".")
for _, p := range eparts {
if containsOnly(p, num) {
if p == "" {
return ErrInvalidMetadata
} else if containsOnly(p, num) {
if len(p) > 1 && p[0] == '0' {
return ErrSegmentStartsZero
}
@ -631,7 +635,9 @@ func validatePrerelease(p string) error {
func validateMetadata(m string) error {
eparts := strings.Split(m, ".")
for _, p := range eparts {
if !containsOnly(p, allowed) {
if p == "" {
return ErrInvalidMetadata
} else if !containsOnly(p, allowed) {
return ErrInvalidMetadata
}
}

View File

@ -26,12 +26,13 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"crypto/rand"
"crypto/sha256"
"encoding/json"
"errors"
"fmt"
"io"
"math/rand"
"math/big"
"os"
"path/filepath"
"reflect"
@ -45,10 +46,6 @@ import (
digest "github.com/opencontainers/go-digest"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
// TestingController is Compression with some helper methods necessary for testing.
type TestingController interface {
Compression
@ -920,9 +917,11 @@ func checkVerifyInvalidTOCEntryFail(filename string) check {
}
if sampleEntry == nil {
t.Fatalf("TOC must contain at least one regfile or chunk entry other than the rewrite target")
return
}
if targetEntry == nil {
t.Fatalf("rewrite target not found")
return
}
targetEntry.Offset = sampleEntry.Offset
},
@ -2291,7 +2290,11 @@ var runes = []rune("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX
func randomContents(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = runes[rand.Intn(len(runes))]
bi, err := rand.Int(rand.Reader, big.NewInt(int64(len(runes))))
if err != nil {
panic(err)
}
b[i] = runes[int(bi.Int64())]
}
return string(b)
}

View File

@ -18,3 +18,9 @@ As a containerd sub-project, you will find the:
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
information in our [`containerd/project`](https://github.com/containerd/project) repository.
## Optional
By default, support for gogoproto is available along side the standard Google
protobuf types.
You can choose to leave gogo support out by using the `!no_gogo` build tag.

View File

@ -24,7 +24,6 @@ import (
"reflect"
"sync"
gogoproto "github.com/gogo/protobuf/proto"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/known/anypb"
@ -33,8 +32,16 @@ import (
var (
mu sync.RWMutex
registry = make(map[reflect.Type]string)
handlers []handler
)
type handler interface {
Marshaller(interface{}) func() ([]byte, error)
Unmarshaller(interface{}) func([]byte) error
TypeURL(interface{}) string
GetType(url string) (reflect.Type, bool)
}
// Definitions of common error types used throughout typeurl.
//
// These error types are used with errors.Wrap and errors.Wrapf to add context
@ -112,9 +119,12 @@ func TypeURL(v interface{}) (string, error) {
switch t := v.(type) {
case proto.Message:
return string(t.ProtoReflect().Descriptor().FullName()), nil
case gogoproto.Message:
return gogoproto.MessageName(t), nil
default:
for _, h := range handlers {
if u := h.TypeURL(v); u != "" {
return u, nil
}
}
return "", fmt.Errorf("type %s: %w", reflect.TypeOf(v), ErrNotFound)
}
}
@ -149,12 +159,19 @@ func MarshalAny(v interface{}) (Any, error) {
marshal = func(v interface{}) ([]byte, error) {
return proto.Marshal(t)
}
case gogoproto.Message:
marshal = func(v interface{}) ([]byte, error) {
return gogoproto.Marshal(t)
}
default:
marshal = json.Marshal
for _, h := range handlers {
if m := h.Marshaller(v); m != nil {
marshal = func(v interface{}) ([]byte, error) {
return m()
}
break
}
}
if marshal == nil {
marshal = json.Marshal
}
}
url, err := TypeURL(v)
@ -223,13 +240,13 @@ func MarshalAnyToProto(from interface{}) (*anypb.Any, error) {
}
func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
t, err := getTypeByUrl(typeURL)
t, isProto, err := getTypeByUrl(typeURL)
if err != nil {
return nil, err
}
if v == nil {
v = reflect.New(t.t).Interface()
v = reflect.New(t).Interface()
} else {
// Validate interface type provided by client
vURL, err := TypeURL(v)
@ -241,51 +258,45 @@ func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error)
}
}
if t.isProto {
switch t := v.(type) {
case proto.Message:
err = proto.Unmarshal(value, t)
case gogoproto.Message:
err = gogoproto.Unmarshal(value, t)
if isProto {
pm, ok := v.(proto.Message)
if ok {
return v, proto.Unmarshal(value, pm)
}
for _, h := range handlers {
if unmarshal := h.Unmarshaller(v); unmarshal != nil {
return v, unmarshal(value)
}
}
} else {
err = json.Unmarshal(value, v)
}
return v, err
// fallback to json unmarshaller
return v, json.Unmarshal(value, v)
}
type urlType struct {
t reflect.Type
isProto bool
}
func getTypeByUrl(url string) (urlType, error) {
func getTypeByUrl(url string) (_ reflect.Type, isProto bool, _ error) {
mu.RLock()
for t, u := range registry {
if u == url {
mu.RUnlock()
return urlType{
t: t,
}, nil
return t, false, nil
}
}
mu.RUnlock()
// fallback to proto registry
t := gogoproto.MessageType(url)
if t != nil {
return urlType{
// get the underlying Elem because proto returns a pointer to the type
t: t.Elem(),
isProto: true,
}, nil
}
mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
if err != nil {
return urlType{}, fmt.Errorf("type with url %s: %w", url, ErrNotFound)
if errors.Is(err, protoregistry.NotFound) {
for _, h := range handlers {
if t, isProto := h.GetType(url); t != nil {
return t, isProto, nil
}
}
}
return nil, false, fmt.Errorf("type with url %s: %w", url, ErrNotFound)
}
empty := mt.New().Interface()
return urlType{t: reflect.TypeOf(empty).Elem(), isProto: true}, nil
return reflect.TypeOf(empty).Elem(), true, nil
}
func tryDereference(v interface{}) reflect.Type {

68
vendor/github.com/containerd/typeurl/v2/types_gogo.go generated vendored Normal file
View File

@ -0,0 +1,68 @@
//go:build !no_gogo
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package typeurl
import (
"reflect"
gogoproto "github.com/gogo/protobuf/proto"
)
func init() {
handlers = append(handlers, gogoHandler{})
}
type gogoHandler struct{}
func (gogoHandler) Marshaller(v interface{}) func() ([]byte, error) {
pm, ok := v.(gogoproto.Message)
if !ok {
return nil
}
return func() ([]byte, error) {
return gogoproto.Marshal(pm)
}
}
func (gogoHandler) Unmarshaller(v interface{}) func([]byte) error {
pm, ok := v.(gogoproto.Message)
if !ok {
return nil
}
return func(dt []byte) error {
return gogoproto.Unmarshal(dt, pm)
}
}
func (gogoHandler) TypeURL(v interface{}) string {
pm, ok := v.(gogoproto.Message)
if !ok {
return ""
}
return gogoproto.MessageName(pm)
}
func (gogoHandler) GetType(url string) (reflect.Type, bool) {
t := gogoproto.MessageType(url)
if t == nil {
return nil, false
}
return t.Elem(), true
}

View File

@ -173,10 +173,10 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
if opts.StdinPassword {
var stdinPasswordStrBuilder strings.Builder
if opts.Password != "" {
return errors.New("Can't specify both --password-stdin and --password")
return errors.New("can't specify both --password-stdin and --password")
}
if opts.Username == "" {
return errors.New("Must provide --username with --password-stdin")
return errors.New("must provide --username with --password-stdin")
}
scanner := bufio.NewScanner(opts.Stdin)
for scanner.Scan() {

View File

@ -5,10 +5,12 @@ import (
"io"
"math"
"net"
"net/http"
"net/url"
"syscall"
"time"
"github.com/containers/image/v5/docker"
"github.com/docker/distribution/registry/api/errcode"
errcodev2 "github.com/docker/distribution/registry/api/v2"
"github.com/hashicorp/go-multierror"
@ -47,7 +49,7 @@ func IfNecessary(ctx context.Context, operation func() error, options *Options)
logrus.Warnf("Failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, options.MaxRetry, err)
select {
case <-time.After(delay):
break
// Do nothing.
case <-ctx.Done():
return err
}
@ -81,6 +83,13 @@ func IsErrorRetryable(err error) bool {
return false
}
return true
case docker.UnexpectedHTTPStatusError:
// Retry on 502, 502 and 503 http server errors, they appear to be quite common in the field.
// https://github.com/containers/common/issues/2299
if e.StatusCode >= http.StatusBadGateway && e.StatusCode <= http.StatusGatewayTimeout {
return true
}
return false
case *net.OpError:
return IsErrorRetryable(e.Err)
case *url.Error: // This includes errors returned by the net/http client.

View File

@ -148,6 +148,13 @@ type Options struct {
// so that storage.ResolveReference returns exactly the created image.
// WARNING: It is unspecified whether the reference also contains a reference.Named element.
ReportResolvedReference *types.ImageReference
// DestinationTimestamp, if set, will force timestamps of content created in the destination to this value.
// Most transports don't support this.
//
// In oci-archive: destinations, this will set the create/mod/access timestamps in each tar entry
// (but not a timestamp of the created archive file).
DestinationTimestamp *time.Time
}
// OptionCompressionVariant allows to supply information about
@ -354,6 +361,7 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
if err := c.dest.CommitWithOptions(ctx, private.CommitOptions{
UnparsedToplevel: c.unparsedToplevel,
ReportResolvedReference: options.ReportResolvedReference,
Timestamp: options.DestinationTimestamp,
}); err != nil {
return nil, fmt.Errorf("committing the finished image: %w", err)
}

View File

@ -83,7 +83,7 @@ func platformCompressionMap(list internalManifest.List, instanceDigests []digest
platformSet = set.New[string]()
res[platform] = platformSet
}
platformSet.AddSlice(instanceDetails.ReadOnly.CompressionAlgorithmNames)
platformSet.AddSeq(slices.Values(instanceDetails.ReadOnly.CompressionAlgorithmNames))
}
return res, nil
}

View File

@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"iter"
"maps"
"reflect"
"slices"
@ -109,7 +110,7 @@ func (c *copier) copySingleImage(ctx context.Context, unparsedImage *image.Unpar
}
}
if err := checkImageDestinationForCurrentRuntime(ctx, c.options.DestinationCtx, src, c.dest); err != nil {
if err := prepareImageConfigForDest(ctx, c.options.DestinationCtx, src, c.dest); err != nil {
return copySingleImageResult{}, err
}
@ -316,32 +317,37 @@ func (c *copier) copySingleImage(ctx context.Context, unparsedImage *image.Unpar
return res, nil
}
// checkImageDestinationForCurrentRuntime enforces dest.MustMatchRuntimeOS, if necessary.
func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.SystemContext, src types.Image, dest types.ImageDestination) error {
// prepareImageConfigForDest enforces dest.MustMatchRuntimeOS and handles dest.NoteOriginalOCIConfig, if necessary.
func prepareImageConfigForDest(ctx context.Context, sys *types.SystemContext, src types.Image, dest private.ImageDestination) error {
ociConfig, configErr := src.OCIConfig(ctx)
// Do not fail on configErr here, this might be an artifact
// and maybe nothing needs this to be a container image and to process the config.
if dest.MustMatchRuntimeOS() {
c, err := src.OCIConfig(ctx)
if err != nil {
return fmt.Errorf("parsing image configuration: %w", err)
if configErr != nil {
return fmt.Errorf("parsing image configuration: %w", configErr)
}
wantedPlatforms := platform.WantedPlatforms(sys)
options := newOrderedSet()
match := false
for _, wantedPlatform := range wantedPlatforms {
if !slices.ContainsFunc(wantedPlatforms, func(wantedPlatform imgspecv1.Platform) bool {
// For a transitional period, this might trigger warnings because the Variant
// field was added to OCI config only recently. If this turns out to be too noisy,
// revert this check to only look for (OS, Architecture).
if platform.MatchesPlatform(c.Platform, wantedPlatform) {
match = true
break
return platform.MatchesPlatform(ociConfig.Platform, wantedPlatform)
}) {
options := newOrderedSet()
for _, p := range wantedPlatforms {
options.append(fmt.Sprintf("%s+%s+%q", p.OS, p.Architecture, p.Variant))
}
options.append(fmt.Sprintf("%s+%s+%q", wantedPlatform.OS, wantedPlatform.Architecture, wantedPlatform.Variant))
}
if !match {
logrus.Infof("Image operating system mismatch: image uses OS %q+architecture %q+%q, expecting one of %q",
c.OS, c.Architecture, c.Variant, strings.Join(options.list, ", "))
ociConfig.OS, ociConfig.Architecture, ociConfig.Variant, strings.Join(options.list, ", "))
}
}
if err := dest.NoteOriginalOCIConfig(ociConfig, configErr); err != nil {
return err
}
return nil
}
@ -412,7 +418,7 @@ func (ic *imageCopier) compareImageDestinationManifestEqual(ctx context.Context,
}
}
algos, err := algorithmsByNames(compressionAlgos.Values())
algos, err := algorithmsByNames(compressionAlgos.All())
if err != nil {
return nil, err
}
@ -547,7 +553,7 @@ func (ic *imageCopier) copyLayers(ctx context.Context) ([]compressiontypes.Algor
if srcInfosUpdated || layerDigestsDiffer(srcInfos, destInfos) {
ic.manifestUpdates.LayerInfos = destInfos
}
algos, err := algorithmsByNames(compressionAlgos.Values())
algos, err := algorithmsByNames(compressionAlgos.All())
if err != nil {
return nil, err
}
@ -983,10 +989,10 @@ func computeDiffID(stream io.Reader, decompressor compressiontypes.DecompressorF
return digest.Canonical.FromReader(stream)
}
// algorithmsByNames returns slice of Algorithms from slice of Algorithm Names
func algorithmsByNames(names []string) ([]compressiontypes.Algorithm, error) {
// algorithmsByNames returns slice of Algorithms from a sequence of Algorithm Names
func algorithmsByNames(names iter.Seq[string]) ([]compressiontypes.Algorithm, error) {
result := []compressiontypes.Algorithm{}
for _, name := range names {
for name := range names {
algo, err := compression.AlgorithmByName(name)
if err != nil {
return nil, err

View File

@ -29,6 +29,7 @@ var ErrNotContainerImageDir = errors.New("not a containers image directory, don'
type dirImageDestination struct {
impl.Compat
impl.PropertyMethodsInitialize
stubs.IgnoresOriginalOCIConfig
stubs.NoPutBlobPartialInitialize
stubs.AlwaysSupportsSignatures

View File

@ -101,6 +101,9 @@ func NewReference(path string, ref reference.NamedTagged) (types.ImageReference,
// NewIndexReference returns a Docker archive reference for a path and a zero-based source manifest index.
func NewIndexReference(path string, sourceIndex int) (types.ImageReference, error) {
if sourceIndex < 0 {
return nil, fmt.Errorf("invalid call to NewIndexReference with negative index %d", sourceIndex)
}
return newReference(path, nil, sourceIndex, nil, nil)
}

View File

@ -35,9 +35,9 @@ type bodyReader struct {
body io.ReadCloser // The currently open connection we use to read data, or nil if there is nothing to read from / close.
lastRetryOffset int64 // -1 if N/A
lastRetryTime time.Time // time.Time{} if N/A
lastRetryTime time.Time // IsZero() if N/A
offset int64 // Current offset within the blob
lastSuccessTime time.Time // time.Time{} if N/A
lastSuccessTime time.Time // IsZero() if N/A
}
// newBodyReader creates a bodyReader for request path in c.
@ -207,9 +207,9 @@ func (br *bodyReader) Read(p []byte) (int, error) {
}
// millisecondsSinceOptional is like currentTime.Sub(tm).Milliseconds, but it returns a floating-point value.
// If tm is time.Time{}, it returns math.NaN()
// If tm.IsZero(), it returns math.NaN()
func millisecondsSinceOptional(currentTime time.Time, tm time.Time) float64 {
if tm == (time.Time{}) {
if tm.IsZero() {
return math.NaN()
}
return float64(currentTime.Sub(tm).Nanoseconds()) / 1_000_000.0
@ -229,7 +229,7 @@ func (br *bodyReader) errorIfNotReconnecting(originalErr error, redactedURL stri
logrus.Infof("Reading blob body from %s failed (%v), reconnecting after %d bytes…", redactedURL, originalErr, progress)
return nil
}
if br.lastRetryTime == (time.Time{}) {
if br.lastRetryTime.IsZero() {
logrus.Infof("Reading blob body from %s failed (%v), reconnecting (first reconnection)…", redactedURL, originalErr)
return nil
}

View File

@ -3,6 +3,7 @@ package daemon
import (
"net/http"
"path/filepath"
"time"
"github.com/containers/image/v5/types"
dockerclient "github.com/docker/docker/client"
@ -47,6 +48,7 @@ func newDockerClient(sys *types.SystemContext) (*dockerclient.Client, error) {
}
switch serverURL.Scheme {
case "unix": // Nothing
case "npipe": // Nothing
case "http":
hc := httpConfig()
opts = append(opts, dockerclient.WithHTTPClient(hc))
@ -82,6 +84,11 @@ func tlsConfig(sys *types.SystemContext) (*http.Client, error) {
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: tlsc,
// In general we want to follow docker/daemon/client.defaultHTTPClient , as long as it doesnt affect compatibility.
// These idle connection limits really only apply to long-running clients, which is not our case here;
// we include the same values purely for symmetry.
MaxIdleConns: 6,
IdleConnTimeout: 30 * time.Second,
},
CheckRedirect: dockerclient.CheckRedirect,
}, nil
@ -92,6 +99,11 @@ func httpConfig() *http.Client {
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: nil,
// In general we want to follow docker/daemon/client.defaultHTTPClient , as long as it doesnt affect compatibility.
// These idle connection limits really only apply to long-running clients, which is not our case here;
// we include the same values purely for symmetry.
MaxIdleConns: 6,
IdleConnTimeout: 30 * time.Second,
},
CheckRedirect: dockerclient.CheckRedirect,
}

View File

@ -92,7 +92,7 @@ func imageLoadGoroutine(ctx context.Context, c *client.Client, reader *io.PipeRe
// imageLoad accepts tar stream on reader and sends it to c
func imageLoad(ctx context.Context, c *client.Client, reader *io.PipeReader) error {
resp, err := c.ImageLoad(ctx, reader, true)
resp, err := c.ImageLoad(ctx, reader, client.ImageLoadWithQuiet(true))
if err != nil {
return fmt.Errorf("starting a load operation in docker engine: %w", err)
}

View File

@ -87,10 +87,13 @@ func ParseReference(refString string) (types.ImageReference, error) {
// NewReference returns a docker-daemon reference for either the supplied image ID (config digest) or the supplied reference (which must satisfy !reference.IsNameOnly)
func NewReference(id digest.Digest, ref reference.Named) (types.ImageReference, error) {
if id != "" && ref != nil {
switch {
case id != "" && ref != nil:
return nil, errors.New("docker-daemon: reference must not have an image ID and a reference string specified at the same time")
}
if ref != nil {
case id == "" && ref == nil:
return nil, errors.New("docker-daemon: reference must have at least one of an image ID and a reference string")
case ref != nil:
if reference.IsNameOnly(ref) {
return nil, fmt.Errorf("docker-daemon: reference %s has neither a tag nor a digest", reference.FamiliarString(ref))
}

View File

@ -24,21 +24,31 @@ import (
"slices"
"github.com/docker/distribution/registry/api/errcode"
dockerChallenge "github.com/docker/distribution/registry/client/auth/challenge"
)
// errNoErrorsInBody is returned when an HTTP response body parses to an empty
// errcode.Errors slice.
var errNoErrorsInBody = errors.New("no error details found in HTTP response body")
// unexpectedHTTPStatusError is returned when an unexpected HTTP status is
// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
// returned when making a registry api call.
type unexpectedHTTPStatusError struct {
Status string
type UnexpectedHTTPStatusError struct {
// StatusCode code as returned from the server, so callers can
// match the exact code to make certain decisions if needed.
StatusCode int
// status text as displayed in the error message, not exposed as callers should match the number.
status string
}
func (e *unexpectedHTTPStatusError) Error() string {
return fmt.Sprintf("received unexpected HTTP status: %s", e.Status)
func (e UnexpectedHTTPStatusError) Error() string {
return fmt.Sprintf("received unexpected HTTP status: %s", e.status)
}
func newUnexpectedHTTPStatusError(resp *http.Response) UnexpectedHTTPStatusError {
return UnexpectedHTTPStatusError{
StatusCode: resp.StatusCode,
status: resp.Status,
}
}
// unexpectedHTTPResponseError is returned when an expected HTTP status code
@ -114,10 +124,11 @@ func mergeErrors(err1, err2 error) error {
// UnexpectedHTTPStatusError returned for response code outside of expected
// range.
func handleErrorResponse(resp *http.Response) error {
if resp.StatusCode >= 400 && resp.StatusCode < 500 {
switch {
case resp.StatusCode == http.StatusUnauthorized:
// Check for OAuth errors within the `WWW-Authenticate` header first
// See https://tools.ietf.org/html/rfc6750#section-3
for _, c := range dockerChallenge.ResponseChallenges(resp) {
for c := range iterateAuthHeader(resp.Header) {
if c.Scheme == "bearer" {
var err errcode.Error
// codes defined at https://tools.ietf.org/html/rfc6750#section-3.1
@ -138,11 +149,13 @@ func handleErrorResponse(resp *http.Response) error {
return mergeErrors(err, parseHTTPErrorResponse(resp.StatusCode, resp.Body))
}
}
fallthrough
case resp.StatusCode >= 400 && resp.StatusCode < 500:
err := parseHTTPErrorResponse(resp.StatusCode, resp.Body)
if uErr, ok := err.(*unexpectedHTTPResponseError); ok && resp.StatusCode == 401 {
return errcode.ErrorCodeUnauthorized.WithDetail(uErr.Response)
}
return err
}
return &unexpectedHTTPStatusError{Status: resp.Status}
return newUnexpectedHTTPStatusError(resp)
}

View File

@ -11,6 +11,7 @@ import (
"net/url"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"sync"
@ -475,12 +476,11 @@ func (c *dockerClient) resolveRequestURL(path string) (*url.URL, error) {
}
// Checks if the auth headers in the response contain an indication of a failed
// authorizdation because of an "insufficient_scope" error. If that's the case,
// authorization because of an "insufficient_scope" error. If that's the case,
// returns the required scope to be used for fetching a new token.
func needsRetryWithUpdatedScope(res *http.Response) (bool, *authScope) {
if res.StatusCode == http.StatusUnauthorized {
challenges := parseAuthHeader(res.Header)
for _, challenge := range challenges {
for challenge := range iterateAuthHeader(res.Header) {
if challenge.Scheme == "bearer" {
if errmsg, ok := challenge.Parameters["error"]; ok && errmsg == "insufficient_scope" {
if scope, ok := challenge.Parameters["scope"]; ok && scope != "" {
@ -907,6 +907,10 @@ func (c *dockerClient) detectPropertiesHelper(ctx context.Context) error {
}
tr := tlsclientconfig.NewTransport()
tr.TLSClientConfig = c.tlsClientConfig
// if set DockerProxyURL explicitly, use the DockerProxyURL instead of system proxy
if c.sys != nil && c.sys.DockerProxyURL != nil {
tr.Proxy = http.ProxyURL(c.sys.DockerProxyURL)
}
c.client = &http.Client{Transport: tr}
ping := func(scheme string) error {
@ -924,7 +928,7 @@ func (c *dockerClient) detectPropertiesHelper(ctx context.Context) error {
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusUnauthorized {
return registryHTTPResponseToError(resp)
}
c.challenges = parseAuthHeader(resp.Header)
c.challenges = slices.Collect(iterateAuthHeader(resp.Header))
c.scheme = scheme
c.supportsSignatures = resp.Header.Get("X-Registry-Supports-Signatures") == "1"
return nil
@ -992,13 +996,18 @@ func (c *dockerClient) getExternalBlob(ctx context.Context, urls []string) (io.R
continue
}
if resp.StatusCode != http.StatusOK {
err := fmt.Errorf("error fetching external blob from %q: %d (%s)", u, resp.StatusCode, http.StatusText(resp.StatusCode))
err := fmt.Errorf("error fetching external blob from %q: %w", u, newUnexpectedHTTPStatusError(resp))
remoteErrors = append(remoteErrors, err)
logrus.Debug(err)
resp.Body.Close()
continue
}
return resp.Body, getBlobSize(resp), nil
size, err := getBlobSize(resp)
if err != nil {
size = -1
}
return resp.Body, size, nil
}
if remoteErrors == nil {
return nil, 0, nil // fallback to non-external blob
@ -1006,12 +1015,20 @@ func (c *dockerClient) getExternalBlob(ctx context.Context, urls []string) (io.R
return nil, 0, fmt.Errorf("failed fetching external blob from all urls: %w", multierr.Format("", ", ", "", remoteErrors))
}
func getBlobSize(resp *http.Response) int64 {
size, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)
if err != nil {
size = -1
func getBlobSize(resp *http.Response) (int64, error) {
hdrs := resp.Header.Values("Content-Length")
if len(hdrs) == 0 {
return -1, errors.New(`Missing "Content-Length" header in response`)
}
return size
hdr := hdrs[0] // Equivalent to resp.Header.Get(…)
size, err := strconv.ParseInt(hdr, 10, 64)
if err != nil { // Gos response reader should already reject such values.
return -1, err
}
if size < 0 { // '-' is not a valid character in Content-Length, so negative values are invalid. Gos response reader should already reject such values.
return -1, fmt.Errorf(`Invalid negative "Content-Length" %q`, hdr)
}
return size, nil
}
// getBlob returns a stream for the specified blob in ref, and the blobs size (or -1 if unknown).
@ -1042,7 +1059,10 @@ func (c *dockerClient) getBlob(ctx context.Context, ref dockerReference, info ty
return nil, 0, fmt.Errorf("fetching blob: %w", err)
}
cache.RecordKnownLocation(ref.Transport(), bicTransportScope(ref), info.Digest, newBICLocationReference(ref))
blobSize := getBlobSize(res)
blobSize, err := getBlobSize(res)
if err != nil {
blobSize = -1
}
reconnectingReader, err := newBodyReader(ctx, c, path, res.Body)
if err != nil {
@ -1056,6 +1076,15 @@ func (c *dockerClient) getBlob(ctx context.Context, ref dockerReference, info ty
func (c *dockerClient) getOCIDescriptorContents(ctx context.Context, ref dockerReference, desc imgspecv1.Descriptor, maxSize int, cache types.BlobInfoCache) ([]byte, error) {
// Note that this copies all kinds of attachments: attestations, and whatever else is there,
// not just signatures. We leave the signature consumers to decide based on the MIME type.
if err := desc.Digest.Validate(); err != nil { // .Algorithm() might panic without this check
return nil, fmt.Errorf("invalid digest %q: %w", desc.Digest.String(), err)
}
digestAlgorithm := desc.Digest.Algorithm()
if !digestAlgorithm.Available() {
return nil, fmt.Errorf("invalid digest %q: unsupported digest algorithm %q", desc.Digest.String(), digestAlgorithm.String())
}
reader, _, err := c.getBlob(ctx, ref, manifest.BlobInfoFromOCI1Descriptor(desc), cache)
if err != nil {
return nil, err
@ -1065,6 +1094,10 @@ func (c *dockerClient) getOCIDescriptorContents(ctx context.Context, ref dockerR
if err != nil {
return nil, fmt.Errorf("reading blob %s in %s: %w", desc.Digest.String(), ref.ref.Name(), err)
}
actualDigest := digestAlgorithm.FromBytes(payload)
if actualDigest != desc.Digest {
return nil, fmt.Errorf("digest mismatch, expected %q, got %q", desc.Digest.String(), actualDigest.String())
}
return payload, nil
}

View File

@ -41,6 +41,7 @@ import (
type dockerImageDestination struct {
impl.Compat
impl.PropertyMethodsInitialize
stubs.IgnoresOriginalOCIConfig
stubs.NoPutBlobPartialInitialize
ref dockerReference
@ -242,8 +243,12 @@ func (d *dockerImageDestination) blobExists(ctx context.Context, repo reference.
defer res.Body.Close()
switch res.StatusCode {
case http.StatusOK:
size, err := getBlobSize(res)
if err != nil {
return false, -1, fmt.Errorf("determining size of blob %s in %s: %w", digest, repo.Name(), err)
}
logrus.Debugf("... already exists")
return true, getBlobSize(res), nil
return true, size, nil
case http.StatusUnauthorized:
logrus.Debugf("... not authorized")
return false, -1, fmt.Errorf("checking whether a blob %s exists in %s: %w", digest, repo.Name(), registryHTTPResponseToError(res))

View File

@ -340,6 +340,10 @@ func handle206Response(streams chan io.ReadCloser, errs chan error, body io.Read
}
return
}
if parts >= len(chunks) {
errs <- errors.New("too many parts returned by the server")
break
}
s := signalCloseReader{
closed: make(chan struct{}),
stream: p,
@ -565,7 +569,7 @@ func (s *dockerImageSource) getOneSignature(ctx context.Context, sigURL *url.URL
logrus.Debugf("... got status 404, as expected = end of signatures")
return nil, true, nil
} else if res.StatusCode != http.StatusOK {
return nil, false, fmt.Errorf("reading signature from %s: status %d (%s)", sigURL.Redacted(), res.StatusCode, http.StatusText(res.StatusCode))
return nil, false, fmt.Errorf("reading signature from %s: %w", sigURL.Redacted(), newUnexpectedHTTPStatusError(res))
}
contentType := res.Header.Get("Content-Type")

View File

@ -40,10 +40,10 @@ func httpResponseToError(res *http.Response, context string) error {
err := registryHTTPResponseToError(res)
return ErrUnauthorizedForCredentials{Err: err}
default:
if context != "" {
context += ": "
if context == "" {
return newUnexpectedHTTPStatusError(res)
}
return fmt.Errorf("%sinvalid status code from registry %d (%s)", context, res.StatusCode, http.StatusText(res.StatusCode))
return fmt.Errorf("%s: %w", context, newUnexpectedHTTPStatusError(res))
}
}

View File

@ -24,6 +24,7 @@ import (
type Destination struct {
impl.Compat
impl.PropertyMethodsInitialize
stubs.IgnoresOriginalOCIConfig
stubs.NoPutBlobPartialInitialize
stubs.NoSignaturesInitialize

View File

@ -242,9 +242,7 @@ func (w *Writer) ensureManifestItemLocked(layerDescriptors []manifest.Schema2Des
}
knownRepoTags := set.New[string]()
for _, repoTag := range item.RepoTags {
knownRepoTags.Add(repoTag)
}
knownRepoTags.AddSeq(slices.Values(item.RepoTags))
for _, tag := range repoTags {
// For github.com/docker/docker consumers, this works just as well as
// refString := ref.String()

View File

@ -1,5 +1,4 @@
//go:build !freebsd
// +build !freebsd
package docker

View File

@ -1,5 +1,4 @@
//go:build freebsd
// +build freebsd
package docker

View File

@ -3,6 +3,7 @@ package docker
import (
"errors"
"fmt"
"io/fs"
"net/url"
"os"
"path"
@ -129,6 +130,11 @@ func loadAndMergeConfig(dirPath string) (*registryConfiguration, error) {
configPath := filepath.Join(dirPath, configName)
configBytes, err := os.ReadFile(configPath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// file must have been removed between the directory listing
// and the open call, ignore that as it is a expected race
continue
}
return nil, err
}

View File

@ -4,6 +4,7 @@ package docker
import (
"fmt"
"iter"
"net/http"
"strings"
)
@ -60,15 +61,17 @@ func init() {
}
}
func parseAuthHeader(header http.Header) []challenge {
challenges := []challenge{}
for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
v, p := parseValueAndParams(h)
if v != "" {
challenges = append(challenges, challenge{Scheme: v, Parameters: p})
func iterateAuthHeader(header http.Header) iter.Seq[challenge] {
return func(yield func(challenge) bool) {
for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
v, p := parseValueAndParams(h)
if v != "" {
if !yield(challenge{Scheme: v, Parameters: p}) {
return
}
}
}
}
return challenges
}
// parseAuthScope parses an authentication scope string of the form `$resource:$remote:$actions`

View File

@ -15,6 +15,9 @@ type UnparsedImage = image.UnparsedImage
// UnparsedInstance returns a types.UnparsedImage implementation for (source, instanceDigest).
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list).
//
// This implementation of [types.UnparsedImage] ensures that [types.UnparsedImage.Manifest] validates the image
// against instanceDigest if set, or, if not, a digest implied by src.Reference, if any.
//
// The UnparsedImage must not be used after the underlying ImageSource is Close()d.
func UnparsedInstance(src types.ImageSource, instanceDigest *digest.Digest) *UnparsedImage {
return image.UnparsedInstance(src, instanceDigest)
@ -33,6 +36,9 @@ func (uwr *unparsedWithRef) Reference() types.ImageReference {
// UnparsedInstanceWithReference returns a types.UnparsedImage for wrappedInstance which claims to be a replacementRef.
// This is useful for combining image data with other reference values, e.g. to check signatures on a locally-pulled image
// based on a remote-registry policy.
//
// For the purposes of digest validation in [types.UnparsedImage.Manifest], what matters is the
// reference originally used to create wrappedInstance, not replacementRef.
func UnparsedInstanceWithReference(wrappedInstance types.UnparsedImage, replacementRef types.ImageReference) types.UnparsedImage {
return &unparsedWithRef{
UnparsedImage: unparsedimage.FromPublic(wrappedInstance),

View File

@ -30,6 +30,9 @@ type UnparsedImage struct {
// UnparsedInstance returns a types.UnparsedImage implementation for (source, instanceDigest).
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list).
//
// This implementation of [types.UnparsedImage] ensures that [types.UnparsedImage.Manifest] validates the image
// against instanceDigest if set, or, if not, a digest implied by src.Reference, if any.
//
// The UnparsedImage must not be used after the underlying ImageSource is Close()d.
//
// This is publicly visible as c/image/image.UnparsedInstance.
@ -48,6 +51,9 @@ func (i *UnparsedImage) Reference() types.ImageReference {
}
// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
//
// Users of UnparsedImage are promised that this validates the image
// against either i.instanceDigest if set, or against a digest included in i.src.Reference.
func (i *UnparsedImage) Manifest(ctx context.Context) ([]byte, string, error) {
if i.cachedManifest == nil {
m, mt, err := i.src.GetManifest(ctx, i.instanceDigest)

View File

@ -0,0 +1,16 @@
package stubs
import (
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
)
// IgnoresOriginalOCIConfig implements NoteOriginalOCIConfig() that does nothing.
type IgnoresOriginalOCIConfig struct{}
// NoteOriginalOCIConfig provides the config of the image, as it exists on the source, BUT converted to OCI format,
// or an error obtaining that value (e.g. if the image is an artifact and not a container image).
// The destination can use it in its TryReusingBlob/PutBlob implementations
// (otherwise it only obtains the final config after all layers are written).
func (stub IgnoresOriginalOCIConfig) NoteOriginalOCIConfig(ociConfig *imgspecv1.Image, configErr error) error {
return nil
}

View File

@ -14,6 +14,7 @@ import (
// wrapped provides the private.ImageDestination operations
// for a destination that only implements types.ImageDestination
type wrapped struct {
stubs.IgnoresOriginalOCIConfig
stubs.NoPutBlobPartialInitialize
types.ImageDestination

View File

@ -74,20 +74,20 @@ func (list *Schema2ListPublic) Instance(instanceDigest digest.Digest) (ListUpdat
// UpdateInstances updates the sizes, digests, and media types of the manifests
// which the list catalogs.
func (index *Schema2ListPublic) UpdateInstances(updates []ListUpdate) error {
func (list *Schema2ListPublic) UpdateInstances(updates []ListUpdate) error {
editInstances := []ListEdit{}
for i, instance := range updates {
editInstances = append(editInstances, ListEdit{
UpdateOldDigest: index.Manifests[i].Digest,
UpdateOldDigest: list.Manifests[i].Digest,
UpdateDigest: instance.Digest,
UpdateSize: instance.Size,
UpdateMediaType: instance.MediaType,
ListOperation: ListOpUpdate})
}
return index.editInstances(editInstances)
return list.editInstances(editInstances)
}
func (index *Schema2ListPublic) editInstances(editInstances []ListEdit) error {
func (list *Schema2ListPublic) editInstances(editInstances []ListEdit) error {
addedEntries := []Schema2ManifestDescriptor{}
for i, editInstance := range editInstances {
switch editInstance.ListOperation {
@ -98,21 +98,21 @@ func (index *Schema2ListPublic) editInstances(editInstances []ListEdit) error {
if err := editInstance.UpdateDigest.Validate(); err != nil {
return fmt.Errorf("Schema2List.EditInstances: Modified digest %s is an invalid digest: %w", editInstance.UpdateDigest, err)
}
targetIndex := slices.IndexFunc(index.Manifests, func(m Schema2ManifestDescriptor) bool {
targetIndex := slices.IndexFunc(list.Manifests, func(m Schema2ManifestDescriptor) bool {
return m.Digest == editInstance.UpdateOldDigest
})
if targetIndex == -1 {
return fmt.Errorf("Schema2List.EditInstances: digest %s not found", editInstance.UpdateOldDigest)
}
index.Manifests[targetIndex].Digest = editInstance.UpdateDigest
list.Manifests[targetIndex].Digest = editInstance.UpdateDigest
if editInstance.UpdateSize < 0 {
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances had an invalid size (%d)", i+1, len(editInstances), editInstance.UpdateSize)
}
index.Manifests[targetIndex].Size = editInstance.UpdateSize
list.Manifests[targetIndex].Size = editInstance.UpdateSize
if editInstance.UpdateMediaType == "" {
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances had no media type (was %q)", i+1, len(editInstances), index.Manifests[i].MediaType)
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances had no media type (was %q)", i+1, len(editInstances), list.Manifests[i].MediaType)
}
index.Manifests[targetIndex].MediaType = editInstance.UpdateMediaType
list.Manifests[targetIndex].MediaType = editInstance.UpdateMediaType
case ListOpAdd:
if editInstance.AddPlatform == nil {
// Should we create a struct with empty fields instead?
@ -135,13 +135,13 @@ func (index *Schema2ListPublic) editInstances(editInstances []ListEdit) error {
if len(addedEntries) != 0 {
// slices.Clone() here to ensure a private backing array;
// an external caller could have manually created Schema2ListPublic with a slice with extra capacity.
index.Manifests = append(slices.Clone(index.Manifests), addedEntries...)
list.Manifests = append(slices.Clone(list.Manifests), addedEntries...)
}
return nil
}
func (index *Schema2List) EditInstances(editInstances []ListEdit) error {
return index.editInstances(editInstances)
func (list *Schema2List) EditInstances(editInstances []ListEdit) error {
return list.editInstances(editInstances)
}
func (list *Schema2ListPublic) ChooseInstanceByCompression(ctx *types.SystemContext, preferGzip types.OptionalBool) (digest.Digest, error) {
@ -280,12 +280,12 @@ func schema2ListFromPublic(public *Schema2ListPublic) *Schema2List {
return &Schema2List{*public}
}
func (index *Schema2List) CloneInternal() List {
return schema2ListFromPublic(Schema2ListPublicClone(&index.Schema2ListPublic))
func (list *Schema2List) CloneInternal() List {
return schema2ListFromPublic(Schema2ListPublicClone(&list.Schema2ListPublic))
}
func (index *Schema2List) Clone() ListPublic {
return index.CloneInternal()
func (list *Schema2List) Clone() ListPublic {
return list.CloneInternal()
}
// Schema2ListFromManifest creates a Schema2 manifest list instance from marshalled

View File

@ -213,12 +213,12 @@ type instanceCandidate struct {
digest digest.Digest // Instance digest
}
func (ic instanceCandidate) isPreferredOver(other *instanceCandidate, preferGzip bool) bool {
func (ic instanceCandidate) isPreferredOver(other *instanceCandidate, preferGzip types.OptionalBool) bool {
switch {
case ic.platformIndex != other.platformIndex:
return ic.platformIndex < other.platformIndex
case ic.isZstd != other.isZstd:
if !preferGzip {
if preferGzip != types.OptionalBoolTrue {
return ic.isZstd
} else {
return !ic.isZstd
@ -232,10 +232,6 @@ func (ic instanceCandidate) isPreferredOver(other *instanceCandidate, preferGzip
// chooseInstance is a private equivalent to ChooseInstanceByCompression,
// shared by ChooseInstance and ChooseInstanceByCompression.
func (index *OCI1IndexPublic) chooseInstance(ctx *types.SystemContext, preferGzip types.OptionalBool) (digest.Digest, error) {
didPreferGzip := false
if preferGzip == types.OptionalBoolTrue {
didPreferGzip = true
}
wantedPlatforms := platform.WantedPlatforms(ctx)
var bestMatch *instanceCandidate
bestMatch = nil
@ -251,7 +247,7 @@ func (index *OCI1IndexPublic) chooseInstance(ctx *types.SystemContext, preferGzi
}
candidate.platformIndex = platformIndex
}
if bestMatch == nil || candidate.isPreferredOver(bestMatch, didPreferGzip) {
if bestMatch == nil || candidate.isPreferredOver(bestMatch, preferGzip) {
bestMatch = &candidate
}
}

View File

@ -3,6 +3,7 @@ package private
import (
"context"
"io"
"time"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/internal/blobinfocache"
@ -10,6 +11,7 @@ import (
compression "github.com/containers/image/v5/pkg/compression/types"
"github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImageSourceInternalOnly is the part of private.ImageSource that is not
@ -41,6 +43,12 @@ type ImageDestinationInternalOnly interface {
// FIXME: Add SupportsSignaturesWithFormat or something like that, to allow early failures
// on unsupported formats.
// NoteOriginalOCIConfig provides the config of the image, as it exists on the source, BUT converted to OCI format,
// or an error obtaining that value (e.g. if the image is an artifact and not a container image).
// The destination can use it in its TryReusingBlob/PutBlob implementations
// (otherwise it only obtains the final config after all layers are written).
NoteOriginalOCIConfig(ociConfig *imgspecv1.Image, configErr error) error
// PutBlobWithOptions writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; if provided, and stream is read to the end without error, the digest MUST match the stream contents.
// inputInfo.Size is the expected length of stream, if known.
@ -163,6 +171,12 @@ type CommitOptions struct {
// What “resolved” means is transport-specific.
// Transports which dont support reporting resolved references can ignore the field; the generic copy code writes "nil" into the value.
ReportResolvedReference *types.ImageReference
// Timestamp, if set, will force timestamps of content created in the destination to this value.
// Most transports don't support this.
//
// In oci-archive: destinations, this will set the create/mod/access timestamps in each tar entry
// (but not a timestamp of the created archive file).
Timestamp *time.Time
}
// ImageSourceChunk is a portion of a blob.

View File

@ -1,6 +1,9 @@
package set
import "golang.org/x/exp/maps"
import (
"iter"
"maps"
)
// FIXME:
// - Docstrings
@ -28,8 +31,8 @@ func (s *Set[E]) Add(v E) {
s.m[v] = struct{}{} // Possibly writing the same struct{}{} presence marker again.
}
func (s *Set[E]) AddSlice(slice []E) {
for _, v := range slice {
func (s *Set[E]) AddSeq(seq iter.Seq[E]) {
for v := range seq {
s.Add(v)
}
}
@ -47,6 +50,6 @@ func (s *Set[E]) Empty() bool {
return len(s.m) == 0
}
func (s *Set[E]) Values() []E {
func (s *Set[E]) All() iter.Seq[E] {
return maps.Keys(s.m)
}

View File

@ -133,12 +133,12 @@ func (m *Schema1) ConfigInfo() types.BlobInfo {
// The Digest field is guaranteed to be provided; Size may be -1.
// WARNING: The list may contain duplicates, and they are semantically relevant.
func (m *Schema1) LayerInfos() []LayerInfo {
layers := make([]LayerInfo, len(m.FSLayers))
for i, layer := range m.FSLayers { // NOTE: This includes empty layers (where m.History.V1Compatibility->ThrowAway)
layers[(len(m.FSLayers)-1)-i] = LayerInfo{
layers := make([]LayerInfo, 0, len(m.FSLayers))
for i, layer := range slices.Backward(m.FSLayers) { // NOTE: This includes empty layers (where m.History.V1Compatibility->ThrowAway)
layers = append(layers, LayerInfo{
BlobInfo: types.BlobInfo{Digest: layer.BlobSum, Size: -1},
EmptyLayer: m.ExtractedV1Compatibility[i].ThrowAway,
}
})
}
return layers
}
@ -284,7 +284,7 @@ func (m *Schema1) ToSchema2Config(diffIDs []digest.Digest) ([]byte, error) {
}
// Build the history.
convertedHistory := []Schema2History{}
for _, compat := range m.ExtractedV1Compatibility {
for _, compat := range slices.Backward(m.ExtractedV1Compatibility) {
hitem := Schema2History{
Created: compat.Created,
CreatedBy: strings.Join(compat.ContainerConfig.Cmd, " "),
@ -292,7 +292,7 @@ func (m *Schema1) ToSchema2Config(diffIDs []digest.Digest) ([]byte, error) {
Comment: compat.Comment,
EmptyLayer: compat.ThrowAway,
}
convertedHistory = append([]Schema2History{hitem}, convertedHistory...)
convertedHistory = append(convertedHistory, hitem)
}
// Build the rootfs information. We need the decompressed sums that we've been
// calculating to fill in the DiffIDs. It's expected (but not enforced by us)

View File

@ -166,10 +166,11 @@ func (m *OCI1) UpdateLayerInfos(layerInfos []types.BlobInfo) error {
// getEncryptedMediaType will return the mediatype to its encrypted counterpart and return
// an error if the mediatype does not support encryption
func getEncryptedMediaType(mediatype string) (string, error) {
if slices.Contains(strings.Split(mediatype, "+")[1:], "encrypted") {
parts := strings.Split(mediatype, "+")
if slices.Contains(parts[1:], "encrypted") {
return "", fmt.Errorf("unsupported mediaType: %q already encrypted", mediatype)
}
unsuffixedMediatype := strings.Split(mediatype, "+")[0]
unsuffixedMediatype := parts[0]
switch unsuffixedMediatype {
case DockerV2Schema2LayerMediaType, imgspecv1.MediaTypeImageLayer,
imgspecv1.MediaTypeImageLayerNonDistributable: //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.

View File

@ -5,6 +5,7 @@ import (
"fmt"
"io"
"os"
"time"
"github.com/containers/image/v5/internal/imagedestination"
"github.com/containers/image/v5/internal/imagedestination/impl"
@ -14,6 +15,7 @@ import (
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/idtools"
digest "github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
)
@ -103,6 +105,14 @@ func (d *ociArchiveImageDestination) SupportsPutBlobPartial() bool {
return d.unpackedDest.SupportsPutBlobPartial()
}
// NoteOriginalOCIConfig provides the config of the image, as it exists on the source, BUT converted to OCI format,
// or an error obtaining that value (e.g. if the image is an artifact and not a container image).
// The destination can use it in its TryReusingBlob/PutBlob implementations
// (otherwise it only obtains the final config after all layers are written).
func (d *ociArchiveImageDestination) NoteOriginalOCIConfig(ociConfig *imgspecv1.Image, configErr error) error {
return d.unpackedDest.NoteOriginalOCIConfig(ociConfig, configErr)
}
// PutBlobWithOptions writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; if provided, and stream is read to the end without error, the digest MUST match the stream contents.
// inputInfo.Size is the expected length of stream, if known.
@ -163,16 +173,19 @@ func (d *ociArchiveImageDestination) CommitWithOptions(ctx context.Context, opti
src := d.tempDirRef.tempDirectory
// path to save tarred up file
dst := d.ref.resolvedFile
return tarDirectory(src, dst)
return tarDirectory(src, dst, options.Timestamp)
}
// tar converts the directory at src and saves it to dst
func tarDirectory(src, dst string) error {
// if contentModTimes is non-nil, tar header entries times are set to this
func tarDirectory(src, dst string, contentModTimes *time.Time) (retErr error) {
// input is a stream of bytes from the archive of the directory at path
input, err := archive.TarWithOptions(src, &archive.TarOptions{
Compression: archive.Uncompressed,
// Dont include the data about the user account this code is running under.
ChownOpts: &idtools.IDPair{UID: 0, GID: 0},
// override tar header timestamps
Timestamp: contentModTimes,
})
if err != nil {
return fmt.Errorf("retrieving stream of bytes from %q: %w", src, err)
@ -184,7 +197,14 @@ func tarDirectory(src, dst string) error {
if err != nil {
return fmt.Errorf("creating tar file %q: %w", dst, err)
}
defer outFile.Close()
// since we are writing to this file, make sure we handle errors
defer func() {
closeErr := outFile.Close()
if retErr == nil {
retErr = closeErr
}
}()
// copies the contents of the directory to the tar file
// TODO: This can take quite some time, and should ideally be cancellable using a context.Context.

View File

@ -52,13 +52,13 @@ func (t ociArchiveTransport) ValidatePolicyConfigurationScope(scope string) erro
return internal.ValidateScope(scope)
}
// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OCI ImageReference.
// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OCI archive ImageReference.
func ParseReference(reference string) (types.ImageReference, error) {
file, image := internal.SplitPathAndImage(reference)
return NewReference(file, image)
}
// NewReference returns an OCI reference for a file and a image.
// NewReference returns an OCI archive reference for a file and an optional image name annotation (if not "").
func NewReference(file, image string) (types.ImageReference, error) {
resolved, err := explicitfilepath.ResolvePathToFullyExplicit(file)
if err != nil {

Some files were not shown because too many files have changed in this diff Show More