Compare commits

...

452 Commits

Author SHA1 Message Date
Miloslav Trmač
a44da449d3 Release 1.4.0
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-08-02 17:37:11 +02:00
Daniel J Walsh
788b2e2dd3 Merge pull request #1396 from saschagrunert/accept-repositories
Accept repositories on login/logout
2021-08-02 10:26:46 -04:00
Daniel J Walsh
2135466ba3 Merge pull request #1399 from vrothberg/update-in-container
vendor-in-container: update to golang:1.16
2021-08-02 10:26:20 -04:00
Valentin Rothberg
3d9340c836 vendor-in-container: update to golang:1.16
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-08-02 15:30:06 +02:00
Sascha Grunert
961d5da7ce Accept repositories on login/logout
We now synchronize the behavior with Podman and accept repositories
during login and logout per default.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
2021-08-02 13:41:45 +02:00
Miloslav Trmač
920f0b2414 Merge pull request #1395 from vrothberg/vendor-dance
update c/common, c/image, c/storage
2021-08-02 13:21:14 +02:00
Valentin Rothberg
fb03e033cc update c/common, c/image, c/storage
Pin them to the specific versions that Podman v3.3 targets for RHEL.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-08-02 09:32:09 +02:00
Miloslav Trmač
caf1469b1d Merge pull request #1394 from n0vad3v/patch-1
Update on Building on Ubuntu
2021-07-31 14:28:06 +02:00
Nova Kwok
d70ea89050 Update on Building on Ubuntu
Build on Ubuntu should include pkg-config otherwise it will fail:
```
skopeo (main) # make bin/skopeo
CGO_CFLAGS="" CGO_LDFLAGS="-L/usr/lib/x86_64-linux-gnu -lgpgme -lassuan -lgpg-error" GO111MODULE=on go build -mod=vendor "-buildmode=pie" -ldflags '-X main.gitCommit=a8f0c902060288bd02db15bf6671c8cd0149704e ' -gcflags "" -tags "  " -o bin/skopeo ./cmd/skopeo
# pkg-config --cflags  -- devmapper
pkg-config: exec: "pkg-config": executable file not found in $PATH
make: *** [Makefile:134: bin/skopeo] Error 2
```
2021-07-31 14:02:48 +08:00
Valentin Rothberg
a8f0c90206 Merge pull request #1390 from mtrmac/start-timeouts
Add timeouts when waiting on OpenShift or the registry to start
2021-07-30 13:44:29 +02:00
Miloslav Trmač
ce6035b738 Add timeouts when waiting on OpenShift or the registry to start
... so that we terminate with the full context and pointing at
the relevant code, instead of relying
on the overall test suite timeout.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-30 12:36:54 +02:00
Miloslav Trmač
b6b7bd9250 Merge pull request #1365 from moio/allow-decompression
Allow decompressing while copying
2021-07-29 16:27:19 +02:00
Daniel J Walsh
c27d9063e5 Merge pull request #1391 from mtrmac/lint
Fix two instances of unused err found by go-staticcheck
2021-07-29 07:09:17 -04:00
Silvio Moioli
3a8d3cb566 Add docs and bash completions
Signed-off-by: Silvio Moioli <moio@suse.com>
2021-07-29 11:37:01 +02:00
Silvio Moioli
aeb61f656c Add support for decompressing while copying to dir://
Signed-off-by: Silvio Moioli <moio@suse.com>
2021-07-29 11:35:02 +02:00
Silvio Moioli
76eb9bc9e9 Update to enabled containers/image version
Signed-off-by: Silvio Moioli <moio@suse.com>
2021-07-29 11:34:13 +02:00
Miloslav Trmač
a1f9318e7b Fix two instances of unused err found by go-staticcheck
*cough* Go is an easy-to-use, hard-to-misuse language *cough*

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-28 21:46:07 +02:00
Miloslav Trmač
64dc748e5e Merge pull request #1389 from containers/dependabot/go_modules/github.com/containers/storage-1.33.0
Bump github.com/containers/storage from 1.32.6 to 1.33.0
2021-07-28 14:54:35 +02:00
dependabot[bot]
d82c662101 Bump github.com/containers/storage from 1.32.6 to 1.33.0
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.32.6 to 1.33.0.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/main/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.32.6...v1.33.0)

---
updated-dependencies:
- dependency-name: github.com/containers/storage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-28 12:33:17 +00:00
Daniel J Walsh
24a75c9608 Merge pull request #1387 from cevich/daily_version_update
[CI:DOCS] Multi-arch image build: Daily version-tag push
2021-07-28 05:54:51 -04:00
Chris Evich
f0c49b5ccc Multi-arch image build: Daily version-tag push
This mirrors changes from
https://github.com/containers/buildah/pull/3381

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-07-27 14:12:48 -04:00
Miloslav Trmač
bef3b0c997 Merge pull request #1386 from moio/patch-2
CONTRIBUTING: small fixes to commands
2021-07-27 14:41:16 +02:00
Silvio Moioli
5e5506646d CONTRIBUTING: small fixes to commands 2021-07-27 14:12:10 +02:00
Valentin Rothberg
76bfc7f07f Merge pull request #1369 from mtrmac/tls-verify
Fix --tls-verify
2021-07-26 14:56:58 +02:00
Miloslav Trmač
726d982ceb Fix --tls-verify
Differentiate, again, between (skopeo --tls-verify subcommand)
and (skope subcommand --tls-verify), by
- using a "local" Corba flag for the (skopeo --tls-verify ...) variant
- adding separate --tls-verify flags to subcommands that only accept
  them as legacy, available through deprecatedTLSVerifyFlags
  (unlike the non-legacy path of dockerImageFlags());
- using TraverseChildren: true; this causes the global and
  per-subcommand flags to be treated separately by Corba,
  i.e. they no longer happen to share the "Hidden" flag
  and Corba actually sets the right flag variable now.

So, we can now warn on (skopeo --tls-verify command) again,
and --help lists the flag correctly (it is hidden at the
global level, and in subcommands like copy that deprecated it,
but visible in subcommands like inspect where it's not deprecated).

NOTE: This removes --tls-verify from (skopeo manifest-digest) and
the three signing commands; it never made sense there. This change
could, in principle, break some users.

Also update man pages to match.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-23 17:50:25 +02:00
Miloslav Trmač
bb447f2f1e Test both imageOptions and imageDestOptions in TestTLSVerifyFlags
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-23 17:13:07 +02:00
Miloslav Trmač
2a98df6b12 Split testing of --tls-verify into separate TestTLSVerifyFlags
It will get bigger, and we will also want to test imageDestOptions
for extra confidence.

Only moves the code, should not change (test) behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-23 17:13:05 +02:00
Miloslav Trmač
a6cf2f4293 Add the --tls-verify option to (skopeo logout)
The current implementation can actually contact the registry (if
logout fails with "not logged in" but there are .docker/config.json
credentials present), so provide a non-deprecated way to disable TLS.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-23 15:47:02 +02:00
Miloslav Trmač
bd309aed2a Merge pull request #1382 from cevich/fix_docker_limits
Fix using images from rate-limited docker hub
2021-07-22 23:01:20 +02:00
Chris Evich
285a5cb6a0 Fix using images from rate-limited docker hub
The necessary images have been manually copied over to quay.  Code was
updated with centralized constants for the utilized images.  Tests then
all reference the constants (in case the image locations need to change
again).

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-07-22 16:28:20 -04:00
Daniel J Walsh
3c2d98875d Merge pull request #1374 from cevich/man_page_checker_3
Implement manpage checker in CI
2021-07-22 14:16:43 -04:00
Chris Evich
02bacf571d Use Fedora container for doccheck
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-07-22 10:10:12 -04:00
Ed Santiago
ae0595c56a Man page validation: part 2 of 2
This is the script that runs 'skopeo COMMAND --help' and
cross-checks that all the option flags are documented
in man pages, and vice-versa (all options listed in man
pages appear in COMMAND's --help message).

Copied from podman, with changes for skopeo-land (removing
the rst checks, and conforming to skopeo conventions).

Signed-off-by: Ed Santiago <santiago@redhat.com>
2021-07-21 14:51:47 -04:00
Miloslav Trmač
b0ebbdd501 Merge pull request #1381 from mtrmac/signatures_docs
docs: Adding info re container signatures
2021-07-21 12:01:59 +02:00
Dave Hay
ec73ff3d91 docs: Adding info re container signatures
Updating docs to reflect container signatures

Fixes #1337

Signed-off-by: Dave Hay <david_hay@uk.ibm.com>
2021-07-21 11:39:48 +02:00
Chris Evich
ce2f64c946 Merge pull request #1379 from cevich/generic_steps
[CI:DOCS] Multi-arch image workflow: Make steps generic
2021-07-19 15:09:31 -04:00
Chris Evich
e460b9aa8c [CI:DOCS] Multi-arch image workflow: Make steps generic
This duplicates the change from
https://github.com/containers/buildah/pull/3385

Since this workflow is duplicated across three repositories, maintaining
changes becomes onerous if the item contents vary between
implementations in any way. Improve this situation by encoding the
repository-specific details into env. vars. then referencing those vars
throughout. This way, a meaningful diff can be worked with to compare
the contents across repositories.

Also included are abstractions for the specific command used to obtain
the project version, and needed details for filtering the output. Both
of these vary across the Buildah, Skopeo, and Podman repos.

NOTE: This change requires the names of two github action secrets
to be updated: SKOPEO_QUAY_USERNAME -> REPONAME_QUAY_USERNAME
(and *PASSWORD).

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-07-16 16:53:43 -04:00
Daniel J Walsh
643920b373 Merge pull request #1376 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-07-14 20:12:30 -04:00
Chris Evich
598f9e7ce3 Merge pull request #1375 from cevich/freshen_vm_images
Cirrus: Freshen CI images
2021-07-14 16:47:06 -04:00
Wong Hoi Sing Edison
ee05486383 Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-07-14 21:20:06 +08:00
Chris Evich
2476e99cb1 Cirrus: Freshen CI images
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-07-12 15:25:56 -04:00
Miloslav Trmač
074cfda358 Merge pull request #1373 from containers/dependabot/go_modules/github.com/containers/common-0.41.0
Bump github.com/containers/common from 0.40.1 to 0.41.0
2021-07-12 18:31:05 +02:00
Daniel J Walsh
cec7aa68f7 Merge branch 'main' into dependabot/go_modules/github.com/containers/common-0.41.0 2021-07-12 10:48:23 -04:00
Daniel J Walsh
dc1cf646e0 Merge pull request #1372 from containers/dependabot/go_modules/github.com/containers/storage-1.32.6
Bump github.com/containers/storage from 1.32.5 to 1.32.6
2021-07-12 10:48:04 -04:00
dependabot[bot]
76103a6c2d Bump github.com/containers/common from 0.40.1 to 0.41.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.40.1 to 0.41.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.40.1...v0.41.0)

---
updated-dependencies:
- dependency-name: github.com/containers/common
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-12 08:26:07 +00:00
dependabot[bot]
990908bf80 Bump github.com/containers/storage from 1.32.5 to 1.32.6
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.32.5 to 1.32.6.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/main/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.32.5...v1.32.6)

---
updated-dependencies:
- dependency-name: github.com/containers/storage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-12 08:25:52 +00:00
Valentin Rothberg
a6e745dad5 Merge pull request #1371 from mtrmac/staticcheck
Fix staticcheck-reported problems
2021-07-10 15:33:12 +02:00
Miloslav Trmač
ede29c9168 Remove an unnecessary break
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-10 11:33:45 +02:00
Miloslav Trmač
75f0183edc Remove an unnecessary Sprintf
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-10 11:33:36 +02:00
Miloslav Trmač
7ace4265fb Fix TestDockerRepositoryReferenceParser
Don't ignore errors, and don't even skip test cases on errors.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-10 11:33:22 +02:00
Miloslav Trmač
3d4fb09f2c Remove unused code
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-10 11:32:42 +02:00
Valentin Rothberg
92ad5eddcc Merge pull request #1370 from mtrmac/stateless-disable-completion
Set cobra.Command.CompletionOption already in createApp
2021-07-10 10:48:18 +02:00
Miloslav Trmač
4efeb71e28 Set cobra.Command.CompletionOption already in createApp
... because our unit tests use createApp, so the current
main()-only edit is not visible to unit tests.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-09 23:03:05 +02:00
Miloslav Trmač
392c6fce02 Merge pull request #1368 from lsm5/bump-version
Bump main version to v1.4.0-dev
2021-07-09 16:53:18 +02:00
Lokesh Mandvekar
a0ce542193 Bump version to v1.4.0-dev
Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2021-07-09 09:54:53 -04:00
Miloslav Trmač
0035a9aecb Merge pull request #1367 from mtrmac/revert-tmp-workaround
Revert "integration tests: disable `ls` for logs"
2021-07-09 13:52:48 +02:00
Miloslav Trmač
f80bf8a39f Revert "integration tests: disable ls for logs"
This reverts commit 65c5b0bf8d.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-09 13:15:13 +02:00
Miloslav Trmač
0fac3f10d3 Merge pull request #1364 from moio/patch-1
CONTRIBUTING: update vendoring instructions
2021-07-08 16:01:36 +02:00
Silvio Moioli
c39b3dc266 CONTRIBUTING: update vendoring instructions
`vndr` was dropped in 2019

Signed-off-by: Silvio Moioli <moio@suse.com>
2021-07-08 13:35:24 +02:00
Miloslav Trmač
07c81c7777 Merge pull request #1363 from vrothberg/completion
disable `completion` command
2021-07-08 12:50:18 +02:00
Valentin Rothberg
8eaf0329f8 disable completion command
Disable the implicit `completion` command that cobra 1.2.x added.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-07-08 10:23:13 +02:00
Daniel J Walsh
378e6694c7 Merge pull request #1362 from containers/dependabot/go_modules/github.com/spf13/cobra-1.2.1
Bump github.com/spf13/cobra from 1.2.0 to 1.2.1
2021-07-05 05:48:10 -04:00
dependabot[bot]
aeb75f3857 Bump github.com/spf13/cobra from 1.2.0 to 1.2.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-05 08:26:05 +00:00
Miloslav Trmač
2286a58a39 Merge pull request #1359 from containers/dependabot/go_modules/github.com/spf13/cobra-1.2.0
Bump github.com/spf13/cobra from 1.1.3 to 1.2.0
2021-07-02 14:56:04 +02:00
dependabot[bot]
83603a79d4 Bump github.com/spf13/cobra from 1.1.3 to 1.2.0
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.1.3 to 1.2.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.1.3...v1.2.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 08:28:08 +00:00
Miloslav Trmač
37b24aedd7 Merge pull request #1356 from mtrmac/error
Update tests for removal of error and Error from error messages
2021-07-01 21:38:15 +02:00
Daniel J Walsh
6d6c8b5609 Update tests for removal of error and Error from error messages
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-07-01 21:02:13 +02:00
Miloslav Trmač
99621f4168 Merge pull request #1351 from mtrmac/man-page-checker
Misc man-page-checker RFCs
2021-07-01 15:49:34 +02:00
Miloslav Trmač
09282bcf88 Fix some comments in man-page-checker
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-30 20:57:08 +02:00
Miloslav Trmač
09ca3ba47f Improve the description of (skopeo list-tags)
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-30 20:56:30 +02:00
Miloslav Trmač
22908fb3e8 Include the mandatory --output option in synopsis of (skopeo standalone-sign)
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-30 20:56:30 +02:00
Miloslav Trmač
a37251289a Support **non-replaceable strings** in synopsis
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-29 23:59:34 +02:00
Miloslav Trmač
e4d1392085 Use (make validate-local) in the validate target
... to keep the two in sync.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-29 23:49:21 +02:00
Daniel J Walsh
71e7a5839e Merge pull request #1347 from edsantiago/man_page_checker
man page checker - part 1 of 2
2021-06-29 17:13:11 -04:00
Miloslav Trmač
316503341b Merge pull request #1341 from cevich/add_local_cross
Cirrus: Rename cross -> osx task, add cross task.
2021-06-29 22:53:44 +02:00
Ed Santiago
e716b2fa66 man page checker - part 1 of 2
Add new script, hack/man-page-checker, copied from podman. Run it
in 'make validate-local' target.

This is NOT the checker requested in #1332 (verify that flags
listed in 'skopeo foo --help' are documented in man pages and
vice-versa). This is a much simpler script that merely looks
for very basic typos or discrepancies between skopeo.1.md
and skopeo-foo.1.md.

The next part (cross-checking flags) is in progress but will
require a huge number of changes to the man pages. I'm submitting
this now because it's easy to review.

Signed-off-by: Ed Santiago <santiago@redhat.com>
2021-06-29 13:07:42 -06:00
Chris Evich
97eaace7db Cirrus: Rename cross -> osx task, add cross task.
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-29 14:01:46 -04:00
Miloslav Trmač
846ea33b40 Merge pull request #1344 from containers/dependabot/go_modules/github.com/containers/ocicrypt-1.1.2
Bump github.com/containers/ocicrypt from 1.1.1 to 1.1.2
2021-06-29 16:55:19 +02:00
dependabot[bot]
30c0eb03f0 Bump github.com/containers/ocicrypt from 1.1.1 to 1.1.2
Bumps [github.com/containers/ocicrypt](https://github.com/containers/ocicrypt) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/containers/ocicrypt/releases)
- [Commits](https://github.com/containers/ocicrypt/compare/v1.1.1...v1.1.2)

---
updated-dependencies:
- dependency-name: github.com/containers/ocicrypt
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-29 08:31:55 +00:00
Miloslav Trmač
7cb70f4e9c Merge pull request #1340 from cevich/add_vendor_check
Cirrus: Add vendor + tree status check
2021-06-28 22:59:19 +02:00
Chris Evich
5918513ed5 Cirrus: Add vendor + tree status check
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-28 16:18:32 -04:00
Miloslav Trmač
b768f4e3af Merge pull request #1339 from mtrmac/unit-integration
Run unit tests as well, not integration tests twice
2021-06-28 20:28:29 +02:00
Miloslav Trmač
b20c2d45f1 Run unit tests as well, not integration tests twice
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-28 19:54:04 +02:00
Daniel J Walsh
fc3678038e Merge pull request #1335 from containers/dependabot/go_modules/github.com/containers/storage-1.32.5
Bump github.com/containers/storage from 1.32.4 to 1.32.5
2021-06-28 13:49:33 -04:00
dependabot[bot]
d0f7339b77 Bump github.com/containers/storage from 1.32.4 to 1.32.5
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.32.4 to 1.32.5.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/main/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.32.4...v1.32.5)

---
updated-dependencies:
- dependency-name: github.com/containers/storage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-25 08:26:29 +00:00
Chris Evich
af550fda48 Merge pull request #1331 from mtrmac/revert-destdir
Reintroduce the GNU semantics of DESTDIR
2021-06-24 13:04:06 -04:00
Miloslav Trmač
012ed6610e Reintroduce the GNU semantics of DESTDIR
This partially reverts commit a81cd74734
so that most path variables like PREFIX and BINDIR refer to paths on
the installed system, and DESTDIR is used only in (make install), following
the philosophy of the GNU coding standards for path variables. (But not precisely
the variable names, which are lowercase in the standard, nor the principle that
even SYSCONFDIR should be under $PREFIX.

Keep the use of ?= instead of = because it somewhat better expresses the idea
that the values can be overridden.

Use ${DESTDIR}${BINDIR} instead of ${DESTDIR}/${BINDIR} etc, so that a plain
(make install) does not use paths like //usr/bin/... ; strictly speaking they
are IIRC reserved by POSIX, and more importantly it just looks untidy :)

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-24 14:14:07 +02:00
Daniel J Walsh
f7aab1aba5 Merge pull request #1332 from rittneje/add-retry-times-docs
Add --retry-times to markdown docs
2021-06-24 05:48:50 -04:00
Jesse Rittner
c30b904cbe Add --retry-times to markdown docs
Fixes #1322.

Signed-off-by: Jesse Rittner <rittneje@gmail.com>
2021-06-23 23:29:53 -04:00
Daniel J Walsh
45028801eb Merge pull request #1330 from cevich/default_registry
[CI:DOCS] Workaround quay.io image build failure
2021-06-23 15:49:03 -04:00
Chris Evich
9fbb9abc6d Workaround quay.io image build failure
Normally it's a best-practice to only use short-names in Dockerfiles.
However, this image is really only ever used for testing/CI purposes.
Side-step the docker hub rate limits entirely by simply hard-coding the
FQIN and hope that's also "okay" for non-CI usage.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-23 15:40:58 -04:00
Miloslav Trmač
69fd1d4be0 Merge pull request #1329 from mtrmac/brew-update
Start macOS tests with (brew update)
2021-06-23 21:14:54 +02:00
Miloslav Trmač
4417dc4402 Update brew to avoid 403 on accessing https://homebrew.bintray.com
Compare https://github.com/Homebrew/brew/issues/11119 .

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-23 20:49:43 +02:00
Daniel J Walsh
8f0ae5bde6 Merge pull request #1328 from cevich/master_to_main
Fix automation re: master->main rename
2021-06-23 14:46:50 -04:00
Chris Evich
93b819a766 Fix automation re: master->main rename
Bump up the global timeout due to some (possibly) temporary failures in
the 'cross' task.  Also fix build-failure in Dockerfile related to use
of pre-module golang packages.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-23 13:31:08 -04:00
Daniel J Walsh
ce06c87817 Merge pull request #1327 from containers/dependabot/go_modules/github.com/containers/storage-1.32.4
Bump github.com/containers/storage from 1.32.3 to 1.32.4
2021-06-23 10:33:55 -04:00
dependabot[bot]
e7c5e9f7e6 Bump github.com/containers/storage from 1.32.3 to 1.32.4
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.32.3 to 1.32.4.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/main/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.32.3...v1.32.4)

---
updated-dependencies:
- dependency-name: github.com/containers/storage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 08:27:06 +00:00
Miloslav Trmač
8a1214a07b Merge pull request #1324 from containers/dependabot/go_modules/github.com/containers/common-0.40.1
Bump github.com/containers/common from 0.40.0 to 0.40.1
2021-06-21 21:41:14 +02:00
dependabot[bot]
1eac38e3ce Bump github.com/containers/common from 0.40.0 to 0.40.1
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.40.0 to 0.40.1.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.40.0...v0.40.1)

---
updated-dependencies:
- dependency-name: github.com/containers/common
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 18:25:00 +00:00
Miloslav Trmač
5000f745b0 Merge pull request #1325 from containers/dependabot/go_modules/github.com/containers/storage-1.32.3
Bump github.com/containers/storage from 1.32.2 to 1.32.3
2021-06-21 19:58:14 +02:00
dependabot[bot]
b1e78efaa2 Bump github.com/containers/storage from 1.32.2 to 1.32.3
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.32.2 to 1.32.3.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/main/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.32.2...v1.32.3)

---
updated-dependencies:
- dependency-name: github.com/containers/storage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 08:26:57 +00:00
Daniel J Walsh
ccdaf6e0f2 Merge pull request #1321 from containers/dependabot/go_modules/github.com/containers/image/v5-5.13.2
Bump github.com/containers/image/v5 from 5.13.1 to 5.13.2
2021-06-18 04:41:40 -04:00
Valentin Rothberg
d25476e4f7 Merge pull request #1319 from mtrmac/format-docs
Fix documentation of the --format option of skopeo copy and skopeo sync
2021-06-18 10:41:17 +02:00
dependabot[bot]
298f7476d0 Bump github.com/containers/image/v5 from 5.13.1 to 5.13.2
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.13.1 to 5.13.2.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.13.1...v5.13.2)

---
updated-dependencies:
- dependency-name: github.com/containers/image/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-18 08:25:40 +00:00
Daniel J Walsh
2fee990acc Merge pull request #1318 from containers/dependabot/go_modules/github.com/containers/common-0.40.0
Bump github.com/containers/common from 0.39.0 to 0.40.0
2021-06-17 16:51:51 -04:00
Chris Evich
6ba1affd23 Merge pull request #1317 from cevich/update_vm_images
Cirrus: New VM Images w/ podman 3.2.1
2021-06-17 16:00:11 -04:00
Miloslav Trmač
5778d9bd67 Fix documentation of the --format option of skopeo copy and skopeo sync
It affects all transports; and without --format, we try several manifest formats.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-06-17 19:29:17 +02:00
dependabot[bot]
df17004709 Bump github.com/containers/common from 0.39.0 to 0.40.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.39.0 to 0.40.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.39.0...v0.40.0)

---
updated-dependencies:
- dependency-name: github.com/containers/common
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 08:23:51 +00:00
Chris Evich
ad4ec8b496 Cirrus: New VM Images w/ podman 3.2.1
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-16 17:07:58 -04:00
Daniel J Walsh
5f8ec87c54 Merge pull request #1316 from containers/dependabot/go_modules/github.com/containers/image/v5-5.13.1
Bump github.com/containers/image/v5 from 5.12.0 to 5.13.1
2021-06-16 17:06:17 -04:00
dependabot[bot]
abdc4a7e42 Bump github.com/containers/image/v5 from 5.12.0 to 5.13.1
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.12.0 to 5.13.1.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.12.0...v5.13.1)

---
updated-dependencies:
- dependency-name: github.com/containers/image/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-16 15:34:27 +00:00
Daniel J Walsh
513a524d7d Merge pull request #1308 from cevich/fix_skopeo_skopeo
Fix multi-arch build version check
2021-06-15 16:32:19 -04:00
Daniel J Walsh
d4a500069e Merge pull request #1310 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-06-15 16:31:42 -04:00
Wong Hoi Sing Edison
bcc18ebfb7 Update nix pin with make nixpkgs
Fixes #1305

Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-06-12 07:20:51 +08:00
Chris Evich
9b9ef675c1 Fix multi-arch build version check
This was copy-pasted from buildah and podman, unfortunately the
Dockerfile entrypoint is different for skopeo. Fix it.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-11 15:00:49 -04:00
Daniel J Walsh
dde3e759f6 Merge pull request #1312 from cevich/fix_links
[CI:DOCS] Fix docs links due to branch rename
2021-06-11 14:40:44 -04:00
Daniel J Walsh
622faa0b8a Merge pull request #1311 from containers/dependabot/go_modules/github.com/containers/storage-1.32.2
Bump github.com/containers/storage from 1.32.1 to 1.32.2
2021-06-11 14:40:22 -04:00
Chris Evich
9a5f009ea2 [CI:DOCS] Fix docs links due to branch rename
Ref: https://github.com/containers/common/issues/549

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-10 11:35:11 -04:00
dependabot[bot]
865407cad0 Bump github.com/containers/storage from 1.32.1 to 1.32.2
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.32.1 to 1.32.2.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.32.1...v1.32.2)

---
updated-dependencies:
- dependency-name: github.com/containers/storage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-10 08:21:38 +00:00
Valentin Rothberg
ec13aa6d87 Merge pull request #1305 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-06-03 15:57:26 +02:00
Daniel J Walsh
780de354d4 Merge pull request #1304 from containers/dependabot/go_modules/github.com/docker/docker-20.10.7incompatible
Bump github.com/docker/docker from 20.10.6+incompatible to 20.10.7+incompatible
2021-06-03 09:40:29 -04:00
Wong Hoi Sing Edison
10c4c877ba Update nix pin with make nixpkgs
- Bugfix `make nixpkgs` which pin with branch `nixos-21.05`
  - Code lint with `nixpkgs-fmt`
  - Code sync between x86\_64 and aarch64

Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-06-03 16:33:04 +08:00
dependabot[bot]
e32f3f1792 Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.6+incompatible to 20.10.7+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Changelog](https://github.com/moby/moby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/docker/docker/compare/v20.10.6...v20.10.7)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-03 08:17:08 +00:00
Daniel J Walsh
a07f1e0f89 Merge pull request #1299 from containers/dependabot/go_modules/github.com/containers/storage-1.32.1
Bump github.com/containers/storage from 1.32.0 to 1.32.1
2021-06-02 09:00:00 -04:00
Daniel J Walsh
a2c8022a21 Merge pull request #1303 from cevich/fix_github_workflows
Fix GitHub workflows + Add [CI:DOCS] mode
2021-06-02 08:56:54 -04:00
Daniel J Walsh
b9661b2a05 Merge pull request #1302 from bentito/patch-1
install.md Building Docs needs MacOS section
2021-06-01 20:34:24 -04:00
Chris Evich
761100143a Fix wrong directory name
Github checks the `workflows` sub-directory for github actions workflow
files.  Since it was called `workflow`, nothing was running.  Fix this
by renaming the directory.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-01 10:15:08 -04:00
Chris Evich
a0b6ea288d Support [CI:DOCS] mode
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-06-01 10:15:08 -04:00
Brett Tofel
e5cb7ce196 install.md Building Docs needs MacOS section
The Building Documentation section of the `install.md` also needs a MacOS section because go-md2man is not present there, by default, either.
2021-06-01 10:01:00 -04:00
dependabot[bot]
c806083830 Bump github.com/containers/storage from 1.32.0 to 1.32.1
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.32.0 to 1.32.1.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.32.0...v1.32.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-28 08:26:20 +00:00
Valentin Rothberg
714ffe1b60 Merge pull request #1297 from containers/dependabot/go_modules/github.com/containers/common-0.39.0
Bump github.com/containers/common from 0.38.4 to 0.39.0
2021-05-26 12:41:27 +02:00
dependabot[bot]
cac3f2b140 Bump github.com/containers/common from 0.38.4 to 0.39.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.38.4 to 0.39.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.38.4...v0.39.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-26 08:25:26 +00:00
Daniel J Walsh
8efffce8be Merge pull request #1294 from containers/dependabot/go_modules/github.com/containers/storage-1.31.2
Bump github.com/containers/storage from 1.31.1 to 1.31.2
2021-05-21 15:45:48 -04:00
Daniel J Walsh
efc789be55 Merge pull request #1288 from cevich/multi_arch_images
Multi-arch github-action workflow unification
2021-05-21 15:45:14 -04:00
Chris Evich
6452a9b6f6 Multi-arch github-action workflow unification
This is a port from the podman and buildah repository workflows.
It's purpose is to build and push multi-arch images containing the
latest upstream, testing, and stable versions of skopeo.  It fully
replaces the last remaining use of Travis in this repo, for
substantially the same purpose.

In a future commit, I intend to de-duplicate this workflow from
podman and buildah, such that all three share a common set of details.
Until then, any changes will need to be manually duplicated across
all three repos.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-05-21 14:33:55 -04:00
dependabot[bot]
184f0eee58 Bump github.com/containers/storage from 1.31.1 to 1.31.2
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.31.1 to 1.31.2.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.31.1...v1.31.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-21 08:16:23 +00:00
Daniel J Walsh
5af5f8a0e7 Merge pull request #1293 from rhatdan/master
Bump to v1.3.0
2021-05-19 17:11:31 -04:00
Daniel J Walsh
65ed9920da Move to v1.3.1-dev 2021-05-19 17:09:51 -04:00
Daniel J Walsh
c35944bec0 Bump to v1.3.0 2021-05-19 17:09:40 -04:00
Daniel J Walsh
266dc3dc9a Merge pull request #1291 from containers/dependabot/go_modules/github.com/containers/common-0.38.3
Bump github.com/containers/common from 0.38.1 to 0.38.4
2021-05-19 17:05:21 -04:00
dependabot[bot]
91d9ccf5e5 Bump github.com/containers/common from 0.38.1 to 0.38.4
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.38.1 to 0.38.4.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.38.1...v0.38.4)

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-05-19 15:55:54 -04:00
Daniel J Walsh
4e57679c9a Merge pull request #1281 from containers/dependabot/go_modules/github.com/containers/common-0.38.1
Bump github.com/containers/common from 0.38.0 to 0.38.1
2021-05-14 04:30:45 -04:00
dependabot[bot]
68f188ae77 Bump github.com/containers/common from 0.38.0 to 0.38.1
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.38.0 to 0.38.1.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.38.0...v0.38.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-13 08:17:04 +00:00
Daniel J Walsh
0faf160170 Merge pull request #1280 from containers/dependabot/go_modules/github.com/containers/common-0.38.0
Bump github.com/containers/common from 0.37.1 to 0.38.0
2021-05-10 17:52:49 -04:00
dependabot[bot]
69decaeb1d Bump github.com/containers/common from 0.37.1 to 0.38.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.37.1 to 0.38.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.37.1...v0.38.0)

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-05-10 15:56:42 -04:00
Daniel J Walsh
001775e994 Merge pull request #1278 from accupara/compilation-fix
Add the missing import and a gitignore entry for bin
2021-05-10 14:57:39 -04:00
Yuvraaj Kelkar
fc448c2253 Add the missing import and a gitignore entry for bin 2021-05-09 11:21:01 -07:00
Daniel J Walsh
b10d3e43a4 Merge pull request #1266 from cgwalters/copy-print-digest
copy: Add --digestfile
2021-05-07 05:17:35 -04:00
Colin Walters
a32be320cb copy: Add --digestfile
`podman push` gained this a while ago, and we want it here for the
same reason.

Motivated by closing a race condition in ostree-rs-ext:
17a991050c/lib/src/container/export.rs (L85)

Co-authored-by: Miloslav Trmač <mitr@redhat.com>
2021-05-06 09:19:16 -04:00
Daniel J Walsh
5e13a55444 Merge pull request #1268 from containers/dependabot/go_modules/github.com/containers/storage-1.30.1
Bump github.com/containers/storage from 1.30.0 to 1.30.1
2021-05-06 08:46:20 -04:00
Daniel J Walsh
c0d259712c Merge pull request #1273 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-05-06 08:46:01 -04:00
Daniel J Walsh
70abdf7334 Merge pull request #1274 from containers/dependabot/go_modules/github.com/containers/image/v5-5.12.0
Bump github.com/containers/image/v5 from 5.11.1 to 5.12.0
2021-05-06 08:45:44 -04:00
dependabot[bot]
f232ae499b Bump github.com/containers/image/v5 from 5.11.1 to 5.12.0
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.11.1 to 5.12.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.11.1...v5.12.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-06 09:21:47 +00:00
Wong Hoi Sing Edison
aba84840dc Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-05-06 11:50:50 +08:00
Lokesh Mandvekar
e536c4da34 Merge branch 'master' into dependabot/go_modules/github.com/containers/storage-1.30.1 2021-05-03 10:37:10 -04:00
Valentin Rothberg
a1a8692457 Merge pull request #1270 from containers/dependabot/go_modules/github.com/containers/common-0.37.1
Bump github.com/containers/common from 0.37.0 to 0.37.1
2021-05-03 13:16:45 +02:00
dependabot[bot]
5a594bff65 Bump github.com/containers/common from 0.37.0 to 0.37.1
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.37.0 to 0.37.1.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.37.0...v0.37.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-03 10:48:29 +00:00
Valentin Rothberg
2eb35e7af9 Merge pull request #1263 from Freakin/sync-manifest-format
Added format parameter to sync command
2021-05-03 10:25:14 +02:00
Valentin Rothberg
00490a2cbb Merge pull request #1267 from containers/dependabot/add-v2-config-file
Upgrade to GitHub-native Dependabot
2021-05-03 10:19:49 +02:00
Valentin Rothberg
9a10ee2f1f Merge branch 'master' into dependabot/add-v2-config-file 2021-05-03 10:19:14 +02:00
dependabot-preview[bot]
002b2e4db9 Upgrade to GitHub-native Dependabot
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-05-01 06:47:49 -04:00
Daniel J Walsh
891d9750a3 Merge pull request #1269 from cevich/update_f34
Update F34beta -> F34 and U2010 -> U2104
2021-05-01 06:42:22 -04:00
dependabot-preview[bot]
d6912022b5 Bump github.com/containers/storage from 1.30.0 to 1.30.1
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.30.0 to 1.30.1.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.30.0...v1.30.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-05-01 06:41:32 -04:00
Chris Evich
eab7c4b0d1 Update F34beta -> F34 and U2010 -> U2104
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-04-29 11:55:26 -04:00
Brendan Aye
7898ffaf23 Added format parameter to sync command
Signed-off-by: Brendan Aye <brendan.aye@t-mobile.com>
2021-04-28 10:54:21 -07:00
Daniel J Walsh
ce4304a0ad Merge pull request #1258 from containers/dependabot/go_modules/github.com/containers/common-0.37.0
Bump github.com/containers/common from 0.36.0 to 0.37.0
2021-04-28 08:29:18 -04:00
dependabot-preview[bot]
610c612129 Bump github.com/containers/common from 0.36.0 to 0.37.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.36.0 to 0.37.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.36.0...v0.37.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-04-28 08:00:24 -04:00
Daniel J Walsh
ad9f1d7bb9 Merge pull request #1260 from lsm5/remove-older-distro-docs
Remove older distro docs
2021-04-23 08:08:29 -04:00
Lokesh Mandvekar
37f15d6d11 Remove older distro docs
This commit removes installation steps for older distros:

1. Amazon Linux 2
2. CentOS 7
3. Debian 10
4. Raspbian 10
5. Raspberry Pi OS armhf

We're no longer building new packages for these distros and the
installation steps for older packages are no longer guaranteed to work.
So, these are best removed from the official docs.

Related blog post (also applies to skopeo):
https://podman.io/blogs/2021/03/02/podman-support-for-older-distros.html

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2021-04-22 14:27:39 -04:00
Valentin Rothberg
2d3f3ed901 Merge pull request #1257 from CharlieTLe/patch-1
Fix typos in docstrings
2021-04-22 07:47:29 +02:00
Charlie Le
65d3890ea1 Fix typos in docstrings 2021-04-21 14:20:04 -07:00
Daniel J Walsh
87f36844c3 Merge pull request #1252 from cevich/travis_osx_to_cirrus
Travis -> Cirrus: MacOS Cross test
2021-04-21 13:20:48 -04:00
Chris Evich
a81cd74734 Travis -> Cirrus: MacOS Cross test
Also cleanup `Makefile` WRT `${DESTDIR}` definition and use to make it's
purpose more clear.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-04-21 10:47:24 -04:00
Valentin Rothberg
5a3e8b6150 Merge pull request #1249 from cevich/travis_to_cirrus
Travis -> Cirrus: validate, vendor, and test
2021-04-21 16:25:50 +02:00
Chris Evich
88979a6a88 Cirrus: Improve test synchronization with c/image
The `test_skopeo_task` must be substantially duplicated between this
repository and containers/image.  Make this easier to maintain by
implementing a runner script to contain any/all differences.  This
allows the `test_skopeo_task` definition to remain 100%
identical across the two repositories.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-04-21 09:55:11 -04:00
Chris Evich
146af8cd59 Travis -> Cirrus: validate, vendor, and test
Also add some basic setup commands to hack/get_ci_vm.sh

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-04-21 09:55:11 -04:00
Daniel J Walsh
6b95125757 Merge pull request #1256 from vrothberg/vendor-image
vendor c/image v5.11.1
2021-04-21 08:33:09 -04:00
Valentin Rothberg
6ee20f9d2a vendor c/image v5.11.1
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-04-21 11:45:03 +02:00
Morten Linderud
c84fc7d243 Makefile: Ensure policy.json uses new variable
In 18e6c6f17b there where changes to
better handle PREFIX and DESTDIR in the Makefile. "CONTAINERSCONFIGDIR"
was renamed to "CONTAINERSCONFDIR" without ensuring it was correct in
the install block. This results in policy.json being isntalled into
"${DESTDIR}/" which is "/policy.json" for Linux distros.

Signed-off-by: Morten Linderud <morten@linderud.pw>
2021-04-19 09:39:51 -04:00
Daniel J Walsh
060fe4b47f Merge pull request #1248 from rhatdan/master
Bump to v1.2.3
2021-04-15 14:48:40 -04:00
Daniel J Walsh
3a759d5136 Move to v1.2.4-dev
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-04-15 14:47:23 -04:00
Daniel J Walsh
f15564f705 Bump to v1.2.3
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-04-15 14:47:07 -04:00
Daniel J Walsh
85e0fde20e Merge pull request #1247 from rhatdan/VERSION
Bump to v1.2.2
2021-04-15 14:45:49 -04:00
Daniel J Walsh
fe1cd126f6 Move to v1.2.3-dev
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-04-15 14:44:41 -04:00
Daniel J Walsh
7a74faf4c1 Bump to v1.2.2
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-04-15 14:44:27 -04:00
Daniel J Walsh
dbe6764b35 Merge pull request #1243 from containers/dependabot/go_modules/github.com/containers/storage-1.29.0
Bump github.com/containers/storage from 1.26.0 to 1.29.0
2021-04-15 14:38:22 -04:00
dependabot-preview[bot]
5485daff13 Bump github.com/containers/storage from 1.26.0 to 1.29.0
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.26.0 to 1.29.0.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.26.0...v1.29.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-04-15 14:05:51 -04:00
Daniel J Walsh
cfbabac961 Merge pull request #1244 from cevich/new_f34b_images
Update to F34beta images + add hack/get_ci_vm.sh script
2021-04-14 16:45:40 -04:00
Daniel J Walsh
5907b4ef08 Merge pull request #1245 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-04-14 09:41:08 -04:00
Wong Hoi Sing Edison
c456cef9bd Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-04-14 10:14:00 +08:00
Chris Evich
0196219924 Cirrus: Add hack/get_ci_vm.sh support
This won't be useful unless/until there are `.cirrus.yml` tasks which
actually utilize VMs.  Once there are, or to support their development,
this script may be helpful.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-04-13 15:12:02 -04:00
Chris Evich
e945435dea Cirrus: Update to use F34beta VM images
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-04-13 15:02:54 -04:00
Valentin Rothberg
c5103c6b51 Merge pull request #1241 from jonstelly/patch-1
Fix for login / logout registry argument
2021-04-13 09:33:55 +02:00
Jon Stelly
61722a8a70 Fix for login / logout registry argument
login and logout don't seem to support or require the `docker://` scheme prefix.

Fixes part of #1240
2021-04-12 13:56:25 -05:00
Daniel J Walsh
cc3ddf4804 Merge pull request #1238 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-04-06 08:31:55 -04:00
Wong Hoi Sing Edison
d9f4377831 Update nix pin with make nixpkgs
- Bugfix `make nixpkgs` which pin with branch `nixos-20.09`
  - Code lint with `nixpkgs-fmt`
  - Code sync between x86\_64 and aarch64

Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-04-04 09:14:48 +08:00
Daniel J Walsh
0717014e46 Merge pull request #1234 from vrothberg/fix-1233
skopeo images: set authfile to /tmp/auth.json
2021-03-23 16:27:06 -04:00
Valentin Rothberg
80dcddef36 skopeo images: set authfile to /tmp/auth.json
The Skopeo images set `REGISTRY_AUTH_FILE=/auth.json` which is breaking
non-root users inside the container from logging in (`/` is writable by
root only).  Setting it to `/tmp/auth.json` will support running
non-root users inside the container.

Fixes: #1233
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-03-22 11:28:11 +01:00
Nikolas Skoufis
6b41287cbf Upgrade dsnet/compress to avoid vulnerable xz version
This updates the indirect dependency we have on dsnet/compress (via
opencontainer/image-tools) to the latest master commit, which includes
an update to a non-vulnerable version of xz.
2021-03-16 11:03:19 +01:00
Hironori Shiina
bef5e4505e Add system tests
Add system tests for the following subcommands and flags:
- skopeo copy --format
- skopeo copy --additional-tag
- skopeo copy --dest-shared-blob-dir
- skopeo copy --src-shared-blob-dir
- skopeo inspect --tls-verify --cert-dir
- skopeo delete --tls-verify --cert-dir
- skopeo copy --dest-creds
- skopeo copy --src-creds
- skopeo copy --authfile
- skopeo inspect --authfile
- skopeo delete --authfile
- skopeo copy --remove-signatures
- skopeo standalone-sign
- skopeo standalone-verify
- skopeo manifest-digest

Signed-off-by: Hironori Shiina <shiina.hironori@jp.fujitsu.com>
2021-03-16 11:00:56 +01:00
Chris Evich
f5a028e4d9 Fix skipping tests in test container
Without this env. var. being set from hack/make.sh, many/most
integration tests will `SKIP`.  Fix this by notifying the user
and setting the magic `SKOPEO_CONTAINER_TESTS` variable.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-03-10 17:41:29 +01:00
Chris Evich
3d1d2978d7 Add local integration and system test targets
These tests need to operate as part of the c/image repository CI to
verify downstream-usage.  That environment is already inside the
container built from the Dockerfile (here).  Support this use-case by
adding 'local' targets which bypass the container build.  Also,
simplify the "in-container" check to more specifically verify the exact
container image it's operating under.

Signed-off-by: Chris Evich <cevich@redhat.com>
2021-03-09 15:16:47 +01:00
Wong Hoi Sing Edison
035eb33f1f Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-03-08 16:02:30 +01:00
Chris Evich
6cbb0c4c88 Cirrus: Initial implementation support for GCP VMs
Signed-off-by: Chris Evich <cevich@redhat.com>
2021-03-03 15:33:31 -05:00
Daniel J Walsh
663fe44f27 Merge pull request #1209 from TomSweeneyRedHat/dev/tsweeney/fed33_dockerfiles
Bump skopoeoimage Dockerfiles to user Fedora 33
2021-03-01 12:49:59 -05:00
TomSweeneyRedHat
cc24482985 Bump skopoeoimage Dockerfiles to user Fedora 33
The quay.io/skopeo/testing:latest image was showing v1.2.0 for a version when it
should have been showing at least v1.2.1.  The issue was the Fedora tag in the
Dockerfiles used to build the images was set to 32 and not the later 33.

Addresses: #1204

Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
2021-02-27 15:08:16 -05:00
Lokesh Mandvekar
b7bf15bc8b Dockerfile.build: switch to fedora:latest
CopySuite.TestCopySignatures: Use quay.io instead of docker.io.

Resolves: gh#174

Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2021-02-24 15:49:14 +01:00
George Jenkins
61b62f9e93 Enable 'OptimizeDestinationImageAlreadyExists' feature
Signed-off-by: George Jenkins <gjenkins8@bloomberg.net>
2021-02-24 12:39:09 +01:00
Daniel J Walsh
2c8655e251 Merge pull request #1193 from containers/dependabot/go_modules/github.com/spf13/cobra-1.1.3
Bump github.com/spf13/cobra from 1.1.2 to 1.1.3
2021-02-23 16:35:40 -05:00
Daniel J Walsh
94d588c480 Merge pull request #1206 from containers/dependabot/go_modules/github.com/containers/image/v5-5.10.3
Bump github.com/containers/image/v5 from 5.10.2 to 5.10.3
2021-02-23 16:35:15 -05:00
Daniel J Walsh
a85e3beccf Bump github.com/spf13/cobra from 1.1.2 to 1.1.3
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.1.2...v1.1.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-02-23 05:54:33 -05:00
Daniel J Walsh
3878a37660 Bump github.com/containers/image/v5 from 5.10.2 to 5.10.3
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.10.2 to 5.10.3.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.10.2...v5.10.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-02-23 05:51:54 -05:00
dependabot-preview[bot]
be600975a9 Bump github.com/containers/storage from 1.25.0 to 1.26.0
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.25.0 to 1.26.0.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.25.0...v1.26.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-02-22 16:54:52 +01:00
Valentin Rothberg
15f0d5cd2f add stale bot
By popular demand, add the stale bot which we'are already using at
Podman.  The bot will remind us every 30 days of inactivity on specific
issues or pull requests and has turned into a useful tool to keep things
on the radar.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-02-17 09:21:45 +01:00
dependabot-preview[bot]
6fa634227c Bump github.com/spf13/cobra from 1.1.1 to 1.1.2
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.1.1...v1.1.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-02-11 09:44:06 +01:00
dependabot-preview[bot]
e224b78efc Bump github.com/containers/image/v5 from 5.10.1 to 5.10.2
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.10.1 to 5.10.2.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.10.1...v5.10.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-02-10 16:38:59 +01:00
Miloslav Trmač
1c4b0fc33d Merge pull request #1124 from nalind/test-mediatype
020-copy.bats: check that we set the manifest type correctly
2021-02-05 21:00:28 +01:00
Nalin Dahyabhai
81e66ffc46 020-copy.bats: check that we set the manifest type correctly
When copying to an OCI layout destination, forcing zstd compression,
check that the manifest correctly describes the type of the layer blob.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-02-05 11:31:12 -05:00
Miloslav Trmač
5995ceedf9 Merge pull request #1186 from TomSweeneyRedHat/dev/tsweeney/protobuf
Bump github.com/gogo/protobuf/proto to v1.3.2
2021-02-04 13:29:36 +01:00
TomSweeneyRedHat
7a9d638989 Bump github.com/gogo/protobuf/proto to v1.3.2
Bumping github.com/gogo/protobuf/proto to v1.3.2 to enusure
a low likelyhood CVE is reached.  Partially addresses:

https://bugzilla.redhat.com/show_bug.cgi?id=1924544

Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
2021-02-03 20:23:10 -05:00
Daniel J Walsh
40f5a8cf69 Merge pull request #1159 from jonjohnsonjr/user-agent
Set User-Agent to skopeo/$VERSION
2021-02-03 16:56:27 -05:00
Daniel J Walsh
a6e50d32d2 Merge pull request #1184 from containers/dependabot/go_modules/github.com/containers/storage-1.25.0
Bump github.com/containers/storage from 1.24.5 to 1.25.0
2021-02-03 16:36:59 -05:00
Jon Johnson
9a88c3986d Set User-Agent to skopeo/$VERSION
Prior to this, the User-Agent used by containers/image would default to
the default User-Agent for golang, which makes it difficult to
distinguish skopeo from any other golang binaries in registry logs.

Signed-off-by: Jon Johnson <jonjohnson@google.com>
2021-02-03 08:39:43 -08:00
dependabot-preview[bot]
ac5241482c Bump github.com/containers/storage from 1.24.5 to 1.25.0
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.24.5 to 1.25.0.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.24.5...v1.25.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-02-03 12:46:11 +01:00
dependabot-preview[bot]
aff1b6215b Bump github.com/containers/ocicrypt from 1.0.3 to 1.1.0
Bumps [github.com/containers/ocicrypt](https://github.com/containers/ocicrypt) from 1.0.3 to 1.1.0.
- [Release notes](https://github.com/containers/ocicrypt/releases)
- [Commits](https://github.com/containers/ocicrypt/compare/v1.0.3...v1.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-02-03 12:42:56 +01:00
Miloslav Trmač
e0ba05af59 Merge pull request #1183 from containers/dependabot/go_modules/github.com/containers/common-0.34.0
Bump github.com/containers/common from 0.33.1 to 0.34.0
2021-02-02 20:43:33 +01:00
Daniel J Walsh
55b9782058 Merge pull request #1171 from containers/dependabot/go_modules/github.com/containers/ocicrypt-1.1.0
Bump github.com/containers/ocicrypt from 1.0.3 to 1.1.0
2021-02-02 08:20:15 -05:00
dependabot-preview[bot]
4ab7faa800 Bump github.com/containers/common from 0.33.1 to 0.34.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.33.1 to 0.34.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.33.1...v0.34.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-02-02 06:32:37 -05:00
Daniel J Walsh
c51c7b4e4d Merge pull request #1178 from containers/dependabot/go_modules/github.com/containers/image/v5-5.10.1
Bump github.com/containers/image/v5 from 5.10.0 to 5.10.1

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-02-02 06:31:37 -05:00
Daniel J Walsh
3375a905cc Merge pull request #1178 from containers/dependabot/go_modules/github.com/containers/image/v5-5.10.1
Bump github.com/containers/image/v5 from 5.10.0 to 5.10.1
2021-02-01 08:50:40 -05:00
Miloslav Trmač
f3c8d26cd8 Merge pull request #1165 from runhyve/fix-freebsd-build
Set PREFIX on FreeBSD and use gpg-config to detect paths
2021-01-30 23:39:42 +01:00
dependabot-preview[bot]
e1dc30b6e1 Bump github.com/containers/image/v5 from 5.10.0 to 5.10.1
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.10.0 to 5.10.1.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.10.0...v5.10.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-01-30 06:21:59 -05:00
Daniel J Walsh
a9e9bdc534 Merge pull request #1176 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-01-30 06:20:46 -05:00
Mateusz Kwiatkowski
6c8b8c20f5 Rebase against master and improve comment about gpgme-config 2021-01-29 14:19:34 +01:00
Wong Hoi Sing Edison
0e1ee196bd Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-01-29 14:05:36 +08:00
TomSweeneyRedHat
77a2e08eb2 Vendor in latest golang.org/x/crypto
Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
2021-01-28 18:16:10 -05:00
Miloslav Trmač
a3c21f25c9 Merge pull request #1173 from containers/dependabot/go_modules/github.com/containers/image/v5-5.10.0
Bump github.com/containers/image/v5 from 5.9.0 to 5.10.0
2021-01-28 22:18:03 +01:00
dependabot-preview[bot]
1e1952693a Bump github.com/containers/image/v5 from 5.9.0 to 5.10.0
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.9.0 to 5.10.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.9.0...v5.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2021-01-28 11:55:09 +01:00
Daniel J Walsh
efc0170ee8 Merge pull request #1169 from edsantiago/dockerpocalypse
Migrate tests from docker.io
2021-01-22 05:23:22 -05:00
Daniel J Walsh
0d0a97eb00 Merge pull request #1168 from rhatdan/Makefile
Fix Makefile to handle PREFIX correctly
2021-01-21 17:47:10 -05:00
Ed Santiago
47a6716921 Migrate tests from docker.io
Switch to using images from quay.io/libpod instead, where
we're not (yet) subject to rate limiting.

Completely rewrite one unclear test. The purpose of the
test was to test #708, in which 'skopeo inspect --raw'
was fixed to be able to inspect images that do not
match the current host's os+arch. We now use a fixed
test image on quay.io, generated by a new script,
whose manifest is pretty unlikely to match our host.

Signed-off-by: Ed Santiago <santiago@redhat.com>
2021-01-21 14:04:01 -07:00
Daniel J Walsh
18e6c6f17b Fix Makefile to handle PREFIX correctly
PREFIX should default to /usr/local according to GNU coding standards.

DESTDIR should just be used for install

This will allow us to specify

make PREFIX=/usr DESTDIR=/tmp/build/ install

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-01-21 13:54:53 -05:00
Daniel J Walsh
ef6f46a3b5 Merge pull request #1162 from containers/dependabot/go_modules/github.com/containers/common-0.33.1
Bump github.com/containers/common from 0.33.0 to 0.33.1
2021-01-15 04:41:04 -05:00
Miloslav Trmač
31562124a3 Merge pull request #1161 from containers/dependabot/go_modules/github.com/stretchr/testify-1.7.0
Bump github.com/stretchr/testify from 1.6.1 to 1.7.0
2021-01-14 23:24:02 +01:00
dependabot-preview[bot]
b544c1be3a Bump github.com/stretchr/testify from 1.6.1 to 1.7.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.6.1 to 1.7.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.6.1...v1.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-01-14 09:50:58 -05:00
dependabot-preview[bot]
0c0a17b641 Bump github.com/containers/common from 0.33.0 to 0.33.1
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.33.0 to 0.33.1.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.33.0...v0.33.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-01-14 09:50:05 -05:00
Miloslav Trmač
2e90a8af5a Merge pull request #1158 from TomSweeneyRedHat/v1.2.1-bump
V1.2.1
2021-01-11 12:20:52 +01:00
TomSweeneyRedHat
2294113c78 Bump to v1.2.2-dev
Bumping to v1.2.2-dev

Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
2021-01-10 12:09:25 -05:00
TomSweeneyRedHat
bdb117ded6 Bump to v1.2.1
Bumping to v1.2.1

Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
2021-01-10 12:08:27 -05:00
Daniel J Walsh
beadcbb17d Merge pull request #1143 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2021-01-10 05:08:02 -05:00
Wong Hoi Sing Edison
fe57e80c18 Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2021-01-10 11:49:55 +08:00
Miloslav Trmač
ac07bf278a Merge pull request #1121 from mtrmac/remapIdentity
Tests for remapIdentity
2021-01-09 17:29:08 +01:00
Miloslav Trmač
3c33cb4556 Add a smoke test for signedIdentity:remapIdentity
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-01-08 17:20:09 +01:00
Miloslav Trmač
f94d85aa8e Split copyWithSignedIdentity from TestCopyVerifyingMirroredSignatures
... because we will add another user.

Also remove an obsolete FIXME.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-01-08 17:20:09 +01:00
Daniel J Walsh
b0da05656d Merge pull request #1152 from rhatdan/VENDOR
Update vendor of containers/common and containers/storage
2021-01-08 10:54:05 -05:00
Daniel J Walsh
9828f21007 Merge pull request #1146 from nalind/test-pause
integration test: sync k8s.gcr.io/pause instead of docker.io/alpine
2021-01-08 10:53:04 -05:00
Nalin Dahyabhai
6ee4b2dc84 integration test: sync k8s.gcr.io/pause instead of docker.io/alpine
Do repository synchronization tests using k8s.gcr.io/pause and
k8s.gcr.io/coredns/coredns instead of docker.io/alpine.
The k8s.gcr.io/pause repository includes multiple tags, at least one of
which is a single image ("1.0"), and at least one of which is a manifest
list ("3.2", "3.3"), and includes a "latest" tag.
The k8s.gcr.io/coredns/coredns repository includes multiple tags, at
least one of which is a single image ("v1.6.6"), and at least one of which
is a manifest list ("v1.8.0").

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-01-08 09:51:08 -05:00
Nalin Dahyabhai
b3a15e7288 integration test: use fedora-minimal for most manifest list tests
Switch most of our tests that exercise reading, copying from, and
inspecting tags that point to manifest lists from using
docker.io/estesp/busybox to using
registry.fedoraproject.org/fedora-minimal, which doesn't limit how often
we can pull the images.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-01-08 09:50:12 -05:00
Daniel J Walsh
f771cb0d39 Update vendor of containers/common and containers/storage
We are preparing for RHEL 8.4 release and want to make
sure all container tools have the same containers suppackages.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-01-08 09:46:28 -05:00
Miloslav Trmač
c4fb93647a Fix reading the after-sync list of tags in SyncSuite.TestYamlUntagged
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2021-01-08 11:16:20 +01:00
Daniel J Walsh
81535c5244 Merge pull request #1144 from containers/dependabot/go_modules/github.com/containers/common-0.31.2
Bump github.com/containers/common from 0.31.1 to 0.31.2
2021-01-04 11:45:26 -05:00
dependabot-preview[bot]
7442052875 Bump github.com/containers/common from 0.31.1 to 0.31.2
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.31.1 to 0.31.2.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.31.1...v0.31.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-01-04 09:05:04 -05:00
Daniel J Walsh
84232cf306 Merge pull request #1140 from jsoref/spelling
Spelling
2020-12-30 07:32:24 -05:00
Daniel J Walsh
c339a1abe9 Merge pull request #1138 from containers/dependabot/go_modules/github.com/containers/common-0.31.1
Bump github.com/containers/common from 0.31.0 to 0.31.1
2020-12-30 07:31:38 -05:00
Daniel J Walsh
766927d1d4 Merge pull request #1142 from QiWang19/sync-creds
fix creds sync from yaml
2020-12-30 07:31:08 -05:00
Qi Wang
fc78c93ad2 fix creds sync from yaml
Pass down the creds from yaml file only if the values are not empty.
    Enables to use credentials from other authfiles alternatively.
Signed-off-by: Qi Wang <qiwan@redhat.com>
2020-12-25 20:18:35 -05:00
Josh Soref
4987a67293 Spelling
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-12-21 16:10:45 -05:00
dependabot-preview[bot]
131b2b8c63 Bump github.com/containers/common from 0.31.0 to 0.31.1
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.31.0 to 0.31.1.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.31.0...v0.31.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-12-21 15:58:05 -05:00
Daniel J Walsh
342b8398e2 Merge pull request #1120 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2020-12-21 15:56:24 -05:00
Wong Hoi Sing Edison
6b260e1686 Update nix pin with make nixpkgs
This PR introduce 3 changes:

  - Upgrade Nix stable channel from 20.03 to 20.09.

    NixOS 20.09 released at 2020-10-27, see
    <https://nixos.org/manual/nixos/stable/release-notes.html#sec-release-20.09>
    for more information.

  - Replace `git` with `gitMinimal`.

    All 6 projects (i.e. crun/conmon/skopeo/buildah/podman/cri-o) are
    having `git` as dependency for failsafe during bootstrap. BTW
    <https://github.com/NixOS/nixpkgs/pull/104896> replace `asciidoc`
    with `asciidoctor` so trigger the dependency chain to `glib` and so
    failed (see below). Switching to `gitMinimal` skip this dependency
    chain to `glib`, which also speed up overall build process.

  - Adding `-pthread` for `glib`

    `conmon` couldn't skip the error by replacing `git` with
    `gitMinimal` since it do depend on `glib`. Since `glib` trigger
    error message "undefined reference to 'pthread\_create'", therefore
    adding `pthread` to `CFLAGS` could solve the problem.

Also see:

  - <https://github.com/containers/crun/pull/550>
  - <https://github.com/containers/conmon/pull/218>
  - <https://github.com/containers/skopeo/pull/1120>
  - <https://github.com/containers/buildah/pull/2831>
  - <https://github.com/containers/podman/pull/8526>
  - <https://github.com/cri-o/cri-o/pull/4395>

Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2020-12-20 18:40:40 +08:00
Daniel J Walsh
6294875a04 Merge pull request #1132 from lsm5/update-debian-docs
update debian/ubuntu docs
2020-12-12 06:21:09 -05:00
Lokesh Mandvekar
8cc9fcae6f update debian/ubuntu docs
Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2020-12-11 13:20:42 -05:00
Miloslav Trmač
4769dd0689 Merge pull request #1118 from containers/dependabot/go_modules/gopkg.in/yaml.v2-2.4.0
Bump gopkg.in/yaml.v2 from 2.3.0 to 2.4.0
2020-12-08 23:59:30 +01:00
Daniel J Walsh
0fb1121f36 Bump gopkg.in/yaml.v2 from 2.3.0 to 2.4.0
Bumps [gopkg.in/yaml.v2](https://github.com/go-yaml/yaml) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/go-yaml/yaml/releases)
- [Commits](https://github.com/go-yaml/yaml/compare/v2.3.0...v2.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-12-08 06:24:11 -05:00
Daniel J Walsh
4aaa9b401d Merge pull request #1127 from containers/dependabot/go_modules/github.com/containers/common-0.31.0
Bump github.com/containers/common from 0.30.0 to 0.31.0
2020-12-08 06:20:17 -05:00
Daniel J Walsh
44087c4866 Merge pull request #1129 from containers/dependabot/go_modules/github.com/containers/storage-1.24.3
Bump github.com/containers/storage from 1.24.1 to 1.24.3
2020-12-08 06:19:43 -05:00
dependabot-preview[bot]
f36f7dbfdf Bump github.com/containers/storage from 1.24.1 to 1.24.3
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.24.1 to 1.24.3.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.24.1...v1.24.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-12-07 20:28:16 -05:00
dependabot-preview[bot]
07c0e6a50f Bump github.com/containers/common from 0.30.0 to 0.31.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.30.0 to 0.31.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.30.0...v0.31.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-12-07 20:27:40 -05:00
Miloslav Trmač
ed321809d3 Merge pull request #1128 from containers/dependabot/go_modules/github.com/containers/image/v5-5.9.0
Bump github.com/containers/image/v5 from 5.8.1 to 5.9.0
2020-12-08 00:10:06 +01:00
dependabot-preview[bot]
13ef91744c Bump github.com/containers/image/v5 from 5.8.1 to 5.9.0
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.8.1 to 5.9.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.8.1...v5.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-12-07 19:44:38 +01:00
Miloslav Trmač
5b8fe7ffa5 Merge pull request #1123 from containers/dependabot/go_modules/github.com/containers/common-0.30.0
Bump github.com/containers/common from 0.27.0 to 0.30.0
2020-12-04 17:58:13 +01:00
dependabot-preview[bot]
8cd57ef8de Bump github.com/containers/common from 0.27.0 to 0.30.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.27.0 to 0.30.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.27.0...v0.30.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-12-03 20:36:21 +01:00
Miloslav Trmač
1b813f805b Merge pull request #1119 from mtrmac/xcode-select
Update to macOS 10.14
2020-11-30 15:03:48 +01:00
Miloslav Trmač
f3a8a7360d Update to macOS 10.14
Homebrew:
> Warning: You are using macOS 10.13.
> We (and Apple) do not provide support for this old version.
> You will encounter build failures with some formulae.

So, update to the 10.14 major version, fully-updated.

Also remove the Xcode update attempt, it was added before
Homebrew was warning about the Xcode version, but updating only
after running Homebrew does not help, and anyway it does not
complain anymore after the update.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-11-28 20:47:26 +01:00
Daniel J Walsh
42e9121eba Merge pull request #1117 from lsm5/update-install-docs
Update install docs
2020-11-24 14:50:52 -05:00
Lokesh Mandvekar
4597c09522 update OSX Travis env before running tests
Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2020-11-24 14:11:11 -05:00
Lokesh Mandvekar
2ec251c2e2 Update installation docs for debian and ubuntu
Continuation of Michael R. Crusoe's pr#1115.

Co-authored-by: Tom Sweeney <tsweeney@redhat.com>
Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2020-11-24 13:41:05 -05:00
Michael R. Crusoe
e717a59174 Update install.md 2020-11-24 08:06:28 -05:00
Daniel J Walsh
c88576b2fc Merge pull request #1112 from rhatdan/VENDOR
vendor in containers/storage v1.24.1 containers/image v5.8,1
2020-11-20 10:52:21 -05:00
Daniel J Walsh
901f7e9c47 vendor in containers/storage v1.24.1 containers/image v5.8,1
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-19 16:29:39 -05:00
Daniel J Walsh
0f4dc80c99 Merge pull request #1110 from barthy1/multi_arch_doc
Add information about multi-arch image to README
2020-11-19 16:25:54 -05:00
Daniel J Walsh
353f3a23e1 Merge pull request #1070 from rhatdan/format
Add --format option to skopeo inspect
2020-11-19 16:25:20 -05:00
Yulia Gaponenko
4b4ad6285e Fix naming and language
- rename skopeo to Skopeo
- improve language

Co-authored-by: Tom Sweeney <tsweeney@redhat.com>
2020-11-19 18:23:46 +01:00
Yulia Gaponenko
6b007c70c7 Add information about multi-arch image to README
Also update to the correct one information about required env variables
for multi-arch build

Signed-off-by: Yulia Gaponenko <yulia.gaponenko1@de.ibm.com>
2020-11-19 18:23:33 +01:00
Daniel J Walsh
6a48870594 Merge pull request #1106 from containers/dependabot/go_modules/github.com/containers/image/v5-5.8.0
Bump github.com/containers/image/v5 from 5.6.0 to 5.8.0
2020-11-19 09:56:08 -05:00
Daniel J Walsh
5d73dea577 Add --format option to skopeo inspect
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-18 16:44:23 -05:00
Daniel J Walsh
82e461ff9d Switch to using errors.Wrapf rather then fmt.Errorsf
We are using both functions throughout the code. Pick
one and stick with it.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-18 16:43:15 -05:00
Daniel J Walsh
e30abff31b Bump github.com/containers/image/v5 from 5.6.0 to 5.8.0
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.6.0 to 5.8.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.6.0...v5.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-18 15:11:11 -05:00
Daniel J Walsh
7fee9122fb Merge pull request #1105 from containers/dependabot/go_modules/github.com/containers/common-0.27.0
Bump github.com/containers/common from 0.26.0 to 0.27.0
2020-11-18 15:09:00 -05:00
Daniel J Walsh
2342171cdf Merge pull request #880 from muff1nman/sync-digests
Fix #858 Add support for digests in sync
2020-11-17 09:06:44 -05:00
Daniel J Walsh
58c9eccffd Bump github.com/containers/common from 0.26.0 to 0.27.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.26.0 to 0.27.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.26.0...v0.27.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-17 09:02:35 -05:00
Daniel J Walsh
23fa1666dd Merge pull request #1104 from cevich/split_quay_envars
Support namespaced logins for quay.io
2020-11-17 09:01:21 -05:00
Daniel J Walsh
fa2e385713 Merge pull request #1107 from containers/dependabot/go_modules/github.com/containers/storage-1.24.0
Bump github.com/containers/storage from 1.23.9 to 1.24.0
2020-11-17 08:57:03 -05:00
Chris Evich
958c361c97 Support namespaced logins for quay.io
Service accounts (a.k.a. robots) in `quay.io` are forcably namespaced
to the user or orginization under which they are created.  Therefore,
it is impossible to use a common login/password to push images for
both `skopeo` and `containers` namespaces.  Worse, because the
authentication is recorded against `quay.io`, multiple login sessions
are required.

Fix this by adding a function definition which verifies non-empty
username/password arguments, before logging in.  Call this function
as needed from relevant targets, prior to pushing images.

Signed-off-by: Chris Evich <cevich@redhat.com>
2020-11-17 08:53:00 -05:00
Daniel J Walsh
72e8af59aa install: make commands copy-pasteable
Based on Elan Ruusamäe patch.
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-17 09:29:43 +01:00
Andrew DeMaria
873fbee01b Fix #858 Add --all sync flag to emulate copy --all
This replicates the --all copy flag to sync to perform the same
behavior. Namely, the default is CopySystemImage unless --all is passed
which changes the behavior to CopyAllImages. While it is probably
desirable for --all to be the default as there is no option to override
ones architecture with the sync command, --all can potentially break
existing sync incantations depending on registry support. Hence
CopySystemImage remains the default.

Signed-off-by: Andrew DeMaria <ademaria@cloudflare.com>
2020-11-16 15:18:56 -07:00
Andrew DeMaria
1a3eb478a7 Fix #858 Add support for digests in sync
Signed-off-by: Andrew DeMaria <ademaria@cloudflare.com>
2020-11-16 15:18:53 -07:00
dependabot-preview[bot]
bc0ecfc8f6 Bump github.com/containers/storage from 1.23.9 to 1.24.0
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.23.9 to 1.24.0.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.23.9...v1.24.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-16 17:14:54 -05:00
Daniel J Walsh
4ad2c75b52 Merge pull request #1091 from saschagrunert/osusergo
Use osusergo build tag for static build
2020-11-12 15:49:46 -05:00
Daniel J Walsh
9662633059 Merge pull request #1098 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2020-11-12 15:46:34 -05:00
Daniel J Walsh
18fe2fd00a Merge pull request #1089 from containers/dependabot/go_modules/github.com/containers/storage-1.23.7
Bump github.com/containers/storage from 1.23.5 to 1.23.9
2020-11-12 09:43:38 -05:00
Wong Hoi Sing Edison
19f9a6adc2 Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2020-11-12 21:11:43 +08:00
Daniel J Walsh
11b4fd3956 Merge pull request #1099 from mbargull/no-LDFLAGS-override
Avoid overriding LDFLAGS in Makefile
2020-11-12 06:29:23 -05:00
Daniel J Walsh
8d2c20f160 Merge pull request #1066 from barthy1/skopeo_upstream
add multi-arch build of upstream skopeo image via Travis
2020-11-12 06:24:22 -05:00
Daniel J Walsh
6d7d0e7d39 Bump github.com/containers/storage from 1.23.5 to 1.23.9
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.23.5 to 1.23.9.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](containers/storage@v1.23.5...v1.23.9)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-11-12 06:18:40 -05:00
Yulia Gaponenko
39f8117c27 add multi-arch builds for upstream and stable skopeo image via Travis
Travis is used, as it has native hardware to run the build for many
architectures (amd64, s390x, ppc64le). Docker is used as build and
manifest tool. `quay.io/skopeo/upstream:master`, `quay.io/skopeo/stable:v1.2.0`
and `quay.io/containers/skopeo:v1.2.0` are specified as target multi-arch
upstream image.
Travis config file has 3 stages:
- local-build to do the local test for linux/amd64 and osx, as it was in
the initial code
- image-build-push to build and push images for specific architectures
(amd64, s390x, ppc64le)
- manifest-multiarch-push to create and push manifest for multi-arch
image - `quay.io/skopeo/upstream:master`, `quay.io/skopeo/stable:v1.2.0`
and `quay.io/containers/skopeo:v1.2.0`

last stage amnd image push step are not done for pull request.

2 env variables specified in Travis settings are expected - QUAY_USERNAME and
QUAY_PASSWORD to push the images to quay.io.
As a result multi-arch images for 3 architectures are published.

README about build setup id prepared

Signed-off-by: Yulia Gaponenko <yulia.gaponenko1@de.ibm.com>
2020-11-09 20:19:24 +01:00
Marcel Bargull
e709329b03 Avoid overriding LDFLAGS in Makefile
Signed-off-by: Marcel Bargull <marcel.bargull@udo.edu>
2020-11-06 19:20:12 +01:00
Miloslav Trmač
1a3ae1411e Merge pull request #1094 from vrothberg/bump-go
Travis: bump go to 1.15.x
2020-11-06 16:46:12 +01:00
Valentin Rothberg
35daba1194 Dockerfile: install openssl
Apparently openssl was dropped from fedora.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2020-11-04 16:53:08 +01:00
Valentin Rothberg
65c5b0bf8d integration tests: disable ls for logs
For yet unknown reasons, Travis throws permission errors when trying to
recursively list the contents of a temp directory.  It passes locally,
so disable the logs to unblock CI.  Note, the reasons for the error are
yet to be revealed.

Related-issue: https://github.com/containers/skopeo/issues/1093
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2020-11-04 16:52:54 +01:00
Valentin Rothberg
cd884fa529 Travis: bump go to 1.15.x
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2020-11-04 12:04:13 +01:00
Sascha Grunert
3a72464068 Use osusergo build tag for static build
We now use the osusergo build tag to not use the glibc functions which
occur in the warnings but them from golang the os/user package.

Signed-off-by: Sascha Grunert <sgrunert@suse.com>
2020-11-02 10:37:50 +01:00
Daniel J Walsh
32e242586c Merge pull request #1090 from jjasghar/patch-1
Update install.md
2020-10-30 14:14:33 -04:00
JJ Asghar
a7f4b26f90 Update install.md
Fixed some formatting.
2020-10-29 15:37:35 -05:00
Daniel J Walsh
9bcae7060a Merge pull request #1088 from j0057/fix-login-example
Fix `skopeo login` example in README
2020-10-27 15:34:55 -04:00
Joost Molenaar
98fdb042a1 Fix skopeo login example in README 2020-10-27 15:21:46 +01:00
Daniel J Walsh
ceaee440a6 Merge pull request #1076 from containers/dependabot/go_modules/github.com/containers/common-0.26.0
Bump github.com/containers/common from 0.24.0 to 0.26.0
2020-10-21 08:44:58 -04:00
Daniel J Walsh
6eb4fb64a0 Merge pull request #1081 from containers/dependabot/go_modules/github.com/spf13/cobra-1.1.1
Bump github.com/spf13/cobra from 1.0.0 to 1.1.1
2020-10-21 08:44:34 -04:00
dependabot-preview[bot]
a75daba386 Bump github.com/containers/common from 0.24.0 to 0.26.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.24.0 to 0.26.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.24.0...v0.26.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-10-19 06:02:04 -04:00
dependabot-preview[bot]
67d72d27c9 Bump github.com/spf13/cobra from 1.0.0 to 1.1.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.0.0 to 1.1.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.0.0...v1.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-10-19 06:01:38 -04:00
Daniel J Walsh
362f70b056 Merge pull request #1074 from steveeJ/patch-1
install.md: mention Nix/NixOS
2020-10-14 18:10:33 -04:00
Stefan Junker
035e25496a install.md: mention Nix/NixOS 2020-10-14 11:31:45 +02:00
Daniel J Walsh
10da9f7012 Merge pull request #1068 from rhatdan/readme
Update README.md
2020-10-10 08:43:39 -04:00
Daniel J Walsh
c18a977e96 Merge pull request #1069 from rhatdan/makefile
Make Makefile a little easier to use
2020-10-10 08:43:16 -04:00
Daniel J Walsh
0954077fd7 Update install.md
Co-authored-by: Tom Sweeney <tsweeney@redhat.com>
2020-10-09 06:57:29 -04:00
Daniel J Walsh
bde39ce91d Update install.md
Co-authored-by: Miloslav Trmač <mitr@redhat.com>
2020-10-09 06:57:12 -04:00
Daniel J Walsh
a422316d48 Update README.md
Add commands section
Add information about skopeo sync

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-10-08 13:39:32 -04:00
Daniel J Walsh
21aa04e3c3 Make Makefile a little easier to use
By default we should build bin/skopeo locally
and build docs locally.

Show output when doing make docs.

Add description in `make help` to explain default
behaviour.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-10-08 10:19:41 -04:00
Daniel J Walsh
4cc72b9f69 Merge pull request #1067 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2020-10-08 05:16:55 -04:00
Wong Hoi Sing Edison
50ff352e41 Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@pantarei-design.com>
2020-10-08 12:05:09 +08:00
Miloslav Trmač
027d7e466a Merge pull request #1064 from containers/dependabot/go_modules/github.com/containers/common-0.24.0
Bump github.com/containers/common from 0.23.0 to 0.24.0
2020-10-02 20:29:57 +02:00
dependabot-preview[bot]
69f51ac183 Bump github.com/containers/common from 0.23.0 to 0.24.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.23.0 to 0.24.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.23.0...v0.24.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-10-02 11:27:01 -04:00
Miloslav Trmač
d8bc8b62e9 Merge pull request #1062 from edsantiago/openssl_san
Add Subject Alternative Name to local openssl cert
2020-10-01 15:31:07 +02:00
Ed Santiago
f9773889a1 Add Subject Alternative Name to local openssl cert
Go 1.15 deprecates checking CN; this broke gating tests:

   Get "https://localhost:5000/v2/": x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0

Easy two-line solution in the 'openssl' invocation. Huge
thanks to Nalin for tracking down and fixing while I was
still getting started:

   https://github.com/containers/buildah/pull/2595

Copied from 0f2892a5b021de3b1cf273f5679fda8298b57c02 in buildah

Signed-off-by: Ed Santiago <santiago@redhat.com>
2020-10-01 06:32:55 -06:00
Daniel J Walsh
6dabefa9db Merge pull request #1055 from nalind/cross
Makefile: add a local-cross target
2020-09-30 07:40:54 -04:00
Daniel J Walsh
5364f84119 Merge pull request #1058 from containers/dependabot/go_modules/github.com/sirupsen/logrus-1.7.0
Bump github.com/sirupsen/logrus from 1.6.0 to 1.7.0
2020-09-30 07:40:36 -04:00
Nalin Dahyabhai
4ba7d50174 Makefile: add a local-cross target
Add a make target that cross-compiles for a handful of the possible
targets that `go tool dist list` can tell us about.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2020-09-29 16:20:40 -04:00
dependabot-preview[bot]
12729c4d7e Bump github.com/sirupsen/logrus from 1.6.0 to 1.7.0
Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/sirupsen/logrus/releases)
- [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sirupsen/logrus/compare/v1.6.0...v1.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-29 14:27:34 -04:00
Daniel J Walsh
44beab63c9 Merge pull request #1057 from containers/dependabot/go_modules/github.com/containers/common-0.23.0
Bump github.com/containers/common from 0.22.0 to 0.23.0
2020-09-25 13:29:14 -04:00
Daniel J Walsh
669627d1b6 Merge pull request #1053 from lsm5/centos-obs
include OBS install steps for CentOS
2020-09-25 04:18:43 -04:00
dependabot-preview[bot]
1c45df1e03 Bump github.com/containers/common from 0.22.0 to 0.23.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.22.0 to 0.23.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.22.0...v0.23.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-25 04:16:44 -04:00
Daniel J Walsh
f91a9c569d Merge pull request #1049 from rhatdan/VENDOR
Bump to v1.2.0
2020-09-25 04:12:30 -04:00
Lokesh Mandvekar
248a1dd01a include OBS install steps for CentOS
additional formatting changes

Co-authored-by: Tom Sweeney <tsweeney@redhat.com>
Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2020-09-24 14:36:31 -04:00
Daniel J Walsh
3a75b51b59 Move to v1.2.1-dev
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-21 14:27:03 -04:00
Daniel J Walsh
2b4097bc13 Bump to v1.2.0
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-21 14:26:24 -04:00
Daniel J Walsh
8151b89b81 Merge pull request #1038 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2020-09-21 13:53:14 -04:00
Daniel J Walsh
cbd7fb7d37 Merge pull request #1045 from containers/dependabot/go_modules/github.com/containers/image/v5-5.6.0
Bump github.com/containers/image/v5 from 5.5.2 to 5.6.0
2020-09-21 13:51:53 -04:00
Miloslav Trmač
77293ff9c4 Merge pull request #1047 from airadier/registry-token-cli-flag
Add --registry-token flags to support Bearer token authentication
2020-09-18 21:32:24 +02:00
Alvaro Iradier
467b462b79 Keep options order in code and add missing bash completions 2020-09-18 20:57:02 +02:00
Alvaro Iradier
242b573f9a Adding periods 2020-09-18 18:11:01 +02:00
Alvaro Iradier
2d5f12b9a6 Add --registry-token tests to utils_tests.go
Signed-off-by: Alvaro Iradier <airadier@gmail.com>
2020-09-18 12:36:54 +02:00
Alvaro Iradier
3c73c0c0cd Add --registry-token flags to support Bearer token authentication
Signed-off-by: Alvaro Iradier <airadier@gmail.com>
2020-09-18 11:42:54 +02:00
Wong Hoi Sing Edison
ec17cfcbf1 Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@gmail.com>
2020-09-17 09:04:41 +08:00
dependabot-preview[bot]
1d0b1671f8 Bump github.com/containers/image/v5 from 5.5.2 to 5.6.0
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.5.2 to 5.6.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.5.2...v5.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-15 06:16:04 -04:00
Daniel J Walsh
bbd800f974 Merge pull request #1042 from rhatdan/codespell
Fix problems found by codespell
2020-09-15 06:14:41 -04:00
Miloslav Trmač
12ab19f5fd Merge pull request #1043 from containers/dependabot/go_modules/github.com/containers/common-0.22.0
Bump github.com/containers/common from 0.21.0 to 0.22.0
2020-09-14 17:51:36 +02:00
dependabot-preview[bot]
05d172a1f5 Bump github.com/containers/common from 0.21.0 to 0.22.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.21.0 to 0.22.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.21.0...v0.22.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-09-14 16:43:36 +02:00
Daniel J Walsh
45a9efb37f Merge pull request #1039 from containers/dependabot/go_modules/github.com/containers/storage-1.23.5
Bump github.com/containers/storage from 1.23.4 to 1.23.5
2020-09-11 14:49:44 -04:00
Daniel J Walsh
62bafb102d Fix problems found by codespell
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-11 10:19:16 -04:00
dependabot-preview[bot]
4eda1d092d Bump github.com/containers/storage from 1.23.4 to 1.23.5
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.23.4 to 1.23.5.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.23.4...v1.23.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-11 06:18:49 -04:00
Daniel J Walsh
5dd09d76c3 Merge pull request #1033 from containers/dependabot/go_modules/github.com/containers/storage-1.23.4
Bump github.com/containers/storage from 1.23.3 to 1.23.4
2020-09-09 15:57:59 -04:00
Miloslav Trmač
23cb1b7f19 Remove an obsolete documentation of (make binary-static)
... which no longer works after #932.

This does not add documentation for the current static build approach,
nor does it add any other place where DISABLE_CGO is documented;
both are not tested by CI, and discouraged due to bad integration
with the rest of the system.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-09-09 10:14:50 +02:00
dependabot-preview[bot]
c1f984a176 Bump github.com/containers/storage from 1.23.3 to 1.23.4
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.23.3 to 1.23.4.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.23.3...v1.23.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-08 06:05:35 -04:00
Daniel J Walsh
662f9ac8f7 Merge pull request #1031 from containers/dependabot/go_modules/github.com/containers/common-0.21.0
Bump github.com/containers/common from 0.20.3 to 0.21.0
2020-09-02 13:34:33 -04:00
Daniel J Walsh
ae26454014 Merge pull request #1008 from myback/master
fix build in docker container
2020-09-02 12:47:30 -04:00
Daniel J Walsh
5e1d64825c Merge pull request #1026 from alvistack/master-linux-amd64
Update nix pin with `make nixpkgs`
2020-09-02 12:46:36 -04:00
dependabot-preview[bot]
8767e73fe9 Bump github.com/containers/common from 0.20.3 to 0.21.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.20.3 to 0.21.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.20.3...v0.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-09-02 12:45:59 -04:00
Wong Hoi Sing Edison
071462199d Update nix pin with make nixpkgs
Signed-off-by: Wong Hoi Sing Edison <hswong3i@gmail.com>
2020-09-01 21:09:48 +08:00
myback
3bb23e355e use base image golang for build 2020-08-31 22:53:25 +07:00
Daniel J Walsh
c4998ebf3f Merge pull request #1027 from containers/dependabot/go_modules/github.com/containers/storage-1.23.2
Bump github.com/containers/storage from 1.23.1 to 1.23.2
2020-08-28 08:28:35 -04:00
Daniel J Walsh
a13b581760 Merge pull request #1028 from jarda-wien/master
Fix skopeo-login docs typo
2020-08-27 05:49:04 -04:00
dependabot-preview[bot]
c8c8d5db78 Bump github.com/containers/storage from 1.23.1 to 1.23.2
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.23.1 to 1.23.2.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.23.1...v1.23.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-27 05:48:03 -04:00
Jaroslav Stepanek
ad3d4aecbb Fix skopeo-login docs typo 2020-08-26 15:57:31 +02:00
Daniel J Walsh
87484a1754 Merge pull request #1023 from containers/dependabot/go_modules/github.com/containers/storage-1.23.1
Bump github.com/containers/storage from 1.23.0 to 1.23.1
2020-08-24 06:31:10 -04:00
Daniel J Walsh
58b9ec9e08 Merge pull request #1024 from containers/dependabot/go_modules/github.com/containers/common-0.20.3
Bump github.com/containers/common from 0.20.2 to 0.20.3
2020-08-24 06:30:50 -04:00
dependabot-preview[bot]
6911642122 Bump github.com/containers/storage from 1.23.0 to 1.23.1
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.23.0 to 1.23.1.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.23.0...v1.23.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-23 06:49:29 -04:00
dependabot-preview[bot]
3ede91cca6 Bump github.com/containers/common from 0.20.2 to 0.20.3
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.20.2 to 0.20.3.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.20.2...v0.20.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-23 06:48:48 -04:00
Daniel J Walsh
5d5756cc83 Merge pull request #1020 from containers/dependabot/go_modules/github.com/containers/image/v5-5.5.2
Bump github.com/containers/image/v5 from 5.5.1 to 5.5.2
2020-08-19 08:54:32 -04:00
Daniel J Walsh
5ad62b9415 Bump github.com/containers/image/v5 from 5.5.1 to 5.5.2
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.5.1 to 5.5.2.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.5.1...v5.5.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-19 08:02:35 -04:00
Daniel J Walsh
88c8c47ce0 Merge pull request #1016 from XiaodongLoong/build-on-mips
-buildmode=pie is not supported for some arch
2020-08-19 07:59:41 -04:00
Daniel J Walsh
e4f656616c Merge pull request #1017 from containers/dependabot/go_modules/github.com/containers/common-0.20.2
Bump github.com/containers/common from 0.18.0 to 0.20.2
2020-08-19 07:56:07 -04:00
dependabot-preview[bot]
b05933fbc4 Bump github.com/containers/common from 0.18.0 to 0.20.2
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.18.0 to 0.20.2.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.18.0...v0.20.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-18 08:52:41 -04:00
Xiaodong Liu
e5f549099b -buildmode=pie is not supported for some arch
Signed-off-by: Xiaodong Liu <liuxiaodong@loongson.cn>
2020-08-14 17:52:48 +08:00
Daniel J Walsh
ea10e61f7d Merge pull request #973 from alvistack/master-linux-amd64
Build static binary with `buildGoModule`
2020-08-11 17:42:05 -04:00
Wong Hoi Sing Edison
915f40d12a Build static binary with buildGoModule
Signed-off-by: Wong Hoi Sing Edison <hswong3i@gmail.com>
2020-08-11 14:10:43 +08:00
Daniel J Walsh
0c2c7f4016 Update docs/skopeo.1.md
Co-authored-by: Tom Sweeney <tsweeney@redhat.com>
2020-08-10 09:45:08 +02:00
Miloslav Trmač
135ce43169 Add oci-archive to transport list, and link to the authoritative man page
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-08-10 09:45:08 +02:00
Daniel J Walsh
0f94dbcdb3 Merge pull request #1004 from mtrmac/copy-example
Use an inter-registry copy as the example for (skopeo copy)
2020-08-09 08:51:43 -04:00
Daniel J Walsh
f30bab47e6 Merge pull request #1003 from mtrmac/copy-independent
Add an extra clarification to skopeo-copy(1)
2020-08-09 08:50:29 -04:00
Miloslav Trmač
baeaad61d9 Merge pull request #1002 from QiWang19/common-retry
Use c/common retry package
2020-08-08 08:04:35 +02:00
Miloslav Trmač
c750be0107 Use an inter-registry copy as the example for (skopeo copy)
because that's what users are looking for, and instead of using
a containers-storage: source, which might not even work all that
well with all the automatic defaults Podman sets up.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-08-08 04:22:24 +02:00
Qi Wang
84d051fc01 Use c/common retry package
Use c/common retry package.

Signed-off-by: Qi Wang <qiwan@redhat.com>
2020-08-07 21:17:05 -04:00
Miloslav Trmač
56f8222e12 Add an extra clarification to skopeo-copy(1)
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-08-08 02:24:46 +02:00
Miloslav Trmač
78d2f67016 Merge pull request #1001 from containers/dependabot/go_modules/github.com/containers/storage-1.22.0
Bump github.com/containers/storage from 1.21.2 to 1.22.0
2020-08-08 00:33:00 +02:00
dependabot-preview[bot]
c24363ccda Bump github.com/containers/storage from 1.21.2 to 1.22.0
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.21.2 to 1.22.0.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.21.2...v1.22.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-07 08:21:01 -04:00
Daniel J Walsh
c052ed7ec8 Merge pull request #992 from rhatdan/inspect
Make InspectOutput an external object
2020-08-03 13:26:18 -04:00
Miloslav Trmač
5e88eb5761 Merge pull request #995 from rhatdan/master
A couple of minor code cleanups.
2020-08-03 15:42:57 +02:00
Daniel J Walsh
4fb724fb7b Make InspectOutput an external object
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-02 07:08:48 -04:00
Daniel J Walsh
e23b780072 Fix make clean to actually remove binaries
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-02 07:04:51 -04:00
Daniel J Walsh
d9058b3021 Switch containers/libpod->containers/podman
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-08-02 07:04:51 -04:00
Daniel J Walsh
62fd5a76e1 Merge pull request #988 from containers/dependabot/go_modules/github.com/containers/common-0.18.0
Bump github.com/containers/common from 0.16.0 to 0.18.0
2020-07-31 07:34:20 -04:00
Daniel J Walsh
6252c22112 Merge pull request #994 from mrueg/dockerfile.build
Dockerfile.build: Upgrade to Ubuntu 20.04
2020-07-30 18:14:26 -04:00
Manuel Rüger
26e6db1cc7 Dockerfile.build: Upgrade to Ubuntu 20.04
19.10 is EOL since July 17, 2020

Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2020-07-29 15:10:52 +02:00
dependabot-preview[bot]
b7cdcb00ac Bump github.com/containers/common from 0.16.0 to 0.18.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.16.0 to 0.18.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.16.0...v0.18.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-07-23 08:28:23 -04:00
Daniel J Walsh
153f18dc0a Merge pull request #986 from containers/dependabot/go_modules/github.com/containers/storage-1.21.2
Bump github.com/containers/storage from 1.21.1 to 1.21.2
2020-07-23 08:18:54 -04:00
dependabot-preview[bot]
4012d0e30c Bump github.com/containers/storage from 1.21.1 to 1.21.2
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.21.1 to 1.21.2.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.21.1...v1.21.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-07-22 06:57:31 -04:00
Miloslav Trmač
494d237789 Merge pull request #977 from QiWang19/commands-retry
Retry on skopeo subcommands
2020-07-18 21:55:52 +02:00
Qi Wang
84c53d104a Retry on skopeo subcommands
Applies retry on more skopeo subcommands.
Related issue: https://github.com/containers/skopeo/issues/918

Signed-off-by: Qi Wang <qiwan@redhat.com>
2020-07-17 12:04:20 -04:00
Daniel J Walsh
89fb89a456 Merge pull request #980 from containers/dependabot/go_modules/github.com/containers/common-0.16.0
Bump github.com/containers/common from 0.15.2 to 0.16.0
2020-07-17 07:11:45 -04:00
dependabot-preview[bot]
960b610ff6 Bump github.com/containers/common from 0.15.2 to 0.16.0
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.15.2 to 0.16.0.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.15.2...v0.16.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-07-17 00:29:35 +02:00
Daniel J Walsh
29eec32795 Merge pull request #976 from containers/dependabot/go_modules/github.com/containers/storage-1.21.1
Bump github.com/containers/storage from 1.21.0 to 1.21.1
2020-07-16 17:16:50 -04:00
Miloslav Trmač
2fa7b998ba Merge pull request #978 from vrothberg/update-x/text
vendor golang.org/x/text@v0.3.3
2020-07-16 19:01:56 +02:00
Valentin Rothberg
ebc438266d vendor golang.org/x/text@v0.3.3
Fixes: CVE-2020-14040
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2020-07-16 11:17:54 +02:00
dependabot-preview[bot]
8f5eb45ba6 Bump github.com/containers/storage from 1.21.0 to 1.21.1
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.21.0 to 1.21.1.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.21.0...v1.21.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-07-14 21:26:24 -04:00
Daniel J Walsh
6284ceb2b6 Merge pull request #974 from containers/dependabot/go_modules/github.com/containers/storage-1.21.0
Bump github.com/containers/storage from 1.20.2 to 1.21.0
2020-07-11 09:29:08 -04:00
Daniel J Walsh
5e2264d2b5 Bump github.com/containers/storage from 1.20.2 to 1.21.0
Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.20.2 to 1.21.0.
- [Release notes](https://github.com/containers/storage/releases)
- [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md)
- [Commits](https://github.com/containers/storage/compare/v1.20.2...v1.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-07-11 07:38:43 -04:00
Daniel J Walsh
6e295a2097 Merge pull request #975 from containers/dependabot/go_modules/github.com/hashicorp/go-multierror-1.1.0
Bump github.com/hashicorp/go-multierror from 1.0.0 to 1.1.0
2020-07-11 07:36:58 -04:00
dependabot-preview[bot]
19f9a5c2fa Bump github.com/hashicorp/go-multierror from 1.0.0 to 1.1.0
Bumps [github.com/hashicorp/go-multierror](https://github.com/hashicorp/go-multierror) from 1.0.0 to 1.1.0.
- [Release notes](https://github.com/hashicorp/go-multierror/releases)
- [Commits](https://github.com/hashicorp/go-multierror/compare/v1.0.0...v1.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-07-10 06:42:30 -04:00
Daniel J Walsh
f63685f3c8 Merge pull request #971 from containers/dependabot/go_modules/github.com/containers/ocicrypt-1.0.3
Bump github.com/containers/ocicrypt from 1.0.2 to 1.0.3
2020-07-10 06:41:12 -04:00
Miloslav Trmač
dc5f68fe5f Merge pull request #933 from QiWang19/retry
Retry skopeo inspect command
2020-07-09 18:56:51 +02:00
Qi Wang
0858cafffc Retry skopeo inspect command
Enables to retry skopeo inspect. Add `--retry-times` to set the number of times to retry. Use exponential backoff and  1s as default initial retry delay.

Signed-off-by: Qi Wang <qiwan@redhat.com>
2020-07-09 11:57:13 -04:00
dependabot-preview[bot]
2e343342d5 Bump github.com/containers/ocicrypt from 1.0.2 to 1.0.3
Bumps [github.com/containers/ocicrypt](https://github.com/containers/ocicrypt) from 1.0.2 to 1.0.3.
- [Release notes](https://github.com/containers/ocicrypt/releases)
- [Commits](https://github.com/containers/ocicrypt/compare/v1.0.2...v1.0.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-07-09 16:31:10 +02:00
Miloslav Trmač
840c48752e Merge pull request #972 from mtrmac/brew-test
Fix macOS builds in Travis
2020-07-09 16:30:02 +02:00
Miloslav Trmač
0382b01687 Fix macOS builds in Travis
... which are currently failing with
> Error: The `brew link` step did not complete successfully
> The formula built, but is not symlinked into /usr/local
> Could not symlink Frameworks/Python.framework/Headers
> Target /usr/local/Frameworks/Python.framework/Headers
> is a symlink belonging to python@2. You can unlink it:
>   brew unlink python@2

because the Travis-installed machine apparently has quite a few
Homebrew formulae installed, with an old version of Homebrew,
including a now-removed python@2, and that prevents updates of
python@3.

Remove the obsolete motivation for running (brew update), and replace it
with a similarly-good motivation that the Travis images are just too old
to be relevant to users.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-07-09 02:17:50 +02:00
Miloslav Trmač
ee72e803ec Merge pull request #969 from containers/dependabot/go_modules/github.com/containers/common-0.15.2
Bump github.com/containers/common from 0.15.1 to 0.15.2
2020-07-08 23:19:06 +02:00
dependabot-preview[bot]
142142c040 Bump github.com/containers/common from 0.15.1 to 0.15.2
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.15.1 to 0.15.2.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.15.1...v0.15.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-07-06 14:53:30 -04:00
Daniel J Walsh
6182aa30b1 Merge pull request #964 from alvistack/master-linux-amd64
nix run -f channel:nixos-20.03
2020-07-02 06:11:50 -04:00
Daniel J Walsh
ec9f8acf00 Merge pull request #967 from containers/dependabot/go_modules/github.com/containers/common-0.15.1
Bump github.com/containers/common from 0.14.3 to 0.15.1
2020-07-02 06:10:46 -04:00
dependabot-preview[bot]
52b3a5bacc Bump github.com/containers/common from 0.14.3 to 0.15.1
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.14.3 to 0.15.1.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.14.3...v0.15.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-01 20:59:28 +02:00
Miloslav Trmač
ac6b871f66 Merge pull request #966 from lumjjb/doc_Change
update enc/dec docs to be consistent with buildah
2020-07-01 20:52:49 +02:00
Brandon Lum
b17fb08f8b update enc/dec docs to be consistent with buildah
Signed-off-by: Brandon Lum <lumjjb@gmail.com>
2020-06-30 21:46:57 +00:00
Wong Hoi Sing Edison
dd2e70e9b7 nix run -f channel:nixos-20.03
Switch from nix `channel:nixpkgs-unstable` to `channel:nixos-20.03` for better stability.

Signed-off-by: Wong Hoi Sing Edison <hswong3i@gmail.com>
2020-06-29 12:07:46 +08:00
Miloslav Trmač
ba8cbf589b Merge pull request #963 from containers/dependabot/go_modules/github.com/containers/common-0.14.3
Bump github.com/containers/common from 0.14.0 to 0.14.3
2020-06-26 20:01:02 +02:00
dependabot-preview[bot]
91dc0f3f4c Bump github.com/containers/common from 0.14.0 to 0.14.3
Bumps [github.com/containers/common](https://github.com/containers/common) from 0.14.0 to 0.14.3.
- [Release notes](https://github.com/containers/common/releases)
- [Commits](https://github.com/containers/common/compare/v0.14.0...v0.14.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-06-26 06:06:56 -04:00
Daniel J Walsh
7815c8ac6f Merge pull request #952 from rhatdan/build
Cleanup Dockerfile builds
2020-06-22 11:21:21 -04:00
Miloslav Trmač
233e61cf9a Merge pull request #960 from mtrmac/htpasswd
Run htpasswd from our build-container instead of registry:2
2020-06-22 15:23:03 +02:00
Miloslav Trmač
0e2611d3a6 Run htpasswd from our build-container instead of registry:2
registry:2 no longer contains htpasswd.

Also don't use log_and_run ... >> $file
because that will cause the command to be logged to $file.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2020-06-19 19:44:52 +02:00
Daniel J Walsh
96bd4a0619 Merge pull request #958 from rhatdan/VERSION
Bump to v1.1.0
2020-06-18 15:28:31 -04:00
Daniel J Walsh
6b78619cd1 Merge pull request #932 from alvistack/master-linux-amd64
[nix] Add nix derivation for static builds
2020-06-18 10:24:32 -04:00
Wong Hoi Sing Edison
0f458eec76 Add nix derivation for static builds
Signed-off-by: Wong Hoi Sing Edison <hswong3i@gmail.com>
2020-06-18 20:57:55 +08:00
Daniel J Walsh
6b960ec031 Cleanup Dockerfile builds
Add `-y` options to yum clean all
Only delete below /var/cache/dnf so that I can use the
-v /var/cache/dnf:/var/cache/dnf:O option when building
to speed up builds.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-06-17 17:22:58 -04:00
Daniel J Walsh
fdc58131f8 Move to v1.1.1-dev
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-06-17 16:41:59 -04:00
1842 changed files with 172734 additions and 61399 deletions

213
.cirrus.yml Normal file
View File

@@ -0,0 +1,213 @@
---
# Main collection of env. vars to set for all tasks and scripts.
env:
####
#### Global variables used for all tasks
####
# Name of the ultimate destination branch for this CI run, PR or post-merge.
DEST_BRANCH: "main"
# Overrides default location (/tmp/cirrus) for repo clone
GOPATH: &gopath "/var/tmp/go"
GOBIN: "${GOPATH}/bin"
GOCACHE: "${GOPATH}/cache"
GOSRC: &gosrc "/var/tmp/go/src/github.com/containers/skopeo"
# Required for consistency with containers/image CI
SKOPEO_PATH: *gosrc
CIRRUS_WORKING_DIR: *gosrc
# The default is 'sh' if unspecified
CIRRUS_SHELL: "/bin/bash"
# Save a little typing (path relative to $CIRRUS_WORKING_DIR)
SCRIPT_BASE: "./contrib/cirrus"
####
#### Cache-image names to test with (double-quotes around names are critical)
####
FEDORA_NAME: "fedora-34"
PRIOR_FEDORA_NAME: "fedora-33"
UBUNTU_NAME: "ubuntu-2104"
PRIOR_UBUNTU_NAME: "ubuntu-2010"
# Google-cloud VM Images
IMAGE_SUFFIX: "c6248193773010944"
FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}"
UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX}"
PRIOR_UBUNTU_CACHE_IMAGE_NAME: "prior-ubuntu-${IMAGE_SUFFIX}"
# Container FQIN's
FEDORA_CONTAINER_FQIN: "quay.io/libpod/fedora_podman:${IMAGE_SUFFIX}"
PRIOR_FEDORA_CONTAINER_FQIN: "quay.io/libpod/prior-fedora_podman:${IMAGE_SUFFIX}"
UBUNTU_CONTAINER_FQIN: "quay.io/libpod/ubuntu_podman:${IMAGE_SUFFIX}"
PRIOR_UBUNTU_CONTAINER_FQIN: "quay.io/libpod/prior-ubuntu_podman:${IMAGE_SUFFIX}"
# Equivilent to image produced by 'make build-container'
SKOPEO_CI_CONTAINER_FQIN: "quay.io/skopeo/ci:${DEST_BRANCH}"
# Default timeout for each task
timeout_in: 45m
gcp_credentials: ENCRYPTED[52d9e807b531b37ab14e958cb5a72499460663f04c8d73e22ad608c027a31118420f1c80f0be0882fbdf96f49d8f9ac0]
validate_task:
# The git-validation tool doesn't work well on branch or tag push,
# under Cirrus-CI, due to challenges obtaining the starting commit ID.
# Only do validation for PRs.
only_if: $CIRRUS_PR != ''
container: &build_container
image: "${SKOPEO_CI_CONTAINER_FQIN}"
cpu: 4
memory: 8
script: |
make validate-local
make vendor && hack/tree_status.sh
doccheck_task:
only_if: $CIRRUS_PR != ''
depends_on:
- validate
container:
image: "${FEDORA_CONTAINER_FQIN}"
cpu: 4
memory: 8
env:
BUILDTAGS: &withopengpg 'btrfs_noversion libdm_no_deferred_remove containers_image_openpgp'
script: |
# TODO: Can't use 'runner.sh setup' inside container. However,
# removing the pre-installed package is the only necessary step
# at the time of this comment.
dnf erase -y skopeo # Guarantee non-interference
"${SKOPEO_PATH}/${SCRIPT_BASE}/runner.sh" build
"${SKOPEO_PATH}/${SCRIPT_BASE}/runner.sh" doccheck
osx_task:
only_if: &not_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
depends_on:
- validate
macos_instance:
image: catalina-xcode
setup_script: |
export PATH=$GOPATH/bin:$PATH
brew update
brew install gpgme go go-md2man
go get -u golang.org/x/lint/golint
test_script: |
export PATH=$GOPATH/bin:$PATH
go version
go env
make validate-local test-unit-local bin/skopeo
sudo make install
/usr/local/bin/skopeo -v
cross_task:
alias: cross
only_if: *not_docs
depends_on:
- validate
gce_instance:
image_project: libpod-218412
zone: "us-central1-f"
cpu: 2
memory: "4Gb"
# Required to be 200gig, do not modify - has i/o performance impact
# according to gcloud CLI tool warning messages.
disk: 200
image_name: ${FEDORA_CACHE_IMAGE_NAME}
env:
BUILDTAGS: *withopengpg
setup_script: >-
"${GOSRC}/${SCRIPT_BASE}/runner.sh" setup
cross_script: >-
"${GOSRC}/${SCRIPT_BASE}/runner.sh" cross
#####
##### NOTE: This task is subtantially duplicated in the containers/image
##### repository's `.cirrus.yml`. Changes made here should be fully merged
##### prior to being manually duplicated and maintained in containers/image.
#####
test_skopeo_task:
alias: test_skopeo
only_if: *not_docs
depends_on:
- validate
gce_instance:
image_project: libpod-218412
zone: "us-central1-f"
cpu: 2
memory: "4Gb"
# Required to be 200gig, do not modify - has i/o performance impact
# according to gcloud CLI tool warning messages.
disk: 200
image_name: ${FEDORA_CACHE_IMAGE_NAME}
matrix:
- name: "Skopeo Test"
env:
BUILDTAGS: 'btrfs_noversion libdm_no_deferred_remove'
- name: "Skopeo Test w/ opengpg"
env:
BUILDTAGS: *withopengpg
setup_script: >-
"${GOSRC}/${SCRIPT_BASE}/runner.sh" setup
vendor_script: >-
"${SKOPEO_PATH}/${SCRIPT_BASE}/runner.sh" vendor
build_script: >-
"${SKOPEO_PATH}/${SCRIPT_BASE}/runner.sh" build
unit_script: >-
"${SKOPEO_PATH}/${SCRIPT_BASE}/runner.sh" unit
integration_script: >-
"${SKOPEO_PATH}/${SCRIPT_BASE}/runner.sh" integration
system_script: >
"${SKOPEO_PATH}/${SCRIPT_BASE}/runner.sh" system
# This task is critical. It updates the "last-used by" timestamp stored
# in metadata for all VM images. This mechanism functions in tandem with
# an out-of-band pruning operation to remove disused VM images.
meta_task:
name: "VM img. keepalive"
alias: meta
container: &smallcontainer
cpu: 2
memory: 2
image: quay.io/libpod/imgts:$IMAGE_SUFFIX
env:
# Space-separated list of images used by this repository state
IMGNAMES: >-
${FEDORA_CACHE_IMAGE_NAME}
${PRIOR_FEDORA_CACHE_IMAGE_NAME}
${UBUNTU_CACHE_IMAGE_NAME}
${PRIOR_UBUNTU_CACHE_IMAGE_NAME}
BUILDID: "${CIRRUS_BUILD_ID}"
REPOREF: "${CIRRUS_REPO_NAME}"
GCPJSON: ENCRYPTED[6867b5a83e960e7c159a98fe6c8360064567a071c6f4b5e7d532283ecd870aa65c94ccd74bdaa9bf7aadac9d42e20a67]
GCPNAME: ENCRYPTED[1cf558ae125e3c39ec401e443ad76452b25d790c45eb73d77c83eb059a0f7fd5085ef7e2f7e410b04ea6e83b0aab2eb1]
GCPPROJECT: libpod-218412
clone_script: &noop mkdir -p "$CIRRUS_WORKING_DIR"
script: /usr/local/bin/entrypoint.sh
# Status aggregator for all tests. This task simply ensures a defined
# set of tasks all passed, and allows confirming that based on the status
# of this task.
success_task:
name: "Total Success"
alias: success
# N/B: ALL tasks must be listed here, minus their '_task' suffix.
depends_on:
- validate
- doccheck
- osx
- cross
- test_skopeo
- meta
container: *smallcontainer
env:
CTR_FQIN: ${FEDORA_CONTAINER_FQIN}
TEST_ENVIRON: container
clone_script: *noop
script: /bin/true

10
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: daily
time: "10:00"
timezone: Europe/Berlin
open-pull-requests-limit: 10

209
.github/workflows/multi-arch-build.yaml vendored Normal file
View File

@@ -0,0 +1,209 @@
---
# Please see contrib/<reponame>image/README.md for details on the intentions
# of this workflow.
#
# BIG FAT WARNING: This workflow is duplicated across containers/skopeo,
# containers/buildah, and containers/podman. ANY AND
# ALL CHANGES MADE HERE MUST BE MANUALLY DUPLICATED
# TO THE OTHER REPOS.
name: build multi-arch images
on:
# Upstream tends to be very active, with many merges per day.
# Only run this daily via cron schedule, or manually, not by branch push.
schedule:
- cron: '0 8 * * *'
# allows to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
multi:
name: multi-arch image build
env:
REPONAME: skopeo # No easy way to parse this out of $GITHUB_REPOSITORY
# Server/namespace value used to format FQIN
REPONAME_QUAY_REGISTRY: quay.io/skopeo
CONTAINERS_QUAY_REGISTRY: quay.io/containers
# list of architectures for build
PLATFORMS: linux/amd64,linux/s390x,linux/ppc64le,linux/arm64
# Command to execute in container to obtain project version number
VERSION_CMD: "--version" # skopeo is the entrypoint
# build several images (upstream, testing, stable) in parallel
strategy:
# By default, failure of one matrix item cancels all others
fail-fast: false
matrix:
# Builds are located under contrib/<reponame>image/<source> directory
source:
- upstream
- testing
- stable
runs-on: ubuntu-latest
# internal registry caches build for inspection before push
services:
registry:
image: quay.io/libpod/registry:2
ports:
- 5000:5000
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host
install: true
- name: Build and locally push image
uses: docker/build-push-action@v2
with:
context: contrib/${{ env.REPONAME }}image/${{ matrix.source }}
file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile
platforms: ${{ env.PLATFORMS }}
push: true
tags: localhost:5000/${{ env.REPONAME }}/${{ matrix.source }}
# Simple verification that stable images work, and
# also grab version number use in forming the FQIN.
- name: amd64 container sniff test
if: matrix.source == 'stable'
id: sniff_test
run: |
podman pull --tls-verify=false \
localhost:5000/$REPONAME/${{ matrix.source }}
VERSION_OUTPUT=$(podman run \
localhost:5000/$REPONAME/${{ matrix.source }} \
$VERSION_CMD)
echo "$VERSION_OUTPUT"
VERSION=$(awk -r -e "/^${REPONAME} version /"'{print $3}' <<<"$VERSION_OUTPUT")
test -n "$VERSION"
echo "::set-output name=version::$VERSION"
- name: Generate image FQIN(s) to push
id: reponame_reg
run: |
if [[ "${{ matrix.source }}" == 'stable' ]]; then
# The command version in image just built
VERSION='v${{ steps.sniff_test.outputs.version }}'
# workaround vim syntax-highlight bug: '
# Push both new|updated version-tag and latest-tag FQINs
FQIN="$REPONAME_QUAY_REGISTRY/stable:$VERSION,$REPONAME_QUAY_REGISTRY/stable:latest"
elif [[ "${{ matrix.source }}" == 'testing' ]]; then
# Assume some contents changed, always push latest testing.
FQIN="$REPONAME_QUAY_REGISTRY/testing:latest"
elif [[ "${{ matrix.source }}" == 'upstream' ]]; then
# Assume some contents changed, always push latest upstream.
FQIN="$REPONAME_QUAY_REGISTRY/upstream:latest"
else
echo "::error::Unknown matrix item '${{ matrix.source }}'"
exit 1
fi
echo "::warning::Pushing $FQIN"
echo "::set-output name=fqin::${FQIN}"
echo '::set-output name=push::true'
# This is substantially similar to the above logic,
# but only handles $CONTAINERS_QUAY_REGISTRY for
# the stable "latest" and named-version tagged images.
- name: Generate containers reg. image FQIN(s)
if: matrix.source == 'stable'
id: containers_reg
run: |
VERSION='v${{ steps.sniff_test.outputs.version }}'
# workaround vim syntax-highlight bug: '
# Push both new|updated version-tag and latest-tag FQINs
FQIN="$CONTAINERS_QUAY_REGISTRY/$REPONAME:$VERSION,$CONTAINERS_QUAY_REGISTRY/$REPONAME:latest"
echo "::warning::Pushing $FQIN"
echo "::set-output name=fqin::${FQIN}"
echo '::set-output name=push::true'
- name: Define LABELS multi-line env. var. value
run: |
# This is a really hacky/strange workflow idiom, required
# for setting multi-line $LABELS value for consumption in
# a future step. There is literally no cleaner way to do this :<
# https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#multiline-strings
function set_labels() {
echo 'LABELS<<DELIMITER' >> "$GITHUB_ENV"
for line; do
echo "$line" | tee -a "$GITHUB_ENV"
done
echo "DELIMITER" >> "$GITHUB_ENV"
}
declare -a lines
lines=(\
"org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}.git"
"org.opencontainers.image.revision=${GITHUB_SHA}"
"org.opencontainers.image.created=$(date -u --iso-8601=seconds)"
)
# Only the 'stable' matrix source obtains $VERSION
if [[ "${{ matrix.source }}" == "stable" ]]; then
lines+=(\
"org.opencontainers.image.version=${{ steps.sniff_test.outputs.version }}"
)
fi
set_labels "${lines[@]}"
# Separate steps to login and push for $REPONAME_QUAY_REGISTRY and
# $CONTAINERS_QUAY_REGISTRY are required, because 2 sets of credentials
# are used and namespaced within the registry. At the same time, reuse
# of non-shell steps is not supported by Github Actions nor are YAML
# anchors/aliases, nor composite actions.
# Push to $REPONAME_QUAY_REGISTRY for stable, testing. and upstream
- name: Login to ${{ env.REPONAME_QUAY_REGISTRY }}
uses: docker/login-action@v1
if: steps.reponame_reg.outputs.push == 'true'
with:
registry: ${{ env.REPONAME_QUAY_REGISTRY }}
# N/B: Secrets are not passed to workflows that are triggered
# by a pull request from a fork
username: ${{ secrets.REPONAME_QUAY_USERNAME }}
password: ${{ secrets.REPONAME_QUAY_PASSWORD }}
- name: Push images to ${{ steps.reponame_reg.outputs.fqin }}
uses: docker/build-push-action@v2
if: steps.reponame_reg.outputs.push == 'true'
with:
cache-from: type=registry,ref=localhost:5000/${{ env.REPONAME }}/${{ matrix.source }}
cache-to: type=inline
context: contrib/${{ env.REPONAME }}image/${{ matrix.source }}
file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile
platforms: ${{ env.PLATFORMS }}
push: true
tags: ${{ steps.reponame_reg.outputs.fqin }}
labels: |
${{ env.LABELS }}
# Push to $CONTAINERS_QUAY_REGISTRY only stable
- name: Login to ${{ env.CONTAINERS_QUAY_REGISTRY }}
if: steps.containers_reg.outputs.push == 'true'
uses: docker/login-action@v1
with:
registry: ${{ env.CONTAINERS_QUAY_REGISTRY}}
username: ${{ secrets.CONTAINERS_QUAY_USERNAME }}
password: ${{ secrets.CONTAINERS_QUAY_PASSWORD }}
- name: Push images to ${{ steps.containers_reg.outputs.fqin }}
if: steps.containers_reg.outputs.push == 'true'
uses: docker/build-push-action@v2
with:
cache-from: type=registry,ref=localhost:5000/${{ env.REPONAME }}/${{ matrix.source }}
cache-to: type=inline
context: contrib/${{ env.REPONAME }}image/${{ matrix.source }}
file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile
platforms: ${{ env.PLATFORMS }}
push: true
tags: ${{ steps.containers_reg.outputs.fqin }}
labels: |
${{ env.LABELS }}

25
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: Mark stale issues and pull requests
# Please refer to https://github.com/actions/stale/blob/master/action.yml
# to see all config knobs of the stale action.
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'A friendly reminder that this issue had no activity for 30 days.'
stale-pr-message: 'A friendly reminder that this PR had no activity for 30 days.'
stale-issue-label: 'stale-issue'
stale-pr-label: 'stale-pr'
days-before-stale: 30
days-before-close: 365
remove-stale-when-updated: true

6
.gitignore vendored
View File

@@ -1,6 +1,10 @@
*.1
/layers-*
/skopeo
result
# ignore JetBrains IDEs (GoLand) config folder
.idea
.idea
# Ignore the bin directory
bin

View File

@@ -1,28 +0,0 @@
language: go
matrix:
include:
- os: linux
sudo: required
services:
- docker
- os: osx
go:
- 1.13.x
notifications:
email: false
install:
# NOTE: The (brew update) should not be necessary, and slows things down;
# we include it as a workaround for https://github.com/Homebrew/brew/issues/3299
# ideally Travis should bake the (brew update) into its images
# (https://github.com/travis-ci/travis-ci/issues/8552 ), but thats only going
# to happen around November 2017 per https://blog.travis-ci.com/2017-10-16-a-new-default-os-x-image-is-coming .
# Remove the (brew update) at that time.
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update && brew install gpgme ; fi
script:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then hack/travis_osx.sh ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make vendor && ./hack/tree_status.sh && make check ; fi

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/master/CODE-OF-CONDUCT.md).
The skopeo project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md).

View File

@@ -117,32 +117,34 @@ commit automatically with `git commit -s`.
### Dependencies management
Make sure [`vndr`](https://github.com/LK4D4/vndr) is installed.
Dependencies are managed via [standard go modules](https://golang.org/ref/mod).
In order to add a new dependency to this project:
- add a new line to `vendor.conf` according to `vndr` rules (e.g. `github.com/pkg/errors master`)
- use `go get -d path/to/dep@version` to add a new line to `go.mod`
- run `make vendor`
In order to update an existing dependency:
- update the relevant dependency line in `vendor.conf`
- use `go get -d -u path/to/dep@version` to update the relevant dependency line in `go.mod`
- run `make vendor`
When new PRs for [containers/image](https://github.com/containers/image) break `skopeo` (i.e. `containers/image` tests fail in `make test-skopeo`):
- create out a new branch in your `skopeo` checkout and switch to it
- update `vendor.conf`. Find out the `containers/image` dependency; update it to vendor from your own branch and your own repository fork (e.g. `github.com/containers/image my-branch https://github.com/runcom/image`)
- find out the version of `containers/image` you want to use and note its commit ID. You might also want to use a fork of `containers/image`, in that case note its repo
- use `go get -d github.com/$REPO/image/v5@$COMMIT_ID` to download the right version. The command will fetch the dependency and then fail because of a conflict in `go.mod`, this is expected. Note the pseudo-version (eg. `v5.13.1-0.20210707123201-50afbf0a326`)
- use `go mod edit -replace=github.com/containers/image/v5=github.com/$REPO/image/v5@$PSEUDO_VERSION` to add a replacement line to `go.mod` (e.g. `replace github.com/containers/image/v5 => github.com/moio/image/v5 v5.13.1-0.20210707123201-50afbf0a3262`)
- run `make vendor`
- make any other necessary changes in the skopeo repo (e.g. add other dependencies now requied by `containers/image`, or update skopeo for changed `containers/image` API)
- make any other necessary changes in the skopeo repo (e.g. add other dependencies now required by `containers/image`, or update skopeo for changed `containers/image` API)
- optionally add new integration tests to the skopeo repo
- submit the resulting branch as a skopeo PR, marked “DO NOT MERGE”
- iterate until tests pass and the PR is reviewed
- then the original `containers/image` PR can be merged, disregarding its `make test-skopeo` failure
- as soon as possible after that, in the skopeo PR, restore the `containers/image` line in `vendor.conf` to use `containers/image:master`
- as soon as possible after that, in the skopeo PR, use `go mod edit -dropreplace=github.com/containers/image` to remove the `replace` line in `go.mod`
- run `make vendor`
- update the skopeo PR with the result, drop the “DO NOT MERGE” marking
- after tests complete succcesfully again, merge the skopeo PR
- after tests complete successfully again, merge the skopeo PR
## Communications

View File

@@ -1,4 +1,4 @@
FROM fedora
FROM registry.fedoraproject.org/fedora:latest
RUN dnf -y update && dnf install -y make git golang golang-github-cpuguy83-md2man \
# storage deps
@@ -7,10 +7,13 @@ RUN dnf -y update && dnf install -y make git golang golang-github-cpuguy83-md2ma
# gpgme bindings deps
libassuan-devel gpgme-devel \
gnupg \
# htpasswd for system tests
httpd-tools \
# OpenShift deps
which tar wget hostname util-linux bsdtar socat ethtool device-mapper iptables tree findutils nmap-ncat e2fsprogs xfsprogs lsof docker iproute \
bats jq podman runc \
golint \
openssl \
&& dnf clean all
# Install two versions of the registry. The first is an older version that
@@ -18,6 +21,7 @@ RUN dnf -y update && dnf install -y make git golang golang-github-cpuguy83-md2ma
# both. This allows integration-cli tests to cover push/pull with both schema1
# and schema2 manifests.
RUN set -x \
&& export GO111MODULE=off \
&& REGISTRY_COMMIT_SCHEMA1=ec87e9b6971d831f0eff752ddb54fb64693e51cd \
&& REGISTRY_COMMIT=47a064d4195a9b56133891bbb13620c3ac83a827 \
&& export GOPATH="$(mktemp -d)" \
@@ -31,6 +35,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
RUN set -x \
&& export GO111MODULE=off \
&& export GOPATH=$(mktemp -d) \
&& git clone --depth 1 -b v1.5.0-alpha.3 git://github.com/openshift/origin "$GOPATH/src/github.com/openshift/origin" \
# The sed edits out a "go < 1.5" check which works incorrectly with go ≥ 1.10. \
@@ -43,6 +48,7 @@ RUN set -x \
ENV GOPATH /usr/share/gocode:/go
ENV PATH $GOPATH/bin:/usr/share/gocode/bin:$PATH
ENV container_magic 85531765-346b-4316-bdb8-358e4cca9e5d
RUN go version
WORKDIR /go/src/github.com/containers/skopeo
COPY . /go/src/github.com/containers/skopeo

View File

@@ -1,13 +1,12 @@
FROM ubuntu:19.10
FROM registry.fedoraproject.org/fedora:33
RUN apt-get update && apt-get install -y \
golang \
libbtrfs-dev \
git-core \
libdevmapper-dev \
libgpgme11-dev \
go-md2man \
libglib2.0-dev
RUN dnf update -y && \
dnf install -y \
btrfs-progs-devel \
device-mapper-devel \
golang \
gpgme-devel \
make
ENV GOPATH=/
WORKDIR /src/github.com/containers/skopeo

139
Makefile
View File

@@ -2,33 +2,37 @@
export GOPROXY=https://proxy.golang.org
ifeq ($(shell uname),Darwin)
PREFIX ?= ${DESTDIR}/usr/local
DARWIN_BUILD_TAG=
# On macOS, (brew install gpgme) installs it within /usr/local, but /usr/local/include is not in the default search path.
# Rather than hard-code this directory, use gpgme-config. Sadly that must be done at the top-level user
# instead of locally in the gpgme subpackage, because cgo supports only pkg-config, not general shell scripts,
# and gpgme does not install a pkg-config file.
# On some plaforms (eg. macOS, FreeBSD) gpgme is installed in /usr/local/ but /usr/local/include/ is
# not in the default search path. Rather than hard-code this directory, use gpgme-config.
# Sadly that must be done at the top-level user instead of locally in the gpgme subpackage, because cgo
# supports only pkg-config, not general shell scripts, and gpgme does not install a pkg-config file.
# If gpgme is not installed or gpgme-config cant be found for other reasons, the error is silently ignored
# (and the user will probably find out because the cgo compilation will fail).
GPGME_ENV := CGO_CFLAGS="$(shell gpgme-config --cflags 2>/dev/null)" CGO_LDFLAGS="$(shell gpgme-config --libs 2>/dev/null)"
else
PREFIX ?= ${DESTDIR}/usr
endif
INSTALLDIR=${PREFIX}/bin
MANINSTALLDIR=${PREFIX}/share/man
CONTAINERSSYSCONFIGDIR=${DESTDIR}/etc/containers
REGISTRIESDDIR=${CONTAINERSSYSCONFIGDIR}/registries.d
SIGSTOREDIR=${DESTDIR}/var/lib/containers/sigstore
BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions
# The following variables very roughly follow https://www.gnu.org/prep/standards/standards.html#Makefile-Conventions .
DESTDIR ?=
PREFIX ?= /usr/local
CONTAINERSCONFDIR ?= /etc/containers
REGISTRIESDDIR ?= ${CONTAINERSCONFDIR}/registries.d
SIGSTOREDIR ?= /var/lib/containers/sigstore
BINDIR ?= ${PREFIX}/bin
MANDIR ?= ${PREFIX}/share/man
BASHCOMPLETIONSDIR ?= ${PREFIX}/share/bash-completion/completions
GO ?= go
GOBIN := $(shell $(GO) env GOBIN)
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)
ifeq ($(GOBIN),)
GOBIN := $(GOPATH)/bin
endif
# Required for integration-tests to detect they are running inside a specific
# container image. Env. var defined in image, make does not automatically
# pass to children unless explicitly exported
export container_magic
CONTAINER_RUNTIME := $(shell command -v podman 2> /dev/null || echo docker)
GOMD2MAN ?= $(shell command -v go-md2man || echo '$(GOBIN)/go-md2man')
@@ -43,8 +47,10 @@ ifeq ($(DEBUG), 1)
override GOGCFLAGS += -N -l
endif
ifeq ($(shell $(GO) env GOOS), linux)
GO_DYN_FLAGS="-buildmode=pie"
ifeq ($(GOOS), linux)
ifneq ($(GOARCH),$(filter $(GOARCH),mips mipsle mips64 mips64le ppc64 riscv64))
GO_DYN_FLAGS="-buildmode=pie"
endif
endif
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
@@ -62,12 +68,15 @@ CONTAINER_RUN := $(CONTAINER_CMD) "$(IMAGE)"
GIT_COMMIT := $(shell git rev-parse HEAD 2> /dev/null || true)
EXTRA_LDFLAGS ?=
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)
LIBDM_BUILD_TAG = $(shell hack/libdm_tag.sh)
LOCAL_BUILD_TAGS = $(BTRFS_BUILD_TAG) $(LIBDM_BUILD_TAG) $(DARWIN_BUILD_TAG)
LOCAL_BUILD_TAGS = $(BTRFS_BUILD_TAG) $(LIBDM_BUILD_TAG)
BUILDTAGS += $(LOCAL_BUILD_TAGS)
ifeq ($(DISABLE_CGO), 1)
@@ -78,14 +87,17 @@ endif
# Note: Uses the -N -l go compiler options to disable compiler optimizations
# and inlining. Using these build options allows you to subsequently
# use source debugging tools like delve.
all: binary docs-in-container
all: bin/skopeo docs
help:
@echo "Usage: make <target>"
@echo
@echo "Defaults to building bin/skopeo and docs"
@echo
@echo " * 'install' - Install binaries and documents to system locations"
@echo " * 'binary' - Build skopeo with a container"
@echo " * 'binary-local' - Build skopeo locally"
@echo " * 'static' - Build statically linked binary"
@echo " * 'bin/skopeo' - Build skopeo locally"
@echo " * 'test-unit' - Execute unit tests"
@echo " * 'test-integration' - Execute integration tests"
@echo " * 'validate' - Verify whether there is no conflict and all Go source files have been formatted, linted and vetted"
@@ -98,25 +110,37 @@ help:
binary: cmd/skopeo
${CONTAINER_RUNTIME} build ${BUILD_ARGS} -f Dockerfile.build -t skopeobuildimage .
${CONTAINER_RUNTIME} run --rm --security-opt label=disable -v $$(pwd):/src/github.com/containers/skopeo \
skopeobuildimage make binary-local $(if $(DEBUG),DEBUG=$(DEBUG)) BUILDTAGS='$(BUILDTAGS)'
skopeobuildimage make bin/skopeo $(if $(DEBUG),DEBUG=$(DEBUG)) BUILDTAGS='$(BUILDTAGS)'
binary-static: cmd/skopeo
${CONTAINER_RUNTIME} build ${BUILD_ARGS} -f Dockerfile.build -t skopeobuildimage .
${CONTAINER_RUNTIME} run --rm --security-opt label=disable -v $$(pwd):/src/github.com/containers/skopeo \
skopeobuildimage make binary-local-static $(if $(DEBUG),DEBUG=$(DEBUG)) BUILDTAGS='$(BUILDTAGS)'
# Update nix/nixpkgs.json its latest stable commit
.PHONY: nixpkgs
nixpkgs:
@nix run \
-f channel:nixos-21.05 nix-prefetch-git \
-c nix-prefetch-git \
--no-deepClone \
https://github.com/nixos/nixpkgs refs/heads/nixos-21.05 > nix/nixpkgs.json
# Build statically linked binary
.PHONY: static
static:
@nix build -f nix/
mkdir -p ./bin
cp -rfp ./result/bin/* ./bin/
# Build w/o using containers
binary-local:
$(GPGME_ENV) $(GO) build $(MOD_VENDOR) ${GO_DYN_FLAGS} -ldflags "-X main.gitCommit=${GIT_COMMIT}" -gcflags "$(GOGCFLAGS)" -tags "$(BUILDTAGS)" -o skopeo ./cmd/skopeo
binary-local-static:
$(GPGME_ENV) $(GO) build $(MOD_VENDOR) -ldflags "-extldflags \"-static\" -X main.gitCommit=${GIT_COMMIT}" -gcflags "$(GOGCFLAGS)" -tags "$(BUILDTAGS)" -o skopeo ./cmd/skopeo
.PHONY: bin/skopeo
bin/skopeo:
$(GPGME_ENV) $(GO) build $(MOD_VENDOR) ${GO_DYN_FLAGS} ${SKOPEO_LDFLAGS} -gcflags "$(GOGCFLAGS)" -tags "$(BUILDTAGS)" -o $@ ./cmd/skopeo
bin/skopeo.%:
GOOS=$(word 2,$(subst ., ,$@)) GOARCH=$(word 3,$(subst ., ,$@)) $(GO) build $(MOD_VENDOR) ${SKOPEO_LDFLAGS} -tags "containers_image_openpgp $(BUILDTAGS)" -o $@ ./cmd/skopeo
local-cross: bin/skopeo.darwin.amd64 bin/skopeo.linux.arm bin/skopeo.linux.arm64 bin/skopeo.windows.386.exe bin/skopeo.windows.amd64.exe
build-container:
${CONTAINER_RUNTIME} build ${BUILD_ARGS} -t "$(IMAGE)" .
$(MANPAGES): %: %.md
@sed -e 's/\((skopeo.*\.md)\)//' -e 's/\[\(skopeo.*\)\]/\1/' $< | $(GOMD2MAN) -in /dev/stdin -out $@
sed -e 's/\((skopeo.*\.md)\)//' -e 's/\[\(skopeo.*\)\]/\1/' $< | $(GOMD2MAN) -in /dev/stdin -out $@
docs: $(MANPAGES)
@@ -126,26 +150,26 @@ docs-in-container:
skopeobuildimage make docs $(if $(DEBUG),DEBUG=$(DEBUG)) BUILDTAGS='$(BUILDTAGS)'
clean:
rm -f skopeo docs/*.1
rm -rf bin docs/*.1
install: install-binary install-docs install-completions
install -d -m 755 ${SIGSTOREDIR}
install -d -m 755 ${CONTAINERSSYSCONFIGDIR}
install -m 644 default-policy.json ${CONTAINERSSYSCONFIGDIR}/policy.json
install -d -m 755 ${REGISTRIESDDIR}
install -m 644 default.yaml ${REGISTRIESDDIR}/default.yaml
install -d -m 755 ${DESTDIR}${SIGSTOREDIR}
install -d -m 755 ${DESTDIR}${CONTAINERSCONFDIR}
install -m 644 default-policy.json ${DESTDIR}${CONTAINERSCONFDIR}/policy.json
install -d -m 755 ${DESTDIR}${REGISTRIESDDIR}
install -m 644 default.yaml ${DESTDIR}${REGISTRIESDDIR}/default.yaml
install-binary: ./skopeo
install -d -m 755 ${INSTALLDIR}
install -m 755 skopeo ${INSTALLDIR}/skopeo
install-binary: bin/skopeo
install -d -m 755 ${DESTDIR}${BINDIR}
install -m 755 bin/skopeo ${DESTDIR}${BINDIR}/skopeo
install-docs: docs
install -d -m 755 ${MANINSTALLDIR}/man1
install -m 644 docs/*.1 ${MANINSTALLDIR}/man1/
install -d -m 755 ${DESTDIR}${MANDIR}/man1
install -m 644 docs/*.1 ${DESTDIR}${MANDIR}/man1
install-completions:
install -m 755 -d ${BASHINSTALLDIR}
install -m 644 completions/bash/skopeo ${BASHINSTALLDIR}/skopeo
install -m 755 -d ${DESTDIR}${BASHCOMPLETIONSDIR}
install -m 644 completions/bash/skopeo ${DESTDIR}${BASHCOMPLETIONSDIR}/skopeo
shell: build-container
$(CONTAINER_RUN) bash
@@ -154,7 +178,11 @@ check: validate test-unit test-integration test-system
# The tests can run out of entropy and block in containers, so replace /dev/random.
test-integration: build-container
$(CONTAINER_RUN) bash -c 'rm -f /dev/random; ln -sf /dev/urandom /dev/random; SKOPEO_CONTAINER_TESTS=1 BUILDTAGS="$(BUILDTAGS)" hack/make.sh test-integration'
$(CONTAINER_RUN) bash -c 'rm -f /dev/random; ln -sf /dev/urandom /dev/random; SKOPEO_CONTAINER_TESTS=1 BUILDTAGS="$(BUILDTAGS)" $(MAKE) test-integration-local'
# Intended for CI, shortcut 'build-container' since already running inside container.
test-integration-local:
hack/make.sh test-integration
# complicated set of options needed to run podman-in-podman
test-system: build-container
@@ -162,24 +190,35 @@ test-system: build-container
$(CONTAINER_CMD) --privileged \
-v $$DTEMP:/var/lib/containers:Z -v /run/systemd/journal/socket:/run/systemd/journal/socket \
"$(IMAGE)" \
bash -c 'BUILDTAGS="$(BUILDTAGS)" hack/make.sh test-system'; \
bash -c 'BUILDTAGS="$(BUILDTAGS)" $(MAKE) test-system-local'; \
rc=$$?; \
$(RM) -rf $$DTEMP; \
exit $$rc
# Intended for CI, shortcut 'build-container' since already running inside container.
test-system-local:
hack/make.sh test-system
test-unit: build-container
# Just call (make test unit-local) here instead of worrying about environment differences
$(CONTAINER_RUN) make test-unit-local BUILDTAGS='$(BUILDTAGS)'
validate: build-container
$(CONTAINER_RUN) hack/make.sh validate-git-marks validate-gofmt validate-lint validate-vet
$(CONTAINER_RUN) make validate-local
# This target is only intended for development, e.g. executing it from an IDE. Use (make test) for CI or pre-release testing.
test-all-local: validate-local test-unit-local
test-all-local: validate-local validate-docs test-unit-local
.PHONY: validate-local
validate-local:
hack/make.sh validate-git-marks validate-gofmt validate-lint validate-vet
# This invokes bin/skopeo, hence cannot be run as part of validate-local
.PHONY: validate-docs
validate-docs:
hack/man-page-checker
hack/xref-helpmsgs-manpages
test-unit-local:
$(GPGME_ENV) $(GO) test $(MOD_VENDOR) -tags "$(BUILDTAGS)" $$($(GO) list $(MOD_VENDOR) -tags "$(BUILDTAGS)" -e ./... | grep -v '^github\.com/containers/skopeo/\(integration\|vendor/.*\)$$')
@@ -189,4 +228,4 @@ vendor:
$(GO) mod verify
vendor-in-container:
podman run --privileged --rm --env HOME=/root -v `pwd`:/src -w /src docker.io/library/golang:1.13 make vendor
podman run --privileged --rm --env HOME=/root -v `pwd`:/src -w /src docker.io/library/golang:1.16 make vendor

View File

@@ -19,6 +19,7 @@ Skopeo works with API V2 container image registries such as [docker.io](https://
For example you can copy images from one registry to another, without requiring privilege.
* Inspecting a remote image showing its properties including its layers, without requiring you to pull the image to the host.
* Deleting an image from an image repository.
* Syncing an external image repository to an internal registry for air-gapped deployments.
* When required by the repository, skopeo can pass the appropriate credentials and certificates for authentication.
Skopeo operates on the following image and repository types:
@@ -121,7 +122,7 @@ $ skopeo inspect --config docker://registry.fedoraproject.org/fedora:latest | j
]
}
```
#### Show unverifed image's digest
#### Show unverified image's digest
```console
$ skopeo inspect docker://registry.fedoraproject.org/fedora:latest | jq '.Digest'
"sha256:655721ff613ee766a4126cb5e0d5ae81598e1b0c3bcf7017c36c4d72cb092fe9"
@@ -136,7 +137,7 @@ $ skopeo inspect docker://registry.fedoraproject.org/fedora:latest | jq '.Digest
* Container Storage backends
- github.com/containers/storage (Backend for [Podman](https://podman.io), [CRI-O](https://cri-o.io), [Buildah](https://buildah.io) and friends)
- [github.com/containers/storage](https://github.com/containers/storage) (Backend for [Podman](https://podman.io), [CRI-O](https://cri-o.io), [Buildah](https://buildah.io) and friends)
- Docker daemon storage
@@ -154,17 +155,22 @@ $ skopeo copy oci:busybox_ocilayout:latest dir:existingemptydirectory
$ skopeo delete docker://localhost:5000/imagename:latest
```
## Syncing registries
```console
$ skopeo sync --src docker --dest dir registry.example.com/busybox /media/usb
```
## Authenticating to a registry
#### Private registries with authentication
skopeo uses credentials from the --creds (for skopeo inspect|delete) or --src-creds|--dest-creds (for skopeo copy) flags, if set; otherwise it uses configuration set by skopeo login, podman login, buildah login, or docker login.
```console
$ skopeo login --user USER docker://myregistrydomain.com:5000
$ skopeo login --username USER myregistrydomain.com:5000
Password:
$ skopeo inspect docker://myregistrydomain.com:5000/busybox
{"Tag":"latest","Digest":"sha256:473bb2189d7b913ed7187a33d11e743fdc2f88931122a44d91a301b64419f092","RepoTags":["latest"],"Comment":"","Created":"2016-01-15T18:06:41.282540103Z","ContainerConfig":{"Hostname":"aded96b43f48","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":["/bin/sh","-c","#(nop) CMD [\"sh\"]"],"Image":"9e77fef7a1c9f989988c06620dabc4020c607885b959a2cbd7c2283c91da3e33","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"DockerVersion":"1.8.3","Author":"","Config":{"Hostname":"aded96b43f48","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":["sh"],"Image":"9e77fef7a1c9f989988c06620dabc4020c607885b959a2cbd7c2283c91da3e33","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"Architecture":"amd64","Os":"linux"}
$ skopeo logout docker://myregistrydomain.com:5000
$ skopeo logout myregistrydomain.com:5000
```
#### Using --creds directly
@@ -189,6 +195,20 @@ Contributing
Please read the [contribution guide](CONTRIBUTING.md) if you want to collaborate in the project.
## Commands
| Command | Description |
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------|
| [skopeo-copy(1)](/docs/skopeo-copy.1.md) | Copy an image (manifest, filesystem layers, signatures) from one location to another. |
| [skopeo-delete(1)](/docs/skopeo-delete.1.md) | Mark the image-name for later deletion by the registry's garbage collector. |
| [skopeo-inspect(1)](/docs/skopeo-inspect.1.md) | Return low-level information about image-name in a registry. |
| [skopeo-list-tags(1)](/docs/skopeo-list-tags.1.md) | Return a list of tags for the transport-specific image repository. |
| [skopeo-login(1)](/docs/skopeo-login.1.md) | Login to a container registry. |
| [skopeo-logout(1)](/docs/skopeo-logout.1.md) | Logout of a container registry. |
| [skopeo-manifest-digest(1)](/docs/skopeo-manifest-digest.1.md) | Compute a manifest digest for a manifest-file and write it to standard output. |
| [skopeo-standalone-sign(1)](/docs/skopeo-standalone-sign.1.md) | Debugging tool - Publish and sign an image in one step. |
| [skopeo-standalone-verify(1)](/docs/skopeo-standalone-verify.1.md)| Verify an image signature. |
| [skopeo-sync(1)](/docs/skopeo-sync.1.md) | Synchronize images between container registries and local directories. |
License
-
skopeo is licensed under the Apache License, Version 2.0. See

View File

@@ -1,3 +1,3 @@
## Security and Disclosure Information Policy for the skopeo Project
The skopeo Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects.
The skopeo Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects.

View File

@@ -4,42 +4,49 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"strings"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/transports/alltransports"
"github.com/spf13/cobra"
encconfig "github.com/containers/ocicrypt/config"
enchelpers "github.com/containers/ocicrypt/helpers"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
)
type copyOptions struct {
global *globalOptions
srcImage *imageOptions
destImage *imageDestOptions
additionalTags []string // For docker-archive: destinations, in addition to the name:tag specified as destination, also add these
removeSignatures bool // Do not copy signatures from the source image
signByFingerprint string // Sign the image using a GPG key with the specified fingerprint
format optionalString // Force conversion of the image to a specified format
quiet bool // Suppress output information when copying images
all bool // Copy all of the images if the source is a list
encryptLayer []int // The list of layers to encrypt
encryptionKeys []string // Keys needed to encrypt the image
decryptionKeys []string // Keys needed to decrypt the image
global *globalOptions
deprecatedTLSVerify *deprecatedTLSVerifyOption
srcImage *imageOptions
destImage *imageDestOptions
retryOpts *retry.RetryOptions
additionalTags []string // For docker-archive: destinations, in addition to the name:tag specified as destination, also add these
removeSignatures bool // Do not copy signatures from the source image
signByFingerprint string // Sign the image using a GPG key with the specified fingerprint
digestFile string // Write digest to this file
format optionalString // Force conversion of the image to a specified format
quiet bool // Suppress output information when copying images
all bool // Copy all of the images if the source is a list
encryptLayer []int // The list of layers to encrypt
encryptionKeys []string // Keys needed to encrypt the image
decryptionKeys []string // Keys needed to decrypt the image
}
func copyCmd(global *globalOptions) *cobra.Command {
sharedFlags, sharedOpts := sharedImageFlags()
srcFlags, srcOpts := imageFlags(global, sharedOpts, "src-", "screds")
destFlags, destOpts := imageDestFlags(global, sharedOpts, "dest-", "dcreds")
deprecatedTLSVerifyFlags, deprecatedTLSVerifyOpt := deprecatedTLSVerifyFlags()
srcFlags, srcOpts := imageFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "src-", "screds")
destFlags, destOpts := imageDestFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "dest-", "dcreds")
retryFlags, retryOpts := retryFlags()
opts := copyOptions{global: global,
srcImage: srcOpts,
destImage: destOpts,
deprecatedTLSVerify: deprecatedTLSVerifyOpt,
srcImage: srcOpts,
destImage: destOpts,
retryOpts: retryOpts,
}
cmd := &cobra.Command{
Use: "copy [command options] SOURCE-IMAGE DESTINATION-IMAGE",
@@ -52,19 +59,22 @@ Supported transports:
See skopeo(1) section "IMAGE NAMES" for the expected format
`, strings.Join(transports.ListNames(), ", ")),
RunE: commandAction(opts.run),
Example: `skopeo copy --sign-by dev@example.com container-storage:example/busybox:streaming docker://example/busybox:gold`,
Example: `skopeo copy docker://quay.io/skopeo/stable:latest docker://registry.example.com/skopeo:latest`,
}
adjustUsage(cmd)
flags := cmd.Flags()
flags.AddFlagSet(&sharedFlags)
flags.AddFlagSet(&deprecatedTLSVerifyFlags)
flags.AddFlagSet(&srcFlags)
flags.AddFlagSet(&destFlags)
flags.AddFlagSet(&retryFlags)
flags.StringSliceVar(&opts.additionalTags, "additional-tag", []string{}, "additional tags (supports docker-archive)")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress output information when copying images")
flags.BoolVarP(&opts.all, "all", "a", false, "Copy all images if SOURCE-IMAGE is a list")
flags.BoolVar(&opts.removeSignatures, "remove-signatures", false, "Do not copy signatures from SOURCE-IMAGE")
flags.StringVar(&opts.signByFingerprint, "sign-by", "", "Sign the image using a GPG key with the specified `FINGERPRINT`")
flags.VarP(newOptionalStringValue(&opts.format), "format", "f", `MANIFEST TYPE (oci, v2s1, or v2s2) to use when saving image to directory using the 'dir:' transport (default is manifest type of source)`)
flags.StringVar(&opts.digestFile, "digestfile", "", "Write the digest of the pushed image to the specified file")
flags.VarP(newOptionalStringValue(&opts.format), "format", "f", `MANIFEST TYPE (oci, v2s1, or v2s2) to use in the destination (default is manifest type of source, with fallbacks)`)
flags.StringSliceVar(&opts.encryptionKeys, "encryption-key", []string{}, "*Experimental* key with the encryption protocol to use needed to encrypt the image (e.g. jwe:/path/to/key.pem)")
flags.IntSliceVar(&opts.encryptLayer, "encrypt-layer", []int{}, "*Experimental* the 0-indexed layer indices, with support for negative indexing (e.g. 0 is the first layer, -1 is the last layer)")
flags.StringSliceVar(&opts.decryptionKeys, "decryption-key", []string{}, "*Experimental* key needed to decrypt the image")
@@ -75,6 +85,7 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error {
if len(args) != 2 {
return errorShouldDisplayUsage{errors.New("Exactly two arguments expected")}
}
opts.deprecatedTLSVerify.warnIfUsed([]string{"--src-tls-verify", "--dest-tls-verify"})
imageNames := args
if err := reexecIfNecessaryForImages(imageNames...); err != nil {
@@ -107,15 +118,9 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error {
var manifestType string
if opts.format.present {
switch opts.format.value {
case "oci":
manifestType = imgspecv1.MediaTypeImageManifest
case "v2s1":
manifestType = manifest.DockerV2Schema1SignedMediaType
case "v2s2":
manifestType = manifest.DockerV2Schema2MediaType
default:
return fmt.Errorf("unknown format %q. Choose one of the supported formats: 'oci', 'v2s1', or 'v2s2'", opts.format.value)
manifestType, err = parseManifestFormat(opts.format.value)
if err != nil {
return err
}
}
@@ -178,17 +183,31 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error {
decConfig = cc.DecryptConfig
}
_, err = copy.Image(ctx, policyContext, destRef, srcRef, &copy.Options{
RemoveSignatures: opts.removeSignatures,
SignBy: opts.signByFingerprint,
ReportWriter: stdout,
SourceCtx: sourceCtx,
DestinationCtx: destinationCtx,
ForceManifestMIMEType: manifestType,
ImageListSelection: imageListSelection,
OciDecryptConfig: decConfig,
OciEncryptLayers: encLayers,
OciEncryptConfig: encConfig,
})
return err
return retry.RetryIfNecessary(ctx, func() error {
manifestBytes, err := copy.Image(ctx, policyContext, destRef, srcRef, &copy.Options{
RemoveSignatures: opts.removeSignatures,
SignBy: opts.signByFingerprint,
ReportWriter: stdout,
SourceCtx: sourceCtx,
DestinationCtx: destinationCtx,
ForceManifestMIMEType: manifestType,
ImageListSelection: imageListSelection,
OciDecryptConfig: decConfig,
OciEncryptLayers: encLayers,
OciEncryptConfig: encConfig,
})
if err != nil {
return err
}
if opts.digestFile != "" {
manifestDigest, err := manifest.Digest(manifestBytes)
if err != nil {
return err
}
if err = ioutil.WriteFile(opts.digestFile, []byte(manifestDigest.String()), 0644); err != nil {
return fmt.Errorf("Failed to write digest to file %q: %w", opts.digestFile, err)
}
}
return nil
}, opts.retryOpts)
}

View File

@@ -6,22 +6,26 @@ import (
"io"
"strings"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/transports/alltransports"
"github.com/spf13/cobra"
)
type deleteOptions struct {
global *globalOptions
image *imageOptions
global *globalOptions
image *imageOptions
retryOpts *retry.RetryOptions
}
func deleteCmd(global *globalOptions) *cobra.Command {
sharedFlags, sharedOpts := sharedImageFlags()
imageFlags, imageOpts := imageFlags(global, sharedOpts, "", "")
imageFlags, imageOpts := imageFlags(global, sharedOpts, nil, "", "")
retryFlags, retryOpts := retryFlags()
opts := deleteOptions{
global: global,
image: imageOpts,
global: global,
image: imageOpts,
retryOpts: retryOpts,
}
cmd := &cobra.Command{
Use: "delete [command options] IMAGE-NAME",
@@ -38,6 +42,7 @@ See skopeo(1) section "IMAGE NAMES" for the expected format
flags := cmd.Flags()
flags.AddFlagSet(&sharedFlags)
flags.AddFlagSet(&imageFlags)
flags.AddFlagSet(&retryFlags)
return cmd
}
@@ -63,5 +68,8 @@ func (opts *deleteOptions) run(args []string, stdout io.Writer) error {
ctx, cancel := opts.global.commandTimeoutContext()
defer cancel()
return ref.DeleteImage(ctx, sys)
return retry.RetryIfNecessary(ctx, func() error {
return ref.DeleteImage(ctx, sys)
}, opts.retryOpts)
}

View File

@@ -4,47 +4,42 @@ import (
"encoding/json"
"fmt"
"io"
"os"
"strings"
"time"
"text/tabwriter"
"text/template"
"github.com/containers/common/pkg/report"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/image"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports"
digest "github.com/opencontainers/go-digest"
"github.com/containers/image/v5/types"
"github.com/containers/skopeo/cmd/skopeo/inspect"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// inspectOutput is the output format of (skopeo inspect), primarily so that we can format it with a simple json.MarshalIndent.
type inspectOutput struct {
Name string `json:",omitempty"`
Tag string `json:",omitempty"`
Digest digest.Digest
RepoTags []string
Created *time.Time
DockerVersion string
Labels map[string]string
Architecture string
Os string
Layers []string
Env []string
}
type inspectOptions struct {
global *globalOptions
image *imageOptions
raw bool // Output the raw manifest instead of parsing information about the image
config bool // Output the raw config blob instead of parsing information about the image
global *globalOptions
image *imageOptions
retryOpts *retry.RetryOptions
format string
raw bool // Output the raw manifest instead of parsing information about the image
config bool // Output the raw config blob instead of parsing information about the image
}
func inspectCmd(global *globalOptions) *cobra.Command {
sharedFlags, sharedOpts := sharedImageFlags()
imageFlags, imageOpts := imageFlags(global, sharedOpts, "", "")
imageFlags, imageOpts := imageFlags(global, sharedOpts, nil, "", "")
retryFlags, retryOpts := retryFlags()
opts := inspectOptions{
global: global,
image: imageOpts,
global: global,
image: imageOpts,
retryOpts: retryOpts,
}
cmd := &cobra.Command{
Use: "inspect [command options] IMAGE-NAME",
@@ -55,25 +50,38 @@ Supported transports:
See skopeo(1) section "IMAGE NAMES" for the expected format
`, strings.Join(transports.ListNames(), ", ")),
RunE: commandAction(opts.run),
Example: `skopeo inspect docker://docker.io/fedora`,
RunE: commandAction(opts.run),
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`,
}
adjustUsage(cmd)
flags := cmd.Flags()
flags.BoolVar(&opts.raw, "raw", false, "output raw manifest or configuration")
flags.BoolVar(&opts.config, "config", false, "output configuration")
flags.StringVarP(&opts.format, "format", "f", "", "Format the output to a Go template")
flags.AddFlagSet(&sharedFlags)
flags.AddFlagSet(&imageFlags)
flags.AddFlagSet(&retryFlags)
return cmd
}
func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error) {
var (
rawManifest []byte
src types.ImageSource
imgInspect *types.ImageInspectInfo
data []interface{}
)
ctx, cancel := opts.global.commandTimeoutContext()
defer cancel()
if len(args) != 1 {
return errors.New("Exactly one argument expected")
}
if opts.raw && opts.format != "" {
return errors.New("raw output does not support format option")
}
imageName := args[0]
if err := reexecIfNecessaryForImages(imageName); err != nil {
@@ -85,9 +93,11 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
return err
}
src, err := parseImageSource(ctx, opts.image, imageName)
if err != nil {
return fmt.Errorf("Error parsing image name %q: %v", imageName, err)
if err := retry.RetryIfNecessary(ctx, func() error {
src, err = parseImageSource(ctx, opts.image, imageName)
return err
}, opts.retryOpts); err != nil {
return errors.Wrapf(err, "Error parsing image name %q", imageName)
}
defer func() {
@@ -96,9 +106,11 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
}
}()
rawManifest, _, err := src.GetManifest(ctx, nil)
if err != nil {
return fmt.Errorf("Error retrieving manifest for image: %v", err)
if err := retry.RetryIfNecessary(ctx, func() error {
rawManifest, _, err = src.GetManifest(ctx, nil)
return err
}, opts.retryOpts); err != nil {
return errors.Wrapf(err, "Error retrieving manifest for image")
}
if opts.raw && !opts.config {
@@ -106,45 +118,65 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
if err != nil {
return fmt.Errorf("Error writing manifest to standard output: %v", err)
}
return nil
}
img, err := image.FromUnparsedImage(ctx, sys, image.UnparsedInstance(src, nil))
if err != nil {
return fmt.Errorf("Error parsing manifest for image: %v", err)
return errors.Wrapf(err, "Error parsing manifest for image")
}
if opts.config && opts.raw {
configBlob, err := img.ConfigBlob(ctx)
if err != nil {
return fmt.Errorf("Error reading configuration blob: %v", err)
var configBlob []byte
if err := retry.RetryIfNecessary(ctx, func() error {
configBlob, err = img.ConfigBlob(ctx)
return err
}, opts.retryOpts); err != nil {
return errors.Wrapf(err, "Error reading configuration blob")
}
_, err = stdout.Write(configBlob)
if err != nil {
return fmt.Errorf("Error writing configuration blob to standard output: %v", err)
return errors.Wrapf(err, "Error writing configuration blob to standard output")
}
return nil
} else if opts.config {
config, err := img.OCIConfig(ctx)
if err != nil {
return fmt.Errorf("Error reading OCI-formatted configuration data: %v", err)
var config *v1.Image
if err := retry.RetryIfNecessary(ctx, func() error {
config, err = img.OCIConfig(ctx)
return err
}, opts.retryOpts); err != nil {
return errors.Wrapf(err, "Error reading OCI-formatted configuration data")
}
if report.IsJSON(opts.format) || opts.format == "" {
var out []byte
out, err = json.MarshalIndent(config, "", " ")
if err == nil {
fmt.Fprintf(stdout, "%s\n", string(out))
}
} else {
row := "{{range . }}" + report.NormalizeFormat(opts.format) + "{{end}}"
data = append(data, config)
err = printTmpl(row, data)
}
err = json.NewEncoder(stdout).Encode(config)
if err != nil {
return fmt.Errorf("Error writing OCI-formatted configuration data to standard output: %v", err)
return errors.Wrapf(err, "Error writing OCI-formatted configuration data to standard output")
}
return nil
}
imgInspect, err := img.Inspect(ctx)
if err != nil {
if err := retry.RetryIfNecessary(ctx, func() error {
imgInspect, err = img.Inspect(ctx)
return err
}, opts.retryOpts); err != nil {
return err
}
outputData := inspectOutput{
outputData := inspect.Output{
Name: "", // Set below if DockerReference() is known
Tag: imgInspect.Tag,
// Digest is set below.
RepoTags: []string{}, // Possibly overriden for docker.Transport.
RepoTags: []string{}, // Possibly overridden for docker.Transport.
Created: imgInspect.Created,
DockerVersion: imgInspect.DockerVersion,
Labels: imgInspect.Labels,
@@ -155,7 +187,7 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
}
outputData.Digest, err = manifest.Digest(rawManifest)
if err != nil {
return fmt.Errorf("Error computing manifest digest: %v", err)
return errors.Wrapf(err, "Error computing manifest digest")
}
if dockerRef := img.Reference().DockerReference(); dockerRef != nil {
outputData.Name = dockerRef.Name()
@@ -173,15 +205,28 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
// In addition, AWS ECR rejects it with 403 (Forbidden) if the "ecr:ListImages"
// action is not allowed.
if !strings.Contains(err.Error(), "401") && !strings.Contains(err.Error(), "403") {
return fmt.Errorf("Error determining repository tags: %v", err)
return errors.Wrapf(err, "Error determining repository tags")
}
logrus.Warnf("Registry disallows tag list retrieval; skipping")
}
}
out, err := json.MarshalIndent(outputData, "", " ")
if report.IsJSON(opts.format) || opts.format == "" {
out, err := json.MarshalIndent(outputData, "", " ")
if err == nil {
fmt.Fprintf(stdout, "%s\n", string(out))
}
return err
}
row := "{{range . }}" + report.NormalizeFormat(opts.format) + "{{end}}"
data = append(data, outputData)
return printTmpl(row, data)
}
func printTmpl(row string, data []interface{}) error {
t, err := template.New("skopeo inspect").Parse(row)
if err != nil {
return err
}
fmt.Fprintf(stdout, "%s\n", string(out))
return nil
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
return t.Execute(w, data)
}

View File

@@ -0,0 +1,23 @@
package inspect
import (
"time"
digest "github.com/opencontainers/go-digest"
)
// Output is the output format of (skopeo inspect),
// primarily so that we can format it with a simple json.MarshalIndent.
type Output struct {
Name string `json:",omitempty"`
Tag string `json:",omitempty"`
Digest digest.Digest
RepoTags []string
Created *time.Time
DockerVersion string
Labels map[string]string
Architecture string
Os string
Layers []string
Env []string
}

View File

@@ -7,6 +7,7 @@ import (
"os"
"strings"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/directory"
"github.com/containers/image/v5/image"
"github.com/containers/image/v5/pkg/blobinfocache"
@@ -17,16 +18,19 @@ import (
)
type layersOptions struct {
global *globalOptions
image *imageOptions
global *globalOptions
image *imageOptions
retryOpts *retry.RetryOptions
}
func layersCmd(global *globalOptions) *cobra.Command {
sharedFlags, sharedOpts := sharedImageFlags()
imageFlags, imageOpts := imageFlags(global, sharedOpts, "", "")
imageFlags, imageOpts := imageFlags(global, sharedOpts, nil, "", "")
retryFlags, retryOpts := retryFlags()
opts := layersOptions{
global: global,
image: imageOpts,
global: global,
image: imageOpts,
retryOpts: retryOpts,
}
cmd := &cobra.Command{
Hidden: true,
@@ -38,6 +42,7 @@ func layersCmd(global *globalOptions) *cobra.Command {
flags := cmd.Flags()
flags.AddFlagSet(&sharedFlags)
flags.AddFlagSet(&imageFlags)
flags.AddFlagSet(&retryFlags)
return cmd
}
@@ -60,12 +65,20 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) {
return err
}
cache := blobinfocache.DefaultCache(sys)
rawSource, err := parseImageSource(ctx, opts.image, imageName)
if err != nil {
var (
rawSource types.ImageSource
src types.ImageCloser
)
if err = retry.RetryIfNecessary(ctx, func() error {
rawSource, err = parseImageSource(ctx, opts.image, imageName)
return err
}, opts.retryOpts); err != nil {
return err
}
src, err := image.FromSource(ctx, sys, rawSource)
if err != nil {
if err = retry.RetryIfNecessary(ctx, func() error {
src, err = image.FromSource(ctx, sys, rawSource)
return err
}, opts.retryOpts); err != nil {
if closeErr := rawSource.Close(); closeErr != nil {
return errors.Wrapf(err, " (close error: %v)", closeErr)
}
@@ -129,8 +142,14 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) {
}()
for _, bd := range blobDigests {
r, blobSize, err := rawSource.GetBlob(ctx, types.BlobInfo{Digest: bd.digest, Size: -1}, cache)
if err != nil {
var (
r io.ReadCloser
blobSize int64
)
if err = retry.RetryIfNecessary(ctx, func() error {
r, blobSize, err = rawSource.GetBlob(ctx, types.BlobInfo{Digest: bd.digest, Size: -1}, cache)
return err
}, opts.retryOpts); err != nil {
return err
}
if _, err := dest.PutBlob(ctx, r, types.BlobInfo{Digest: bd.digest, Size: blobSize}, cache, bd.isConfig); err != nil {
@@ -141,8 +160,11 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) {
}
}
manifest, _, err := src.Manifest(ctx)
if err != nil {
var manifest []byte
if err = retry.RetryIfNecessary(ctx, func() error {
manifest, _, err = src.Manifest(ctx)
return err
}, opts.retryOpts); err != nil {
return err
}
if err := dest.PutManifest(ctx, manifest, nil); err != nil {

View File

@@ -7,6 +7,7 @@ import (
"io"
"strings"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/transports/alltransports"
@@ -22,17 +23,20 @@ type tagListOutput struct {
}
type tagsOptions struct {
global *globalOptions
image *imageOptions
global *globalOptions
image *imageOptions
retryOpts *retry.RetryOptions
}
func tagsCmd(global *globalOptions) *cobra.Command {
sharedFlags, sharedOpts := sharedImageFlags()
imageFlags, imageOpts := dockerImageFlags(global, sharedOpts, "", "")
imageFlags, imageOpts := dockerImageFlags(global, sharedOpts, nil, "", "")
retryFlags, retryOpts := retryFlags()
opts := tagsOptions{
global: global,
image: imageOpts,
global: global,
image: imageOpts,
retryOpts: retryOpts,
}
cmd := &cobra.Command{
Use: "list-tags [command options] REPOSITORY-NAME",
@@ -51,6 +55,7 @@ See skopeo-list-tags(1) section "REPOSITORY NAMES" for the expected format
flags := cmd.Flags()
flags.AddFlagSet(&sharedFlags)
flags.AddFlagSet(&imageFlags)
flags.AddFlagSet(&retryFlags)
return cmd
}
@@ -118,8 +123,12 @@ func (opts *tagsOptions) run(args []string, stdout io.Writer) (retErr error) {
return err
}
repositoryName, tagListing, err := listDockerTags(ctx, sys, imgRef)
if err != nil {
var repositoryName string
var tagListing []string
if err = retry.RetryIfNecessary(ctx, func() error {
repositoryName, tagListing, err = listDockerTags(ctx, sys, imgRef)
return err
}, opts.retryOpts); err != nil {
return err
}

View File

@@ -5,6 +5,7 @@ import (
"github.com/containers/image/v5/transports/alltransports"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Tests the kinds of inputs allowed and expected to the command
@@ -17,10 +18,10 @@ func TestDockerRepositoryReferenceParser(t *testing.T) {
} {
ref, err := parseDockerRepositoryReference(test[0])
require.NoError(t, err)
expected, err := alltransports.ParseImageName(test[0])
if assert.NoError(t, err, "Could not parse, got error on %v", test[0]) {
assert.Equal(t, expected.DockerReference().Name(), ref.DockerReference().Name(), "Mismatched parse result for input %v", test[0])
}
require.NoError(t, err)
assert.Equal(t, expected.DockerReference().Name(), ref.DockerReference().Name(), "Mismatched parse result for input %v", test[0])
}
for _, test := range [][]string{

View File

@@ -12,7 +12,6 @@ import (
type loginOptions struct {
global *globalOptions
loginOpts auth.LoginOptions
getLogin optionalBool
tlsVerify optionalBool
}
@@ -21,7 +20,7 @@ func loginCmd(global *globalOptions) *cobra.Command {
global: global,
}
cmd := &cobra.Command{
Use: "login",
Use: "login [command options] REGISTRY",
Short: "Login to a container registry",
Long: "Login to a container registry on a specified server.",
RunE: commandAction(opts.run),
@@ -39,6 +38,7 @@ func (opts *loginOptions) run(args []string, stdout io.Writer) error {
defer cancel()
opts.loginOpts.Stdout = stdout
opts.loginOpts.Stdin = os.Stdin
opts.loginOpts.AcceptRepositories = true
sys := opts.global.newSystemContext()
if opts.tlsVerify.present {
sys.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.value)

View File

@@ -4,12 +4,14 @@ import (
"io"
"github.com/containers/common/pkg/auth"
"github.com/containers/image/v5/types"
"github.com/spf13/cobra"
)
type logoutOptions struct {
global *globalOptions
logoutOpts auth.LogoutOptions
tlsVerify optionalBool
}
func logoutCmd(global *globalOptions) *cobra.Command {
@@ -17,19 +19,25 @@ func logoutCmd(global *globalOptions) *cobra.Command {
global: global,
}
cmd := &cobra.Command{
Use: "logout",
Use: "logout [command options] REGISTRY",
Short: "Logout of a container registry",
Long: "Logout of a container registry on a specified server.",
RunE: commandAction(opts.run),
Example: `skopeo logout quay.io`,
}
adjustUsage(cmd)
cmd.Flags().AddFlagSet(auth.GetLogoutFlags(&opts.logoutOpts))
flags := cmd.Flags()
optionalBoolFlag(flags, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the registry")
flags.AddFlagSet(auth.GetLogoutFlags(&opts.logoutOpts))
return cmd
}
func (opts *logoutOptions) run(args []string, stdout io.Writer) error {
opts.logoutOpts.Stdout = stdout
opts.logoutOpts.AcceptRepositories = true
sys := opts.global.newSystemContext()
if opts.tlsVerify.present {
sys.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.tlsVerify.value)
}
return auth.Logout(sys, &opts.logoutOpts, args)
}

View File

@@ -17,6 +17,8 @@ import (
// and will be populated by the Makefile
var gitCommit = ""
var defaultUserAgent = "skopeo/" + version.Version
type globalOptions struct {
debug bool // Enable debug output
tlsVerify optionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:)
@@ -43,6 +45,17 @@ func createApp() (*cobra.Command, *globalOptions) {
},
SilenceUsage: true,
SilenceErrors: true,
// Currently, skopeo uses manually written completions. Cobra allows
// for auto-generating completions for various shells. Podman is
// already making us of that. If Skopeo decides to follow, please
// remove the line below (and hide the `completion` command).
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
// This is documented to parse "local" (non-PersistentFlags) flags of parent commands before
// running subcommands and handling their options. We don't really run into such cases,
// because all of our flags on rootCommand are in PersistentFlags, except for the deprecated --tls-verify;
// in that case we need TraverseChildren so that we can distinguish between
// (skopeo --tls-verify inspect) (causes a warning) and (skopeo inspect --tls-verify) (no warning).
TraverseChildren: true,
}
if gitCommit != "" {
rootCommand.Version = fmt.Sprintf("%s commit: %s", version.Version, gitCommit)
@@ -53,8 +66,6 @@ func createApp() (*cobra.Command, *globalOptions) {
var dummyVersion bool
rootCommand.Flags().BoolVarP(&dummyVersion, "version", "v", false, "Version for Skopeo")
rootCommand.PersistentFlags().BoolVar(&opts.debug, "debug", false, "enable debug output")
flag := optionalBoolFlag(rootCommand.PersistentFlags(), &opts.tlsVerify, "tls-verify", "Require HTTPS and verify certificates when accessing the registry")
flag.Hidden = true
rootCommand.PersistentFlags().StringVar(&opts.policyPath, "policy", "", "Path to a trust policy file")
rootCommand.PersistentFlags().BoolVar(&opts.insecurePolicy, "insecure-policy", false, "run the tool without any policy check")
rootCommand.PersistentFlags().StringVar(&opts.registriesDirPath, "registries.d", "", "use registry configuration files in `DIR` (e.g. for container signature storage)")
@@ -67,6 +78,8 @@ func createApp() (*cobra.Command, *globalOptions) {
logrus.Fatal("unable to mark registries-conf flag as hidden")
}
rootCommand.PersistentFlags().StringVar(&opts.tmpDir, "tmpdir", "", "directory used to store temporary files")
flag := optionalBoolFlag(rootCommand.Flags(), &opts.tlsVerify, "tls-verify", "Require HTTPS and verify certificates when accessing the registry")
flag.Hidden = true
rootCommand.AddCommand(
copyCmd(&opts),
deleteCmd(&opts),
@@ -143,6 +156,7 @@ func (opts *globalOptions) newSystemContext() *types.SystemContext {
VariantChoice: opts.overrideVariant,
SystemRegistriesConfPath: opts.registriesConfPath,
BigFilesTemporaryDir: opts.tmpDir,
DockerRegistryUserAgent: defaultUserAgent,
}
// DEPRECATED: We support this for backward compatibility, but override it if a per-image flag is provided.
if opts.tlsVerify.present {

View File

@@ -23,7 +23,10 @@ func TestGlobalOptionsNewSystemContext(t *testing.T) {
// Default state
opts, _ := fakeGlobalOptions(t, []string{})
res := opts.newSystemContext()
assert.Equal(t, &types.SystemContext{}, res)
assert.Equal(t, &types.SystemContext{
// User-Agent is set by default.
DockerRegistryUserAgent: defaultUserAgent,
}, res)
// Set everything to non-default values.
opts, _ = fakeGlobalOptions(t, []string{
"--registries.d", "/srv/registries.d",
@@ -43,5 +46,6 @@ func TestGlobalOptionsNewSystemContext(t *testing.T) {
BigFilesTemporaryDir: "/srv",
SystemRegistriesConfPath: "/srv/registries.conf",
DockerInsecureSkipTLSVerify: types.OptionalBoolTrue,
DockerRegistryUserAgent: defaultUserAgent,
}, res)
}

View File

@@ -16,7 +16,7 @@ type manifestDigestOptions struct {
func manifestDigestCmd() *cobra.Command {
var opts manifestDigestOptions
cmd := &cobra.Command{
Use: "manifest-digest MANIFEST",
Use: "manifest-digest MANIFEST-FILE",
Short: "Compute a manifest digest of a file",
RunE: commandAction(opts.run),
Example: "skopeo manifest-digest manifest.json",

View File

@@ -17,8 +17,8 @@ func TestManifestDigest(t *testing.T) {
}
// Error reading manifest
out, err := runSkopeo("manifest-digest", "/this/doesnt/exist")
assertTestFailed(t, out, err, "/this/doesnt/exist")
out, err := runSkopeo("manifest-digest", "/this/does/not/exist")
assertTestFailed(t, out, err, "/this/does/not/exist")
// Error computing manifest
out, err = runSkopeo("manifest-digest", "fixtures/v2s1-invalid-signatures.manifest.json")

View File

@@ -18,7 +18,7 @@ type standaloneSignOptions struct {
func standaloneSignCmd() *cobra.Command {
opts := standaloneSignOptions{}
cmd := &cobra.Command{
Use: "standalone-sign [command options] MANIFEST DOCKER-REFERENCE KEY-FINGERPRINT",
Use: "standalone-sign [command options] MANIFEST DOCKER-REFERENCE KEY-FINGERPRINT --output|-o SIGNATURE",
Short: "Create a signature using local files",
RunE: commandAction(opts.run),
}

View File

@@ -58,8 +58,8 @@ func TestStandaloneSign(t *testing.T) {
// Error reading manifest
out, err := runSkopeo("standalone-sign", "-o", "/dev/null",
"/this/doesnt/exist", dockerReference, fixturesTestKeyFingerprint)
assertTestFailed(t, out, err, "/this/doesnt/exist")
"/this/does/not/exist", dockerReference, fixturesTestKeyFingerprint)
assertTestFailed(t, out, err, "/this/does/not/exist")
// Invalid Docker reference
out, err = runSkopeo("standalone-sign", "-o", "/dev/null",
@@ -117,14 +117,14 @@ func TestStandaloneVerify(t *testing.T) {
}
// Error reading manifest
out, err := runSkopeo("standalone-verify", "/this/doesnt/exist",
out, err := runSkopeo("standalone-verify", "/this/does/not/exist",
dockerReference, fixturesTestKeyFingerprint, signaturePath)
assertTestFailed(t, out, err, "/this/doesnt/exist")
assertTestFailed(t, out, err, "/this/does/not/exist")
// Error reading signature
out, err = runSkopeo("standalone-verify", manifestPath,
dockerReference, fixturesTestKeyFingerprint, "/this/doesnt/exist")
assertTestFailed(t, out, err, "/this/doesnt/exist")
dockerReference, fixturesTestKeyFingerprint, "/this/does/not/exist")
assertTestFailed(t, out, err, "/this/does/not/exist")
// Error verifying signature
out, err = runSkopeo("standalone-verify", manifestPath,
@@ -151,8 +151,8 @@ func TestUntrustedSignatureDump(t *testing.T) {
// Error reading manifest
out, err := runSkopeo("untrusted-signature-dump-without-verification",
"/this/doesnt/exist")
assertTestFailed(t, out, err, "/this/doesnt/exist")
"/this/does/not/exist")
assertTestFailed(t, out, err, "/this/does/not/exist")
// Error reading signature (input is not a signature)
out, err = runSkopeo("untrusted-signature-dump-without-verification", "fixtures/image.manifest.json")

View File

@@ -11,12 +11,14 @@ import (
"regexp"
"strings"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/copy"
"github.com/containers/image/v5/directory"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -25,24 +27,28 @@ import (
// syncOptions contains information retrieved from the skopeo sync command line.
type syncOptions struct {
global *globalOptions // Global (not command dependant) skopeo options
srcImage *imageOptions // Source image options
destImage *imageDestOptions // Destination image options
removeSignatures bool // Do not copy signatures from the source image
signByFingerprint string // Sign the image using a GPG key with the specified fingerprint
source string // Source repository name
destination string // Destination registry name
scoped bool // When true, namespace copied images at destination using the source repository name
global *globalOptions // Global (not command dependent) skopeo options
deprecatedTLSVerify *deprecatedTLSVerifyOption
srcImage *imageOptions // Source image options
destImage *imageDestOptions // Destination image options
retryOpts *retry.RetryOptions
removeSignatures bool // Do not copy signatures from the source image
signByFingerprint string // Sign the image using a GPG key with the specified fingerprint
format optionalString // Force conversion of the image to a specified format
source string // Source repository name
destination string // Destination registry name
scoped bool // When true, namespace copied images at destination using the source repository name
all bool // Copy all of the images if an image in the source is a list
}
// repoDescriptor contains information of a single repository used as a sync source.
type repoDescriptor struct {
DirBasePath string // base path when source is 'dir'
TaggedImages []types.ImageReference // List of tagged image found for the repository
Context *types.SystemContext // SystemContext for the sync command
DirBasePath string // base path when source is 'dir'
ImageRefs []types.ImageReference // List of tagged image found for the repository
Context *types.SystemContext // SystemContext for the sync command
}
// tlsVerify is an implementation of the Unmarshaler interface, used to
// tlsVerifyConfig is an implementation of the Unmarshaler interface, used to
// customize the unmarshaling behaviour of the tls-verify YAML key.
type tlsVerifyConfig struct {
skip types.OptionalBool // skip TLS verification check (false by default)
@@ -51,7 +57,7 @@ type tlsVerifyConfig struct {
// registrySyncConfig contains information about a single registry, read from
// the source YAML file
type registrySyncConfig struct {
Images map[string][]string // Images map images name to slices with the images' tags
Images map[string][]string // Images map images name to slices with the images' references (tags, digests)
ImagesByTagRegex map[string]string `yaml:"images-by-tag-regex"` // Images map images name to regular expression with the images' tags
Credentials types.DockerAuthConfig // Username and password used to authenticate with the registry
TLSVerify tlsVerifyConfig `yaml:"tls-verify"` // TLS verification mode (enabled by default)
@@ -63,25 +69,29 @@ type sourceConfig map[string]registrySyncConfig
func syncCmd(global *globalOptions) *cobra.Command {
sharedFlags, sharedOpts := sharedImageFlags()
srcFlags, srcOpts := dockerImageFlags(global, sharedOpts, "src-", "screds")
destFlags, destOpts := dockerImageFlags(global, sharedOpts, "dest-", "dcreds")
deprecatedTLSVerifyFlags, deprecatedTLSVerifyOpt := deprecatedTLSVerifyFlags()
srcFlags, srcOpts := dockerImageFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "src-", "screds")
destFlags, destOpts := dockerImageFlags(global, sharedOpts, deprecatedTLSVerifyOpt, "dest-", "dcreds")
retryFlags, retryOpts := retryFlags()
opts := syncOptions{
global: global,
srcImage: srcOpts,
destImage: &imageDestOptions{imageOptions: destOpts},
global: global,
deprecatedTLSVerify: deprecatedTLSVerifyOpt,
srcImage: srcOpts,
destImage: &imageDestOptions{imageOptions: destOpts},
retryOpts: retryOpts,
}
cmd := &cobra.Command{
Use: "sync [command options] --src SOURCE-LOCATION --dest DESTINATION-LOCATION SOURCE DESTINATION",
Use: "sync [command options] --src TRANSPORT --dest TRANSPORT SOURCE DESTINATION",
Short: "Synchronize one or more images from one location to another",
Long: fmt.Sprint(`Copy all the images from a SOURCE to a DESTINATION.
Long: `Copy all the images from a SOURCE to a DESTINATION.
Allowed SOURCE transports (specified with --src): docker, dir, yaml.
Allowed DESTINATION transports (specified with --dest): docker, dir.
See skopeo-sync(1) for details.
`),
`,
RunE: commandAction(opts.run),
Example: `skopeo sync --src docker --dest dir --scoped registry.example.com/busybox /media/usb`,
}
@@ -89,16 +99,20 @@ See skopeo-sync(1) for details.
flags := cmd.Flags()
flags.BoolVar(&opts.removeSignatures, "remove-signatures", false, "Do not copy signatures from SOURCE images")
flags.StringVar(&opts.signByFingerprint, "sign-by", "", "Sign the image using a GPG key with the specified `FINGERPRINT`")
flags.VarP(newOptionalStringValue(&opts.format), "format", "f", `MANIFEST TYPE (oci, v2s1, or v2s2) to use when syncing image(s) to a destination (default is manifest type of source, with fallbacks)`)
flags.StringVarP(&opts.source, "src", "s", "", "SOURCE transport type")
flags.StringVarP(&opts.destination, "dest", "d", "", "DESTINATION transport type")
flags.BoolVar(&opts.scoped, "scoped", false, "Images at DESTINATION are prefix using the full source image path as scope")
flags.BoolVarP(&opts.all, "all", "a", false, "Copy all images if SOURCE-IMAGE is a list")
flags.AddFlagSet(&sharedFlags)
flags.AddFlagSet(&deprecatedTLSVerifyFlags)
flags.AddFlagSet(&srcFlags)
flags.AddFlagSet(&destFlags)
flags.AddFlagSet(&retryFlags)
return cmd
}
// unmarshalYAML is the implementation of the Unmarshaler interface method
// UnmarshalYAML is the implementation of the Unmarshaler interface method
// method for the tlsVerifyConfig type.
// It unmarshals the 'tls-verify' YAML key so that, when they key is not
// specified, tls verification is enforced.
@@ -197,7 +211,6 @@ func getImageTags(ctx context.Context, sysCtx *types.SystemContext, repoRef refe
// Some registries may decide to block the "list all tags" endpoint.
// Gracefully allow the sync to continue in this case.
logrus.Warnf("Registry disallows tag list retrieval: %s", err)
break
default:
return tags, errors.Wrapf(err, "Error determining repository tags for image %s", name)
}
@@ -230,7 +243,7 @@ func imagesToCopyFromRepo(sys *types.SystemContext, repoRef reference.Named) ([]
return sourceReferences, nil
}
// imagesTopCopyFromDir builds a list of image references from the images found
// imagesToCopyFromDir builds a list of image references from the images found
// in the source directory.
// It returns an image reference slice with as many elements as the images found
// and any error encountered.
@@ -260,11 +273,11 @@ func imagesToCopyFromDir(dirPath string) ([]types.ImageReference, error) {
return sourceReferences, nil
}
// imagesTopCopyFromDir builds a list of repository descriptors from the images
// imagesToCopyFromRegistry builds a list of repository descriptors from the images
// in a registry configuration.
// It returns a repository descriptors slice with as many elements as the images
// found and any error encountered. Each element of the slice is a list of
// tagged image references, to be used as sync source.
// image references, to be used as sync source.
func imagesToCopyFromRegistry(registryName string, cfg registrySyncConfig, sourceCtx types.SystemContext) ([]repoDescriptor, error) {
serverCtx := &sourceCtx
// override ctx with per-registryName options
@@ -272,10 +285,11 @@ func imagesToCopyFromRegistry(registryName string, cfg registrySyncConfig, sourc
serverCtx.DockerDaemonCertPath = cfg.CertDir
serverCtx.DockerDaemonInsecureSkipTLSVerify = (cfg.TLSVerify.skip == types.OptionalBoolTrue)
serverCtx.DockerInsecureSkipTLSVerify = cfg.TLSVerify.skip
serverCtx.DockerAuthConfig = &cfg.Credentials
if cfg.Credentials != (types.DockerAuthConfig{}) {
serverCtx.DockerAuthConfig = &cfg.Credentials
}
var repoDescList []repoDescriptor
for imageName, tags := range cfg.Images {
for imageName, refs := range cfg.Images {
repoLogger := logrus.WithFields(logrus.Fields{
"repo": imageName,
"registry": registryName,
@@ -290,24 +304,37 @@ func imagesToCopyFromRegistry(registryName string, cfg registrySyncConfig, sourc
repoLogger.Info("Processing repo")
var sourceReferences []types.ImageReference
if len(tags) != 0 {
for _, tag := range tags {
tagLogger := logrus.WithFields(logrus.Fields{"tag": tag})
taggedRef, err := reference.WithTag(repoRef, tag)
if err != nil {
tagLogger.Error("Error parsing tag, skipping")
logrus.Error(err)
continue
if len(refs) != 0 {
for _, ref := range refs {
tagLogger := logrus.WithFields(logrus.Fields{"ref": ref})
var named reference.Named
// first try as digest
if d, err := digest.Parse(ref); err == nil {
named, err = reference.WithDigest(repoRef, d)
if err != nil {
tagLogger.Error("Error processing ref, skipping")
logrus.Error(err)
continue
}
} else {
tagLogger.Debugf("Ref was not a digest, trying as a tag: %s", err)
named, err = reference.WithTag(repoRef, ref)
if err != nil {
tagLogger.Error("Error parsing ref, skipping")
logrus.Error(err)
continue
}
}
imageRef, err := docker.NewReference(taggedRef)
imageRef, err := docker.NewReference(named)
if err != nil {
tagLogger.Error("Error processing tag, skipping")
tagLogger.Error("Error processing ref, skipping")
logrus.Errorf("Error getting image reference: %s", err)
continue
}
sourceReferences = append(sourceReferences, imageRef)
}
} else { // len(tags) == 0
} else { // len(refs) == 0
repoLogger.Info("Querying registry for image tags")
sourceReferences, err = imagesToCopyFromRepo(serverCtx, repoRef)
if err != nil {
@@ -318,12 +345,12 @@ func imagesToCopyFromRegistry(registryName string, cfg registrySyncConfig, sourc
}
if len(sourceReferences) == 0 {
repoLogger.Warnf("No tags to sync found")
repoLogger.Warnf("No refs to sync found")
continue
}
repoDescList = append(repoDescList, repoDescriptor{
TaggedImages: sourceReferences,
Context: serverCtx})
ImageRefs: sourceReferences,
Context: serverCtx})
}
for imageName, tagRegex := range cfg.ImagesByTagRegex {
@@ -372,12 +399,12 @@ func imagesToCopyFromRegistry(registryName string, cfg registrySyncConfig, sourc
}
if len(sourceReferences) == 0 {
repoLogger.Warnf("No tags to sync found")
repoLogger.Warnf("No refs to sync found")
continue
}
repoDescList = append(repoDescList, repoDescriptor{
TaggedImages: sourceReferences,
Context: serverCtx})
ImageRefs: sourceReferences,
Context: serverCtx})
}
return repoDescList, nil
@@ -410,13 +437,13 @@ func imagesToCopy(source string, transport string, sourceCtx *types.SystemContex
if err != nil {
return nil, errors.Wrapf(err, "Cannot obtain a valid image reference for transport %q and reference %q", docker.Transport.Name(), named.String())
}
desc.TaggedImages = []types.ImageReference{srcRef}
desc.ImageRefs = []types.ImageReference{srcRef}
} else {
desc.TaggedImages, err = imagesToCopyFromRepo(sourceCtx, named)
desc.ImageRefs, err = imagesToCopyFromRepo(sourceCtx, named)
if err != nil {
return descriptors, err
}
if len(desc.TaggedImages) == 0 {
if len(desc.ImageRefs) == 0 {
return descriptors, errors.Errorf("No images to sync found in %q", source)
}
}
@@ -432,11 +459,11 @@ func imagesToCopy(source string, transport string, sourceCtx *types.SystemContex
}
desc.DirBasePath = source
var err error
desc.TaggedImages, err = imagesToCopyFromDir(source)
desc.ImageRefs, err = imagesToCopyFromDir(source)
if err != nil {
return descriptors, err
}
if len(desc.TaggedImages) == 0 {
if len(desc.ImageRefs) == 0 {
return descriptors, errors.Errorf("No images to sync found in %q", source)
}
descriptors = append(descriptors, desc)
@@ -469,6 +496,7 @@ func (opts *syncOptions) run(args []string, stdout io.Writer) error {
if len(args) != 2 {
return errorShouldDisplayUsage{errors.New("Exactly two arguments expected")}
}
opts.deprecatedTLSVerify.warnIfUsed([]string{"--src-tls-verify", "--dest-tls-verify"})
policyContext, err := opts.global.getPolicyContext()
if err != nil {
@@ -504,14 +532,33 @@ func (opts *syncOptions) run(args []string, stdout io.Writer) error {
return errors.New("sync from 'dir' to 'dir' not implemented, consider using rsync instead")
}
imageListSelection := copy.CopySystemImage
if opts.all {
imageListSelection = copy.CopyAllImages
}
sourceCtx, err := opts.srcImage.newSystemContext()
if err != nil {
return err
}
var manifestType string
if opts.format.present {
manifestType, err = parseManifestFormat(opts.format.value)
if err != nil {
return err
}
}
ctx, cancel := opts.global.commandTimeoutContext()
defer cancel()
sourceArg := args[0]
srcRepoList, err := imagesToCopy(sourceArg, opts.source, sourceCtx)
if err != nil {
var srcRepoList []repoDescriptor
if err = retry.RetryIfNecessary(ctx, func() error {
srcRepoList, err = imagesToCopy(sourceArg, opts.source, sourceCtx)
return err
}, opts.retryOpts); err != nil {
return err
}
@@ -521,20 +568,20 @@ func (opts *syncOptions) run(args []string, stdout io.Writer) error {
return err
}
ctx, cancel := opts.global.commandTimeoutContext()
defer cancel()
imagesNumber := 0
options := copy.Options{
RemoveSignatures: opts.removeSignatures,
SignBy: opts.signByFingerprint,
ReportWriter: os.Stdout,
DestinationCtx: destinationCtx,
RemoveSignatures: opts.removeSignatures,
SignBy: opts.signByFingerprint,
ReportWriter: os.Stdout,
DestinationCtx: destinationCtx,
ImageListSelection: imageListSelection,
OptimizeDestinationImageAlreadyExists: true,
ForceManifestMIMEType: manifestType,
}
for _, srcRepo := range srcRepoList {
options.SourceCtx = srcRepo.Context
for counter, ref := range srcRepo.TaggedImages {
for counter, ref := range srcRepo.ImageRefs {
var destSuffix string
switch ref.Transport() {
case docker.Transport:
@@ -561,11 +608,13 @@ func (opts *syncOptions) run(args []string, stdout io.Writer) error {
logrus.WithFields(logrus.Fields{
"from": transports.ImageName(ref),
"to": transports.ImageName(destRef),
}).Infof("Copying image tag %d/%d", counter+1, len(srcRepo.TaggedImages))
}).Infof("Copying image ref %d/%d", counter+1, len(srcRepo.ImageRefs))
_, err = copy.Image(ctx, policyContext, destRef, ref, &options)
if err != nil {
return errors.Wrapf(err, "Error copying tag %q", transports.ImageName(ref))
if err = retry.RetryIfNecessary(ctx, func() error {
_, err = copy.Image(ctx, policyContext, destRef, ref, &options)
return err
}, opts.retryOpts); err != nil {
return errors.Wrapf(err, "Error copying ref %q", transports.ImageName(ref))
}
imagesNumber++
}

View File

@@ -2,10 +2,6 @@
package main
func maybeReexec() error {
return nil
}
func reexecIfNecessaryForImages(inputImageNames ...string) error {
return nil
}

View File

@@ -2,14 +2,19 @@ package main
import (
"context"
"fmt"
"io"
"os"
"strings"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/compression"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@@ -34,6 +39,35 @@ func commandAction(handler func(args []string, stdout io.Writer) error) func(cmd
}
}
// deprecatedTLSVerifyOption represents a deprecated --tls-verify option,
// which was accepted for all subcommands, for a time.
// Every user should call deprecatedTLSVerifyOption.warnIfUsed() as part of handling the CLI,
// whether or not the value actually ends up being used.
// DO NOT ADD ANY NEW USES OF THIS; just call dockerImageFlags with an appropriate, possibly empty, flagPrefix.
type deprecatedTLSVerifyOption struct {
tlsVerify optionalBool // FIXME FIXME: Warn if this is used, or even if it is ignored.
}
// warnIfUsed warns if tlsVerify was set by the user, and suggests alternatives (which should
// start with "--").
// Every user should call this as part of handling the CLI, whether or not the value actually
// ends up being used.
func (opts *deprecatedTLSVerifyOption) warnIfUsed(alternatives []string) {
if opts.tlsVerify.present {
logrus.Warnf("'--tls-verify' is deprecated, instead use: %s", strings.Join(alternatives, ", "))
}
}
// deprecatedTLSVerifyFlags prepares the CLI flag writing into deprecatedTLSVerifyOption, and the managed deprecatedTLSVerifyOption structure.
// DO NOT ADD ANY NEW USES OF THIS; just call dockerImageFlags with an appropriate, possibly empty, flagPrefix.
func deprecatedTLSVerifyFlags() (pflag.FlagSet, *deprecatedTLSVerifyOption) {
opts := deprecatedTLSVerifyOption{}
fs := pflag.FlagSet{}
flag := optionalBoolFlag(&fs, &opts.tlsVerify, "tls-verify", "require HTTPS and verify certificates when accessing the container registry (defaults to true)")
flag.Hidden = true
return fs, &opts
}
// sharedImageOptions collects CLI flags which are image-related, but do not change across images.
// This really should be a part of globalOptions, but that would break existing users of (skopeo copy --authfile=).
type sharedImageOptions struct {
@@ -52,13 +86,15 @@ func sharedImageFlags() (pflag.FlagSet, *sharedImageOptions) {
// the same across subcommands, but may be different for each image
// (e.g. may differ between the source and destination of a copy)
type dockerImageOptions struct {
global *globalOptions // May be shared across several imageOptions instances.
shared *sharedImageOptions // May be shared across several imageOptions instances.
authFilePath optionalString // Path to a */containers/auth.json (prefixed version to override shared image option).
credsOption optionalString // username[:password] for accessing a registry
dockerCertPath string // A directory using Docker-like *.{crt,cert,key} files for connecting to a registry or a daemon
tlsVerify optionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:)
noCreds bool // Access the registry anonymously
global *globalOptions // May be shared across several imageOptions instances.
shared *sharedImageOptions // May be shared across several imageOptions instances.
deprecatedTLSVerify *deprecatedTLSVerifyOption // May be shared across several imageOptions instances, or nil.
authFilePath optionalString // Path to a */containers/auth.json (prefixed version to override shared image option).
credsOption optionalString // username[:password] for accessing a registry
registryToken optionalString // token to be used directly as a Bearer token when accessing the registry
dockerCertPath string // A directory using Docker-like *.{crt,cert,key} files for connecting to a registry or a daemon
tlsVerify optionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:)
noCreds bool // Access the registry anonymously
}
// imageOptions collects CLI flags which are the same across subcommands, but may be different for each image
@@ -71,11 +107,12 @@ type imageOptions struct {
// dockerImageFlags prepares a collection of docker-transport specific CLI flags
// writing into imageOptions, and the managed imageOptions structure.
func dockerImageFlags(global *globalOptions, shared *sharedImageOptions, flagPrefix, credsOptionAlias string) (pflag.FlagSet, *imageOptions) {
func dockerImageFlags(global *globalOptions, shared *sharedImageOptions, deprecatedTLSVerify *deprecatedTLSVerifyOption, flagPrefix, credsOptionAlias string) (pflag.FlagSet, *imageOptions) {
flags := imageOptions{
dockerImageOptions: dockerImageOptions{
global: global,
shared: shared,
global: global,
shared: shared,
deprecatedTLSVerify: deprecatedTLSVerify,
},
}
@@ -91,6 +128,7 @@ func dockerImageFlags(global *globalOptions, shared *sharedImageOptions, flagPre
f := fs.VarPF(newOptionalStringValue(&flags.credsOption), credsOptionAlias, "", "Use `USERNAME[:PASSWORD]` for accessing the registry")
f.Hidden = true
}
fs.Var(newOptionalStringValue(&flags.registryToken), flagPrefix+"registry-token", "Provide a Bearer token for accessing the registry")
fs.StringVar(&flags.dockerCertPath, flagPrefix+"cert-dir", "", "use certificates at `PATH` (*.crt, *.cert, *.key) to connect to the registry or daemon")
optionalBoolFlag(&fs, &flags.tlsVerify, flagPrefix+"tls-verify", "require HTTPS and verify certificates when talking to the container registry or daemon (defaults to true)")
fs.BoolVar(&flags.noCreds, flagPrefix+"no-creds", false, "Access the registry anonymously")
@@ -98,8 +136,8 @@ func dockerImageFlags(global *globalOptions, shared *sharedImageOptions, flagPre
}
// imageFlags prepares a collection of CLI flags writing into imageOptions, and the managed imageOptions structure.
func imageFlags(global *globalOptions, shared *sharedImageOptions, flagPrefix, credsOptionAlias string) (pflag.FlagSet, *imageOptions) {
dockerFlags, opts := dockerImageFlags(global, shared, flagPrefix, credsOptionAlias)
func imageFlags(global *globalOptions, shared *sharedImageOptions, deprecatedTLSVerify *deprecatedTLSVerifyOption, flagPrefix, credsOptionAlias string) (pflag.FlagSet, *imageOptions) {
dockerFlags, opts := dockerImageFlags(global, shared, deprecatedTLSVerify, flagPrefix, credsOptionAlias)
fs := pflag.FlagSet{}
fs.StringVar(&opts.sharedBlobDir, flagPrefix+"shared-blob-dir", "", "`DIRECTORY` to use to share blobs across OCI repositories")
@@ -108,6 +146,13 @@ func imageFlags(global *globalOptions, shared *sharedImageOptions, flagPrefix, c
return fs, opts
}
func retryFlags() (pflag.FlagSet, *retry.RetryOptions) {
opts := retry.RetryOptions{}
fs := pflag.FlagSet{}
fs.IntVar(&opts.MaxRetry, "retry-times", 0, "the number of times to possibly retry")
return fs, &opts
}
// newSystemContext returns a *types.SystemContext corresponding to opts.
// It is guaranteed to return a fresh instance, so it is safe to make additional updates to it.
func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) {
@@ -122,6 +167,10 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) {
if opts.dockerImageOptions.authFilePath.present {
ctx.AuthFilePath = opts.dockerImageOptions.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.
ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!opts.deprecatedTLSVerify.tlsVerify.value)
}
if opts.tlsVerify.present {
ctx.DockerDaemonInsecureSkipTLSVerify = !opts.tlsVerify.value
}
@@ -138,6 +187,9 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) {
return nil, err
}
}
if opts.registryToken.present {
ctx.DockerBearerRegistryToken = opts.registryToken.value
}
if opts.noCreds {
ctx.DockerAuthConfig = &types.DockerAuthConfig{}
}
@@ -145,22 +197,24 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) {
return ctx, nil
}
// imageDestOptions is a superset of imageOptions specialized for iamge destinations.
// imageDestOptions is a superset of imageOptions specialized for image destinations.
type imageDestOptions struct {
*imageOptions
dirForceCompression bool // Compress layers when saving to the dir: transport
dirForceDecompression bool // Decompress layers when saving to the dir: transport
ociAcceptUncompressedLayers bool // Whether to accept uncompressed layers in the oci: transport
compressionFormat string // Format to use for the compression
compressionLevel optionalInt // Level to use for the compression
}
// imageDestFlags prepares a collection of CLI flags writing into imageDestOptions, and the managed imageDestOptions structure.
func imageDestFlags(global *globalOptions, shared *sharedImageOptions, flagPrefix, credsOptionAlias string) (pflag.FlagSet, *imageDestOptions) {
genericFlags, genericOptions := imageFlags(global, shared, flagPrefix, credsOptionAlias)
func imageDestFlags(global *globalOptions, shared *sharedImageOptions, deprecatedTLSVerify *deprecatedTLSVerifyOption, flagPrefix, credsOptionAlias string) (pflag.FlagSet, *imageDestOptions) {
genericFlags, genericOptions := imageFlags(global, shared, deprecatedTLSVerify, flagPrefix, credsOptionAlias)
opts := imageDestOptions{imageOptions: genericOptions}
fs := pflag.FlagSet{}
fs.AddFlagSet(&genericFlags)
fs.BoolVar(&opts.dirForceCompression, flagPrefix+"compress", false, "Compress tarball image layers when saving to directory using the 'dir' transport. (default is same compression type as source)")
fs.BoolVar(&opts.dirForceDecompression, flagPrefix+"decompress", false, "Decompress tarball image layers when saving to directory using the 'dir' transport. (default is same compression type as source)")
fs.BoolVar(&opts.ociAcceptUncompressedLayers, flagPrefix+"oci-accept-uncompressed-layers", false, "Allow uncompressed image layers when saving to an OCI image using the 'oci' transport. (default is to compress things that aren't compressed)")
fs.StringVar(&opts.compressionFormat, flagPrefix+"compress-format", "", "`FORMAT` to use for the compression")
fs.Var(newOptionalIntValue(&opts.compressionLevel), flagPrefix+"compress-level", "`LEVEL` to use for the compression")
@@ -176,6 +230,7 @@ func (opts *imageDestOptions) newSystemContext() (*types.SystemContext, error) {
}
ctx.DirForceCompress = opts.dirForceCompression
ctx.DirForceDecompress = opts.dirForceDecompression
ctx.OCIAcceptUncompressedLayers = opts.ociAcceptUncompressedLayers
if opts.compressionFormat != "" {
cf, err := compression.AlgorithmByName(opts.compressionFormat)
@@ -229,6 +284,21 @@ func parseImageSource(ctx context.Context, opts *imageOptions, name string) (typ
return ref.NewImageSource(ctx, sys)
}
// parseManifestFormat parses format parameter for copy and sync command.
// It returns string value to use as manifest MIME type
func parseManifestFormat(manifestFormat string) (string, error) {
switch manifestFormat {
case "oci":
return imgspecv1.MediaTypeImageManifest, nil
case "v2s1":
return manifest.DockerV2Schema1SignedMediaType, nil
case "v2s2":
return manifest.DockerV2Schema2MediaType, nil
default:
return "", fmt.Errorf("unknown format %q. Choose one of the supported formats: 'oci', 'v2s1', or 'v2s2'", manifestFormat)
}
}
// usageTemplate returns the usage template for skopeo commands
// This blocks the displaying of the global options. The main skopeo
// command should not use this.

View File

@@ -4,8 +4,11 @@ import (
"os"
"testing"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -15,17 +18,26 @@ func fakeGlobalOptions(t *testing.T, flags []string) (*globalOptions, *cobra.Com
app, opts := createApp()
cmd := &cobra.Command{}
app.AddCommand(cmd)
err := cmd.ParseFlags(flags)
err := app.ParseFlags(flags)
require.NoError(t, err)
return opts, cmd
}
// fakeImageOptions creates imageOptions and sets it according to globalFlags/cmdFlags.
func fakeImageOptions(t *testing.T, flagPrefix string, globalFlags []string, cmdFlags []string) *imageOptions {
func fakeImageOptions(t *testing.T, flagPrefix string, useDeprecatedTLSVerify bool,
globalFlags []string, cmdFlags []string) *imageOptions {
globalOpts, cmd := fakeGlobalOptions(t, globalFlags)
sharedFlags, sharedOpts := sharedImageFlags()
imageFlags, imageOpts := imageFlags(globalOpts, sharedOpts, flagPrefix, "")
var deprecatedTLSVerifyFlag pflag.FlagSet
var deprecatedTLSVerifyOpt *deprecatedTLSVerifyOption
if useDeprecatedTLSVerify {
deprecatedTLSVerifyFlag, deprecatedTLSVerifyOpt = deprecatedTLSVerifyFlags()
}
imageFlags, imageOpts := imageFlags(globalOpts, sharedOpts, deprecatedTLSVerifyOpt, flagPrefix, "")
cmd.Flags().AddFlagSet(&sharedFlags)
if useDeprecatedTLSVerify {
cmd.Flags().AddFlagSet(&deprecatedTLSVerifyFlag)
}
cmd.Flags().AddFlagSet(&imageFlags)
err := cmd.ParseFlags(cmdFlags)
require.NoError(t, err)
@@ -34,13 +46,15 @@ func fakeImageOptions(t *testing.T, flagPrefix string, globalFlags []string, cmd
func TestImageOptionsNewSystemContext(t *testing.T) {
// Default state
opts := fakeImageOptions(t, "dest-", []string{}, []string{})
opts := fakeImageOptions(t, "dest-", true, []string{}, []string{})
res, err := opts.newSystemContext()
require.NoError(t, err)
assert.Equal(t, &types.SystemContext{}, res)
assert.Equal(t, &types.SystemContext{
DockerRegistryUserAgent: defaultUserAgent,
}, res)
// Set everything to non-default values.
opts = fakeImageOptions(t, "dest-", []string{
opts = fakeImageOptions(t, "dest-", true, []string{
"--registries.d", "/srv/registries.d",
"--override-arch", "overridden-arch",
"--override-os", "overridden-os",
@@ -54,6 +68,7 @@ func TestImageOptionsNewSystemContext(t *testing.T) {
"--dest-daemon-host", "daemon-host.example.com",
"--dest-tls-verify=false",
"--dest-creds", "creds-user:creds-password",
"--dest-registry-token", "faketoken",
})
res, err = opts.newSystemContext()
require.NoError(t, err)
@@ -67,55 +82,37 @@ func TestImageOptionsNewSystemContext(t *testing.T) {
DockerCertPath: "/srv/cert-dir",
DockerInsecureSkipTLSVerify: types.OptionalBoolTrue,
DockerAuthConfig: &types.DockerAuthConfig{Username: "creds-user", Password: "creds-password"},
DockerBearerRegistryToken: "faketoken",
DockerDaemonCertPath: "/srv/cert-dir",
DockerDaemonHost: "daemon-host.example.com",
DockerDaemonInsecureSkipTLSVerify: true,
DockerRegistryUserAgent: defaultUserAgent,
BigFilesTemporaryDir: "/srv",
}, res)
// Global/per-command tlsVerify behavior
for _, c := range []struct {
global, cmd string
expectedDocker types.OptionalBool
expectedDockerDaemon bool
}{
{"", "", types.OptionalBoolUndefined, false},
{"", "false", types.OptionalBoolTrue, true},
{"", "true", types.OptionalBoolFalse, false},
{"false", "", types.OptionalBoolTrue, false},
{"false", "false", types.OptionalBoolTrue, true},
{"false", "true", types.OptionalBoolFalse, false},
{"true", "", types.OptionalBoolFalse, false},
{"true", "false", types.OptionalBoolTrue, true},
{"true", "true", types.OptionalBoolFalse, false},
} {
globalFlags := []string{}
if c.global != "" {
globalFlags = append(globalFlags, "--tls-verify="+c.global)
}
cmdFlags := []string{}
if c.cmd != "" {
cmdFlags = append(cmdFlags, "--dest-tls-verify="+c.cmd)
}
opts := fakeImageOptions(t, "dest-", globalFlags, cmdFlags)
res, err = opts.newSystemContext()
require.NoError(t, err)
assert.Equal(t, c.expectedDocker, res.DockerInsecureSkipTLSVerify, "%#v", c)
assert.Equal(t, c.expectedDockerDaemon, res.DockerDaemonInsecureSkipTLSVerify, "%#v", c)
}
// Global/per-command tlsVerify behavior is tested in TestTLSVerifyFlags.
// Invalid option values
opts = fakeImageOptions(t, "dest-", []string{}, []string{"--dest-creds", ""})
opts = fakeImageOptions(t, "dest-", true, []string{}, []string{"--dest-creds", ""})
_, err = opts.newSystemContext()
assert.Error(t, err)
}
// fakeImageDestOptions creates imageDestOptions and sets it according to globalFlags/cmdFlags.
func fakeImageDestOptions(t *testing.T, flagPrefix string, globalFlags []string, cmdFlags []string) *imageDestOptions {
func fakeImageDestOptions(t *testing.T, flagPrefix string, useDeprecatedTLSVerify bool,
globalFlags []string, cmdFlags []string) *imageDestOptions {
globalOpts, cmd := fakeGlobalOptions(t, globalFlags)
sharedFlags, sharedOpts := sharedImageFlags()
imageFlags, imageOpts := imageDestFlags(globalOpts, sharedOpts, flagPrefix, "")
var deprecatedTLSVerifyFlag pflag.FlagSet
var deprecatedTLSVerifyOpt *deprecatedTLSVerifyOption
if useDeprecatedTLSVerify {
deprecatedTLSVerifyFlag, deprecatedTLSVerifyOpt = deprecatedTLSVerifyFlags()
}
imageFlags, imageOpts := imageDestFlags(globalOpts, sharedOpts, deprecatedTLSVerifyOpt, flagPrefix, "")
cmd.Flags().AddFlagSet(&sharedFlags)
if useDeprecatedTLSVerify {
cmd.Flags().AddFlagSet(&deprecatedTLSVerifyFlag)
}
cmd.Flags().AddFlagSet(&imageFlags)
err := cmd.ParseFlags(cmdFlags)
require.NoError(t, err)
@@ -124,10 +121,12 @@ func fakeImageDestOptions(t *testing.T, flagPrefix string, globalFlags []string,
func TestImageDestOptionsNewSystemContext(t *testing.T) {
// Default state
opts := fakeImageDestOptions(t, "dest-", []string{}, []string{})
opts := fakeImageDestOptions(t, "dest-", true, []string{}, []string{})
res, err := opts.newSystemContext()
require.NoError(t, err)
assert.Equal(t, &types.SystemContext{}, res)
assert.Equal(t, &types.SystemContext{
DockerRegistryUserAgent: defaultUserAgent,
}, res)
oldXRD, hasXRD := os.LookupEnv("REGISTRY_AUTH_FILE")
defer func() {
@@ -142,15 +141,18 @@ func TestImageDestOptionsNewSystemContext(t *testing.T) {
os.Setenv("REGISTRY_AUTH_FILE", authFile)
// Explicitly set everything to default, except for when the default is “not present”
opts = fakeImageDestOptions(t, "dest-", []string{}, []string{
opts = fakeImageDestOptions(t, "dest-", true, []string{}, []string{
"--dest-compress=false",
})
res, err = opts.newSystemContext()
require.NoError(t, err)
assert.Equal(t, &types.SystemContext{AuthFilePath: authFile}, res)
assert.Equal(t, &types.SystemContext{
AuthFilePath: authFile,
DockerRegistryUserAgent: defaultUserAgent,
}, res)
// Set everything to non-default values.
opts = fakeImageDestOptions(t, "dest-", []string{
opts = fakeImageDestOptions(t, "dest-", true, []string{
"--registries.d", "/srv/registries.d",
"--override-arch", "overridden-arch",
"--override-os", "overridden-os",
@@ -164,6 +166,7 @@ func TestImageDestOptionsNewSystemContext(t *testing.T) {
"--dest-daemon-host", "daemon-host.example.com",
"--dest-tls-verify=false",
"--dest-creds", "creds-user:creds-password",
"--dest-registry-token", "faketoken",
})
res, err = opts.newSystemContext()
require.NoError(t, err)
@@ -177,19 +180,145 @@ func TestImageDestOptionsNewSystemContext(t *testing.T) {
DockerCertPath: "/srv/cert-dir",
DockerInsecureSkipTLSVerify: types.OptionalBoolTrue,
DockerAuthConfig: &types.DockerAuthConfig{Username: "creds-user", Password: "creds-password"},
DockerBearerRegistryToken: "faketoken",
DockerDaemonCertPath: "/srv/cert-dir",
DockerDaemonHost: "daemon-host.example.com",
DockerDaemonInsecureSkipTLSVerify: true,
DockerRegistryUserAgent: defaultUserAgent,
DirForceCompress: true,
BigFilesTemporaryDir: "/srv",
}, res)
// Global/per-command tlsVerify behavior is tested in TestTLSVerifyFlags.
// Invalid option values in imageOptions
opts = fakeImageDestOptions(t, "dest-", []string{}, []string{"--dest-creds", ""})
opts = fakeImageDestOptions(t, "dest-", true, []string{}, []string{"--dest-creds", ""})
_, err = opts.newSystemContext()
assert.Error(t, err)
}
func TestTLSVerifyFlags(t *testing.T) {
type systemContextOpts interface { // Either *imageOptions or *imageDestOptions
newSystemContext() (*types.SystemContext, error)
}
for _, creator := range []struct {
name string
newOpts func(useDeprecatedTLSVerify bool, globalFlags, cmdFlags []string) systemContextOpts
}{
{
"imageFlags",
func(useDeprecatedTLSVerify bool, globalFlags, cmdFlags []string) systemContextOpts {
return fakeImageOptions(t, "dest-", useDeprecatedTLSVerify, globalFlags, cmdFlags)
},
},
{
"imageDestFlags",
func(useDeprecatedTLSVerify bool, globalFlags, cmdFlags []string) systemContextOpts {
return fakeImageDestOptions(t, "dest-", useDeprecatedTLSVerify, globalFlags, cmdFlags)
},
},
} {
t.Run(creator.name, func(t *testing.T) {
for _, c := range []struct {
global, deprecatedCmd, cmd string
expectedDocker types.OptionalBool
expectedDockerDaemon bool
}{
{"", "", "", types.OptionalBoolUndefined, false},
{"", "", "false", types.OptionalBoolTrue, true},
{"", "", "true", types.OptionalBoolFalse, false},
{"", "false", "", types.OptionalBoolTrue, false},
{"", "false", "false", types.OptionalBoolTrue, true},
{"", "false", "true", types.OptionalBoolFalse, false},
{"", "true", "", types.OptionalBoolFalse, false},
{"", "true", "false", types.OptionalBoolTrue, true},
{"", "true", "true", types.OptionalBoolFalse, false},
{"false", "", "", types.OptionalBoolTrue, false},
{"false", "", "false", types.OptionalBoolTrue, true},
{"false", "", "true", types.OptionalBoolFalse, false},
{"false", "false", "", types.OptionalBoolTrue, false},
{"false", "false", "false", types.OptionalBoolTrue, true},
{"false", "false", "true", types.OptionalBoolFalse, false},
{"false", "true", "", types.OptionalBoolFalse, false},
{"false", "true", "false", types.OptionalBoolTrue, true},
{"false", "true", "true", types.OptionalBoolFalse, false},
{"true", "", "", types.OptionalBoolFalse, false},
{"true", "", "false", types.OptionalBoolTrue, true},
{"true", "", "true", types.OptionalBoolFalse, false},
{"true", "false", "", types.OptionalBoolTrue, false},
{"true", "false", "false", types.OptionalBoolTrue, true},
{"true", "false", "true", types.OptionalBoolFalse, false},
{"true", "true", "", types.OptionalBoolFalse, false},
{"true", "true", "false", types.OptionalBoolTrue, true},
{"true", "true", "true", types.OptionalBoolFalse, false},
} {
globalFlags := []string{}
if c.global != "" {
globalFlags = append(globalFlags, "--tls-verify="+c.global)
}
cmdFlags := []string{}
if c.deprecatedCmd != "" {
cmdFlags = append(cmdFlags, "--tls-verify="+c.deprecatedCmd)
}
if c.cmd != "" {
cmdFlags = append(cmdFlags, "--dest-tls-verify="+c.cmd)
}
opts := creator.newOpts(true, globalFlags, cmdFlags)
res, err := opts.newSystemContext()
require.NoError(t, err)
assert.Equal(t, c.expectedDocker, res.DockerInsecureSkipTLSVerify, "%#v", c)
assert.Equal(t, c.expectedDockerDaemon, res.DockerDaemonInsecureSkipTLSVerify, "%#v", c)
if c.deprecatedCmd == "" { // Test also the behavior when deprecatedTLSFlag is not recognized
// Use globalFlags from the previous test
cmdFlags := []string{}
if c.cmd != "" {
cmdFlags = append(cmdFlags, "--dest-tls-verify="+c.cmd)
}
opts := creator.newOpts(false, globalFlags, cmdFlags)
res, err = opts.newSystemContext()
require.NoError(t, err)
assert.Equal(t, c.expectedDocker, res.DockerInsecureSkipTLSVerify, "%#v", c)
assert.Equal(t, c.expectedDockerDaemon, res.DockerDaemonInsecureSkipTLSVerify, "%#v", c)
}
}
})
}
}
func TestParseManifestFormat(t *testing.T) {
for _, testCase := range []struct {
formatParam string
expectedManifestType string
expectErr bool
}{
{"oci",
imgspecv1.MediaTypeImageManifest,
false},
{"v2s1",
manifest.DockerV2Schema1SignedMediaType,
false},
{"v2s2",
manifest.DockerV2Schema2MediaType,
false},
{"",
"",
true},
{"badValue",
"",
true},
} {
manifestType, err := parseManifestFormat(testCase.formatParam)
if testCase.expectErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
assert.Equal(t, manifestType, testCase.expectedManifestType)
}
}
// since there is a shared authfile image option and a non-shared (prefixed) one, make sure the override logic
// works correctly.
func TestImageOptionsAuthfileOverride(t *testing.T) {
@@ -224,12 +353,13 @@ func TestImageOptionsAuthfileOverride(t *testing.T) {
}, "/srv/dest-authfile",
},
} {
opts := fakeImageOptions(t, testCase.flagPrefix, []string{}, testCase.cmdFlags)
opts := fakeImageOptions(t, testCase.flagPrefix, false, []string{}, testCase.cmdFlags)
res, err := opts.newSystemContext()
require.NoError(t, err)
assert.Equal(t, &types.SystemContext{
AuthFilePath: testCase.expectedAuthfilePath,
AuthFilePath: testCase.expectedAuthfilePath,
DockerRegistryUserAgent: defaultUserAgent,
}, res)
}
}

View File

@@ -49,11 +49,14 @@ _skopeo_copy() {
--dest-tls-verify
--src-daemon-host
--dest-daemon-host
--src-registry-token
--dest-registry-token
"
local boolean_options="
--all
--dest-compress
--dest-decompress
--remove-signatures
--src-no-creds
--dest-no-creds
@@ -68,11 +71,50 @@ _skopeo_copy() {
_complete_ "$options_with_args" "$boolean_options" "$transports"
}
_skopeo_sync() {
local options_with_args="
--authfile
--dest
--dest-authfile
--dest-cert-
--dest-creds
--dest-registry-token string
--format
--retry-times
--sign-by
--src
--src-authfile
--src-cert-dir
--src-creds
--src-registry-token
"
local boolean_options="
--all
--dest-no-creds
--dest-tls-verify
--remove-signatures
--scoped
--src-no-creds
--src-tls-verify
"
local transports
transports="
$(_skopeo_supported_transports "${FUNCNAME//"_skopeo_"/}")
"
_complete_ "$options_with_args" "$boolean_options" "$transports"
}
_skopeo_inspect() {
local options_with_args="
--authfile
--creds
--cert-dir
--format
--retry-times
--registry-token
"
local boolean_options="
--config
@@ -119,6 +161,7 @@ _skopeo_delete() {
--authfile
--creds
--cert-dir
--registry-token
"
local boolean_options="
--tls-verify
@@ -135,11 +178,14 @@ _skopeo_delete() {
_skopeo_layers() {
local options_with_args="
--authfile
--creds
--cert-dir
--registry-token
"
local boolean_options="
--tls-verify
--no-creds
"
_complete_ "$options_with_args" "$boolean_options"
}
@@ -149,6 +195,7 @@ _skopeo_list_repository_tags() {
--authfile
--creds
--cert-dir
--registry-token
"
local boolean_options="
@@ -186,7 +233,7 @@ _skopeo_logout() {
}
_skopeo_skopeo() {
# XXX: Changes here need to be refleceted in the manually expanded
# XXX: Changes here need to be reflected in the manually expanded
# string in the `case` statement below as well.
local options_with_args="
--policy
@@ -220,7 +267,7 @@ _skopeo_skopeo() {
)
case "$prev" in
# XXX: Changes here need to be refleceted in $options_with_args as well.
# XXX: Changes here need to be reflected in $options_with_args as well.
--policy|--registries.d|--override-arch|--override-os|--override-variant|--command-timeout)
return
;;
@@ -250,7 +297,7 @@ _cli_bash_autocomplete() {
local counter=1
while [ $counter -lt "$cword" ]; do
case "${words[$counter]}" in
skopeo|copy|inspect|delete|manifest-digest|standalone-sign|standalone-verify|help|h|list-repository-tags)
skopeo|copy|sync|inspect|delete|manifest-digest|standalone-sign|standalone-verify|help|h|list-repository-tags)
command="${words[$counter]//-/_}"
cpos=$counter
(( cpos++ ))

95
contrib/cirrus/runner.sh Executable file
View File

@@ -0,0 +1,95 @@
#!/bin/bash
# This script is intended to be executed by automation or humans
# under a hack/get_ci_vm.sh context. Use under any other circumstances
# is unlikely to function.
set -e
if [[ -r "/etc/automation_environment" ]]; then
source /etc/automation_environment
source $AUTOMATION_LIB_PATH/common_lib.sh
else
(
echo "WARNING: It does not appear that containers/automation was installed."
echo " Functionality of most of ${BASH_SOURCE[0]} will be negatively"
echo " impacted."
) > /dev/stderr
fi
OS_RELEASE_ID="$(source /etc/os-release; echo $ID)"
# GCE image-name compatible string representation of distribution _major_ version
OS_RELEASE_VER="$(source /etc/os-release; echo $VERSION_ID | tr -d '.')"
# Combined to ease some usage
OS_REL_VER="${OS_RELEASE_ID}-${OS_RELEASE_VER}"
export "PATH=$PATH:$GOPATH/bin"
podmanmake() {
req_env_vars GOPATH SKOPEO_PATH SKOPEO_CI_CONTAINER_FQIN
warn "Accumulated technical-debt requires execution inside a --privileged container. This is very likely hiding bugs!"
showrun podman run -it --rm --privileged \
-e GOPATH=$GOPATH \
-v $GOPATH:$GOPATH:Z \
-w $SKOPEO_PATH \
$SKOPEO_CI_CONTAINER_FQIN \
make "$@"
}
_run_setup() {
if [[ "$OS_RELEASE_ID" == "fedora" ]]; then
# This is required as part of the standard Fedora VM setup
growpart /dev/sda 1
resize2fs /dev/sda1
# VM's come with the distro. skopeo pre-installed
dnf erase -y skopeo
else
die "Unknown/unsupported distro. $OS_REL_VER"
fi
}
_run_vendor() {
podmanmake vendor BUILDTAGS="$BUILDTAGS"
}
_run_build() {
make bin/skopeo BUILDTAGS="$BUILDTAGS"
}
_run_cross() {
podmanmake local-cross BUILDTAGS="$BUILDTAGS"
}
_run_doccheck() {
make validate-docs BUILDTAGS="$BUILDTAGS"
}
_run_unit() {
podmanmake test-unit-local BUILDTAGS="$BUILDTAGS"
}
_run_integration() {
podmanmake test-integration-local BUILDTAGS="$BUILDTAGS"
}
_run_system() {
# Ensure we start with a clean-slate
podman system reset --force
# Executes with containers required for testing.
showrun make test-system-local BUILDTAGS="$BUILDTAGS"
}
req_env_vars SKOPEO_PATH BUILDTAGS
handler="_run_${1}"
if [ "$(type -t $handler)" != "function" ]; then
die "Unknown/Unsupported command-line argument '$1'"
fi
msg "************************************************************"
msg "Runner executing $1 on $OS_REL_VER"
msg "************************************************************"
cd "$SKOPEO_PATH"
$handler

View File

@@ -6,19 +6,39 @@
## Overview
This directory contains the Dockerfiles necessary to create the three skopeoimage container
images that are housed on quay.io under the skopeo account. All three repositories where
the images live are public and can be pulled without credentials. These container images
are secured and the resulting containers can run safely. The container images are built
using the latest Fedora and then Skopeo is installed into them:
This directory contains the Dockerfiles necessary to create the skopeoimage container
images that are housed on quay.io under the skopeo account. All repositories where
the images live are public and can be pulled without credentials. These container images are secured and the
resulting containers can run safely with privileges within the container.
The container images are built using the latest Fedora and then Skopeo is installed into them.
The PATH in the container images is set to the default PATH provided by Fedora. Also, the
ENTRYPOINT and the WORKDIR variables are not set within these container images, as such they
default to `/`.
The container images are:
* `quay.io/containers/skopeo:<version>` and `quay.io/skopeo/stable:<version>` -
These images are built when a new Skopeo version becomes available in
Fedora. These images are intended to be unchanging and stable, they will
never be updated by automation once they've been pushed. For build details,
please [see the configuration file](stable/Dockerfile).
* `quay.io/containers/skopeo:latest` and `quay.io/skopeo/stable:latest` -
Built daily using the same Dockerfile as above. The skopeo version
will remain the "latest" available in Fedora, however the image
contents may vary compared to the version-tagged images.
* `quay.io/skopeo/testing:latest` - This image is built daily, using the
latest version of Skopeo that was in the Fedora `updates-testing` repository.
The image is Built with [the testing Dockerfile](testing/Dockerfile).
* `quay.io/skopeo/upstream:latest` - This image is built daily using the latest
code found in this GitHub repository. Due to the image changing frequently,
it's not guaranteed to be stable or even executable. The image is built with
[the upstream Dockerfile](upstream/Dockerfile).
* quay.io/skopeo/stable - This image is built using the latest stable version of Skopeo in a Fedora based container. Built with skopeoimage/stable/Dockerfile.
* quay.io/skopeo/upstream - This image is built using the latest code found in this GitHub repository. When someone creates a commit and pushes it, the image is created. Due to that the image changes frequently and is not guaranteed to be stable. Built with skopeoimage/upstream/Dockerfile.
* quay.io/skopeo/testing - This image is built using the latest version of Skopeo that is or was in updates testing for Fedora. At times this may be the same as the stable image. This container image will primarily be used by the development teams for verification testing when a new package is created. Built with skopeoimage/testing/Dockerfile.
## Sample Usage
Although not required, it is suggested that [Podman](https://github.com/containers/libpod) be used with these container images.
Although not required, it is suggested that [Podman](https://github.com/containers/podman) be used with these container images.
```
# Get Help on Skopeo

View File

@@ -6,14 +6,14 @@
# This image can be used to create a secured container
# that runs safely with privileges within the container.
#
FROM registry.fedoraproject.org/fedora:32
FROM registry.fedoraproject.org/fedora:33
# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space. Also reinstall shadow-utils as without
# doing so, the setuid/setgid bits on newuidmap
# and newgidmap are lost in the Fedora images.
RUN useradd skopeo; yum -y update; yum -y reinstall shadow-utils; yum -y install skopeo fuse-overlayfs --exclude container-selinux; yum clean all; rm -rf /var/cache /var/log/dnf* /var/log/yum.*;
RUN useradd skopeo; yum -y update; yum -y reinstall shadow-utils; yum -y install skopeo fuse-overlayfs --exclude container-selinux; yum -y clean all; rm -rf /var/cache/dnf/* /var/log/dnf* /var/log/yum*
# Adjust storage.conf to enable Fuse storage.
RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
@@ -27,7 +27,7 @@ RUN echo skopeo:100000:65536 > /etc/subuid
RUN echo skopeo:100000:65536 > /etc/subgid
# Point to the Authorization file
ENV REGISTRY_AUTH_FILE=/auth.json
ENV REGISTRY_AUTH_FILE=/tmp/auth.json
# Set the entrypoint
ENTRYPOINT ["/usr/bin/skopeo"]

View File

@@ -7,14 +7,14 @@
# This image can be used to create a secured container
# that runs safely with privileges within the container.
#
FROM registry.fedoraproject.org/fedora:32
FROM registry.fedoraproject.org/fedora:33
# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space. Also reinstall shadow-utils as without
# doing so, the setuid/setgid bits on newuidmap
# and newgidmap are lost in the Fedora images.
RUN useradd skopeo; yum -y update; yum -y reinstall shadow-utils; yum -y install skopeo fuse-overlayfs --enablerepo updates-testing --exclude container-selinux; yum clean all; rm -rf /var/cache /var/log/dnf* /var/log/yum.*;
RUN useradd skopeo; yum -y update; yum -y reinstall shadow-utils; yum -y install skopeo fuse-overlayfs --enablerepo updates-testing --exclude container-selinux; yum -y clean all; rm -rf /var/cache/dnf/* /var/log/dnf* /var/log/yum*
# Adjust storage.conf to enable Fuse storage.
RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
@@ -28,7 +28,7 @@ RUN echo skopeo:100000:65536 > /etc/subuid
RUN echo skopeo:100000:65536 > /etc/subgid
# Point to the Authorization file
ENV REGISTRY_AUTH_FILE=/auth.json
ENV REGISTRY_AUTH_FILE=/tmp/auth.json
# Set the entrypoint
ENTRYPOINT ["/usr/bin/skopeo"]

View File

@@ -6,7 +6,7 @@
# This image can be used to create a secured container
# that runs safely with privileges within the container.
#
FROM registry.fedoraproject.org/fedora:32
FROM registry.fedoraproject.org/fedora:33
# Don't include container-selinux and remove
# directories used by yum that are just taking
@@ -29,11 +29,12 @@ mkdir /root/skopeo; \
git clone https://github.com/containers/skopeo /root/skopeo/src/github.com/containers/skopeo; \
export GOPATH=/root/skopeo; \
cd /root/skopeo/src/github.com/containers/skopeo; \
make binary-local;\
make install;\
make bin/skopeo;\
make PREFIX=/usr install;\
rm -rf /root/skopeo/*; \
yum -y remove git golang go-md2man make; \
yum clean all; rm -rf /var/cache /var/log/dnf* /var/log/yum.*;
yum -y clean all; yum -y clean all; rm -rf /var/cache/dnf/* /var/log/dnf* /var/log/yum*
# Adjust storage.conf to enable Fuse storage.
RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
@@ -47,7 +48,7 @@ RUN echo skopeo:100000:65536 > /etc/subuid
RUN echo skopeo:100000:65536 > /etc/subgid
# Point to the Authorization file
ENV REGISTRY_AUTH_FILE=/auth.json
ENV REGISTRY_AUTH_FILE=/tmp/auth.json
# Set the entrypoint
ENTRYPOINT ["/usr/bin/skopeo"]

View File

@@ -4,7 +4,7 @@
skopeo\-copy - Copy an image (manifest, filesystem layers, signatures) from one location to another.
## SYNOPSIS
**skopeo copy** [**--sign-by=**_key-ID_] _source-image destination-image_
**skopeo copy** [*options*] _source-image_ _destination-image_
## DESCRIPTION
Copy an image (manifest, filesystem layers, signatures) from one location to another.
@@ -15,9 +15,16 @@ Uses the system's trust policy to validate images, rejects images not trusted by
_destination-image_ use the "image name" format described above
_source-image_ and _destination-image_ are interpreted completely independently; e.g. the destination name does not
automatically inherit any parts of the source name.
## OPTIONS
**--all**
**--additional-tag**=_strings_
Additional tags (supports docker-archive).
**--all**, **-a**
If _source-image_ refers to a list of images, instead of copying just the image which matches the current OS and
architecture (subject to the use of the global --override-os, --override-arch and --override-variant options), attempt to copy all of
@@ -39,50 +46,131 @@ Path of the authentication file for the source registry. Uses path given by `--a
Path of the authentication file for the destination registry. Uses path given by `--authfile`, if not provided.
**--format, -f** _manifest-type_ Manifest type (oci, v2s1, or v2s2) to use when saving image to directory using the 'dir:' transport (default is manifest type of source)
**--dest-shared-blob-dir** _directory_
**--quiet, -q** suppress output information when copying images
Directory to use to share blobs across OCI repositories.
**--remove-signatures** do not copy signatures, if any, from _source-image_. Necessary when copying a signed image to a destination which does not support signatures.
**--digestfile** _path_
**--sign-by=**_key-id_ add a signature using that key ID for an image name corresponding to _destination-image_
After copying the image, write the digest of the resulting image to the file.
**--encryption-key** _Key_ a reference prefixed with the encryption protocol to use. The supported protocols are JWE, PGP and PKCS7. For instance, jwe:/path/to/key.pem or pgp:admin@example.com or pkcs7:/path/to/x509-file. This feature is still *experimental*.
**--encrypt-layer** _ints_
**--decryption-key** _Key_ a reference required to perform decryption of container images. This should point to files which represent keys and/or certificates that can be used for decryption. Decryption will be tried with all keys. This feature is still *experimental*.
*Experimental* the 0-indexed layer indices, with support for negative indexing (e.g. 0 is the first layer, -1 is the last layer)
**--src-creds** _username[:password]_ for accessing the source registry
**--format**, **-f** _manifest-type_
**--dest-compress** _bool-value_ Compress tarball image layers when saving to directory using the 'dir' transport. (default is same compression type as source)
MANIFEST TYPE (oci, v2s1, or v2s2) to use in the destination (default is manifest type of source, with fallbacks)
**--dest-oci-accept-uncompressed-layers** _bool-value_ Allow uncompressed image layers when saving to an OCI image using the 'oci' transport. (default is to compress things that aren't compressed)
**--help**, **-h**
**--dest-creds** _username[:password]_ for accessing the destination registry
Print usage statement
**--src-cert-dir** _path_ Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the source registry or daemon
**--quiet**, **-q**
**--src-no-creds** _bool-value_ Access the registry anonymously.
Suppress output information when copying images.
**--src-tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to container source registry or daemon (defaults to true)
**--remove-signatures**
**--dest-cert-dir** _path_ Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the destination registry or daemon
Do not copy signatures, if any, from _source-image_. Necessary when copying a signed image to a destination which does not support signatures.
**--dest-no-creds** _bool-value_ Access the registry anonymously.
**--sign-by**=_key-id_
**--dest-tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to container destination registry or daemon (defaults to true)
Add a signature using that key ID for an image name corresponding to _destination-image_
**--src-daemon-host** _host_ Copy from docker daemon at _host_. If _host_ starts with `tcp://`, HTTPS is enabled by default. To use plain HTTP, use the form `http://` (default is `unix:///var/run/docker.sock`).
**--src-shared-blob-dir** _directory_
**--dest-daemon-host** _host_ Copy to docker daemon at _host_. If _host_ starts with `tcp://`, HTTPS is enabled by default. To use plain HTTP, use the form `http://` (default is `unix:///var/run/docker.sock`).
Directory to use to share blobs across OCI repositories.
**--encryption-key** _protocol:keyfile_
Specifies the encryption protocol, which can be JWE (RFC7516), PGP (RFC4880), and PKCS7 (RFC2315) and the key material required for image encryption. For instance, jwe:/path/to/key.pem or pgp:admin@example.com or pkcs7:/path/to/x509-file.
**--decryption-key** _key[:passphrase]_
Key to be used for decryption of images. Key can point to keys and/or certificates. Decryption will be tried with all keys. If the key is protected by a passphrase, it is required to be passed in the argument and omitted otherwise.
**--src-creds** _username[:password]_
Credentials for accessing the source registry.
**--dest-compress** _bool-value_
Compress tarball image layers when saving to directory using the 'dir' transport. (default is same compression type as source).
**--dest-decompress** _bool-value_
Decompress tarball image layers when saving to directory using the 'dir' transport. (default is same compression type as source).
**--dest-oci-accept-uncompressed-layers** _bool-value_
Allow uncompressed image layers when saving to an OCI image using the 'oci' transport. (default is to compress things that aren't compressed).
**--dest-creds** _username[:password]_
Credentials for accessing the destination registry.
**--src-cert-dir** _path_
Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the source registry or daemon.
**--src-no-creds** _bool-value_
Access the registry anonymously.
**--src-tls-verify** _bool-value_
Require HTTPS and verify certificates when talking to container source registry or daemon (defaults to true).
**--dest-cert-dir** _path_
Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the destination registry or daemon.
**--dest-no-creds** _bool-value_
Access the registry anonymously.
**--dest-tls-verify** _bool-value_
Require HTTPS and verify certificates when talking to container destination registry or daemon (defaults to true).
**--src-daemon-host** _host_
Copy from docker daemon at _host_. If _host_ starts with `tcp://`, HTTPS is enabled by default. To use plain HTTP, use the form `http://` (default is `unix:///var/run/docker.sock`).
**--dest-daemon-host** _host_
Copy to docker daemon at _host_. If _host_ starts with `tcp://`, HTTPS is enabled by default. To use plain HTTP, use the form `http://` (default is `unix:///var/run/docker.sock`).
Existing signatures, if any, are preserved as well.
**--dest-compress-format** _format_ Specifies the compression format to use. Supported values are: `gzip` and `zstd`.
**--dest-compress-format** _format_
**--dest-compress-level** _format_ Specifies the compression level to use. The value is specific to the compression algorithm used, e.g. for zstd the accepted values are in the range 1-20 (inclusive), while for gzip it is 1-9 (inclusive).
Specifies the compression format to use. Supported values are: `gzip` and `zstd`.
**--dest-compress-level** _format_
Specifies the compression level to use. The value is specific to the compression algorithm used, e.g. for zstd the accepted values are in the range 1-20 (inclusive), while for gzip it is 1-9 (inclusive).
**--src-registry-token** _token_
Bearer token for accessing the source registry.
**--dest-registry-token** _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.
## EXAMPLES
To just copy an image from one registry to another:
```sh
$ skopeo copy docker://quay.io/skopeo/stable:latest docker://registry.example.com/skopeo:latest
```
To copy the layers of the docker.io busybox image to a local directory:
```sh
$ mkdir -p /var/lib/images/busybox
@@ -132,9 +220,8 @@ skopeo copy --encryption-key jwe:./public.key --encrypt-layer 1 oci:local_nginx
```
## SEE ALSO
skopeo(1), skopeo-login(1), docker-login(1), containers-auth.json(5), containers-policy.json(5), containers-transports(5)
skopeo(1), skopeo-login(1), docker-login(1), containers-auth.json(5), containers-policy.json(5), containers-transports(5), containers-signature(5)
## AUTHORS
Antonio Murdaca <runcom@redhat.com>, Miloslav Trmac <mitr@redhat.com>, Jhon Honce <jhonce@redhat.com>

View File

@@ -1,10 +1,10 @@
% skopeo-delete(1)
## NAME
skopeo\-delete - Mark _image-name_ for deletion.
skopeo\-delete - Mark the _image-name_ for later deletion by the registry's garbage collector.
## SYNOPSIS
**skopeo delete** _image-name_
**skopeo delete** [*options*] _image-name_
Mark _image-name_ for deletion. To release the allocated disk space, you must login to the container registry server and execute the container registry garbage collector. E.g.,
@@ -19,21 +19,51 @@ $ docker exec -it registry /usr/bin/registry garbage-collect /etc/docker-distrib
```
## OPTIONS
**--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`.
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`.
**--creds** _username[:password]_ for accessing the registry
**--creds** _username[:password]_
**--cert-dir** _path_ Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the registry
Credentials for accessing the registry.
**--tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to container registries (defaults to true)
**--cert-dir** _path_
**--no-creds** _bool-value_ Access the registry anonymously.
Use certificates at _path_ (*.crt, *.cert, *.key) to connect to the registry.
**--daemon-host** _host_
Use docker daemon host at _host_ (`docker-daemon:` transport only)
**--help**, **-h**
Print usage statement
**--no-creds** _bool-value_
Access the registry anonymously.
Additionally, the registry must allow deletions by setting `REGISTRY_STORAGE_DELETE_ENABLED=true` for the registry daemon.
**--registry-token** _token_
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.
**--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 (defaults to true)
## EXAMPLES
Mark image example/pause for deletion from the registry.example.com registry:
@@ -49,4 +79,3 @@ skopeo(1), skopeo-login(1), docker-login(1), containers-auth.json(5)
## AUTHORS
Antonio Murdaca <runcom@redhat.com>, Miloslav Trmac <mitr@redhat.com>, Jhon Honce <jhonce@redhat.com>

View File

@@ -1,37 +1,73 @@
% skopeo-inspect(1)
## NAME
skopeo\-inspect - Return low-level information about _image-name_ in a registry
skopeo\-inspect - Return low-level information about _image-name_ in a registry.
## SYNOPSIS
**skopeo inspect** [**--raw**] [**--config**] _image-name_
**skopeo inspect** [*options*] _image-name_
## DESCRIPTION
Return low-level information about _image-name_ in a registry
**--raw** output raw manifest, default is to format in JSON
_image-name_ name of image to retrieve information about
_image-name_ name of image to retrieve information about
## OPTIONS
**--config** output configuration in OCI format, default is to format in JSON
**--authfile** _path_
_image-name_ name of image to retrieve configuration for
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`.
**--config** **--raw** output configuration in raw format
**--cert-dir** _path_
_image-name_ name of image to retrieve configuration for
Use certificates at _path_ (\*.crt, \*.cert, \*.key) to connect to the registry.
**--authfile** _path_
**--config**
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`.
Output configuration in OCI format, default is to format in JSON format.
**--creds** _username[:password]_ for accessing the registry
**--creds** _username[:password]_
**--cert-dir** _path_ Use certificates at _path_ (\*.crt, \*.cert, \*.key) to connect to the registry
Username and password for accessing the registry.
**--tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to container registries (defaults to true)
**--daemon-host** _host_
**--no-creds** _bool-value_ Access the registry anonymously.
Use docker daemon host at _host_ (`docker-daemon:` transport only)
**--format**, **-f**=*format*
Format the output using the given Go template.
The keys of the returned JSON can be used as the values for the --format flag (see examples below).
**--help**, **-h**
Print usage statement
**--no-creds**
Access the registry anonymously.
**--raw**
Output raw manifest or config data depending on --config option.
The --format option is not supported with --raw option.
**--registry-token** _Bearer token_
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.
**--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 (defaults to true)
## EXAMPLES
@@ -42,14 +78,14 @@ $ skopeo inspect docker://docker.io/fedora
"Name": "docker.io/library/fedora",
"Digest": "sha256:a97914edb6ba15deb5c5acf87bd6bd5b6b0408c96f48a5cbd450b5b04509bb7d",
"RepoTags": [
"20",
"21",
"22",
"23",
"24",
"heisenbug",
"latest",
"rawhide"
"20",
"21",
"22",
"23",
"24",
"heisenbug",
"latest",
"rawhide"
],
"Created": "2016-06-20T19:33:43.220526898Z",
"DockerVersion": "1.10.3",
@@ -57,15 +93,24 @@ $ skopeo inspect docker://docker.io/fedora
"Architecture": "amd64",
"Os": "linux",
"Layers": [
"sha256:7c91a140e7a1025c3bc3aace4c80c0d9933ac4ee24b8630a6b0b5d8b9ce6b9d4"
"sha256:7c91a140e7a1025c3bc3aace4c80c0d9933ac4ee24b8630a6b0b5d8b9ce6b9d4"
]
}
```
```
$ /bin/skopeo inspect --config docker://registry.fedoraproject.org/fedora --format "{{ .Architecture }}"
amd64
```
```
$ /bin/skopeo inspect --format '{{ .Env }}' docker://registry.access.redhat.com/ubi8
[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin container=oci]
```
# SEE ALSO
skopeo(1), skopeo-login(1), docker-login(1), containers-auth.json(5)
## AUTHORS
Antonio Murdaca <runcom@redhat.com>, Miloslav Trmac <mitr@redhat.com>, Jhon Honce <jhonce@redhat.com>

View File

@@ -1,27 +1,47 @@
% skopeo-list-tags(1)
## NAME
skopeo\-list\-tags - Return a list of tags the transport-specific image repository
skopeo\-list\-tags - List tags in the transport-specific image repository.
## SYNOPSIS
**skopeo list-tags** _repository-name_
**skopeo list-tags** [*options*] _repository-name_
Return a list of tags from _repository-name_ in a registry.
_repository-name_ name of repository to retrieve tag listing from
**--authfile** _path_
## OPTIONS
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `skopeo login`.
**--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`.
**--creds** _username[:password]_ for accessing the registry
**--creds** _username[:password]_ for accessing the registry.
**--cert-dir** _path_ Use certificates at _path_ (\*.crt, \*.cert, \*.key) to connect to the registry
**--cert-dir** _path_
**--tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to container registries (defaults to true)
Use certificates at _path_ (\*.crt, \*.cert, \*.key) to connect to the registry.
**--no-creds** _bool-value_ Access the registry anonymously.
**--help**, **-h**
Print usage statement
**--no-creds** _bool-value_
Access the registry anonymously.
**--registry-token** _Bearer token_
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.
**--tls-verify**=_bool_
Require HTTPS and verify certificates when talking to the container registry or daemon (defaults to true)
## REPOSITORY NAMES
@@ -32,18 +52,18 @@ This commands refers to repositories using a _transport_`:`_details_ format. The
**docker://**_docker-repository-reference_
A repository in a registry implementing the "Docker Registry HTTP API V2". By default, uses the authorization state in either `$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)`.
A _docker-repository-reference_ is of the form: **registryhost:port/repositoryname** which is similar to an _image-reference_ but with no tag or digest allowed as the last component (e.g no `:latest` or `@sha256:xyz`)
Examples of valid docker-repository-references:
"docker.io/myuser/myrepo"
"docker.io/nginx"
"docker.io/library/fedora"
"localhost:5000/myrepository"
Examples of invalid references:
"docker.io/nginx:latest"
"docker.io/myuser/myimage:v1.0"
"docker.io/myuser/myimage@sha256:f48c4cc192f4c3c6a069cb5cca6d0a9e34d6076ba7c214fd0cc3ca60e0af76bb"
## EXAMPLES
@@ -99,4 +119,3 @@ skopeo(1), skopeo-login(1), docker-login(1), containers-auth.json(5)
## AUTHORS
Zach Hill <zach@anchore.com>

View File

@@ -1,10 +1,10 @@
% skopeo-login(1)
## NAME
skopeo\-login - Login to a container registry
skopeo\-login - Login to a container registry.
## SYNOPSIS
**skoepo login** [*options*] *registry*
**skopeo login** [*options*] _registry_
## DESCRIPTION
**skopeo login** logs into a specified registry server with the correct username
@@ -43,16 +43,18 @@ Return the logged-in user for the registry. Return error if no login is found.
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
Default certificates directory is _/etc/containers/certs.d_.
**--tls-verify**=*true|false*
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
**--help**, **-h**
Print usage statement
**--tls-verify**=_bool_
Require HTTPS and verify certificates when talking to the container registry or daemon (defaults to true)
**--verbose**, **-v**
Write more detailed information to stdout
## EXAMPLES
```

View File

@@ -1,10 +1,10 @@
% skopeo-logout(1)
## NAME
skopeo\-logout - Logout of a container registry
skopeo\-logout - Logout of a container registry.
## SYNOPSIS
**skopeo logout** [*options*] *registry*
**skopeo logout** [*options*] _registry_
## DESCRIPTION
**skopeo logout** logs out of a specified registry server by deleting the cached credentials
@@ -29,6 +29,10 @@ Remove the cached credentials for all registries in the auth file
Print usage statement
**--tls-verify**=_bool_
Require HTTPS and verify certificates when talking to the container registry or daemon (defaults to true)
## EXAMPLES
```

View File

@@ -1,7 +1,7 @@
% skopeo-manifest-digest(1)
## NAME
skopeo\-manifest\-digest -Compute a manifest digest of manifest-file and write it to standard output.
skopeo\-manifest\-digest - Compute a manifest digest for a manifest-file and write it to standard output.
## SYNOPSIS
**skopeo manifest-digest** _manifest-file_
@@ -10,6 +10,12 @@ skopeo\-manifest\-digest -Compute a manifest digest of manifest-file and write i
Compute a manifest digest of _manifest-file_ and write it to standard output.
## OPTIONS
**--help**, **-h**
Print usage statement
## EXAMPLES
```sh
@@ -23,4 +29,3 @@ skopeo(1)
## AUTHORS
Antonio Murdaca <runcom@redhat.com>, Miloslav Trmac <mitr@redhat.com>, Jhon Honce <jhonce@redhat.com>

View File

@@ -1,14 +1,13 @@
% skopeo-standalone-sign(1)
## NAME
skopeo\-standalone-sign - Simple Sign an image
skopeo\-standalone-sign - Debugging tool - Publish and sign an image in one step.
## SYNOPSIS
**skopeo standalone-sign** _manifest docker-reference key-fingerprint_ **--output**|**-o** _signature_
**skopeo standalone-sign** [*options*] _manifest_ _docker-reference_ _key-fingerprint_ **--output**|**-o** _signature_
## DESCRIPTION
This is primarily a debugging tool, or useful for special cases,
and usually should not be a part of your normal operational workflow; use `skopeo copy --sign-by` instead to publish and sign an image in one step.
This is primarily a debugging tool, useful for special cases, and usually should not be a part of your normal operational workflow; use `skopeo copy --sign-by` instead to publish and sign an image in one step.
_manifest_ Path to a file containing the image manifest
@@ -16,7 +15,15 @@ and usually should not be a part of your normal operational workflow; use `skope
_key-fingerprint_ Key identity to use for signing
**--output**|**-o** output file
## OPTIONS
**--help**, **-h**
Print usage statement
**--output**, **-o** _output file_
Write signature to _output file_.
## EXAMPLES
@@ -25,10 +32,13 @@ $ skopeo standalone-sign busybox-manifest.json registry.example.com/example/busy
$
```
## NOTES
This command is intended for use with local signatures e.g. OpenPGP ( other signature formats may be added in the future ), as per containers-signature(5). Furthermore, this command does **not** interact with the artifacts generated by Docker Content Trust (DCT). For more information, please see [containers-signature(5)](https://github.com/containers/image/blob/main/docs/containers-signature.5.md).
## SEE ALSO
skopeo(1), skopeo-copy(1), containers-signature(5)
## AUTHORS
Antonio Murdaca <runcom@redhat.com>, Miloslav Trmac <mitr@redhat.com>, Jhon Honce <jhonce@redhat.com>

View File

@@ -1,14 +1,16 @@
% skopeo-standalone-verify(1)
## NAME
skopeo\-standalone\-verify - Verify an image signature
skopeo\-standalone\-verify - Verify an image signature.
## SYNOPSIS
**skopeo standalone-verify** _manifest docker-reference key-fingerprint signature_
**skopeo standalone-verify** _manifest_ _docker-reference_ _key-fingerprint_ _signature_
## DESCRIPTION
Verify a signature using local files, digest will be printed on success.
Verify a signature using local files; the digest will be printed on success. This is primarily a debugging tool, useful for special cases,
and usually should not be a part of your normal operational workflow. Additionally, consider configuring a signature verification policy file,
as per containers-policy.json(5).
_manifest_ Path to a file containing the image manifest
@@ -20,6 +22,12 @@ Verify a signature using local files, digest will be printed on success.
**Note:** If you do use this, make sure that the image can not be changed at the source location between the times of its verification and use.
## OPTIONS
**--help**, **-h**
Print usage statement
## EXAMPLES
```sh
@@ -27,10 +35,13 @@ $ skopeo standalone-verify busybox-manifest.json registry.example.com/example/bu
Signature verified, digest sha256:20bf21ed457b390829cdbeec8795a7bea1626991fda603e0d01b4e7f60427e55
```
## NOTES
This command is intended for use with local signatures e.g. OpenPGP ( other signature formats may be added in the future ), as per containers-signature(5). Furthermore, this command does **not** interact with the artifacts generated by Docker Content Trust (DCT). For more information, please see [containers-signature(5)](https://github.com/containers/image/blob/main/docs/containers-signature.5.md).
## SEE ALSO
skopeo(1), containers-signature(5)
skopeo(1), containers-signature(5), containers-policy.json(5)
## AUTHORS
Antonio Murdaca <runcom@redhat.com>, Miloslav Trmac <mitr@redhat.com>, Jhon Honce <jhonce@redhat.com>

View File

@@ -5,7 +5,7 @@ skopeo\-sync - Synchronize images between container registries and local directo
## SYNOPSIS
**skopeo sync** --src _transport_ --dest _transport_ _source_ _destination_
**skopeo sync** [*options*] --src _transport_ --dest _transport_ _source_ _destination_
## DESCRIPTION
Synchronize images between container registries and local directories.
@@ -32,6 +32,11 @@ When the `--scoped` option is specified, images are prefixed with the source ima
name can be stored at _destination_.
## OPTIONS
**--all**, **-a**
If one of the images in __src__ refers to a list of images, instead of copying just the image which matches the current OS and
architecture (subject to the use of the global --override-os, --override-arch and --override-variant options), attempt to copy all of
the images in the list, and the list itself.
**--authfile** _path_
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `skopeo login`.
@@ -45,15 +50,21 @@ Path of the authentication file for the source registry. Uses path given by `--a
Path of the authentication file for the destination registry. Uses path given by `--authfile`, if not provided.
**--src** _transport_ Transport for the source repository.
**--src**, **-s** _transport_ Transport for the source repository.
**--dest** _transport_ Destination transport.
**--dest**, **-d** _transport_ Destination transport.
**--format**, **-f** _manifest-type_ Manifest Type (oci, v2s1, or v2s2) to use when syncing image(s) to a destination (default is manifest type of source, with fallbacks).
**--help**, **-h**
Print usage statement.
**--scoped** Prefix images with the source image path, so that multiple images with the same name can be stored at _destination_.
**--remove-signatures** Do not copy signatures, if any, from _source-image_. This is necessary when copying a signed image to a destination which does not support signatures.
**--sign-by=**_key-id_ Add a signature using that key ID for an image name corresponding to _destination-image_.
**--sign-by**=_key-id_ Add a signature using that key ID for an image name corresponding to _destination-image_.
**--src-creds** _username[:password]_ for accessing the source registry.
@@ -71,6 +82,12 @@ Path of the authentication file for the destination registry. Uses path given by
**--dest-tls-verify** _bool-value_ Require HTTPS and verify certificates when talking to a container destination registry or daemon (defaults to true).
**--src-registry-token** _Bearer token_ for accessing the source registry.
**--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.
## EXAMPLES
### Synchronizing to a local directory
@@ -143,6 +160,7 @@ registry.example.com:
redis:
- "1.0"
- "2.0"
- "sha256:0000000000000000000000000000000011111111111111111111111111111111"
images-by-tag-regex:
nginx: ^1\.13\.[12]-alpine-perl$
credentials:
@@ -162,14 +180,14 @@ skopeo sync --src yaml --dest docker sync.yml my-registry.local.lan/repo/
```
This will copy the following images:
- Repository `registry.example.com/busybox`: all images, as no tags are specified.
- Repository `registry.example.com/redis`: images tagged "1.0" and "2.0".
- Repository `registry.example.com/redis`: images tagged "1.0" and "2.0" along with image with digest "sha256:0000000000000000000000000000000011111111111111111111111111111111".
- Repository `registry.example.com/nginx`: images tagged "1.13.1-alpine-perl" and "1.13.2-alpine-perl".
- Repository `quay.io/coreos/etcd`: images tagged "latest".
For the registry `registry.example.com`, the "john"/"this is a secret" credentials are used, with server TLS certificates located at `/home/john/certs`.
TLS verification is normally enabled, and it can be disabled setting `tls-verify` to `false`.
In the above example, TLS verification is enabled for `reigstry.example.com`, while is
In the above example, TLS verification is enabled for `registry.example.com`, while is
disabled for `quay.io`.
## SEE ALSO

View File

@@ -44,44 +44,71 @@ Most commands refer to container images, using a _transport_`:`_details_ format.
**oci:**_path_**:**_tag_
An image _tag_ in a directory compliant with "Open Container Image Layout Specification" at _path_.
**oci-archive:**_path_**:**_tag_
An image _tag_ in a tar archive compliant with "Open Container Image Layout Specification" at _path_.
See [containers-transports(5)](https://github.com/containers/image/blob/master/docs/containers-transports.5.md) for details.
## OPTIONS
**--command-timeout** _duration_ Timeout for the command execution.
**--command-timeout** _duration_
**--debug** enable debug output
Timeout for the command execution.
**--help**|**-h** Show help
**--debug**
**--insecure-policy** Adopt an insecure, permissive policy that allows anything. This obviates the need for a policy file.
enable debug output
**--override-arch** _arch_ Use _arch_ instead of the architecture of the machine for choosing images.
**--help**, **-h**
**--override-os** _OS_ Use _OS_ instead of the running OS for choosing images.
Show help
**--override-variant** _VARIANT_ Use _VARIANT_ instead of the running architecture variant for choosing images.
**--insecure-policy**
**--policy** _path-to-policy_ Path to a policy.json file to use for verifying signatures and deciding whether an image is trusted, overriding the default trust policy file.
Adopt an insecure, permissive policy that allows anything. This obviates the need for a policy file.
**--registries.d** _dir_ use registry configuration files in _dir_ (e.g. for container signature storage), overriding the default path.
**--override-arch** _arch_
**--tmpdir** _dir_ used to store temporary files. Defaults to /var/tmp.
Use _arch_ instead of the architecture of the machine for choosing images.
**--version**|**-v** print the version number
**--override-os** _os_
Use _OS_ instead of the running OS for choosing images.
**--override-variant** _variant_
Use _variant_ instead of the running architecture variant for choosing images.
**--policy** _path-to-policy_
Path to a policy.json file to use for verifying signatures and deciding whether an image is trusted, overriding the default trust policy file.
**--registries.d** _dir_
Use registry configuration files in _dir_ (e.g. for container signature storage), overriding the default path.
**--tmpdir** _dir_
Directory used to store temporary files. Defaults to /var/tmp.
**--version**, **-v**
Print the version number
## COMMANDS
| Command | Description |
| ----------------------------------------- | ------------------------------------------------------------------------------ |
| [skopeo-copy(1)](skopeo-copy.1.md) | Copy an image (manifest, filesystem layers, signatures) from one location to another. |
| [skopeo-delete(1)](skopeo-delete.1.md) | Mark image-name for deletion. |
| [skopeo-inspect(1)](skopeo-inspect.1.md) | Return low-level information about image-name in a registry. |
| [skopeo-list-tags(1)](skopeo-list-tags.1.md) | List the tags for the given transport/repository. |
| [skopeo-delete(1)](skopeo-delete.1.md) | Mark the _image-name_ for later deletion by the registry's garbage collector. |
| [skopeo-inspect(1)](skopeo-inspect.1.md) | Return low-level information about _image-name_ in a registry. |
| [skopeo-list-tags(1)](skopeo-list-tags.1.md) | List tags in the transport-specific image repository. |
| [skopeo-login(1)](skopeo-login.1.md) | Login to a container registry. |
| [skopeo-logout(1)](skopeo-logout.1.md) | Logout of a container registry. |
| [skopeo-manifest-digest(1)](skopeo-manifest-digest.1.md) | Compute a manifest digest of manifest-file and write it to standard output.|
| [skopeo-standalone-sign(1)](skopeo-standalone-sign.1.md) | Sign an image. |
| [skopeo-standalone-verify(1)](skopeo-standalone-verify.1.md)| Verify an image. |
| [skopeo-sync(1)](skopeo-sync.1.md)| Copy images from one or more repositories to a user specified destination. |
| [skopeo-manifest-digest(1)](skopeo-manifest-digest.1.md) | Compute a manifest digest for a manifest-file and write it to standard output. |
| [skopeo-standalone-sign(1)](skopeo-standalone-sign.1.md) | Debugging tool - Publish and sign an image in one step. |
| [skopeo-standalone-verify(1)](skopeo-standalone-verify.1.md)| Verify an image signature. |
| [skopeo-sync(1)](skopeo-sync.1.md)| Synchronize images between container registries and local directories. |
## FILES
**/etc/containers/policy.json**

23
go.mod
View File

@@ -3,24 +3,23 @@ module github.com/containers/skopeo
go 1.12
require (
github.com/containers/common v0.14.0
github.com/containers/image/v5 v5.5.1
github.com/containers/ocicrypt v1.0.2
github.com/containers/storage v1.20.2
github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f
github.com/dsnet/compress v0.0.1 // indirect
github.com/containers/common v0.42.0
github.com/containers/image/v5 v5.15.0
github.com/containers/ocicrypt v1.1.2
github.com/containers/storage v1.33.1
github.com/docker/docker v20.10.7+incompatible
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/go-check/check v0.0.0-20180628173108-788fd7840127
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/image-tools v0.0.0-20170926011501-6d941547fa1d
github.com/opencontainers/runtime-spec v1.0.0 // indirect
github.com/pkg/errors v0.9.1
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v1.0.0
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
github.com/stretchr/testify v1.7.0
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
go4.org v0.0.0-20190218023631-ce4c26f7be8e // indirect
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v2 v2.4.0
)

1099
go.sum

File diff suppressed because it is too large Load Diff

61
hack/get_ci_vm.sh Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env bash
#
# For help and usage information, simply execute the script w/o any arguments.
#
# This script is intended to be run by Red Hat skopeo developers who need
# to debug problems specifically related to Cirrus-CI automated testing.
# It requires that you have been granted prior access to create VMs in
# google-cloud. For non-Red Hat contributors, VMs are available as-needed,
# with supervision upon request.
set -e
SCRIPT_FILEPATH=$(realpath "${BASH_SOURCE[0]}")
SCRIPT_DIRPATH=$(dirname "$SCRIPT_FILEPATH")
REPO_DIRPATH=$(realpath "$SCRIPT_DIRPATH/../")
# Help detect if we were called by get_ci_vm container
GET_CI_VM="${GET_CI_VM:-0}"
in_get_ci_vm() {
if ((GET_CI_VM==0)); then
echo "Error: $1 is not intended for use in this context"
exit 2
fi
}
# get_ci_vm APIv1 container entrypoint calls into this script
# to obtain required repo. specific configuration options.
if [[ "$1" == "--config" ]]; then
in_get_ci_vm "$1"
cat <<EOF
DESTDIR="/var/tmp/go/src/github.com/containers/skopeo"
UPSTREAM_REPO="https://github.com/containers/skopeo.git"
GCLOUD_PROJECT="skopeo"
GCLOUD_IMGPROJECT="libpod-218412"
GCLOUD_CFG="skopeo"
GCLOUD_ZONE="${GCLOUD_ZONE:-us-central1-f}"
GCLOUD_CPUS="2"
GCLOUD_MEMORY="4Gb"
GCLOUD_DISK="200"
EOF
elif [[ "$1" == "--setup" ]]; then
in_get_ci_vm "$1"
# get_ci_vm container entrypoint calls us with this option on the
# Cirrus-CI environment instance, to perform repo.-specific setup.
echo "+ Executing setup" > /dev/stderr
${GOSRC}/${SCRIPT_BASE}/runner.sh setup
else
# Create and access VM for specified Cirrus-CI task
mkdir -p $HOME/.config/gcloud/ssh
podman run -it --rm \
--tz=local \
-e NAME="$USER" \
-e SRCDIR=/src \
-e GCLOUD_ZONE="$GCLOUD_ZONE" \
-e DEBUG="${DEBUG:-0}" \
-v $REPO_DIRPATH:/src:O \
-v $HOME/.config/gcloud:/root/.config/gcloud:z \
-v $HOME/.config/gcloud/ssh:/root/.ssh:z \
quay.io/libpod/get_ci_vm:latest "$@"
fi

View File

@@ -25,12 +25,8 @@ export MAKEDIR="$SCRIPTDIR/make"
# We're a nice, sexy, little shell script, and people might try to run us;
# but really, they shouldn't. We want to be in a container!
inContainer="AssumeSoInitially"
if [ "$PWD" != "/go/src/$SKOPEO_PKG" ]; then
unset inContainer
fi
if [ -z "$inContainer" ]; then
# The magic value is defined inside our Dockerfile.
if [[ "$container_magic" != "85531765-346b-4316-bdb8-358e4cca9e5d" ]]; then
{
echo "# WARNING! I don't seem to be running in a Docker container."
echo "# The result of this command might be an incorrect build, and will not be"
@@ -39,6 +35,9 @@ if [ -z "$inContainer" ]; then
echo "# Try this instead: make all"
echo "#"
} >&2
else
echo "# I appear to be running inside my designated container image, good!"
export SKOPEO_CONTAINER_TESTS=1
fi
echo

View File

@@ -5,7 +5,7 @@ if [ -z "$VALIDATE_UPSTREAM" ]; then
# are running more than one validate bundlescript
VALIDATE_REPO='https://github.com/containers/skopeo.git'
VALIDATE_BRANCH='master'
VALIDATE_BRANCH='main'
if [ "$TRAVIS" = 'true' -a "$TRAVIS_PULL_REQUEST" != 'false' ]; then
VALIDATE_REPO="https://github.com/${TRAVIS_REPO_SLUG}.git"

View File

@@ -8,7 +8,7 @@ bundle_test_integration() {
# subshell so that we can export PATH without breaking other things
(
make binary-local ${BUILDTAGS:+BUILDTAGS="$BUILDTAGS"}
make install
make bin/skopeo ${BUILDTAGS:+BUILDTAGS="$BUILDTAGS"}
make PREFIX=/usr install
bundle_test_integration
) 2>&1

View File

@@ -11,8 +11,8 @@ sed -i \
/etc/containers/storage.conf
# Build skopeo, install into /usr/bin
make binary-local ${BUILDTAGS:+BUILDTAGS="$BUILDTAGS"}
make install
make bin/skopeo ${BUILDTAGS:+BUILDTAGS="$BUILDTAGS"}
make PREFIX=/usr install
# Run tests
SKOPEO_BINARY=/usr/bin/skopeo bats --tap systemtest

150
hack/man-page-checker Executable file
View File

@@ -0,0 +1,150 @@
#!/usr/bin/env bash
#
# man-page-checker - validate and cross-reference man page names
#
# This is the script that cross-checks BETWEEN MAN PAGES. It is not the
# script that cross-checks that each option in skopeo foo --help is listed
# in skopeo-foo.1.md and vice-versa; that one is xref-helpmsgs-manpages.
#
verbose=
for i; do
case "$i" in
-v|--verbose) verbose=verbose ;;
esac
done
die() {
echo "$(basename $0): $*" >&2
exit 1
}
cd $(dirname $0)/../docs || die "Please run me from top-level skopeo dir"
rc=0
# Pass 1: cross-check file names with NAME section
#
# for a given skopeo-foo.1.md, the NAME should be 'skopeo-foo'
for md in *.1.md;do
# Read the first line after '## NAME'
name=$(egrep -A1 '^## NAME' $md|tail -1|awk '{print $1}' | tr -d \\\\)
expect=$(basename $md .1.md)
if [ "$name" != "$expect" ]; then
echo
printf "Inconsistent program NAME in %s:\n" $md
printf " NAME= %s (expected: %s)\n" $name $expect
rc=1
fi
done
# Pass 2: compare descriptions.
#
# Make sure the descriptive text in skopeo-foo.1.md matches the one
# in the table in skopeo.1.md.
for md in $(ls -1 *-*.1.md);do
desc=$(egrep -A1 '^## NAME' $md|tail -1|sed -E -e 's/^skopeo[^[:space:]]+ - //')
# Find the descriptive text in the main skopeo man page.
parent=skopeo.1.md
parent_desc=$(grep $md $parent | awk -F'|' '{print $3}' | sed -E -e 's/^[[:space:]]+//' -e 's/[[:space:]]+$//')
if [ "$desc" != "$parent_desc" ]; then
echo
printf "Inconsistent subcommand descriptions:\n"
printf " %-32s = '%s'\n" $md "$desc"
printf " %-32s = '%s'\n" $parent "$parent_desc"
printf "Please ensure that the NAME section of $md\n"
printf "matches the subcommand description in $parent\n"
rc=1
fi
done
# Helper function: compares man page synopsis vs --help usage message
function compare_usage() {
local cmd="$1"
local from_man="$2"
# Run 'cmd --help', grab the line immediately after 'Usage:'
local help_output=$(../bin/$cmd --help)
local from_help=$(echo "$help_output" | grep -A1 '^Usage:' | tail -1)
# strip off command name from both
from_man=$(sed -E -e "s/\*\*$cmd\*\*[[:space:]]*//" <<<"$from_man")
from_help=$(sed -E -e "s/^[[:space:]]*$cmd[[:space:]]*//" <<<"$from_help")
# man page lists 'foo [*options*]', help msg shows 'foo [command options]'.
# Make sure if one has it, the other does too.
if expr "$from_man" : "\[\*options\*\]" >/dev/null; then
if expr "$from_help" : "\[command options\]" >/dev/null; then
:
else
echo "WARNING: $cmd: man page shows '[*options*]', help does not show [command options]"
rc=1
fi
elif expr "$from_help" : "\[command options\]" >/dev/null; then
echo "WARNING: $cmd: --help shows [command options], man page does not show [*options*]"
rc=1
fi
# Strip off options and flags; start comparing arguments
from_man=$(sed -E -e 's/^\[\*options\*\][[:space:]]*//' <<<"$from_man")
from_help=$(sed -E -e 's/^\[command options\][[:space:]]*//' <<<"$from_help")
# Constant strings in man page are '**foo**', in --help are 'foo'.
from_man=$(sed -E -e 's/\*\*([^*]+)\*\*/\1/g' <<<"$from_man")
# Args in man page are '_foo_', in --help are 'FOO'. Convert all to
# UPCASE simply because it stands out better to the eye.
from_man=$(sed -E -e 's/_([a-z-]+)_/\U\1/g' <<<"$from_man")
# Compare man-page and --help usage strings. Skip 'skopeo' itself,
# because the man page includes '[global options]' which we don't grok.
if [[ "$from_man" != "$from_help" && "$cmd" != "skopeo" ]]; then
printf "%-25s man='%s' help='%s'\n" "$cmd:" "$from_man" "$from_help"
rc=1
fi
}
# Pass 3: compare synopses.
#
# Make sure the SYNOPSIS line in skopeo-foo.1.md reads '**skopeo foo** ...'
for md in *.1.md;do
synopsis=$(egrep -A1 '^#* SYNOPSIS' $md|tail -1)
# Command name must be bracketed by double asterisks; options and
# arguments are bracketed by single ones.
# E.g. '**skopeo copy** [*options*] _..._'
# Get the command name, and confirm that it matches the md file name.
cmd=$(echo "$synopsis" | sed -E -e 's/^\*\*([^*]+)\*\*.*/\1/' | tr -d \*)
# Use sed, not tr, so we only replace the first dash: we want
# skopeo-list-tags -> "skopeo list-tags", not "skopeo list tags"
md_nodash=$(basename "$md" .1.md | sed -e 's/-/ /')
if [ "$cmd" != "$md_nodash" ]; then
echo
printf "Inconsistent program name in SYNOPSIS in %s:\n" $md
printf " SYNOPSIS = %s (expected: '%s')\n" "$cmd" "$md_nodash"
rc=1
fi
# The convention is to use UPPER CASE in 'skopeo foo --help',
# but *lower case bracketed by asterisks* in the man page
if expr "$synopsis" : ".*[A-Z]" >/dev/null; then
echo
printf "Inconsistent capitalization in SYNOPSIS in %s\n" $md
printf " '%s' should not contain upper-case characters\n" "$synopsis"
rc=1
fi
# (for debugging, and getting a sense of standard conventions)
#printf " %-32s ------ '%s'\n" $md "$synopsis"
# If bin/skopeo is available, run "cmd --help" and compare Usage
# messages. This is complicated, so do it in a helper function.
compare_usage "$md_nodash" "$synopsis"
done
exit $rc

View File

@@ -1,17 +0,0 @@
#!/usr/bin/env bash
set -e
export GOPATH=$(pwd)/_gopath
export PATH=$GOPATH/bin:$PATH
_containers="${GOPATH}/src/github.com/containers"
mkdir -vp ${_containers}
ln -vsf $(pwd) ${_containers}/skopeo
go version
GO111MODULE=off go get -u github.com/cpuguy83/go-md2man golang.org/x/lint/golint
cd ${_containers}/skopeo
make validate-local test-unit-local binary-local
sudo make install
skopeo -v

277
hack/xref-helpmsgs-manpages Executable file
View File

@@ -0,0 +1,277 @@
#!/usr/bin/perl
#
# xref-helpmsgs-manpages - cross-reference --help options against man pages
#
package LibPod::CI::XrefHelpmsgsManpages;
use v5.14;
use utf8;
use strict;
use warnings;
(our $ME = $0) =~ s|.*/||;
our $VERSION = '0.1';
# For debugging, show data structures using DumpTree($var)
#use Data::TreeDumper; $Data::TreeDumper::Displayaddress = 0;
# unbuffer output
$| = 1;
###############################################################################
# BEGIN user-customizable section
# Path to skopeo executable
my $Default_Skopeo = './bin/skopeo';
my $SKOPEO = $ENV{SKOPEO} || $Default_Skopeo;
# Path to all doc files (markdown)
my $Docs_Path = 'docs';
# Global error count
my $Errs = 0;
# END user-customizable section
###############################################################################
###############################################################################
# BEGIN boilerplate args checking, usage messages
sub usage {
print <<"END_USAGE";
Usage: $ME [OPTIONS]
$ME recursively runs 'skopeo --help' against
all subcommands; and recursively reads skopeo-*.1.md files
in $Docs_Path, then cross-references that each --help
option is listed in the appropriate man page and vice-versa.
$ME invokes '\$SKOPEO' (default: $Default_Skopeo).
Exit status is zero if no inconsistencies found, one otherwise
OPTIONS:
-v, --verbose show verbose progress indicators
-n, --dry-run make no actual changes
--help display this message
--version display program name and version
END_USAGE
exit;
}
# Command-line options. Note that this operates directly on @ARGV !
our $debug = 0;
our $verbose = 0;
sub handle_opts {
use Getopt::Long;
GetOptions(
'debug!' => \$debug,
'verbose|v' => \$verbose,
help => \&usage,
version => sub { print "$ME version $VERSION\n"; exit 0 },
) or die "Try `$ME --help' for help\n";
}
# END boilerplate args checking, usage messages
###############################################################################
############################## CODE BEGINS HERE ###############################
# The term is "modulino".
__PACKAGE__->main() unless caller();
# Main code.
sub main {
# Note that we operate directly on @ARGV, not on function parameters.
# This is deliberate: it's because Getopt::Long only operates on @ARGV
# and there's no clean way to make it use @_.
handle_opts(); # will set package globals
# Fetch command-line arguments. Barf if too many.
die "$ME: Too many arguments; try $ME --help\n" if @ARGV;
my $help = skopeo_help();
my $man = skopeo_man('skopeo');
xref_by_help($help, $man);
xref_by_man($help, $man);
exit !!$Errs;
}
###############################################################################
# BEGIN cross-referencing
##################
# xref_by_help # Find keys in '--help' but not in man
##################
sub xref_by_help {
my ($help, $man, @subcommand) = @_;
for my $k (sort keys %$help) {
if (exists $man->{$k}) {
if (ref $help->{$k}) {
xref_by_help($help->{$k}, $man->{$k}, @subcommand, $k);
}
# Otherwise, non-ref is leaf node such as a --option
}
else {
my $man = $man->{_path} || 'man';
warn "$ME: skopeo @subcommand --help lists $k, but $k not in $man\n";
++$Errs;
}
}
}
#################
# xref_by_man # Find keys in man pages but not in --help
#################
#
# In an ideal world we could share the functionality in one function; but
# there are just too many special cases in man pages.
#
sub xref_by_man {
my ($help, $man, @subcommand) = @_;
# FIXME: this generates way too much output
for my $k (grep { $_ ne '_path' } sort keys %$man) {
if (exists $help->{$k}) {
if (ref $man->{$k}) {
xref_by_man($help->{$k}, $man->{$k}, @subcommand, $k);
}
}
elsif ($k ne '--help' && $k ne '-h') {
my $man = $man->{_path} || 'man';
warn "$ME: skopeo @subcommand: $k in $man, but not --help\n";
++$Errs;
}
}
}
# END cross-referencing
###############################################################################
# BEGIN data gathering
#################
# skopeo_help # Parse output of 'skopeo [subcommand] --help'
#################
sub skopeo_help {
my %help;
open my $fh, '-|', $SKOPEO, @_, '--help'
or die "$ME: Cannot fork: $!\n";
my $section = '';
while (my $line = <$fh>) {
# Cobra is blessedly consistent in its output:
# Usage: ...
# Available Commands:
# ....
# Options:
# ....
#
# Start by identifying the section we're in...
if ($line =~ /^Available\s+(Commands):/) {
$section = lc $1;
}
elsif ($line =~ /^(Flags):/) {
$section = lc $1;
}
# ...then track commands and options. For subcommands, recurse.
elsif ($section eq 'commands') {
if ($line =~ /^\s{1,4}(\S+)\s/) {
my $subcommand = $1;
print "> skopeo @_ $subcommand\n" if $debug;
$help{$subcommand} = skopeo_help(@_, $subcommand)
unless $subcommand eq 'help'; # 'help' not in man
}
}
elsif ($section eq 'flags') {
# Handle '--foo' or '-f, --foo'
if ($line =~ /^\s{1,10}(--\S+)\s/) {
print "> skopeo @_ $1\n" if $debug;
$help{$1} = 1;
}
elsif ($line =~ /^\s{1,10}(-\S),\s+(--\S+)\s/) {
print "> skopeo @_ $1, $2\n" if $debug;
$help{$1} = $help{$2} = 1;
}
}
}
close $fh
or die "$ME: Error running 'skopeo @_ --help'\n";
return \%help;
}
################
# skopeo_man # Parse contents of skopeo-*.1.md
################
sub skopeo_man {
my $command = shift;
my $manpath = "$Docs_Path/$command.1.md";
print "** $manpath \n" if $debug;
my %man = (_path => $manpath);
open my $fh, '<', $manpath
or die "$ME: Cannot read $manpath: $!\n";
my $section = '';
my @most_recent_flags;
my $previous_subcmd = '';
while (my $line = <$fh>) {
chomp $line;
next unless $line; # skip empty lines
# .md files designate sections with leading double hash
if ($line =~ /^##\s*OPTIONS/) {
$section = 'flags';
}
elsif ($line =~ /^\#\#\s+(SUB)?COMMANDS/) {
$section = 'commands';
}
elsif ($line =~ /^\#\#[^#]/) {
$section = '';
}
# This will be a table containing subcommand names, links to man pages.
elsif ($section eq 'commands') {
# In skopeo.1.md
if ($line =~ /^\|\s*\[skopeo-(\S+?)\(\d\)\]/) {
# $1 will be changed by recursion _*BEFORE*_ left-hand assignment
my $subcmd = $1;
$man{$subcmd} = skopeo_man("skopeo-$1");
}
}
# Options should always be of the form '**-f**' or '**\-\-flag**',
# possibly separated by comma-space.
elsif ($section eq 'flags') {
# If option has long and short form, long must come first.
# This is a while-loop because there may be multiple long
# option names (not in skopeo ATM, but leave the possibility open)
while ($line =~ s/^\*\*(--[a-z0-9.-]+)\*\*(=\*[a-zA-Z0-9-]+\*)?(,\s+)?//g) {
$man{$1} = 1;
}
# Short form
if ($line =~ s/^\*\*(-[a-zA-Z0-9.])\*\*(=\*[a-zA-Z0-9-]+\*)?//g) {
$man{$1} = 1;
}
}
}
close $fh;
return \%man;
}
# END data gathering
###############################################################################
1;

View File

@@ -1,76 +1,123 @@
# Installing from packages
`skopeo` may already be packaged in your distribution, for example on
RHEL/CentOS ≥ 8 or Fedora you can install it using:
## Distribution Packages
`skopeo` may already be packaged in your distribution.
### Fedora
```sh
$ sudo dnf install skopeo
sudo dnf -y install skopeo
```
on RHEL/CentOS ≤ 7.x:
### RHEL/CentOS ≥ 8 and CentOS Stream
```sh
$ sudo yum install skopeo
sudo dnf -y install skopeo
```
for openSUSE:
Newer Skopeo releases may be available on the repositories provided by the
Kubic project. Beware, these may not be suitable for production environments.
on CentOS 8:
```sh
$ sudo zypper install skopeo
sudo dnf -y module disable container-tools
sudo dnf -y install 'dnf-command(copr)'
sudo dnf -y copr enable rhcontainerbot/container-selinux
sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_8/devel:kubic:libcontainers:stable.repo
sudo dnf -y install skopeo
```
on alpine:
on CentOS 8 Stream:
```sh
$ sudo apk add skopeo
sudo dnf -y module disable container-tools
sudo dnf -y install 'dnf-command(copr)'
sudo dnf -y copr enable rhcontainerbot/container-selinux
sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_8_Stream/devel:kubic:libcontainers:stable.repo
sudo dnf -y install skopeo
```
on macOS:
### RHEL/CentOS ≤ 7.x
```sh
$ brew install skopeo
sudo yum -y install skopeo
```
Debian (10 and newer including Raspbian) and Ubuntu (18.04 and newer): Packages
are available via the [Kubic][0] project repositories:
### openSUSE
[0]: https://build.opensuse.org/project/show/devel:kubic:libcontainers:stable
```sh
sudo zypper install skopeo
```
### Alpine
```sh
sudo apk add skopeo
```
### macOS
```sh
brew install skopeo
```
### Nix / NixOS
```sh
$ nix-env -i skopeo
```
### Debian
The skopeo package is available in
the [Bullseye (testing) branch](https://packages.debian.org/bullseye/skopeo), which
will be the next stable release (Debian 11) as well as Debian Unstable/Sid.
```bash
# Debian Unstable/Sid:
$ echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Unstable/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
$ wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Unstable/Release.key -O- | sudo apt-key add -
# Debian Testing/Bullseye or Unstable/Sid
sudo apt-get update
sudo apt-get -y install skopeo
```
```bash
# Debian Testing:
$ echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Testing/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
$ wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Testing/Release.key -O- | sudo apt-key add -
```
### Raspberry Pi OS arm64 (beta)
Raspberry Pi OS uses the standard Debian's repositories,
so it is fully compatible with Debian's arm64 repository.
You can simply follow the [steps for Debian](#debian) to install Skopeo.
### Ubuntu
The skopeo package is available in the official repositories for Ubuntu 20.10
and newer.
```bash
# Debian 10:
$ echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
$ wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_10/Release.key -O- | sudo apt-key add -
# Ubuntu 20.10 and newer
sudo apt-get -y update
sudo apt-get -y install skopeo
```
```bash
# Raspbian 10:
$ echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Raspbian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
$ wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Raspbian_10/Release.key -O- | sudo apt-key add -
```
If you would prefer newer (though not as well-tested) packages,
the [Kubic project](https://build.opensuse.org/package/show/devel:kubic:libcontainers:stable/skopeo)
provides packages for active Ubuntu releases 20.04 and newer (it should also work with direct derivatives like Pop!\_OS).
Checkout the [Kubic project page](https://build.opensuse.org/package/show/devel:kubic:libcontainers:stable/skopeo)
for a list of supported Ubuntu version and
architecture combinations. **NOTE:** The command `sudo apt-get -y upgrade`
maybe required in some cases if Skopeo cannot be installed without it.
The build sources for the Kubic packages can be found [here](https://gitlab.com/rhcontainerbot/skopeo/-/tree/debian/debian).
CAUTION: On Ubuntu 20.10 and newer, we highly recommend you use Buildah, Podman and Skopeo ONLY from EITHER the Kubic repo
OR the official Ubuntu repos. Mixing and matching may lead to unpredictable situations including installation conflicts.
```bash
# Ubuntu (18.04, 19.04 and 19.10):
$ . /etc/os-release
$ sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/x${NAME}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
$ wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/x${NAME}_${VERSION_ID}/Release.key -O- | sudo apt-key add -
. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add -
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install skopeo
```
```bash
$ sudo apt-get update -qq
$ sudo apt-get install skopeo
```
Otherwise, read on for building and installing it from source:
@@ -79,6 +126,8 @@ To build the `skopeo` binary you need at least Go 1.12.
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.
## Building from Source
### Building without a container
Building without a container requires a bit more manual work and setup in your
@@ -92,49 +141,32 @@ Install the necessary dependencies:
```bash
# Fedora:
$ sudo dnf install gpgme-devel libassuan-devel btrfs-progs-devel device-mapper-devel
sudo dnf install gpgme-devel libassuan-devel btrfs-progs-devel device-mapper-devel
```
```bash
# Ubuntu (`libbtrfs-dev` requires Ubuntu 18.10 and above):
$ sudo apt install libgpgme-dev libassuan-dev libbtrfs-dev libdevmapper-dev
sudo apt install libgpgme-dev libassuan-dev libbtrfs-dev libdevmapper-dev pkg-config
```
```bash
# macOS:
$ brew install gpgme
brew install gpgme
```
```bash
# openSUSE:
$ sudo zypper install libgpgme-devel device-mapper-devel libbtrfs-devel glib2-devel
sudo zypper install libgpgme-devel device-mapper-devel libbtrfs-devel glib2-devel
```
Make sure to clone this repository in your `GOPATH` - otherwise compilation fails.
```bash
$ git clone https://github.com/containers/skopeo $GOPATH/src/github.com/containers/skopeo
$ cd $GOPATH/src/github.com/containers/skopeo && make binary-local
git clone https://github.com/containers/skopeo $GOPATH/src/github.com/containers/skopeo
cd $GOPATH/src/github.com/containers/skopeo && make bin/skopeo
```
### Building in a container
Building in a container is simpler, but more restrictive:
- It requires the `podman` command and the ability to run Linux containers
- The created executable is a Linux executable, and depends on dynamic libraries
which may only be available only in a container of a similar Linux
distribution.
```bash
$ make binary # Or (make all) to also build documentation, see below.
```
To build a pure-Go static binary (disables devicemapper, btrfs, and gpgme):
```bash
$ make binary-static DISABLE_CGO=1
```
By default the `make` command (make all) will build bin/skopeo and the documentation locally.
### Building documentation
@@ -142,18 +174,36 @@ To build the manual you will need go-md2man.
```bash
# Debian:
$ sudo apt-get install go-md2man
sudo apt-get install go-md2man
```
```
# Fedora:
$ sudo dnf install go-md2man
sudo dnf install go-md2man
```
```
# MacOS:
brew install go-md2man
```
Then
```bash
$ make docs
make docs
```
### Building in a container
Building in a container is simpler, but more restrictive:
- It requires the `podman` command and the ability to run Linux containers.
- The created executable is a Linux executable, and depends on dynamic libraries
which may only be available only in a container of a similar Linux
distribution.
```bash
$ make binary
```
### Installation
@@ -161,5 +211,5 @@ $ make docs
Finally, after the binary and documentation is built:
```bash
$ sudo make install
sudo make install
```

View File

@@ -101,8 +101,8 @@ func (s *SkopeoSuite) TestCopyWithLocalAuth(c *check.C) {
assertSkopeoSucceeds(c, wanted, "login", "--tls-verify=false", "--username="+s.regV2WithAuth.username, "--password="+s.regV2WithAuth.password, s.regV2WithAuth.url)
// copy to private registry using local authentication
imageName := fmt.Sprintf("docker://%s/busybox:mine", s.regV2WithAuth.url)
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", "docker://docker.io/library/busybox:latest", imageName)
// inspec from private registry
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", testFQIN+":latest", imageName)
// inspect from private registry
assertSkopeoSucceeds(c, "", "inspect", "--tls-verify=false", imageName)
// logout from the registry
wanted = fmt.Sprintf("^Removed login credentials for %s\n$", s.regV2WithAuth.url)

View File

@@ -31,6 +31,7 @@ const (
v2DockerRegistryURL = "localhost:5555" // Update also policy.json
v2s1DockerRegistryURL = "localhost:5556"
knownWindowsOnlyImage = "docker://mcr.microsoft.com/windows/nanoserver:1909"
knownListImage = "docker://registry.fedoraproject.org/fedora-minimal" // could have either ":latest" or "@sha256:..." appended
)
type CopySuite struct {
@@ -99,14 +100,14 @@ func (s *CopySuite) TestCopyWithManifestList(c *check.C) {
dir, err := ioutil.TempDir("", "copy-manifest-list")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir)
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "dir:"+dir)
assertSkopeoSucceeds(c, "", "copy", knownListImage, "dir:"+dir)
}
func (s *CopySuite) TestCopyAllWithManifestList(c *check.C) {
dir, err := ioutil.TempDir("", "copy-all-manifest-list")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir)
assertSkopeoSucceeds(c, "", "copy", "--all", "docker://estesp/busybox:latest", "dir:"+dir)
assertSkopeoSucceeds(c, "", "copy", "--all", knownListImage, "dir:"+dir)
}
func (s *CopySuite) TestCopyAllWithManifestListRoundTrip(c *check.C) {
@@ -122,7 +123,7 @@ func (s *CopySuite) TestCopyAllWithManifestListRoundTrip(c *check.C) {
dir2, err := ioutil.TempDir("", "copy-all-manifest-list-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
assertSkopeoSucceeds(c, "", "copy", "--all", "docker://estesp/busybox:latest", "oci:"+oci1)
assertSkopeoSucceeds(c, "", "copy", "--all", knownListImage, "oci:"+oci1)
assertSkopeoSucceeds(c, "", "copy", "--all", "oci:"+oci1, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "--all", "dir:"+dir1, "oci:"+oci2)
assertSkopeoSucceeds(c, "", "copy", "--all", "oci:"+oci2, "dir:"+dir2)
@@ -144,9 +145,9 @@ func (s *CopySuite) TestCopyAllWithManifestListConverge(c *check.C) {
dir2, err := ioutil.TempDir("", "copy-all-manifest-list-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
assertSkopeoSucceeds(c, "", "copy", "--all", "docker://estesp/busybox:latest", "oci:"+oci1)
assertSkopeoSucceeds(c, "", "copy", "--all", knownListImage, "oci:"+oci1)
assertSkopeoSucceeds(c, "", "copy", "--all", "oci:"+oci1, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "--all", "--format", "oci", "docker://estesp/busybox:latest", "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", "--all", "--format", "oci", knownListImage, "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", "--all", "dir:"+dir2, "oci:"+oci2)
assertDirImagesAreEqual(c, dir1, dir2)
out := combinedOutputOfCommand(c, "diff", "-urN", oci1, oci2)
@@ -166,9 +167,9 @@ func (s *CopySuite) TestCopyWithManifestListConverge(c *check.C) {
dir2, err := ioutil.TempDir("", "copy-all-manifest-list-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "oci:"+oci1)
assertSkopeoSucceeds(c, "", "copy", knownListImage, "oci:"+oci1)
assertSkopeoSucceeds(c, "", "copy", "--all", "oci:"+oci1, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "--format", "oci", "docker://estesp/busybox:latest", "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", "--format", "oci", knownListImage, "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", "--all", "dir:"+dir2, "oci:"+oci2)
assertDirImagesAreEqual(c, dir1, dir2)
out := combinedOutputOfCommand(c, "diff", "-urN", oci1, oci2)
@@ -180,7 +181,7 @@ func (s *CopySuite) TestCopyAllWithManifestListStorageFails(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
assertSkopeoFails(c, `.*destination transport .* does not support copying multiple images as a group.*`, "copy", "--all", "docker://estesp/busybox:latest", "containers-storage:"+storage+"test")
assertSkopeoFails(c, `.*destination transport .* does not support copying multiple images as a group.*`, "copy", "--all", knownListImage, "containers-storage:"+storage+"test")
}
func (s *CopySuite) TestCopyWithManifestListStorage(c *check.C) {
@@ -194,8 +195,8 @@ func (s *CopySuite) TestCopyWithManifestListStorage(c *check.C) {
dir2, err := ioutil.TempDir("", "copy-manifest-list-storage-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "containers-storage:"+storage+"test")
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:latest", "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", knownListImage, "containers-storage:"+storage+"test")
assertSkopeoSucceeds(c, "", "copy", knownListImage, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "containers-storage:"+storage+"test", "dir:"+dir2)
runDecompressDirs(c, "", dir1, dir2)
assertDirImagesAreEqual(c, dir1, dir2)
@@ -212,9 +213,9 @@ func (s *CopySuite) TestCopyWithManifestListStorageMultiple(c *check.C) {
dir2, err := ioutil.TempDir("", "copy-manifest-list-storage-multiple-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
assertSkopeoSucceeds(c, "", "--override-arch", "amd64", "copy", "docker://estesp/busybox:latest", "containers-storage:"+storage+"test")
assertSkopeoSucceeds(c, "", "--override-arch", "arm64", "copy", "docker://estesp/busybox:latest", "containers-storage:"+storage+"test")
assertSkopeoSucceeds(c, "", "--override-arch", "arm64", "copy", "docker://estesp/busybox:latest", "dir:"+dir1)
assertSkopeoSucceeds(c, "", "--override-arch", "amd64", "copy", knownListImage, "containers-storage:"+storage+"test")
assertSkopeoSucceeds(c, "", "--override-arch", "arm64", "copy", knownListImage, "containers-storage:"+storage+"test")
assertSkopeoSucceeds(c, "", "--override-arch", "arm64", "copy", knownListImage, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "containers-storage:"+storage+"test", "dir:"+dir2)
runDecompressDirs(c, "", dir1, dir2)
assertDirImagesAreEqual(c, dir1, dir2)
@@ -233,18 +234,33 @@ func (s *CopySuite) TestCopyWithManifestListDigest(c *check.C) {
oci2, err := ioutil.TempDir("", "copy-manifest-list-digest-oci")
c.Assert(err, check.IsNil)
defer os.RemoveAll(oci2)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox@"+digest, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "--all", "docker://estesp/busybox@"+digest, "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", knownListImage+"@"+digest, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "--all", knownListImage+"@"+digest, "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", "dir:"+dir1, "oci:"+oci1)
assertSkopeoSucceeds(c, "", "copy", "dir:"+dir2, "oci:"+oci2)
out := combinedOutputOfCommand(c, "diff", "-urN", oci1, oci2)
c.Assert(out, check.Equals, "")
}
func (s *CopySuite) TestCopyWithDigestfileOutput(c *check.C) {
tempdir, err := ioutil.TempDir("", "tempdir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(tempdir)
dir1, err := ioutil.TempDir("", "copy-manifest-list-digest-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir1)
digestOutPath := filepath.Join(tempdir, "digest.txt")
assertSkopeoSucceeds(c, "", "copy", "--digestfile="+digestOutPath, knownListImage, "dir:"+dir1)
readDigest, err := ioutil.ReadFile(digestOutPath)
c.Assert(err, check.IsNil)
_, err = digest.Parse(string(readDigest))
c.Assert(err, check.IsNil)
}
func (s *CopySuite) TestCopyWithManifestListStorageDigest(c *check.C) {
storage, err := ioutil.TempDir("", "copy-manifest-list-storage-digest")
c.Assert(err, check.IsNil)
@@ -256,13 +272,13 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigest(c *check.C) {
dir2, err := ioutil.TempDir("", "copy-manifest-list-storage-digest-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "copy", "containers-storage:"+storage+"test@"+digest, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox@"+digest, "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", knownListImage+"@"+digest, "dir:"+dir2)
runDecompressDirs(c, "", dir1, dir2)
assertDirImagesAreEqual(c, dir1, dir2)
}
@@ -278,13 +294,13 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArches(c *check
dir2, err := ioutil.TempDir("", "copy-manifest-list-storage-digest-dir")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "copy", "containers-storage:"+storage+"test@"+digest, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox@"+digest, "dir:"+dir2)
assertSkopeoSucceeds(c, "", "copy", knownListImage+"@"+digest, "dir:"+dir2)
runDecompressDirs(c, "", dir1, dir2)
assertDirImagesAreEqual(c, dir1, dir2)
}
@@ -294,16 +310,16 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesBothUseLi
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
_, err = manifest.ListFromBlob([]byte(m), manifest.GuessMIMEType([]byte(m)))
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
i2 := combinedOutputOfCommand(c, skopeoBinary, "--override-arch=arm64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
var image2 imgspecv1.Image
err = json.Unmarshal([]byte(i2), &image2)
@@ -316,7 +332,7 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesFirstUses
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
@@ -326,8 +342,8 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesFirstUses
c.Assert(err, check.IsNil)
arm64Instance, err := list.ChooseInstance(&types.SystemContext{ArchitectureChoice: "arm64"})
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", "docker://estesp/busybox@"+arm64Instance.String(), "containers-storage:"+storage+"test@"+arm64Instance.String())
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", knownListImage+"@"+arm64Instance.String(), "containers-storage:"+storage+"test@"+arm64Instance.String())
i1 := combinedOutputOfCommand(c, skopeoBinary, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
var image1 imgspecv1.Image
err = json.Unmarshal([]byte(i1), &image1)
@@ -338,8 +354,8 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesFirstUses
err = json.Unmarshal([]byte(i2), &image2)
c.Assert(err, check.IsNil)
c.Assert(image2.Architecture, check.Equals, "amd64")
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=arm64", "inspect", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=arm64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=arm64", "inspect", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=arm64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
i3 := combinedOutputOfCommand(c, skopeoBinary, "--override-arch=arm64", "inspect", "--config", "containers-storage:"+storage+"test@"+arm64Instance.String())
var image3 imgspecv1.Image
err = json.Unmarshal([]byte(i3), &image3)
@@ -352,7 +368,7 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesSecondUse
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
@@ -362,15 +378,15 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesSecondUse
c.Assert(err, check.IsNil)
arm64Instance, err := list.ChooseInstance(&types.SystemContext{ArchitectureChoice: "arm64"})
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", "docker://estesp/busybox@"+amd64Instance.String(), "containers-storage:"+storage+"test@"+amd64Instance.String())
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", knownListImage+"@"+amd64Instance.String(), "containers-storage:"+storage+"test@"+amd64Instance.String())
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
i1 := combinedOutputOfCommand(c, skopeoBinary, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+amd64Instance.String())
var image1 imgspecv1.Image
err = json.Unmarshal([]byte(i1), &image1)
c.Assert(err, check.IsNil)
c.Assert(image1.Architecture, check.Equals, "amd64")
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
i2 := combinedOutputOfCommand(c, skopeoBinary, "--override-arch=arm64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
var image2 imgspecv1.Image
err = json.Unmarshal([]byte(i2), &image2)
@@ -388,7 +404,7 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesThirdUses
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
@@ -398,10 +414,10 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesThirdUses
c.Assert(err, check.IsNil)
arm64Instance, err := list.ChooseInstance(&types.SystemContext{ArchitectureChoice: "arm64"})
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", "docker://estesp/busybox@"+amd64Instance.String(), "containers-storage:"+storage+"test@"+amd64Instance.String())
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", knownListImage+"@"+amd64Instance.String(), "containers-storage:"+storage+"test@"+amd64Instance.String())
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
i1 := combinedOutputOfCommand(c, skopeoBinary, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+amd64Instance.String())
var image1 imgspecv1.Image
err = json.Unmarshal([]byte(i1), &image1)
@@ -424,7 +440,7 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesTagAndDig
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", "docker://estesp/busybox:latest")
m := combinedOutputOfCommand(c, skopeoBinary, "inspect", "--raw", knownListImage)
manifestDigest, err := manifest.Digest([]byte(m))
c.Assert(err, check.IsNil)
digest := manifestDigest.String()
@@ -434,9 +450,9 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesTagAndDig
c.Assert(err, check.IsNil)
arm64Instance, err := list.ChooseInstance(&types.SystemContext{ArchitectureChoice: "arm64"})
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", "docker://estesp/busybox:latest", "containers-storage:"+storage+"test:latest")
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", "docker://estesp/busybox@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*error reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
assertSkopeoSucceeds(c, "", "--override-arch=amd64", "copy", knownListImage, "containers-storage:"+storage+"test:latest")
assertSkopeoSucceeds(c, "", "--override-arch=arm64", "copy", knownListImage+"@"+digest, "containers-storage:"+storage+"test@"+digest)
assertSkopeoFails(c, `.*reading manifest for image instance.*does not exist.*`, "--override-arch=amd64", "inspect", "--config", "containers-storage:"+storage+"test@"+digest)
i1 := combinedOutputOfCommand(c, skopeoBinary, "--override-arch=arm64", "inspect", "--config", "containers-storage:"+storage+"test:latest")
var image1 imgspecv1.Image
err = json.Unmarshal([]byte(i1), &image1)
@@ -464,16 +480,16 @@ func (s *CopySuite) TestCopyWithManifestListStorageDigestMultipleArchesTagAndDig
c.Assert(image5.Architecture, check.Equals, "arm64")
}
func (s *CopySuite) TestCopyFailsWhenImageOSDoesntMatchRuntimeOS(c *check.C) {
storage, err := ioutil.TempDir("", "copy-fails-image-doesnt-match-runtime")
func (s *CopySuite) TestCopyFailsWhenImageOSDoesNotMatchRuntimeOS(c *check.C) {
storage, err := ioutil.TempDir("", "copy-fails-image-does-not-match-runtime")
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
assertSkopeoFails(c, `.*no image found in manifest list for architecture .*, variant .*, OS .*`, "copy", knownWindowsOnlyImage, "containers-storage:"+storage+"test")
}
func (s *CopySuite) TestCopySucceedsWhenImageDoesntMatchRuntimeButWeOverride(c *check.C) {
storage, err := ioutil.TempDir("", "copy-succeeds-image-doesnt-match-runtime-but-override")
func (s *CopySuite) TestCopySucceedsWhenImageDoesNotMatchRuntimeButWeOverride(c *check.C) {
storage, err := ioutil.TempDir("", "copy-succeeds-image-does-not-match-runtime-but-override")
c.Assert(err, check.IsNil)
defer os.RemoveAll(storage)
storage = fmt.Sprintf("[vfs@%s/root+%s/runroot]", storage, storage)
@@ -488,14 +504,14 @@ func (s *CopySuite) TestCopySimpleAtomicRegistry(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
// "pull": docker: → dir:
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", testFQIN64, "dir:"+dir1)
// "push": dir: → atomic:
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "dir:"+dir1, "atomic:localhost:5000/myns/unsigned:unsigned")
// The result of pushing and pulling is an equivalent image, except for schema1 embedded names.
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:unsigned", "dir:"+dir2)
assertSchema1DirImagesAreEqualExceptNames(c, dir1, "estesp/busybox:amd64", dir2, "myns/unsigned:unsigned")
assertSchema1DirImagesAreEqualExceptNames(c, dir1, "libpod/busybox:amd64", dir2, "myns/unsigned:unsigned")
}
// The most basic (skopeo copy) use:
@@ -509,30 +525,30 @@ func (s *CopySuite) TestCopySimple(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
// "pull": docker: → dir:
assertSkopeoSucceeds(c, "", "copy", "docker://busybox", "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", "docker://k8s.gcr.io/pause", "dir:"+dir1)
// "push": dir: → docker(v2s2):
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "dir:"+dir1, ourRegistry+"busybox:unsigned")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "dir:"+dir1, ourRegistry+"pause:unsigned")
// The result of pushing and pulling is an unmodified image.
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", ourRegistry+"busybox:unsigned", "dir:"+dir2)
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", ourRegistry+"pause:unsigned", "dir:"+dir2)
out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2)
c.Assert(out, check.Equals, "")
// docker v2s2 -> OCI image layout with image name
// ociDest will be created by oci: if it doesn't exist
// so don't create it here to exercise auto-creation
ociDest := "busybox-latest-image"
ociImgName := "busybox"
ociDest := "pause-latest-image"
ociImgName := "pause"
defer os.RemoveAll(ociDest)
assertSkopeoSucceeds(c, "", "copy", "docker://busybox:latest", "oci:"+ociDest+":"+ociImgName)
assertSkopeoSucceeds(c, "", "copy", "docker://k8s.gcr.io/pause:latest", "oci:"+ociDest+":"+ociImgName)
_, err = os.Stat(ociDest)
c.Assert(err, check.IsNil)
// docker v2s2 -> OCI image layout without image name
ociDest = "busybox-latest-noimage"
ociDest = "pause-latest-noimage"
defer os.RemoveAll(ociDest)
assertSkopeoSucceeds(c, "", "copy", "docker://busybox:latest", "oci:"+ociDest)
assertSkopeoSucceeds(c, "", "copy", "docker://k8s.gcr.io/pause:latest", "oci:"+ociDest)
_, err = os.Stat(ociDest)
c.Assert(err, check.IsNil)
}
@@ -552,6 +568,7 @@ func (s *CopySuite) TestCopyEncryption(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(keysDir)
undecryptedImgDir, err := ioutil.TempDir("", "copy-5")
c.Assert(err, check.IsNil)
defer os.RemoveAll(undecryptedImgDir)
multiLayerImageDir, err := ioutil.TempDir("", "copy-6")
c.Assert(err, check.IsNil)
@@ -586,7 +603,7 @@ func (s *CopySuite) TestCopyEncryption(c *check.C) {
"oci:"+encryptedImgDir+":encrypted", "oci:"+decryptedImgDir+":decrypted")
// Copy a standard busybox image locally
assertSkopeoSucceeds(c, "", "copy", "docker://busybox:1.31.1", "oci:"+originalImageDir+":latest")
assertSkopeoSucceeds(c, "", "copy", testFQIN+":1.30.1", "oci:"+originalImageDir+":latest")
// Encrypt the image
assertSkopeoSucceeds(c, "", "copy", "--encryption-key",
@@ -617,7 +634,7 @@ func (s *CopySuite) TestCopyEncryption(c *check.C) {
matchLayerBlobBinaryType(c, decryptedImgDir+"/blobs/sha256", "application/x-gzip", 1)
// Copy a standard multi layer nginx image locally
assertSkopeoSucceeds(c, "", "copy", "docker://nginx:1.17.8", "oci:"+multiLayerImageDir+":latest")
assertSkopeoSucceeds(c, "", "copy", testFQINMultiLayer, "oci:"+multiLayerImageDir+":latest")
// Partially encrypt the image
assertSkopeoSucceeds(c, "", "copy", "--encryption-key", "jwe:"+keysDir+"/public.key",
@@ -626,7 +643,7 @@ func (s *CopySuite) TestCopyEncryption(c *check.C) {
// Since the image is partially encrypted we should find layers that aren't encrypted
matchLayerBlobBinaryType(c, partiallyEncryptedImgDir+"/blobs/sha256", "application/x-gzip", 2)
// Decrypt the partically encrypted image
// Decrypt the partially encrypted image
assertSkopeoSucceeds(c, "", "copy", "--decryption-key", keysDir+"/private.key",
"oci:"+partiallyEncryptedImgDir+":encrypted", "oci:"+partiallyDecryptedImgDir+":decrypted")
@@ -720,13 +737,13 @@ func (s *CopySuite) TestCopyStreaming(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir2)
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
// streaming: docker: → atomic:
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "docker://estesp/busybox:amd64", "atomic:localhost:5000/myns/unsigned:streaming")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", testFQIN64, "atomic:localhost:5000/myns/unsigned:streaming")
// Compare (copies of) the original and the copy:
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1)
assertSkopeoSucceeds(c, "", "copy", testFQIN64, "dir:"+dir1)
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:streaming", "dir:"+dir2)
assertSchema1DirImagesAreEqualExceptNames(c, dir1, "estesp/busybox:amd64", dir2, "myns/unsigned:streaming")
assertSchema1DirImagesAreEqualExceptNames(c, dir1, "libpod/busybox:amd64", dir2, "myns/unsigned:streaming")
// FIXME: Also check pushing to docker://
}
@@ -746,7 +763,7 @@ func (s *CopySuite) TestCopyOCIRoundTrip(c *check.C) {
defer os.RemoveAll(oci2)
// Docker -> OCI
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "docker://busybox", "oci:"+oci1+":latest")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", testFQIN, "oci:"+oci1+":latest")
// OCI -> Docker
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "oci:"+oci1+":latest", ourRegistry+"original/busybox:oci_copy")
// Docker -> OCI
@@ -797,16 +814,16 @@ func (s *CopySuite) TestCopySignatures(c *check.C) {
defer os.Remove(policy)
// type: reject
assertSkopeoFails(c, ".*Source image rejected: Running image docker://busybox:latest is rejected by policy.*",
"--policy", policy, "copy", "docker://busybox:latest", dirDest)
assertSkopeoFails(c, fmt.Sprintf(".*Source image rejected: Running image %s:latest is rejected by policy.*", testFQIN),
"--policy", policy, "copy", testFQIN+":latest", dirDest)
// type: insecureAcceptAnything
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "docker://openshift/hello-openshift", dirDest)
assertSkopeoSucceeds(c, "", "--policy", policy, "copy", "docker://quay.io/openshift/origin-hello-openshift", dirDest)
// type: signedBy
// Sign the images
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "personal@example.com", "docker://busybox:1.26", "atomic:localhost:5006/myns/personal:personal")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "official@example.com", "docker://busybox:1.26.1", "atomic:localhost:5006/myns/official:official")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "personal@example.com", testFQIN+":1.26", "atomic:localhost:5006/myns/personal:personal")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "official@example.com", testFQIN+":1.26.1", "atomic:localhost:5006/myns/official:official")
// Verify that we can pull them
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/personal:personal", dirDest)
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/official:official", dirDest)
@@ -860,10 +877,10 @@ func (s *CopySuite) TestCopyDirSignatures(c *check.C) {
defer os.Remove(policy)
// Get some images.
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:armfh", topDirDest+"/dir1")
assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:s390x", topDirDest+"/dir2")
assertSkopeoSucceeds(c, "", "copy", testFQIN+":armfh", topDirDest+"/dir1")
assertSkopeoSucceeds(c, "", "copy", testFQIN+":s390x", topDirDest+"/dir2")
// Sign the images. By coping fom a topDirDest/dirN, also test that non-/restricted paths
// Sign the images. By coping from a topDirDest/dirN, also test that non-/restricted paths
// use the dir:"" default of insecureAcceptAnything.
// (For signing, we must push to atomic: to get a Docker identity to use in the signature.)
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "--sign-by", "personal@example.com", topDirDest+"/dir1", "atomic:localhost:5000/myns/personal:dirstaging")
@@ -977,7 +994,7 @@ func (s *CopySuite) TestCopyDockerSigstore(c *check.C) {
c.Assert(err, check.IsNil)
// Get an image to work with. Also verifies that we can use Docker repositories with no sigstore configured.
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--registries.d", registriesDir, "copy", "docker://busybox", ourRegistry+"original/busybox")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--registries.d", registriesDir, "copy", testFQIN, ourRegistry+"original/busybox")
// Pulling an unsigned image fails.
assertSkopeoFails(c, ".*Source image rejected: A signature was required, but no signature exists.*",
"--tls-verify=false", "--policy", policy, "--registries.d", registriesDir, "copy", ourRegistry+"original/busybox", dirDest)
@@ -1031,7 +1048,7 @@ func (s *CopySuite) TestCopyAtomicExtension(c *check.C) {
defer os.Remove(policy)
// Get an image to work with to an atomic: destination. Also verifies that we can use Docker repositories without X-Registry-Supports-Signatures
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--registries.d", registriesDir, "copy", "docker://busybox", "atomic:localhost:5000/myns/extension:unsigned")
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--registries.d", registriesDir, "copy", testFQIN, "atomic:localhost:5000/myns/extension:unsigned")
// Pulling an unsigned image using atomic: fails.
assertSkopeoFails(c, ".*Source image rejected: A signature was required, but no signature exists.*",
"--tls-verify=false", "--policy", policy,
@@ -1055,7 +1072,7 @@ func (s *CopySuite) TestCopyAtomicExtension(c *check.C) {
// Get another image (different so that they don't share signatures, and sign it using docker://)
assertSkopeoSucceeds(c, "", "--tls-verify=false", "--registries.d", registriesDir,
"copy", "--sign-by", "personal@example.com", "docker://estesp/busybox:ppc64le", "docker://localhost:5000/myns/extension:extension")
"copy", "--sign-by", "personal@example.com", testFQIN+":ppc64le", "docker://localhost:5000/myns/extension:extension")
c.Logf("%s", combinedOutputOfCommand(c, "oc", "get", "istag", "extension:extension", "-o", "json"))
// Pulling the image using atomic: succeeds.
assertSkopeoSucceeds(c, "", "--debug", "--tls-verify=false", "--policy", policy,
@@ -1067,6 +1084,23 @@ func (s *CopySuite) TestCopyAtomicExtension(c *check.C) {
assertDirImagesAreEqual(c, filepath.Join(topDir, "dirDA"), filepath.Join(topDir, "dirDD"))
}
// copyWithSignedIdentity creates a copy of an unsigned image, adding a signature for an unrelated identity
// This should be easier than using standalone-sign.
func copyWithSignedIdentity(c *check.C, src, dest, signedIdentity, signBy, registriesDir string) {
topDir, err := ioutil.TempDir("", "copyWithSignedIdentity")
c.Assert(err, check.IsNil)
defer os.RemoveAll(topDir)
signingDir := filepath.Join(topDir, "signing-temp")
assertSkopeoSucceeds(c, "", "copy", "--src-tls-verify=false", src, "dir:"+signingDir)
c.Logf("%s", combinedOutputOfCommand(c, "ls", "-laR", signingDir))
assertSkopeoSucceeds(c, "^$", "standalone-sign", "-o", filepath.Join(signingDir, "signature-1"),
filepath.Join(signingDir, "manifest.json"), signedIdentity, signBy)
c.Logf("%s", combinedOutputOfCommand(c, "ls", "-laR", signingDir))
assertSkopeoSucceeds(c, "", "--registries.d", registriesDir, "copy", "--dest-tls-verify=false", "dir:"+signingDir, dest)
}
// Both mirroring support in registries.conf, and mirrored remapIdentity support in policy.json
func (s *CopySuite) TestCopyVerifyingMirroredSignatures(c *check.C) {
const regPrefix = "docker://localhost:5006/myns/mirroring-"
@@ -1077,7 +1111,7 @@ func (s *CopySuite) TestCopyVerifyingMirroredSignatures(c *check.C) {
c.Skip(fmt.Sprintf("Signing not supported: %v", err))
}
topDir, err := ioutil.TempDir("", "mirrored-signatures") // FIXME: Will this be used?
topDir, err := ioutil.TempDir("", "mirrored-signatures")
c.Assert(err, check.IsNil)
defer os.RemoveAll(topDir)
registriesDir := filepath.Join(topDir, "registries.d") // An empty directory to disable sigstore use
@@ -1087,12 +1121,12 @@ func (s *CopySuite) TestCopyVerifyingMirroredSignatures(c *check.C) {
defer os.Remove(policy)
// We use X-R-S-S for this testing to avoid having to deal with the sigstores.
// A downside is that OpenShift records signatures per image, so the error messsages below
// A downside is that OpenShift records signatures per image, so the error messages below
// list all signatures for other tags used for the same image as well.
// So, make sure to never create a signature that could be considered valid in a different part of the test (i.e. don't reuse tags).
// Get an image to work with.
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", "docker://busybox", regPrefix+"primary:unsigned")
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", testFQIN, regPrefix+"primary:unsigned")
// Verify that unsigned images are rejected
assertSkopeoFails(c, ".*Source image rejected: A signature was required, but no signature exists.*",
"--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"primary:unsigned", dirDest)
@@ -1103,7 +1137,7 @@ func (s *CopySuite) TestCopyVerifyingMirroredSignatures(c *check.C) {
// Sign the image for the mirror
assertSkopeoSucceeds(c, "", "--registries.d", registriesDir, "copy", "--src-tls-verify=false", "--dest-tls-verify=false", "--sign-by", "personal@example.com", regPrefix+"primary:unsigned", regPrefix+"mirror:mirror-signed")
// Verify that a correctly signed image for the mirror is acessible using the mirror's reference
// Verify that a correctly signed image for the mirror is accessible using the mirror's reference
assertSkopeoSucceeds(c, "", "--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"mirror:mirror-signed", dirDest)
// … but verify that while it is accessible using the primary location redirecting to the mirror, …
assertSkopeoSucceeds(c, "" /* no --policy */, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"primary:mirror-signed", dirDest)
@@ -1111,14 +1145,10 @@ func (s *CopySuite) TestCopyVerifyingMirroredSignatures(c *check.C) {
assertSkopeoFails(c, ".*Source image rejected: None of the signatures were accepted, reasons: Signature for identity localhost:5006/myns/mirroring-primary:direct is not accepted; Signature for identity localhost:5006/myns/mirroring-mirror:mirror-signed is not accepted.*",
"--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"primary:mirror-signed", dirDest)
// Create a signature for mirroring-primary:primary-signed without pushing there. This should be easier than using standalone-sign.
signingDir := filepath.Join(topDir, "signing-temp")
assertSkopeoSucceeds(c, "", "copy", "--src-tls-verify=false", regPrefix+"primary:unsigned", "dir:"+signingDir)
c.Logf("%s", combinedOutputOfCommand(c, "ls", "-laR", signingDir))
assertSkopeoSucceeds(c, "^$", "standalone-sign", "-o", filepath.Join(signingDir, "signature-1"),
filepath.Join(signingDir, "manifest.json"), "localhost:5006/myns/mirroring-primary:primary-signed", "personal@example.com")
c.Logf("%s", combinedOutputOfCommand(c, "ls", "-laR", signingDir))
assertSkopeoSucceeds(c, "", "--registries.d", registriesDir, "copy", "--dest-tls-verify=false", "dir:"+signingDir, regPrefix+"mirror:primary-signed")
// Create a signature for mirroring-primary:primary-signed without pushing there.
copyWithSignedIdentity(c, regPrefix+"primary:unsigned", regPrefix+"mirror:primary-signed",
"localhost:5006/myns/mirroring-primary:primary-signed", "personal@example.com",
registriesDir)
// Verify that a correctly signed image for the primary is accessible using the primary's reference
assertSkopeoSucceeds(c, "", "--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"primary:primary-signed", dirDest)
// … but verify that while it is accessible using the mirror location
@@ -1126,10 +1156,24 @@ func (s *CopySuite) TestCopyVerifyingMirroredSignatures(c *check.C) {
// … verify it is NOT accessible when requiring a signature.
assertSkopeoFails(c, ".*Source image rejected: None of the signatures were accepted, reasons: Signature for identity localhost:5006/myns/mirroring-primary:direct is not accepted; Signature for identity localhost:5006/myns/mirroring-mirror:mirror-signed is not accepted; Signature for identity localhost:5006/myns/mirroring-primary:primary-signed is not accepted.*",
"--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"mirror:primary-signed", dirDest)
assertSkopeoSucceeds(c, "", "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", "--dest-tls-verify=false", regPrefix+"primary:unsigned", regPrefix+"remap:remapped")
// Verify that while a remapIdentity image is accessible using the remapped (mirror) location
assertSkopeoSucceeds(c, "" /* no --policy */, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"remap:remapped", dirDest)
// … it is NOT accessible when requiring a signature …
assertSkopeoFails(c, ".*Source image rejected: None of the signatures were accepted, reasons: Signature for identity localhost:5006/myns/mirroring-primary:direct is not accepted; Signature for identity localhost:5006/myns/mirroring-mirror:mirror-signed is not accepted; Signature for identity localhost:5006/myns/mirroring-primary:primary-signed is not accepted.*", "--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"remap:remapped", dirDest)
// … until signed.
copyWithSignedIdentity(c, regPrefix+"remap:remapped", regPrefix+"remap:remapped",
"localhost:5006/myns/mirroring-primary:remapped", "personal@example.com",
registriesDir)
assertSkopeoSucceeds(c, "", "--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"remap:remapped", dirDest)
// To be extra clear about the semantics, verify that the signedPrefix (primary) location never exists
// and only the remapped prefix (mirror) is accessed.
assertSkopeoFails(c, ".*initializing source docker://localhost:5006/myns/mirroring-primary:remapped:.*manifest unknown: manifest unknown.*", "--policy", policy, "--registries.d", registriesDir, "--registries-conf", "fixtures/registries.conf", "copy", "--src-tls-verify=false", regPrefix+"primary:remapped", dirDest)
}
func (s *SkopeoSuite) TestCopySrcWithAuth(c *check.C) {
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--dest-creds=testuser:testpassword", "docker://busybox", fmt.Sprintf("docker://%s/busybox:latest", s.regV2WithAuth.url))
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--dest-creds=testuser:testpassword", testFQIN, fmt.Sprintf("docker://%s/busybox:latest", s.regV2WithAuth.url))
dir1, err := ioutil.TempDir("", "copy-1")
c.Assert(err, check.IsNil)
defer os.RemoveAll(dir1)
@@ -1137,15 +1181,15 @@ func (s *SkopeoSuite) TestCopySrcWithAuth(c *check.C) {
}
func (s *SkopeoSuite) TestCopyDestWithAuth(c *check.C) {
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--dest-creds=testuser:testpassword", "docker://busybox", fmt.Sprintf("docker://%s/busybox:latest", s.regV2WithAuth.url))
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--dest-creds=testuser:testpassword", testFQIN, fmt.Sprintf("docker://%s/busybox:latest", s.regV2WithAuth.url))
}
func (s *SkopeoSuite) TestCopySrcAndDestWithAuth(c *check.C) {
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--dest-creds=testuser:testpassword", "docker://busybox", fmt.Sprintf("docker://%s/busybox:latest", s.regV2WithAuth.url))
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--dest-creds=testuser:testpassword", testFQIN, fmt.Sprintf("docker://%s/busybox:latest", s.regV2WithAuth.url))
assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--src-creds=testuser:testpassword", "--dest-creds=testuser:testpassword", fmt.Sprintf("docker://%s/busybox:latest", s.regV2WithAuth.url), fmt.Sprintf("docker://%s/test:auth", s.regV2WithAuth.url))
}
func (s *CopySuite) TestCopyNoPanicOnHTTPResponseWOTLSVerifyFalse(c *check.C) {
func (s *CopySuite) TestCopyNoPanicOnHTTPResponseWithoutTLSVerifyFalse(c *check.C) {
const ourRegistry = "docker://" + v2DockerRegistryURL + "/"
// dir:test isn't created beforehand just because we already know this could
@@ -1171,7 +1215,7 @@ func (s *CopySuite) TestCopyManifestConversion(c *check.C) {
// oci to v2s1 and vice-versa not supported yet
// get v2s2 manifest type
assertSkopeoSucceeds(c, "", "copy", "docker://busybox", "dir:"+srcDir)
assertSkopeoSucceeds(c, "", "copy", testFQIN, "dir:"+srcDir)
verifyManifestMIMEType(c, srcDir, manifest.DockerV2Schema2MediaType)
// convert from v2s2 to oci
assertSkopeoSucceeds(c, "", "copy", "--format=oci", "dir:"+srcDir, "dir:"+destDir1)
@@ -1201,7 +1245,7 @@ func (s *CopySuite) testCopySchemaConversionRegistries(c *check.C, schema1Regist
// Ensure we are working with a schema2 image.
// dir: accepts any manifest format, i.e. this makes …/input2 a schema2 source which cannot be asked to produce schema1 like ordinary docker: registries can.
assertSkopeoSucceeds(c, "", "copy", "docker://busybox", "dir:"+input2Dir)
assertSkopeoSucceeds(c, "", "copy", testFQIN, "dir:"+input2Dir)
verifyManifestMIMEType(c, input2Dir, manifest.DockerV2Schema2MediaType)
// 2→2 (the "f2t2" in tag means "from 2 to 2")
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", "dir:"+input2Dir, schema2Registry+":f2t2")
@@ -1221,14 +1265,6 @@ func (s *CopySuite) testCopySchemaConversionRegistries(c *check.C, schema1Regist
verifyManifestMIMEType(c, destDir, manifest.DockerV2Schema1SignedMediaType)
}
// Verify manifest in a dir: image at dir is expectedMIMEType.
func verifyManifestMIMEType(c *check.C, dir string, expectedMIMEType string) {
manifestBlob, err := ioutil.ReadFile(filepath.Join(dir, "manifest.json"))
c.Assert(err, check.IsNil)
mimeType := manifest.GuessMIMEType(manifestBlob)
c.Assert(mimeType, check.Equals, expectedMIMEType)
}
const regConfFixture = "./fixtures/registries.conf"
func (s *SkopeoSuite) TestSuccessCopySrcWithMirror(c *check.C) {

View File

@@ -34,10 +34,27 @@
"keyPath": "@keydir@/personal-pubkey.gpg"
}
],
"localhost:5006/myns/mirroring-remap": [
{
"type": "signedBy",
"keyType": "GPGKeys",
"keyPath": "@keydir@/personal-pubkey.gpg",
"signedIdentity": {
"type": "remapIdentity",
"prefix": "localhost:5006/myns/mirroring-remap",
"signedPrefix": "localhost:5006/myns/mirroring-primary"
}
}
],
"docker.io/openshift": [
{
"type": "insecureAcceptAnything"
}
],
"quay.io/openshift": [
{
"type": "insecureAcceptAnything"
}
]
},
"dir": {

View File

@@ -2,6 +2,7 @@ package main
import (
"bufio"
"context"
"encoding/base64"
"fmt"
"io/ioutil"
@@ -9,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/docker/docker/pkg/homedir"
"github.com/go-check/check"
@@ -62,6 +64,7 @@ func (cluster *openshiftCluster) startMaster(c *check.C) {
cmd := cluster.clusterCmd(nil, "openshift", "start", "master")
cluster.processes = append(cluster.processes, cmd)
stdout, err := cmd.StdoutPipe()
c.Assert(err, check.IsNil)
// Send both to the same pipe. This might cause the two streams to be mixed up,
// but logging actually goes only to stderr - this primarily ensure we log any
// unexpected output to stdout.
@@ -108,6 +111,8 @@ func (cluster *openshiftCluster) startMaster(c *check.C) {
gotPortCheck := false
gotLogCheck := false
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
for !gotPortCheck || !gotLogCheck {
c.Logf("Waiting for master")
select {
@@ -120,6 +125,8 @@ func (cluster *openshiftCluster) startMaster(c *check.C) {
c.Fatal("log check done, success message not found")
}
gotLogCheck = true
case <-ctx.Done():
c.Fatalf("Timed out waiting for master: %v", ctx.Err())
}
}
c.Logf("OK, master started!")
@@ -165,8 +172,14 @@ func (cluster *openshiftCluster) startRegistryProcess(c *check.C, port int, conf
terminatePortCheck <- true
}()
c.Logf("Waiting for registry to start")
<-portOpen
c.Logf("OK, Registry port open")
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
select {
case <-portOpen:
c.Logf("OK, Registry port open")
case <-ctx.Done():
c.Fatalf("Timed out waiting for registry to start: %v", ctx.Err())
}
return cmd
}

View File

@@ -19,8 +19,8 @@ to start a container, then within the container:
SKOPEO_CONTAINER_TESTS=1 PS1='nested> ' go test -tags openshift_shell -timeout=24h ./integration -v -check.v -check.vv -check.f='CopySuite.TestRunShell'
An example of what can be done within the container:
cd ..; make binary-local install
./skopeo --tls-verify=false copy --sign-by=personal@example.com docker://busybox:latest atomic:localhost:5000/myns/personal:personal
cd ..; make bin/skopeo PREFIX=/usr install
./skopeo --tls-verify=false copy --sign-by=personal@example.com docker://quay.io/libpod/busybox:latest atomic:localhost:5000/myns/personal:personal
oc get istag personal:personal -o json
curl -L -v 'http://localhost:5000/v2/'
cat ~/.docker/config.json

View File

@@ -11,8 +11,26 @@ import (
"strings"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
"github.com/go-check/check"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
)
const (
// A repository with a path with multiple components in it which
// contains multiple tags, preferably with some tags pointing to
// manifest lists, and with some tags that don't.
pullableRepo = "k8s.gcr.io/coredns/coredns"
// A tagged image in the repository that we can inspect and copy.
pullableTaggedImage = "k8s.gcr.io/coredns/coredns:v1.6.6"
// A tagged manifest list in the repository that we can inspect and copy.
pullableTaggedManifestList = "k8s.gcr.io/coredns/coredns:v1.8.0"
// A repository containing multiple tags, some of which are for
// manifest lists, and which includes a "latest" tag. We specify the
// name here without a tag.
pullableRepoWithLatestTag = "k8s.gcr.io/pause"
)
func init() {
@@ -94,8 +112,8 @@ func (s *SyncSuite) TestDocker2DirTagged(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
image := "busybox:latest"
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
image := pullableTaggedImage
imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image))
c.Assert(err, check.IsNil)
imagePath := imageRef.DockerReference().String()
@@ -117,9 +135,37 @@ func (s *SyncSuite) TestDocker2DirTagged(c *check.C) {
c.Assert(out, check.Equals, "")
}
func (s *SyncSuite) TestDocker2DirTaggedAll(c *check.C) {
tmpDir, err := ioutil.TempDir("", "skopeo-sync-test")
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
image := pullableTaggedManifestList
imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image))
c.Assert(err, check.IsNil)
imagePath := imageRef.DockerReference().String()
dir1 := path.Join(tmpDir, "dir1")
dir2 := path.Join(tmpDir, "dir2")
// sync docker => dir
assertSkopeoSucceeds(c, "", "sync", "--all", "--scoped", "--src", "docker", "--dest", "dir", image, dir1)
_, err = os.Stat(path.Join(dir1, imagePath, "manifest.json"))
c.Assert(err, check.IsNil)
// copy docker => dir
assertSkopeoSucceeds(c, "", "copy", "--all", "docker://"+image, "dir:"+dir2)
_, err = os.Stat(path.Join(dir2, "manifest.json"))
c.Assert(err, check.IsNil)
out := combinedOutputOfCommand(c, "diff", "-urN", path.Join(dir1, imagePath), dir2)
c.Assert(out, check.Equals, "")
}
func (s *SyncSuite) TestScoped(c *check.C) {
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
image := "busybox:latest"
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
image := pullableTaggedImage
imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image))
c.Assert(err, check.IsNil)
imagePath := imageRef.DockerReference().String()
@@ -127,7 +173,7 @@ func (s *SyncSuite) TestScoped(c *check.C) {
dir1, err := ioutil.TempDir("", "skopeo-sync-test")
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "sync", "--src", "docker", "--dest", "dir", image, dir1)
_, err = os.Stat(path.Join(dir1, image, "manifest.json"))
_, err = os.Stat(path.Join(dir1, path.Base(imagePath), "manifest.json"))
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "sync", "--scoped", "--src", "docker", "--dest", "dir", image, dir1)
@@ -138,30 +184,30 @@ func (s *SyncSuite) TestScoped(c *check.C) {
}
func (s *SyncSuite) TestDirIsNotOverwritten(c *check.C) {
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
image := "busybox:latest"
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
image := pullableRepoWithLatestTag
imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image))
c.Assert(err, check.IsNil)
imagePath := imageRef.DockerReference().String()
// make a copy of the image in the local registry
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", "docker://"+image, "docker://"+path.Join(v2DockerRegistryURL, image))
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", "docker://"+image, "docker://"+path.Join(v2DockerRegistryURL, reference.Path(imageRef.DockerReference())))
//sync upstream image to dir, not scoped
dir1, err := ioutil.TempDir("", "skopeo-sync-test")
c.Assert(err, check.IsNil)
assertSkopeoSucceeds(c, "", "sync", "--src", "docker", "--dest", "dir", image, dir1)
_, err = os.Stat(path.Join(dir1, image, "manifest.json"))
_, err = os.Stat(path.Join(dir1, path.Base(imagePath), "manifest.json"))
c.Assert(err, check.IsNil)
//sync local registry image to dir, not scoped
assertSkopeoFails(c, ".*Refusing to overwrite destination directory.*", "sync", "--src-tls-verify=false", "--src", "docker", "--dest", "dir", path.Join(v2DockerRegistryURL, image), dir1)
assertSkopeoFails(c, ".*Refusing to overwrite destination directory.*", "sync", "--src-tls-verify=false", "--src", "docker", "--dest", "dir", path.Join(v2DockerRegistryURL, reference.Path(imageRef.DockerReference())), dir1)
//sync local registry image to dir, scoped
imageRef, err = docker.ParseReference(fmt.Sprintf("//%s", path.Join(v2DockerRegistryURL, image)))
imageRef, err = docker.ParseReference(fmt.Sprintf("//%s", path.Join(v2DockerRegistryURL, reference.Path(imageRef.DockerReference()))))
c.Assert(err, check.IsNil)
imagePath = imageRef.DockerReference().String()
assertSkopeoSucceeds(c, "", "sync", "--scoped", "--src-tls-verify=false", "--src", "docker", "--dest", "dir", path.Join(v2DockerRegistryURL, image), dir1)
assertSkopeoSucceeds(c, "", "sync", "--scoped", "--src-tls-verify=false", "--src", "docker", "--dest", "dir", path.Join(v2DockerRegistryURL, reference.Path(imageRef.DockerReference())), dir1)
_, err = os.Stat(path.Join(dir1, imagePath, "manifest.json"))
c.Assert(err, check.IsNil)
os.RemoveAll(dir1)
@@ -173,8 +219,8 @@ func (s *SyncSuite) TestDocker2DirUntagged(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
image := "alpine"
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
image := pullableRepo
imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image))
c.Assert(err, check.IsNil)
imagePath := imageRef.DockerReference().String()
@@ -198,7 +244,7 @@ func (s *SyncSuite) TestYamlUntagged(c *check.C) {
defer os.RemoveAll(tmpDir)
dir1 := path.Join(tmpDir, "dir1")
image := "alpine"
image := pullableRepo
imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image))
c.Assert(err, check.IsNil)
imagePath := imageRef.DockerReference().Name()
@@ -209,23 +255,22 @@ func (s *SyncSuite) TestYamlUntagged(c *check.C) {
c.Check(len(tags), check.Not(check.Equals), 0)
yamlConfig := fmt.Sprintf(`
docker.io:
%s:
images:
%s:
`, image)
%s: []
`, reference.Domain(imageRef.DockerReference()), reference.Path(imageRef.DockerReference()))
//sync to the local reg
// sync to the local registry
yamlFile := path.Join(tmpDir, "registries.yaml")
ioutil.WriteFile(yamlFile, []byte(yamlConfig), 0644)
assertSkopeoSucceeds(c, "", "sync", "--scoped", "--src", "yaml", "--dest", "docker", "--dest-tls-verify=false", yamlFile, v2DockerRegistryURL)
// sync back from local reg to a folder
// sync back from local registry to a folder
os.Remove(yamlFile)
yamlConfig = fmt.Sprintf(`
%s:
tls-verify: false
images:
%s:
%s: []
`, v2DockerRegistryURL, imagePath)
ioutil.WriteFile(yamlFile, []byte(yamlConfig), 0644)
@@ -234,7 +279,9 @@ docker.io:
sysCtx = types.SystemContext{
DockerInsecureSkipTLSVerify: types.NewOptionalBool(true),
}
localTags, err := docker.GetRepositoryTags(context.Background(), &sysCtx, imageRef)
localImageRef, err := docker.ParseReference(fmt.Sprintf("//%s/%s", v2DockerRegistryURL, imagePath))
c.Assert(err, check.IsNil)
localTags, err := docker.GetRepositoryTags(context.Background(), &sysCtx, localImageRef)
c.Assert(err, check.IsNil)
c.Check(len(localTags), check.Not(check.Equals), 0)
c.Assert(len(localTags), check.Equals, len(tags))
@@ -262,9 +309,9 @@ func (s *SyncSuite) TestYamlRegex2Dir(c *check.C) {
dir1 := path.Join(tmpDir, "dir1")
yamlConfig := `
docker.io:
k8s.gcr.io:
images-by-tag-regex:
nginx: ^1\.13\.[12]-alpine-perl$ # regex string test
pause: ^[12]\.0$ # regex string test
`
// the ↑ regex strings always matches only 2 images
var nTags = 2
@@ -289,6 +336,37 @@ docker.io:
c.Assert(nManifests, check.Equals, nTags)
}
func (s *SyncSuite) TestYamlDigest2Dir(c *check.C) {
tmpDir, err := ioutil.TempDir("", "skopeo-sync-test")
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
dir1 := path.Join(tmpDir, "dir1")
yamlConfig := `
k8s.gcr.io:
images:
pause:
- sha256:59eec8837a4d942cc19a52b8c09ea75121acc38114a2c68b98983ce9356b8610
`
yamlFile := path.Join(tmpDir, "registries.yaml")
ioutil.WriteFile(yamlFile, []byte(yamlConfig), 0644)
assertSkopeoSucceeds(c, "", "sync", "--scoped", "--src", "yaml", "--dest", "dir", yamlFile, dir1)
nManifests := 0
err = filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && info.Name() == "manifest.json" {
nManifests++
return filepath.SkipDir
}
return nil
})
c.Assert(err, check.IsNil)
c.Assert(nManifests, check.Equals, 1)
}
func (s *SyncSuite) TestYaml2Dir(c *check.C) {
tmpDir, err := ioutil.TempDir("", "skopeo-sync-test")
c.Assert(err, check.IsNil)
@@ -296,21 +374,21 @@ func (s *SyncSuite) TestYaml2Dir(c *check.C) {
dir1 := path.Join(tmpDir, "dir1")
yamlConfig := `
docker.io:
k8s.gcr.io:
images:
busybox:
- latest
- musl
alpine:
- edge
- 3.8
opensuse/leap:
coredns/coredns:
- v1.8.0
- v1.7.1
k8s-dns-kube-dns:
- 1.14.12
- 1.14.13
pause:
- latest
quay.io:
images:
quay/busybox:
- latest`
quay/busybox:
- latest`
// get the number of tags
re := regexp.MustCompile(`^ +- +[^:/ ]+`)
@@ -347,10 +425,10 @@ func (s *SyncSuite) TestYamlTLSVerify(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
dir1 := path.Join(tmpDir, "dir1")
image := "busybox"
image := pullableRepoWithLatestTag
tag := "latest"
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
// copy docker => docker
assertSkopeoSucceeds(c, "", "copy", "--dest-tls-verify=false", "docker://"+image+":"+tag, localRegURL+image+":"+tag)
@@ -396,6 +474,26 @@ func (s *SyncSuite) TestYamlTLSVerify(c *check.C) {
}
func (s *SyncSuite) TestSyncManifestOutput(c *check.C) {
tmpDir, err := ioutil.TempDir("", "sync-manifest-output")
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
destDir1 := filepath.Join(tmpDir, "dest1")
destDir2 := filepath.Join(tmpDir, "dest2")
destDir3 := filepath.Join(tmpDir, "dest3")
//Split image:tag path from image URI for manifest comparison
imageDir := pullableTaggedImage[strings.LastIndex(pullableTaggedImage, "/")+1:]
assertSkopeoSucceeds(c, "", "sync", "--format=oci", "--all", "--src", "docker", "--dest", "dir", pullableTaggedImage, destDir1)
verifyManifestMIMEType(c, filepath.Join(destDir1, imageDir), imgspecv1.MediaTypeImageManifest)
assertSkopeoSucceeds(c, "", "sync", "--format=v2s2", "--all", "--src", "docker", "--dest", "dir", pullableTaggedImage, destDir2)
verifyManifestMIMEType(c, filepath.Join(destDir2, imageDir), manifest.DockerV2Schema2MediaType)
assertSkopeoSucceeds(c, "", "sync", "--format=v2s1", "--all", "--src", "docker", "--dest", "dir", pullableTaggedImage, destDir3)
verifyManifestMIMEType(c, filepath.Join(destDir3, imageDir), manifest.DockerV2Schema1SignedMediaType)
}
func (s *SyncSuite) TestDocker2DockerTagged(c *check.C) {
const localRegURL = "docker://" + v2DockerRegistryURL + "/"
@@ -403,8 +501,8 @@ func (s *SyncSuite) TestDocker2DockerTagged(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
image := "busybox:latest"
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
image := pullableTaggedImage
imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image))
c.Assert(err, check.IsNil)
imagePath := imageRef.DockerReference().String()
@@ -436,8 +534,8 @@ func (s *SyncSuite) TestDir2DockerTagged(c *check.C) {
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
// FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection.
image := "busybox:latest"
// FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection.
image := pullableRepoWithLatestTag
dir1 := path.Join(tmpDir, "dir1")
err = os.Mkdir(dir1, 0755)
@@ -446,6 +544,10 @@ func (s *SyncSuite) TestDir2DockerTagged(c *check.C) {
err = os.Mkdir(dir2, 0755)
c.Assert(err, check.IsNil)
// create leading dirs
err = os.MkdirAll(path.Dir(path.Join(dir1, image)), 0755)
c.Assert(err, check.IsNil)
// copy docker => dir
assertSkopeoSucceeds(c, "", "copy", "docker://"+image, "dir:"+path.Join(dir1, image))
_, err = os.Stat(path.Join(dir1, image, "manifest.json"))
@@ -454,9 +556,13 @@ func (s *SyncSuite) TestDir2DockerTagged(c *check.C) {
// sync dir => docker
assertSkopeoSucceeds(c, "", "sync", "--scoped", "--dest-tls-verify=false", "--src", "dir", "--dest", "docker", dir1, v2DockerRegistryURL)
// create leading dirs
err = os.MkdirAll(path.Dir(path.Join(dir2, image)), 0755)
c.Assert(err, check.IsNil)
// copy docker => dir
assertSkopeoSucceeds(c, "", "copy", "--src-tls-verify=false", localRegURL+image, "dir:"+path.Join(dir2, image))
_, err = os.Stat(path.Join(path.Join(dir2, image), "manifest.json"))
_, err = os.Stat(path.Join(dir2, image, "manifest.json"))
c.Assert(err, check.IsNil)
out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2)
@@ -519,7 +625,7 @@ func (s *SyncSuite) TestFailsWithDockerSourceUnauthorized(c *check.C) {
}
func (s *SyncSuite) TestFailsWithDockerSourceNotExisting(c *check.C) {
repo := path.Join(v2DockerRegistryURL, "imagedoesdotexist")
repo := path.Join(v2DockerRegistryURL, "imagedoesnotexist")
tmpDir, err := ioutil.TempDir("", "skopeo-sync-test")
c.Assert(err, check.IsNil)
defer os.RemoveAll(tmpDir)
@@ -529,7 +635,7 @@ func (s *SyncSuite) TestFailsWithDockerSourceNotExisting(c *check.C) {
"sync", "--scoped", "--src-tls-verify=false", "--src", "docker", "--dest", "dir", repo, tmpDir)
//tagged
assertSkopeoFails(c, ".*Error reading manifest.*",
assertSkopeoFails(c, ".*reading manifest.*",
"sync", "--scoped", "--src-tls-verify=false", "--src", "docker", "--dest", "dir", repo+":thetag", tmpDir)
}

View File

@@ -10,12 +10,17 @@ import (
"strings"
"time"
"github.com/containers/image/v5/manifest"
"github.com/go-check/check"
)
const skopeoBinary = "skopeo"
const decompressDirsBinary = "./decompress-dirs.sh"
const testFQIN = "docker://quay.io/libpod/busybox" // tag left off on purpose, some tests need to add a special one
const testFQIN64 = "docker://quay.io/libpod/busybox:amd64"
const testFQINMultiLayer = "docker://quay.io/libpod/alpine_nginx:master" // multi-layer
// consumeAndLogOutputStream takes (f, err) from an exec.*Pipe(), and causes all output to it to be logged to c.
func consumeAndLogOutputStream(c *check.C, id string, f io.ReadCloser, err error) {
c.Assert(err, check.IsNil)
@@ -200,3 +205,11 @@ func runDecompressDirs(c *check.C, regexp string, args ...string) {
c.Assert(string(out), check.Matches, "(?s)"+regexp) // (?s) : '.' will also match newlines
}
}
// Verify manifest in a dir: image at dir is expectedMIMEType.
func verifyManifestMIMEType(c *check.C, dir string, expectedMIMEType string) {
manifestBlob, err := ioutil.ReadFile(filepath.Join(dir, "manifest.json"))
c.Assert(err, check.IsNil)
mimeType := manifest.GuessMIMEType(manifestBlob)
c.Assert(mimeType, check.Equals, expectedMIMEType)
}

85
nix/default-arm64.nix Normal file
View File

@@ -0,0 +1,85 @@
let
pkgs = (import ./nixpkgs.nix {
crossSystem = {
config = "aarch64-unknown-linux-gnu";
};
config = {
packageOverrides = pkg: {
gpgme = (static pkg.gpgme);
libassuan = (static pkg.libassuan);
libgpgerror = (static pkg.libgpgerror);
libseccomp = (static pkg.libseccomp);
glib = (static pkg.glib).overrideAttrs (x: {
outputs = [ "bin" "out" "dev" ];
mesonFlags = [
"-Ddefault_library=static"
"-Ddevbindir=${placeholder ''dev''}/bin"
"-Dgtk_doc=false"
"-Dnls=disabled"
];
postInstall = ''
moveToOutput "share/glib-2.0" "$dev"
substituteInPlace "$dev/bin/gdbus-codegen" --replace "$out" "$dev"
sed -i "$dev/bin/glib-gettextize" -e "s|^gettext_dir=.*|gettext_dir=$dev/share/glib-2.0/gettext|"
sed '1i#line 1 "${x.pname}-${x.version}/include/glib-2.0/gobject/gobjectnotifyqueue.c"' \
-i "$dev"/include/glib-2.0/gobject/gobjectnotifyqueue.c
'';
});
pcsclite = (static pkg.pcsclite).overrideAttrs (x: {
configureFlags = [
"--enable-confdir=/etc"
"--enable-usbdropdir=/var/lib/pcsc/drivers"
"--disable-libsystemd"
"--disable-libudev"
"--disable-libusb"
];
buildInputs = [ pkgs.python3 pkgs.dbus ];
});
systemd = (static pkg.systemd).overrideAttrs (x: {
outputs = [ "out" "dev" ];
mesonFlags = x.mesonFlags ++ [
"-Dglib=false"
"-Dstatic-libsystemd=true"
];
});
};
};
});
static = pkg: pkg.overrideAttrs (x: {
doCheck = false;
configureFlags = (x.configureFlags or [ ]) ++ [
"--without-shared"
"--disable-shared"
];
dontDisableStatic = true;
enableSharedExecutables = false;
enableStatic = true;
});
self = with pkgs; buildGoModule rec {
name = "skopeo";
src = ./..;
vendorSha256 = null;
doCheck = false;
enableParallelBuilding = true;
outputs = [ "out" ];
nativeBuildInputs = [ bash gitMinimal go-md2man pkg-config which ];
buildInputs = [ glibc glibc.static glib gpgme libassuan libgpgerror libseccomp ];
prePatch = ''
export CFLAGS='-static -pthread'
export LDFLAGS='-s -w -static-libgcc -static'
export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"'
export BUILDTAGS='static netgo osusergo exclude_graphdriver_btrfs exclude_graphdriver_devicemapper'
export CGO_ENABLED=1
'';
buildPhase = ''
patchShebangs .
make bin/skopeo
'';
installPhase = ''
install -Dm755 bin/skopeo $out/bin/skopeo
'';
};
in
self

83
nix/default.nix Normal file
View File

@@ -0,0 +1,83 @@
{ system ? builtins.currentSystem }:
let
pkgs = (import ./nixpkgs.nix {
config = {
packageOverrides = pkg: {
gpgme = (static pkg.gpgme);
libassuan = (static pkg.libassuan);
libgpgerror = (static pkg.libgpgerror);
libseccomp = (static pkg.libseccomp);
glib = (static pkg.glib).overrideAttrs (x: {
outputs = [ "bin" "out" "dev" ];
mesonFlags = [
"-Ddefault_library=static"
"-Ddevbindir=${placeholder ''dev''}/bin"
"-Dgtk_doc=false"
"-Dnls=disabled"
];
postInstall = ''
moveToOutput "share/glib-2.0" "$dev"
substituteInPlace "$dev/bin/gdbus-codegen" --replace "$out" "$dev"
sed -i "$dev/bin/glib-gettextize" -e "s|^gettext_dir=.*|gettext_dir=$dev/share/glib-2.0/gettext|"
sed '1i#line 1 "${x.pname}-${x.version}/include/glib-2.0/gobject/gobjectnotifyqueue.c"' \
-i "$dev"/include/glib-2.0/gobject/gobjectnotifyqueue.c
'';
});
pcsclite = (static pkg.pcsclite).overrideAttrs (x: {
configureFlags = [
"--enable-confdir=/etc"
"--enable-usbdropdir=/var/lib/pcsc/drivers"
"--disable-libsystemd"
"--disable-libudev"
"--disable-libusb"
];
buildInputs = [ pkgs.python3 pkgs.dbus ];
});
systemd = (static pkg.systemd).overrideAttrs (x: {
outputs = [ "out" "dev" ];
mesonFlags = x.mesonFlags ++ [
"-Dglib=false"
"-Dstatic-libsystemd=true"
];
});
};
};
});
static = pkg: pkg.overrideAttrs (x: {
doCheck = false;
configureFlags = (x.configureFlags or [ ]) ++ [
"--without-shared"
"--disable-shared"
];
dontDisableStatic = true;
enableSharedExecutables = false;
enableStatic = true;
});
self = with pkgs; buildGoModule rec {
name = "skopeo";
src = ./..;
vendorSha256 = null;
doCheck = false;
enableParallelBuilding = true;
outputs = [ "out" ];
nativeBuildInputs = [ bash gitMinimal go-md2man pkg-config which ];
buildInputs = [ glibc glibc.static glib gpgme libassuan libgpgerror libseccomp ];
prePatch = ''
export CFLAGS='-static -pthread'
export LDFLAGS='-s -w -static-libgcc -static'
export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"'
export BUILDTAGS='static netgo osusergo exclude_graphdriver_btrfs exclude_graphdriver_devicemapper'
export CGO_ENABLED=1
'';
buildPhase = ''
patchShebangs .
make bin/skopeo
'';
installPhase = ''
install -Dm755 bin/skopeo $out/bin/skopeo
'';
};
in
self

10
nix/nixpkgs.json Normal file
View File

@@ -0,0 +1,10 @@
{
"url": "https://github.com/nixos/nixpkgs",
"rev": "2a96414d7e350160a33ed0978449c9ff5b5a6eb3",
"date": "2021-07-13T18:21:47+02:00",
"path": "/nix/store/2ai9q8ac6vxb2rrngdz82y8jxnk15cvm-nixpkgs",
"sha256": "1dzrfqdjq3yq5jjskiqflzy58l2xx6059gay9p1k07zrlm1wigy5",
"fetchSubmodules": false,
"deepClone": false,
"leaveDotGit": false
}

9
nix/nixpkgs.nix Normal file
View File

@@ -0,0 +1,9 @@
let
json = builtins.fromJSON (builtins.readFile ./nixpkgs.json);
nixpkgs = import (builtins.fetchTarball {
name = "nixos-unstable";
url = "${json.url}/archive/${json.rev}.tar.gz";
inherit (json) sha256;
});
in
nixpkgs

View File

@@ -65,59 +65,47 @@ END_EXPECT
}
@test "inspect: env" {
remote_image=docker://docker.io/fedora:latest
remote_image=docker://quay.io/libpod/fedora:31
run_skopeo inspect $remote_image
inspect_remote=$output
# Simple check on 'inspect' output with environment variables.
# 1) Get remote image values of environment variables (the value of 'Env')
# 2) Confirm substring in check_array and the value of 'Env' match.
check_array=(PATH=.* )
check_array=(FGC=f31 DISTTAG=f31container)
remote=$(jq '.Env[]' <<<"$inspect_remote")
for substr in ${check_array[@]}; do
expect_output --from="$remote" --substring "$substr"
done
}
# Tests https://github.com/containers/skopeo/pull/708
@test "inspect: image manifest list w/ diff platform" {
# When --raw is provided, can inspect show the raw manifest list, w/o
# requiring any particular platform to be present
# To test whether container image can be inspected successfully w/o
# platform dependency.
# 1) Get current platform arch
# 2) Inspect container image is different from current platform arch
# 3) Compare output w/ expected result
# This image's manifest is for an os + arch that is... um, unlikely
# to support skopeo in the foreseeable future. Or past. The image
# is created by the make-noarch-manifest script in this directory.
img=docker://quay.io/libpod/notmyarch:20210121
# Here we see a revolting workaround for a podman incompatibility
# change: in April 2020, podman info completely changed format
# of the keys. What worked until then now throws an error. We
# need to work with both old and new podman.
arch=$(podman info --format '{{.host.arch}}' || true)
if [[ -z "$arch" ]]; then
arch=$(podman info --format '{{.Host.Arch}}')
fi
# Get our host arch (what we're running on). This assumes that skopeo
# arch matches podman; it also assumes running podman >= April 2020
# (prior to that, the format keys were lower-case).
arch=$(podman info --format '{{.Host.Arch}}')
case $arch in
"amd64")
diff_arch_list="s390x ppc64le"
;;
"s390x")
diff_arch_list="amd64 ppc64le"
;;
"ppc64le")
diff_arch_list="amd64 s390x"
;;
"*")
diff_arch_list="amd64 s390x ppc64le"
;;
esac
# By default, 'inspect' tries to match our host os+arch. This should fail.
run_skopeo 1 inspect $img
expect_output --substring "parsing manifest for image: choosing image instance: no image found in manifest list for architecture $arch, variant " \
"skopeo inspect, without --raw, fails"
for arch in $diff_arch_list; do
remote_image=docker://docker.io/$arch/golang
run_skopeo inspect --tls-verify=false --raw $remote_image
remote_arch=$(jq -r '.manifests[0]["platform"]["architecture"]' <<< "$output")
expect_output --from="$remote_arch" "$arch" "platform arch of $remote_image"
done
# With --raw, we can inspect
run_skopeo inspect --raw $img
expect_output --substring "manifests.*platform.*architecture" \
"skopeo inspect --raw returns reasonable output"
# ...and what we get should be consistent with what our script created.
archinfo=$(jq -r '.manifests[0].platform | {os,variant,architecture} | join("-")' <<<"$output")
expect_output --from="$archinfo" "amigaos-1000-mc68000" \
"os - variant - architecture of $img"
}
# vim: filetype=sh

View File

@@ -14,7 +14,7 @@ function setup() {
# From remote, to dir1, to local, to dir2;
# compare dir1 and dir2, expect no changes
@test "copy: dir, round trip" {
local remote_image=docker://docker.io/library/busybox:latest
local remote_image=docker://quay.io/libpod/busybox:latest
local localimg=docker://localhost:5000/busybox:unsigned
local dir1=$TESTDIR/dir1
@@ -30,7 +30,7 @@ function setup() {
# Same as above, but using 'oci:' instead of 'dir:' and with a :latest tag
@test "copy: oci, round trip" {
local remote_image=docker://docker.io/library/busybox:latest
local remote_image=docker://quay.io/libpod/busybox:latest
local localimg=docker://localhost:5000/busybox:unsigned
local dir1=$TESTDIR/oci1
@@ -45,8 +45,8 @@ function setup() {
}
# Compression zstd
@test "copy: oci, round trip, zstd" {
local remote_image=docker://docker.io/library/busybox:latest
@test "copy: oci, zstd" {
local remote_image=docker://quay.io/libpod/busybox:latest
local dir=$TESTDIR/dir
@@ -57,11 +57,17 @@ function setup() {
# Check there is at least one file that has the zstd magic number as the first 4 bytes
(for i in $dir/blobs/sha256/*; do test "$(head -c 4 $i)" = $magic && exit 0; done; exit 1)
# Check that the manifest's description of the image's first layer is the zstd layer type
instance=$(jq -r '.manifests[0].digest' $dir/index.json)
[[ "$instance" != null ]]
mediatype=$(jq -r '.layers[0].mediaType' < $dir/blobs/${instance/://})
[[ "$mediatype" == "application/vnd.oci.image.layer.v1.tar+zstd" ]]
}
# Same image, extracted once with :tag and once without
@test "copy: oci w/ and w/o tags" {
local remote_image=docker://docker.io/library/busybox:latest
local remote_image=docker://quay.io/libpod/busybox:latest
local dir1=$TESTDIR/dir1
local dir2=$TESTDIR/dir2
@@ -78,7 +84,7 @@ function setup() {
# Registry -> storage -> oci-archive
@test "copy: registry -> storage -> oci-archive" {
local alpine=docker.io/library/alpine:latest
local alpine=quay.io/libpod/alpine:latest
local tmp=$TESTDIR/oci
run_skopeo copy docker://$alpine containers-storage:$alpine
@@ -94,6 +100,50 @@ function setup() {
docker://localhost:5000/foo
}
# manifest format
@test "copy: manifest format" {
local remote_image=docker://quay.io/libpod/busybox:latest
local dir1=$TESTDIR/dir1
local dir2=$TESTDIR/dir2
run_skopeo copy --format v2s2 $remote_image dir:$dir1
run_skopeo copy --format oci $remote_image dir:$dir2
grep 'application/vnd.docker.distribution.manifest.v2' $dir1/manifest.json
grep 'application/vnd.oci.image' $dir2/manifest.json
}
# additional tag
@test "copy: additional tag" {
local remote_image=docker://quay.io/libpod/busybox:latest
# additional-tag is supported only for docker-archive
run_skopeo copy --additional-tag busybox:mine $remote_image \
docker-archive:$TESTDIR/mybusybox.tar:busybox:latest
mkdir -p $TESTDIR/podmanroot
run podman --root $TESTDIR/podmanroot load -i $TESTDIR/mybusybox.tar
run podman --root $TESTDIR/podmanroot images
expect_output --substring "mine"
}
# shared blob directory
@test "copy: shared blob directory" {
local remote_image=docker://quay.io/libpod/busybox:latest
local shareddir=$TESTDIR/shareddir
local dir1=$TESTDIR/dir1
local dir2=$TESTDIR/dir2
run_skopeo copy --dest-shared-blob-dir $shareddir \
$remote_image oci:$dir1
[ -n "$(ls $shareddir)" ]
[ -z "$(ls $dir1/blobs)" ]
run_skopeo copy --src-shared-blob-dir $shareddir \
oci:$dir1 oci:$dir2
diff -urN $shareddir $dir2/blobs
}
teardown() {
podman rm -f reg

View File

@@ -8,19 +8,28 @@ load helpers
function setup() {
standard_setup
start_registry --with-cert reg
start_registry --with-cert --enable-delete=true reg
}
@test "local registry, with cert" {
# Push to local registry...
run_skopeo copy --dest-cert-dir=$TESTDIR/client-auth \
docker://docker.io/library/busybox:latest \
docker://quay.io/libpod/busybox:latest \
docker://localhost:5000/busybox:unsigned
# ...and pull it back out
run_skopeo copy --src-cert-dir=$TESTDIR/client-auth \
docker://localhost:5000/busybox:unsigned \
dir:$TESTDIR/extracted
# inspect with cert
run_skopeo inspect --cert-dir=$TESTDIR/client-auth \
docker://localhost:5000/busybox:unsigned
expect_output --substring "localhost:5000/busybox"
# delete with cert
run_skopeo delete --cert-dir=$TESTDIR/client-auth \
docker://localhost:5000/busybox:unsigned
}
teardown() {

View File

@@ -18,7 +18,7 @@ function setup() {
testuser=testuser
testpassword=$(random_string 15)
start_registry --testuser=$testuser --testpassword=$testpassword reg
start_registry --testuser=$testuser --testpassword=$testpassword --enable-delete=true reg
}
@test "auth: credentials on command line" {
@@ -43,7 +43,7 @@ function setup() {
# These should pass
run_skopeo copy --dest-tls-verify=false --dcreds=$testuser:$testpassword \
docker://docker.io/library/busybox:latest \
docker://quay.io/libpod/busybox:latest \
docker://localhost:5000/busybox:mine
run_skopeo inspect --tls-verify=false --creds=$testuser:$testpassword \
docker://localhost:5000/busybox:mine
@@ -55,7 +55,7 @@ function setup() {
podman login --tls-verify=false -u $testuser -p $testpassword localhost:5000
run_skopeo copy --dest-tls-verify=false \
docker://docker.io/library/busybox:latest \
docker://quay.io/libpod/busybox:latest \
docker://localhost:5000/busybox:mine
run_skopeo inspect --tls-verify=false docker://localhost:5000/busybox:mine
expect_output --substring "localhost:5000/busybox"
@@ -67,6 +67,47 @@ function setup() {
expect_output --substring "unauthorized: authentication required"
}
@test "auth: copy with --src-creds and --dest-creds" {
run_skopeo copy --dest-tls-verify=false --dest-creds=$testuser:$testpassword \
docker://quay.io/libpod/busybox:latest \
docker://localhost:5000/busybox:mine
run_skopeo copy --src-tls-verify=false --src-creds=$testuser:$testpassword \
docker://localhost:5000/busybox:mine \
dir:$TESTDIR/dir1
run ls $TESTDIR/dir1
expect_output --substring "manifest.json"
}
@test "auth: credentials via authfile" {
podman login --tls-verify=false --authfile $TESTDIR/test.auth -u $testuser -p $testpassword localhost:5000
# copy without authfile: should fail
run_skopeo 1 copy --dest-tls-verify=false \
docker://quay.io/libpod/busybox:latest \
docker://localhost:5000/busybox:mine
# copy with authfile: should work
run_skopeo copy --dest-tls-verify=false \
--authfile $TESTDIR/test.auth \
docker://quay.io/libpod/busybox:latest \
docker://localhost:5000/busybox:mine
# inspect without authfile: should fail
run_skopeo 1 inspect --tls-verify=false docker://localhost:5000/busybox:mine
expect_output --substring "unauthorized: authentication required"
# inspect with authfile: should work
run_skopeo inspect --tls-verify=false --authfile $TESTDIR/test.auth docker://localhost:5000/busybox:mine
expect_output --substring "localhost:5000/busybox"
# delete without authfile: should fail
run_skopeo 1 delete --tls-verify=false docker://localhost:5000/busybox:mine
expect_output --substring "authentication required"
# delete with authfile: should work
run_skopeo delete --tls-verify=false --authfile $TESTDIR/test.auth docker://localhost:5000/busybox:mine
}
teardown() {
podman rm -f reg

View File

@@ -92,7 +92,7 @@ END_POLICY_JSON
fi
# Cache local copy
run_skopeo copy docker://docker.io/library/busybox:latest \
run_skopeo copy docker://quay.io/libpod/busybox:latest \
dir:$TESTDIR/busybox
# Push a bunch of images. Do so *without* --policy flag; this lets us
@@ -143,6 +143,75 @@ END_PUSH
END_TESTS
}
@test "signing: remove signature" {
run_skopeo '?' standalone-sign /dev/null busybox alice@test.redhat.com -o /dev/null
if [[ "$output" =~ 'signing is not supported' ]]; then
skip "skopeo built without support for creating signatures"
return 1
fi
if [ "$status" -ne 0 ]; then
die "exit code is $status; expected 0"
fi
# Cache local copy
run_skopeo copy docker://quay.io/libpod/busybox:latest \
dir:$TESTDIR/busybox
# Push a signed image
run_skopeo --registries.d $REGISTRIES_D \
copy --dest-tls-verify=false \
--sign-by=alice@test.redhat.com \
dir:$TESTDIR/busybox \
docker://localhost:5000/myns/alice:signed
# Fetch the image with signature
run_skopeo --registries.d $REGISTRIES_D \
--policy $POLICY_JSON \
copy --src-tls-verify=false \
docker://localhost:5000/myns/alice:signed \
dir:$TESTDIR/busybox-signed
# Fetch the image with removing signature
run_skopeo --registries.d $REGISTRIES_D \
--policy $POLICY_JSON \
copy --src-tls-verify=false \
--remove-signatures \
docker://localhost:5000/myns/alice:signed \
dir:$TESTDIR/busybox-unsigned
ls $TESTDIR/busybox-signed | grep "signature"
[ -z "$(ls $TESTDIR/busybox-unsigned | grep "signature")" ]
}
@test "signing: standalone" {
run_skopeo '?' standalone-sign /dev/null busybox alice@test.redhat.com -o /dev/null
if [[ "$output" =~ 'signing is not supported' ]]; then
skip "skopeo built without support for creating signatures"
return 1
fi
if [ "$status" -ne 0 ]; then
die "exit code is $status; expected 0"
fi
run_skopeo copy --dest-tls-verify=false \
docker://quay.io/libpod/busybox:latest \
docker://localhost:5000/busybox:latest
run_skopeo copy --src-tls-verify=false \
docker://localhost:5000/busybox:latest \
dir:$TESTDIR/busybox
# Standalone sign
run_skopeo standalone-sign -o $TESTDIR/busybox.signature \
$TESTDIR/busybox/manifest.json \
localhost:5000/busybox:latest \
alice@test.redhat.com
# Standalone verify
fingerprint=$(gpg --list-keys | grep -B1 alice.test.redhat.com | head -n 1)
run_skopeo standalone-verify $TESTDIR/busybox/manifest.json \
localhost:5000/busybox:latest \
$fingerprint \
$TESTDIR/busybox.signature
# manifest digest
digest=$(echo "$output" | awk '{print $4;}')
run_skopeo manifest-digest $TESTDIR/busybox/manifest.json
expect_output $digest
}
teardown() {
podman rm -f reg

View File

@@ -13,7 +13,7 @@ function setup() {
# delete image from registry
@test "delete: remove image from registry" {
local remote_image=docker://docker.io/library/busybox:latest
local remote_image=docker://quay.io/libpod/busybox:latest
local localimg=docker://localhost:5000/busybox:unsigned
local output=

View File

@@ -6,7 +6,7 @@ SKOPEO_BINARY=${SKOPEO_BINARY:-$(dirname ${BASH_SOURCE})/../skopeo}
SKOPEO_TIMEOUT=${SKOPEO_TIMEOUT:-300}
# Default image to run as a local registry
REGISTRY_FQIN=${SKOPEO_TEST_REGISTRY_FQIN:-docker.io/library/registry:2}
REGISTRY_FQIN=${SKOPEO_TEST_REGISTRY_FQIN:-quay.io/libpod/registry:2}
###############################################################################
# BEGIN setup/teardown
@@ -194,7 +194,7 @@ function expect_output() {
fi
# This is a multi-line message, which may in turn contain multi-line
# output, so let's format it ourself, readably
# output, so let's format it ourselves, readably
local -a actual_split
readarray -t actual_split <<<"$actual"
printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2
@@ -314,8 +314,7 @@ start_registry() {
fi
if ! egrep -q "^$testuser:" $AUTHDIR/htpasswd; then
log_and_run $PODMAN run --rm --entrypoint htpasswd $REGISTRY_FQIN \
-Bbn $testuser $testpassword >> $AUTHDIR/htpasswd
htpasswd -Bbn $testuser $testpassword >> $AUTHDIR/htpasswd
fi
reg_args+=(
@@ -332,7 +331,8 @@ start_registry() {
log_and_run openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout $AUTHDIR/domain.key -x509 -days 2 \
-out $CERT \
-subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
-subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=registry host certificate" \
-addext subjectAltName=DNS:localhost
fi
reg_args+=(

70
systemtest/make-noarch-manifest Executable file
View File

@@ -0,0 +1,70 @@
#!/bin/sh
#
# Tool for creating an image whose OS and arch will (probably) never
# match a system on which skopeo will run. This image will be used
# in the 'inspect' test.
#
set -ex
# Name and tag of the image we create
imgname=notmyarch
imgtag=$(date +%Y%m%d)
# (In case older image exists from a prior run)
buildah rmi $imgname:$imgtag &>/dev/null || true
#
# Step 1: create an image containing only a README and a copy of this script
#
id=$(buildah from scratch)
now=$(date --rfc-3339=seconds)
readme=$(mktemp -t README.XXXXXXXX)
ME=$(basename $0)
cat >| $readme <<EOF
This is a dummy image intended solely for skopeo testing.
This image was created $now
The script used to create this image is available as $ME
EOF
buildah copy $id $readme /README
buildah copy $id $0 /$ME
buildah commit $id my_tmp_image
buildah rm $id
#
# Step 2: create a manifest list, then add the above image but with
# an os+arch override.
#
buildah manifest create $imgname:$imgtag
buildah manifest add \
--os amigaos \
--arch mc68000 \
--variant 1000 \
$imgname:$imgtag my_tmp_image
# Done. Show instructions.
cat <<EOF
DONE!
You can inspect the created image with:
skopeo inspect --raw containers-storage:localhost/$imgname:$imgtag | jq .
(FIXME: is there a way to, like, mount the image and verify the files?)
If you're happy with this image, you can now:
buildah manifest push --all $imgname:$imgtag docker://quay.io/libpod/$imgname:$imgtag
Once done, you urgently need to:
buildah rmi $imgname:$imgtag my_tmp_image
If you don't do this, 'podman images' will barf catastrophically!
EOF

1
vendor/github.com/Microsoft/go-winio/CODEOWNERS generated vendored Normal file
View File

@@ -0,0 +1 @@
* @microsoft/containerplat

View File

@@ -1,4 +1,4 @@
# go-winio
# go-winio [![Build Status](https://github.com/microsoft/go-winio/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/go-winio/actions/workflows/ci.yml)
This repository contains utilities for efficiently performing Win32 IO operations in
Go. Currently, this is focused on accessing named pipes and other file handles, and

View File

@@ -1,344 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package tar implements access to tar archives.
// It aims to cover most of the variations, including those produced
// by GNU and BSD tars.
//
// References:
// http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5
// http://www.gnu.org/software/tar/manual/html_node/Standard.html
// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
package tar
import (
"bytes"
"errors"
"fmt"
"os"
"path"
"time"
)
const (
blockSize = 512
// Types
TypeReg = '0' // regular file
TypeRegA = '\x00' // regular file
TypeLink = '1' // hard link
TypeSymlink = '2' // symbolic link
TypeChar = '3' // character device node
TypeBlock = '4' // block device node
TypeDir = '5' // directory
TypeFifo = '6' // fifo node
TypeCont = '7' // reserved
TypeXHeader = 'x' // extended header
TypeXGlobalHeader = 'g' // global extended header
TypeGNULongName = 'L' // Next file has a long name
TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name
TypeGNUSparse = 'S' // sparse file
)
// A Header represents a single header in a tar archive.
// Some fields may not be populated.
type Header struct {
Name string // name of header file entry
Mode int64 // permission and mode bits
Uid int // user id of owner
Gid int // group id of owner
Size int64 // length in bytes
ModTime time.Time // modified time
Typeflag byte // type of header entry
Linkname string // target name of link
Uname string // user name of owner
Gname string // group name of owner
Devmajor int64 // major number of character or block device
Devminor int64 // minor number of character or block device
AccessTime time.Time // access time
ChangeTime time.Time // status change time
CreationTime time.Time // creation time
Xattrs map[string]string
Winheaders map[string]string
}
// File name constants from the tar spec.
const (
fileNameSize = 100 // Maximum number of bytes in a standard tar name.
fileNamePrefixSize = 155 // Maximum number of ustar extension bytes.
)
// FileInfo returns an os.FileInfo for the Header.
func (h *Header) FileInfo() os.FileInfo {
return headerFileInfo{h}
}
// headerFileInfo implements os.FileInfo.
type headerFileInfo struct {
h *Header
}
func (fi headerFileInfo) Size() int64 { return fi.h.Size }
func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime }
func (fi headerFileInfo) Sys() interface{} { return fi.h }
// Name returns the base name of the file.
func (fi headerFileInfo) Name() string {
if fi.IsDir() {
return path.Base(path.Clean(fi.h.Name))
}
return path.Base(fi.h.Name)
}
// Mode returns the permission and mode bits for the headerFileInfo.
func (fi headerFileInfo) Mode() (mode os.FileMode) {
// Set file permission bits.
mode = os.FileMode(fi.h.Mode).Perm()
// Set setuid, setgid and sticky bits.
if fi.h.Mode&c_ISUID != 0 {
// setuid
mode |= os.ModeSetuid
}
if fi.h.Mode&c_ISGID != 0 {
// setgid
mode |= os.ModeSetgid
}
if fi.h.Mode&c_ISVTX != 0 {
// sticky
mode |= os.ModeSticky
}
// Set file mode bits.
// clear perm, setuid, setgid and sticky bits.
m := os.FileMode(fi.h.Mode) &^ 07777
if m == c_ISDIR {
// directory
mode |= os.ModeDir
}
if m == c_ISFIFO {
// named pipe (FIFO)
mode |= os.ModeNamedPipe
}
if m == c_ISLNK {
// symbolic link
mode |= os.ModeSymlink
}
if m == c_ISBLK {
// device file
mode |= os.ModeDevice
}
if m == c_ISCHR {
// Unix character device
mode |= os.ModeDevice
mode |= os.ModeCharDevice
}
if m == c_ISSOCK {
// Unix domain socket
mode |= os.ModeSocket
}
switch fi.h.Typeflag {
case TypeSymlink:
// symbolic link
mode |= os.ModeSymlink
case TypeChar:
// character device node
mode |= os.ModeDevice
mode |= os.ModeCharDevice
case TypeBlock:
// block device node
mode |= os.ModeDevice
case TypeDir:
// directory
mode |= os.ModeDir
case TypeFifo:
// fifo node
mode |= os.ModeNamedPipe
}
return mode
}
// sysStat, if non-nil, populates h from system-dependent fields of fi.
var sysStat func(fi os.FileInfo, h *Header) error
// Mode constants from the tar spec.
const (
c_ISUID = 04000 // Set uid
c_ISGID = 02000 // Set gid
c_ISVTX = 01000 // Save text (sticky bit)
c_ISDIR = 040000 // Directory
c_ISFIFO = 010000 // FIFO
c_ISREG = 0100000 // Regular file
c_ISLNK = 0120000 // Symbolic link
c_ISBLK = 060000 // Block special file
c_ISCHR = 020000 // Character special file
c_ISSOCK = 0140000 // Socket
)
// Keywords for the PAX Extended Header
const (
paxAtime = "atime"
paxCharset = "charset"
paxComment = "comment"
paxCtime = "ctime" // please note that ctime is not a valid pax header.
paxCreationTime = "LIBARCHIVE.creationtime"
paxGid = "gid"
paxGname = "gname"
paxLinkpath = "linkpath"
paxMtime = "mtime"
paxPath = "path"
paxSize = "size"
paxUid = "uid"
paxUname = "uname"
paxXattr = "SCHILY.xattr."
paxWindows = "MSWINDOWS."
paxNone = ""
)
// FileInfoHeader creates a partially-populated Header from fi.
// If fi describes a symlink, FileInfoHeader records link as the link target.
// If fi describes a directory, a slash is appended to the name.
// Because os.FileInfo's Name method returns only the base name of
// the file it describes, it may be necessary to modify the Name field
// of the returned header to provide the full path name of the file.
func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
if fi == nil {
return nil, errors.New("tar: FileInfo is nil")
}
fm := fi.Mode()
h := &Header{
Name: fi.Name(),
ModTime: fi.ModTime(),
Mode: int64(fm.Perm()), // or'd with c_IS* constants later
}
switch {
case fm.IsRegular():
h.Mode |= c_ISREG
h.Typeflag = TypeReg
h.Size = fi.Size()
case fi.IsDir():
h.Typeflag = TypeDir
h.Mode |= c_ISDIR
h.Name += "/"
case fm&os.ModeSymlink != 0:
h.Typeflag = TypeSymlink
h.Mode |= c_ISLNK
h.Linkname = link
case fm&os.ModeDevice != 0:
if fm&os.ModeCharDevice != 0 {
h.Mode |= c_ISCHR
h.Typeflag = TypeChar
} else {
h.Mode |= c_ISBLK
h.Typeflag = TypeBlock
}
case fm&os.ModeNamedPipe != 0:
h.Typeflag = TypeFifo
h.Mode |= c_ISFIFO
case fm&os.ModeSocket != 0:
h.Mode |= c_ISSOCK
default:
return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
}
if fm&os.ModeSetuid != 0 {
h.Mode |= c_ISUID
}
if fm&os.ModeSetgid != 0 {
h.Mode |= c_ISGID
}
if fm&os.ModeSticky != 0 {
h.Mode |= c_ISVTX
}
// If possible, populate additional fields from OS-specific
// FileInfo fields.
if sys, ok := fi.Sys().(*Header); ok {
// This FileInfo came from a Header (not the OS). Use the
// original Header to populate all remaining fields.
h.Uid = sys.Uid
h.Gid = sys.Gid
h.Uname = sys.Uname
h.Gname = sys.Gname
h.AccessTime = sys.AccessTime
h.ChangeTime = sys.ChangeTime
if sys.Xattrs != nil {
h.Xattrs = make(map[string]string)
for k, v := range sys.Xattrs {
h.Xattrs[k] = v
}
}
if sys.Typeflag == TypeLink {
// hard link
h.Typeflag = TypeLink
h.Size = 0
h.Linkname = sys.Linkname
}
}
if sysStat != nil {
return h, sysStat(fi, h)
}
return h, nil
}
var zeroBlock = make([]byte, blockSize)
// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values.
// We compute and return both.
func checksum(header []byte) (unsigned int64, signed int64) {
for i := 0; i < len(header); i++ {
if i == 148 {
// The chksum field (header[148:156]) is special: it should be treated as space bytes.
unsigned += ' ' * 8
signed += ' ' * 8
i += 7
continue
}
unsigned += int64(header[i])
signed += int64(int8(header[i]))
}
return
}
type slicer []byte
func (sp *slicer) next(n int) (b []byte) {
s := *sp
b, *sp = s[0:n], s[n:]
return
}
func isASCII(s string) bool {
for _, c := range s {
if c >= 0x80 {
return false
}
}
return true
}
func toASCII(s string) string {
if isASCII(s) {
return s
}
var buf bytes.Buffer
for _, c := range s {
if c < 0x80 {
buf.WriteByte(byte(c))
}
}
return buf.String()
}
// isHeaderOnlyType checks if the given type flag is of the type that has no
// data section even if a size is specified.
func isHeaderOnlyType(flag byte) bool {
switch flag {
case TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, TypeFifo:
return true
default:
return false
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux dragonfly openbsd solaris
package tar
import (
"syscall"
"time"
)
func statAtime(st *syscall.Stat_t) time.Time {
return time.Unix(st.Atim.Unix())
}
func statCtime(st *syscall.Stat_t) time.Time {
return time.Unix(st.Ctim.Unix())
}

View File

@@ -1,20 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin freebsd netbsd
package tar
import (
"syscall"
"time"
)
func statAtime(st *syscall.Stat_t) time.Time {
return time.Unix(st.Atimespec.Unix())
}
func statCtime(st *syscall.Stat_t) time.Time {
return time.Unix(st.Ctimespec.Unix())
}

View File

@@ -1,32 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux darwin dragonfly freebsd openbsd netbsd solaris
package tar
import (
"os"
"syscall"
)
func init() {
sysStat = statUnix
}
func statUnix(fi os.FileInfo, h *Header) error {
sys, ok := fi.Sys().(*syscall.Stat_t)
if !ok {
return nil
}
h.Uid = int(sys.Uid)
h.Gid = int(sys.Gid)
// TODO(bradfitz): populate username & group. os/user
// doesn't cache LookupId lookups, and lacks group
// lookup functions.
h.AccessTime = statAtime(sys)
h.ChangeTime = statCtime(sys)
// TODO(bradfitz): major/minor device numbers?
return nil
}

View File

@@ -1,444 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tar
// TODO(dsymonds):
// - catch more errors (no first header, etc.)
import (
"bytes"
"errors"
"fmt"
"io"
"path"
"sort"
"strconv"
"strings"
"time"
)
var (
ErrWriteTooLong = errors.New("archive/tar: write too long")
ErrFieldTooLong = errors.New("archive/tar: header field too long")
ErrWriteAfterClose = errors.New("archive/tar: write after close")
errInvalidHeader = errors.New("archive/tar: header field too long or contains invalid values")
)
// A Writer provides sequential writing of a tar archive in POSIX.1 format.
// A tar archive consists of a sequence of files.
// Call WriteHeader to begin a new file, and then call Write to supply that file's data,
// writing at most hdr.Size bytes in total.
type Writer struct {
w io.Writer
err error
nb int64 // number of unwritten bytes for current file entry
pad int64 // amount of padding to write after current file entry
closed bool
usedBinary bool // whether the binary numeric field extension was used
preferPax bool // use pax header instead of binary numeric header
hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header
paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
}
type formatter struct {
err error // Last error seen
}
// NewWriter creates a new Writer writing to w.
func NewWriter(w io.Writer) *Writer { return &Writer{w: w, preferPax: true} }
// Flush finishes writing the current file (optional).
func (tw *Writer) Flush() error {
if tw.nb > 0 {
tw.err = fmt.Errorf("archive/tar: missed writing %d bytes", tw.nb)
return tw.err
}
n := tw.nb + tw.pad
for n > 0 && tw.err == nil {
nr := n
if nr > blockSize {
nr = blockSize
}
var nw int
nw, tw.err = tw.w.Write(zeroBlock[0:nr])
n -= int64(nw)
}
tw.nb = 0
tw.pad = 0
return tw.err
}
// Write s into b, terminating it with a NUL if there is room.
func (f *formatter) formatString(b []byte, s string) {
if len(s) > len(b) {
f.err = ErrFieldTooLong
return
}
ascii := toASCII(s)
copy(b, ascii)
if len(ascii) < len(b) {
b[len(ascii)] = 0
}
}
// Encode x as an octal ASCII string and write it into b with leading zeros.
func (f *formatter) formatOctal(b []byte, x int64) {
s := strconv.FormatInt(x, 8)
// leading zeros, but leave room for a NUL.
for len(s)+1 < len(b) {
s = "0" + s
}
f.formatString(b, s)
}
// fitsInBase256 reports whether x can be encoded into n bytes using base-256
// encoding. Unlike octal encoding, base-256 encoding does not require that the
// string ends with a NUL character. Thus, all n bytes are available for output.
//
// If operating in binary mode, this assumes strict GNU binary mode; which means
// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is
// equivalent to the sign bit in two's complement form.
func fitsInBase256(n int, x int64) bool {
var binBits = uint(n-1) * 8
return n >= 9 || (x >= -1<<binBits && x < 1<<binBits)
}
// Write x into b, as binary (GNUtar/star extension).
func (f *formatter) formatNumeric(b []byte, x int64) {
if fitsInBase256(len(b), x) {
for i := len(b) - 1; i >= 0; i-- {
b[i] = byte(x)
x >>= 8
}
b[0] |= 0x80 // Highest bit indicates binary format
return
}
f.formatOctal(b, 0) // Last resort, just write zero
f.err = ErrFieldTooLong
}
var (
minTime = time.Unix(0, 0)
// There is room for 11 octal digits (33 bits) of mtime.
maxTime = minTime.Add((1<<33 - 1) * time.Second)
)
// WriteHeader writes hdr and prepares to accept the file's contents.
// WriteHeader calls Flush if it is not the first header.
// Calling after a Close will return ErrWriteAfterClose.
func (tw *Writer) WriteHeader(hdr *Header) error {
return tw.writeHeader(hdr, true)
}
// WriteHeader writes hdr and prepares to accept the file's contents.
// WriteHeader calls Flush if it is not the first header.
// Calling after a Close will return ErrWriteAfterClose.
// As this method is called internally by writePax header to allow it to
// suppress writing the pax header.
func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
if tw.closed {
return ErrWriteAfterClose
}
if tw.err == nil {
tw.Flush()
}
if tw.err != nil {
return tw.err
}
// a map to hold pax header records, if any are needed
paxHeaders := make(map[string]string)
// TODO(shanemhansen): we might want to use PAX headers for
// subsecond time resolution, but for now let's just capture
// too long fields or non ascii characters
var f formatter
var header []byte
// We need to select which scratch buffer to use carefully,
// since this method is called recursively to write PAX headers.
// If allowPax is true, this is the non-recursive call, and we will use hdrBuff.
// If allowPax is false, we are being called by writePAXHeader, and hdrBuff is
// already being used by the non-recursive call, so we must use paxHdrBuff.
header = tw.hdrBuff[:]
if !allowPax {
header = tw.paxHdrBuff[:]
}
copy(header, zeroBlock)
s := slicer(header)
// Wrappers around formatter that automatically sets paxHeaders if the
// argument extends beyond the capacity of the input byte slice.
var formatString = func(b []byte, s string, paxKeyword string) {
needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s)
if needsPaxHeader {
paxHeaders[paxKeyword] = s
return
}
f.formatString(b, s)
}
var formatNumeric = func(b []byte, x int64, paxKeyword string) {
// Try octal first.
s := strconv.FormatInt(x, 8)
if len(s) < len(b) {
f.formatOctal(b, x)
return
}
// If it is too long for octal, and PAX is preferred, use a PAX header.
if paxKeyword != paxNone && tw.preferPax {
f.formatOctal(b, 0)
s := strconv.FormatInt(x, 10)
paxHeaders[paxKeyword] = s
return
}
tw.usedBinary = true
f.formatNumeric(b, x)
}
var formatTime = func(b []byte, t time.Time, paxKeyword string) {
var unixTime int64
if !t.Before(minTime) && !t.After(maxTime) {
unixTime = t.Unix()
}
formatNumeric(b, unixTime, paxNone)
// Write a PAX header if the time didn't fit precisely.
if paxKeyword != "" && tw.preferPax && allowPax && (t.Nanosecond() != 0 || !t.Before(minTime) || !t.After(maxTime)) {
paxHeaders[paxKeyword] = formatPAXTime(t)
}
}
// keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
pathHeaderBytes := s.next(fileNameSize)
formatString(pathHeaderBytes, hdr.Name, paxPath)
f.formatOctal(s.next(8), hdr.Mode) // 100:108
formatNumeric(s.next(8), int64(hdr.Uid), paxUid) // 108:116
formatNumeric(s.next(8), int64(hdr.Gid), paxGid) // 116:124
formatNumeric(s.next(12), hdr.Size, paxSize) // 124:136
formatTime(s.next(12), hdr.ModTime, paxMtime) // 136:148
s.next(8) // chksum (148:156)
s.next(1)[0] = hdr.Typeflag // 156:157
formatString(s.next(100), hdr.Linkname, paxLinkpath)
copy(s.next(8), []byte("ustar\x0000")) // 257:265
formatString(s.next(32), hdr.Uname, paxUname) // 265:297
formatString(s.next(32), hdr.Gname, paxGname) // 297:329
formatNumeric(s.next(8), hdr.Devmajor, paxNone) // 329:337
formatNumeric(s.next(8), hdr.Devminor, paxNone) // 337:345
// keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
prefixHeaderBytes := s.next(155)
formatString(prefixHeaderBytes, "", paxNone) // 345:500 prefix
// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
if tw.usedBinary {
copy(header[257:265], []byte("ustar \x00"))
}
_, paxPathUsed := paxHeaders[paxPath]
// try to use a ustar header when only the name is too long
if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
prefix, suffix, ok := splitUSTARPath(hdr.Name)
if ok {
// Since we can encode in USTAR format, disable PAX header.
delete(paxHeaders, paxPath)
// Update the path fields
formatString(pathHeaderBytes, suffix, paxNone)
formatString(prefixHeaderBytes, prefix, paxNone)
}
}
// The chksum field is terminated by a NUL and a space.
// This is different from the other octal fields.
chksum, _ := checksum(header)
f.formatOctal(header[148:155], chksum) // Never fails
header[155] = ' '
// Check if there were any formatting errors.
if f.err != nil {
tw.err = f.err
return tw.err
}
if allowPax {
if !hdr.AccessTime.IsZero() {
paxHeaders[paxAtime] = formatPAXTime(hdr.AccessTime)
}
if !hdr.ChangeTime.IsZero() {
paxHeaders[paxCtime] = formatPAXTime(hdr.ChangeTime)
}
if !hdr.CreationTime.IsZero() {
paxHeaders[paxCreationTime] = formatPAXTime(hdr.CreationTime)
}
for k, v := range hdr.Xattrs {
paxHeaders[paxXattr+k] = v
}
for k, v := range hdr.Winheaders {
paxHeaders[paxWindows+k] = v
}
}
if len(paxHeaders) > 0 {
if !allowPax {
return errInvalidHeader
}
if err := tw.writePAXHeader(hdr, paxHeaders); err != nil {
return err
}
}
tw.nb = int64(hdr.Size)
tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize
_, tw.err = tw.w.Write(header)
return tw.err
}
func formatPAXTime(t time.Time) string {
sec := t.Unix()
usec := t.Nanosecond()
s := strconv.FormatInt(sec, 10)
if usec != 0 {
s = fmt.Sprintf("%s.%09d", s, usec)
}
return s
}
// splitUSTARPath splits a path according to USTAR prefix and suffix rules.
// If the path is not splittable, then it will return ("", "", false).
func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
length := len(name)
if length <= fileNameSize || !isASCII(name) {
return "", "", false
} else if length > fileNamePrefixSize+1 {
length = fileNamePrefixSize + 1
} else if name[length-1] == '/' {
length--
}
i := strings.LastIndex(name[:length], "/")
nlen := len(name) - i - 1 // nlen is length of suffix
plen := i // plen is length of prefix
if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize {
return "", "", false
}
return name[:i], name[i+1:], true
}
// writePaxHeader writes an extended pax header to the
// archive.
func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) error {
// Prepare extended header
ext := new(Header)
ext.Typeflag = TypeXHeader
// Setting ModTime is required for reader parsing to
// succeed, and seems harmless enough.
ext.ModTime = hdr.ModTime
// The spec asks that we namespace our pseudo files
// with the current pid. However, this results in differing outputs
// for identical inputs. As such, the constant 0 is now used instead.
// golang.org/issue/12358
dir, file := path.Split(hdr.Name)
fullName := path.Join(dir, "PaxHeaders.0", file)
ascii := toASCII(fullName)
if len(ascii) > 100 {
ascii = ascii[:100]
}
ext.Name = ascii
// Construct the body
var buf bytes.Buffer
// Keys are sorted before writing to body to allow deterministic output.
var keys []string
for k := range paxHeaders {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Fprint(&buf, formatPAXRecord(k, paxHeaders[k]))
}
ext.Size = int64(len(buf.Bytes()))
if err := tw.writeHeader(ext, false); err != nil {
return err
}
if _, err := tw.Write(buf.Bytes()); err != nil {
return err
}
if err := tw.Flush(); err != nil {
return err
}
return nil
}
// formatPAXRecord formats a single PAX record, prefixing it with the
// appropriate length.
func formatPAXRecord(k, v string) string {
const padding = 3 // Extra padding for ' ', '=', and '\n'
size := len(k) + len(v) + padding
size += len(strconv.Itoa(size))
record := fmt.Sprintf("%d %s=%s\n", size, k, v)
// Final adjustment if adding size field increased the record size.
if len(record) != size {
size = len(record)
record = fmt.Sprintf("%d %s=%s\n", size, k, v)
}
return record
}
// Write writes to the current entry in the tar archive.
// Write returns the error ErrWriteTooLong if more than
// hdr.Size bytes are written after WriteHeader.
func (tw *Writer) Write(b []byte) (n int, err error) {
if tw.closed {
err = ErrWriteAfterClose
return
}
overwrite := false
if int64(len(b)) > tw.nb {
b = b[0:tw.nb]
overwrite = true
}
n, err = tw.w.Write(b)
tw.nb -= int64(n)
if err == nil && overwrite {
err = ErrWriteTooLong
return
}
tw.err = err
return
}
// Close closes the tar archive, flushing any unwritten
// data to the underlying writer.
func (tw *Writer) Close() error {
if tw.err != nil || tw.closed {
return tw.err
}
tw.Flush()
tw.closed = true
if tw.err != nil {
return tw.err
}
// trailer: two zero blocks
for i := 0; i < 2; i++ {
_, tw.err = tw.w.Write(zeroBlock)
if tw.err != nil {
break
}
}
return tw.err
}

View File

@@ -0,0 +1,68 @@
package backuptar
import (
"archive/tar"
"fmt"
"strconv"
"strings"
"time"
)
// Functions copied from https://github.com/golang/go/blob/master/src/archive/tar/strconv.go
// as we need to manage the LIBARCHIVE.creationtime PAXRecord manually.
// Idea taken from containerd which did the same thing.
// parsePAXTime takes a string of the form %d.%d as described in the PAX
// specification. Note that this implementation allows for negative timestamps,
// which is allowed for by the PAX specification, but not always portable.
func parsePAXTime(s string) (time.Time, error) {
const maxNanoSecondDigits = 9
// Split string into seconds and sub-seconds parts.
ss, sn := s, ""
if pos := strings.IndexByte(s, '.'); pos >= 0 {
ss, sn = s[:pos], s[pos+1:]
}
// Parse the seconds.
secs, err := strconv.ParseInt(ss, 10, 64)
if err != nil {
return time.Time{}, tar.ErrHeader
}
if len(sn) == 0 {
return time.Unix(secs, 0), nil // No sub-second values
}
// Parse the nanoseconds.
if strings.Trim(sn, "0123456789") != "" {
return time.Time{}, tar.ErrHeader
}
if len(sn) < maxNanoSecondDigits {
sn += strings.Repeat("0", maxNanoSecondDigits-len(sn)) // Right pad
} else {
sn = sn[:maxNanoSecondDigits] // Right truncate
}
nsecs, _ := strconv.ParseInt(sn, 10, 64) // Must succeed
if len(ss) > 0 && ss[0] == '-' {
return time.Unix(secs, -1*nsecs), nil // Negative correction
}
return time.Unix(secs, nsecs), nil
}
// formatPAXTime converts ts into a time of the form %d.%d as described in the
// PAX specification. This function is capable of negative timestamps.
func formatPAXTime(ts time.Time) (s string) {
secs, nsecs := ts.Unix(), ts.Nanosecond()
if nsecs == 0 {
return strconv.FormatInt(secs, 10)
}
// If seconds is negative, then perform correction.
sign := ""
if secs < 0 {
sign = "-" // Remember sign
secs = -(secs + 1) // Add a second to secs
nsecs = -(nsecs - 1e9) // Take that second away from nsecs
}
return strings.TrimRight(fmt.Sprintf("%s%d.%09d", sign, secs, nsecs), "0")
}

View File

@@ -3,6 +3,7 @@
package backuptar
import (
"archive/tar"
"encoding/base64"
"errors"
"fmt"
@@ -15,7 +16,7 @@ import (
"time"
"github.com/Microsoft/go-winio"
"github.com/Microsoft/go-winio/archive/tar" // until archive/tar supports pax extensions in its interface
"golang.org/x/sys/windows"
)
const (
@@ -32,11 +33,13 @@ const (
)
const (
hdrFileAttributes = "fileattr"
hdrSecurityDescriptor = "sd"
hdrRawSecurityDescriptor = "rawsd"
hdrMountPoint = "mountpoint"
hdrEaPrefix = "xattr."
hdrFileAttributes = "MSWINDOWS.fileattr"
hdrSecurityDescriptor = "MSWINDOWS.sd"
hdrRawSecurityDescriptor = "MSWINDOWS.rawsd"
hdrMountPoint = "MSWINDOWS.mountpoint"
hdrEaPrefix = "MSWINDOWS.xattr."
hdrCreationTime = "LIBARCHIVE.creationtime"
)
func writeZeroes(w io.Writer, count int64) error {
@@ -86,16 +89,17 @@ func copySparse(t *tar.Writer, br *winio.BackupStreamReader) error {
// BasicInfoHeader creates a tar header from basic file information.
func BasicInfoHeader(name string, size int64, fileInfo *winio.FileBasicInfo) *tar.Header {
hdr := &tar.Header{
Name: filepath.ToSlash(name),
Size: size,
Typeflag: tar.TypeReg,
ModTime: time.Unix(0, fileInfo.LastWriteTime.Nanoseconds()),
ChangeTime: time.Unix(0, fileInfo.ChangeTime.Nanoseconds()),
AccessTime: time.Unix(0, fileInfo.LastAccessTime.Nanoseconds()),
CreationTime: time.Unix(0, fileInfo.CreationTime.Nanoseconds()),
Winheaders: make(map[string]string),
Format: tar.FormatPAX,
Name: filepath.ToSlash(name),
Size: size,
Typeflag: tar.TypeReg,
ModTime: time.Unix(0, fileInfo.LastWriteTime.Nanoseconds()),
ChangeTime: time.Unix(0, fileInfo.ChangeTime.Nanoseconds()),
AccessTime: time.Unix(0, fileInfo.LastAccessTime.Nanoseconds()),
PAXRecords: make(map[string]string),
}
hdr.Winheaders[hdrFileAttributes] = fmt.Sprintf("%d", fileInfo.FileAttributes)
hdr.PAXRecords[hdrFileAttributes] = fmt.Sprintf("%d", fileInfo.FileAttributes)
hdr.PAXRecords[hdrCreationTime] = formatPAXTime(time.Unix(0, fileInfo.CreationTime.Nanoseconds()))
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
hdr.Mode |= c_ISDIR
@@ -155,7 +159,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
if err != nil {
return err
}
hdr.Winheaders[hdrRawSecurityDescriptor] = base64.StdEncoding.EncodeToString(sd)
hdr.PAXRecords[hdrRawSecurityDescriptor] = base64.StdEncoding.EncodeToString(sd)
case winio.BackupReparseData:
hdr.Mode |= c_ISLNK
@@ -166,7 +170,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
return err
}
if rp.IsMountPoint {
hdr.Winheaders[hdrMountPoint] = "1"
hdr.PAXRecords[hdrMountPoint] = "1"
}
hdr.Linkname = rp.Target
@@ -183,7 +187,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
// Use base64 encoding for the binary value. Note that there
// is no way to encode the EA's flags, since their use doesn't
// make any sense for persisted EAs.
hdr.Winheaders[hdrEaPrefix+ea.Name] = base64.StdEncoding.EncodeToString(ea.Value)
hdr.PAXRecords[hdrEaPrefix+ea.Name] = base64.StdEncoding.EncodeToString(ea.Value)
}
case winio.BackupAlternateData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData:
@@ -254,6 +258,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
}
if (bhdr.Attributes & winio.StreamSparseAttributes) == 0 {
hdr = &tar.Header{
Format: hdr.Format,
Name: name + altName,
Mode: hdr.Mode,
Typeflag: tar.TypeReg,
@@ -293,12 +298,13 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win
size = hdr.Size
}
fileInfo = &winio.FileBasicInfo{
LastAccessTime: syscall.NsecToFiletime(hdr.AccessTime.UnixNano()),
LastWriteTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()),
ChangeTime: syscall.NsecToFiletime(hdr.ChangeTime.UnixNano()),
CreationTime: syscall.NsecToFiletime(hdr.CreationTime.UnixNano()),
LastAccessTime: windows.NsecToFiletime(hdr.AccessTime.UnixNano()),
LastWriteTime: windows.NsecToFiletime(hdr.ModTime.UnixNano()),
ChangeTime: windows.NsecToFiletime(hdr.ChangeTime.UnixNano()),
// Default to ModTime, we'll pull hdrCreationTime below if present
CreationTime: windows.NsecToFiletime(hdr.ModTime.UnixNano()),
}
if attrStr, ok := hdr.Winheaders[hdrFileAttributes]; ok {
if attrStr, ok := hdr.PAXRecords[hdrFileAttributes]; ok {
attr, err := strconv.ParseUint(attrStr, 10, 32)
if err != nil {
return "", 0, nil, err
@@ -309,6 +315,13 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win
fileInfo.FileAttributes |= syscall.FILE_ATTRIBUTE_DIRECTORY
}
}
if creationTimeStr, ok := hdr.PAXRecords[hdrCreationTime]; ok {
creationTime, err := parsePAXTime(creationTimeStr)
if err != nil {
return "", 0, nil, err
}
fileInfo.CreationTime = windows.NsecToFiletime(creationTime.UnixNano())
}
return
}
@@ -321,13 +334,13 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (
var err error
// Maintaining old SDDL-based behavior for backward compatibility. All new tar headers written
// by this library will have raw binary for the security descriptor.
if sddl, ok := hdr.Winheaders[hdrSecurityDescriptor]; ok {
if sddl, ok := hdr.PAXRecords[hdrSecurityDescriptor]; ok {
sd, err = winio.SddlToSecurityDescriptor(sddl)
if err != nil {
return nil, err
}
}
if sdraw, ok := hdr.Winheaders[hdrRawSecurityDescriptor]; ok {
if sdraw, ok := hdr.PAXRecords[hdrRawSecurityDescriptor]; ok {
sd, err = base64.StdEncoding.DecodeString(sdraw)
if err != nil {
return nil, err
@@ -348,7 +361,7 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (
}
}
var eas []winio.ExtendedAttribute
for k, v := range hdr.Winheaders {
for k, v := range hdr.PAXRecords {
if !strings.HasPrefix(k, hdrEaPrefix) {
continue
}
@@ -380,7 +393,7 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (
}
}
if hdr.Typeflag == tar.TypeSymlink {
_, isMountPoint := hdr.Winheaders[hdrMountPoint]
_, isMountPoint := hdr.PAXRecords[hdrMountPoint]
rp := winio.ReparsePoint{
Target: filepath.FromSlash(hdr.Linkname),
IsMountPoint: isMountPoint,

View File

@@ -5,21 +5,14 @@ package winio
import (
"os"
"runtime"
"syscall"
"unsafe"
)
//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx
//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle
const (
fileBasicInfo = 0
fileIDInfo = 0x12
"golang.org/x/sys/windows"
)
// FileBasicInfo contains file access time and file attributes information.
type FileBasicInfo struct {
CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
FileAttributes uint32
pad uint32 // padding
}
@@ -27,7 +20,7 @@ type FileBasicInfo struct {
// GetFileBasicInfo retrieves times and attributes for a file.
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
bi := &FileBasicInfo{}
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
@@ -36,13 +29,32 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
// SetFileBasicInfo sets times and attributes for a file.
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return nil
}
// FileStandardInfo contains extended information for the file.
// FILE_STANDARD_INFO in WinBase.h
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info
type FileStandardInfo struct {
AllocationSize, EndOfFile int64
NumberOfLinks uint32
DeletePending, Directory bool
}
// GetFileStandardInfo retrieves ended information for the file.
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
si := &FileStandardInfo{}
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return si, nil
}
// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
// unique on a system.
type FileIDInfo struct {
@@ -53,7 +65,7 @@ type FileIDInfo struct {
// GetFileID retrieves the unique (volume, file ID) pair for a file.
func GetFileID(f *os.File) (*FileIDInfo, error) {
fileID := &FileIDInfo{}
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)

View File

@@ -3,7 +3,7 @@ module github.com/Microsoft/go-winio
go 1.12
require (
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.4.1
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
)

View File

@@ -1,18 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@@ -1,3 +1,5 @@
// +build windows
package winio
import (

View File

@@ -182,13 +182,14 @@ func (s pipeAddress) String() string {
}
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
func tryDialPipe(ctx context.Context, path *string) (syscall.Handle, error) {
func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
for {
select {
case <-ctx.Done():
return syscall.Handle(0), ctx.Err()
default:
h, err := createFile(*path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
if err == nil {
return h, nil
}
@@ -197,7 +198,7 @@ func tryDialPipe(ctx context.Context, path *string) (syscall.Handle, error) {
}
// Wait 10 msec and try again. This is a rather simplistic
// view, as we always try each 10 milliseconds.
time.Sleep(time.Millisecond * 10)
time.Sleep(10 * time.Millisecond)
}
}
}
@@ -210,7 +211,7 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
if timeout != nil {
absTimeout = time.Now().Add(*timeout)
} else {
absTimeout = time.Now().Add(time.Second * 2)
absTimeout = time.Now().Add(2 * time.Second)
}
ctx, _ := context.WithDeadline(context.Background(), absTimeout)
conn, err := DialPipeContext(ctx, path)
@@ -223,9 +224,15 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
// DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
// cancellation or timeout.
func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE)
}
// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx`
// cancellation or timeout.
func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) {
var err error
var h syscall.Handle
h, err = tryDialPipe(ctx, &path)
h, err = tryDialPipe(ctx, &path, access)
if err != nil {
return nil, err
}
@@ -422,10 +429,10 @@ type PipeConfig struct {
// when the pipe is in message mode.
MessageMode bool
// InputBufferSize specifies the size the input buffer, in bytes.
// InputBufferSize specifies the size of the input buffer, in bytes.
InputBufferSize int32
// OutputBufferSize specifies the size the input buffer, in bytes.
// OutputBufferSize specifies the size of the output buffer, in bytes.
OutputBufferSize int32
}

View File

@@ -1,3 +1,5 @@
// +build windows
// Package guid provides a GUID type. The backing structure for a GUID is
// identical to that used by the golang.org/x/sys/windows GUID type.
// There are two main binary encodings used for a GUID, the big-endian encoding,

View File

@@ -0,0 +1,161 @@
// +build windows
package security
import (
"os"
"syscall"
"unsafe"
"github.com/pkg/errors"
)
type (
accessMask uint32
accessMode uint32
desiredAccess uint32
inheritMode uint32
objectType uint32
shareMode uint32
securityInformation uint32
trusteeForm uint32
trusteeType uint32
explicitAccess struct {
accessPermissions accessMask
accessMode accessMode
inheritance inheritMode
trustee trustee
}
trustee struct {
multipleTrustee *trustee
multipleTrusteeOperation int32
trusteeForm trusteeForm
trusteeType trusteeType
name uintptr
}
)
const (
accessMaskDesiredPermission accessMask = 1 << 31 // GENERIC_READ
accessModeGrant accessMode = 1
desiredAccessReadControl desiredAccess = 0x20000
desiredAccessWriteDac desiredAccess = 0x40000
gvmga = "GrantVmGroupAccess:"
inheritModeNoInheritance inheritMode = 0x0
inheritModeSubContainersAndObjectsInherit inheritMode = 0x3
objectTypeFileObject objectType = 0x1
securityInformationDACL securityInformation = 0x4
shareModeRead shareMode = 0x1
shareModeWrite shareMode = 0x2
sidVmGroup = "S-1-5-83-0"
trusteeFormIsSid trusteeForm = 0
trusteeTypeWellKnownGroup trusteeType = 5
)
// GrantVMGroupAccess sets the DACL for a specified file or directory to
// include Grant ACE entries for the VM Group SID. This is a golang re-
// implementation of the same function in vmcompute, just not exported in
// RS5. Which kind of sucks. Sucks a lot :/
func GrantVmGroupAccess(name string) error {
// Stat (to determine if `name` is a directory).
s, err := os.Stat(name)
if err != nil {
return errors.Wrapf(err, "%s os.Stat %s", gvmga, name)
}
// Get a handle to the file/directory. Must defer Close on success.
fd, err := createFile(name, s.IsDir())
if err != nil {
return err // Already wrapped
}
defer syscall.CloseHandle(fd)
// Get the current DACL and Security Descriptor. Must defer LocalFree on success.
ot := objectTypeFileObject
si := securityInformationDACL
sd := uintptr(0)
origDACL := uintptr(0)
if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil {
return errors.Wrapf(err, "%s GetSecurityInfo %s", gvmga, name)
}
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd)))
// Generate a new DACL which is the current DACL with the required ACEs added.
// Must defer LocalFree on success.
newDACL, err := generateDACLWithAcesAdded(name, s.IsDir(), origDACL)
if err != nil {
return err // Already wrapped
}
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL)))
// And finally use SetSecurityInfo to apply the updated DACL.
if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil {
return errors.Wrapf(err, "%s SetSecurityInfo %s", gvmga, name)
}
return nil
}
// createFile is a helper function to call [Nt]CreateFile to get a handle to
// the file or directory.
func createFile(name string, isDir bool) (syscall.Handle, error) {
namep := syscall.StringToUTF16(name)
da := uint32(desiredAccessReadControl | desiredAccessWriteDac)
sm := uint32(shareModeRead | shareModeWrite)
fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
if isDir {
fa = uint32(fa | syscall.FILE_FLAG_BACKUP_SEMANTICS)
}
fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0)
if err != nil {
return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name)
}
return fd, nil
}
// generateDACLWithAcesAdded generates a new DACL with the two needed ACEs added.
// The caller is responsible for LocalFree of the returned DACL on success.
func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) {
// Generate pointers to the SIDs based on the string SIDs
sid, err := syscall.StringToSid(sidVmGroup)
if err != nil {
return 0, errors.Wrapf(err, "%s syscall.StringToSid %s %s", gvmga, name, sidVmGroup)
}
inheritance := inheritModeNoInheritance
if isDir {
inheritance = inheritModeSubContainersAndObjectsInherit
}
eaArray := []explicitAccess{
explicitAccess{
accessPermissions: accessMaskDesiredPermission,
accessMode: accessModeGrant,
inheritance: inheritance,
trustee: trustee{
trusteeForm: trusteeFormIsSid,
trusteeType: trusteeTypeWellKnownGroup,
name: uintptr(unsafe.Pointer(sid)),
},
},
}
modifiedDACL := uintptr(0)
if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil {
return 0, errors.Wrapf(err, "%s SetEntriesInAcl %s", gvmga, name)
}
return modifiedDACL, nil
}

View File

@@ -0,0 +1,7 @@
package security
//go:generate go run mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
//sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo
//sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) [failretval!=0] = advapi32.SetSecurityInfo
//sys setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) [failretval!=0] = advapi32.SetEntriesInAclW

View File

@@ -0,0 +1,70 @@
// Code generated by 'go generate'; DO NOT EDIT.
package security
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo")
procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW")
procSetSecurityInfo = modadvapi32.NewProc("SetSecurityInfo")
)
func getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) {
r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(ppsidOwner)), uintptr(unsafe.Pointer(ppsidGroup)), uintptr(unsafe.Pointer(ppDacl)), uintptr(unsafe.Pointer(ppSacl)), uintptr(unsafe.Pointer(ppSecurityDescriptor)), 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) {
r1, _, e1 := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(count), uintptr(pListOfEEs), uintptr(oldAcl), uintptr(unsafe.Pointer(newAcl)), 0, 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) {
r1, _, e1 := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(psidOwner), uintptr(psidGroup), uintptr(pDacl), uintptr(pSacl), 0, 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -28,8 +28,9 @@ const (
ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
SeBackupPrivilege = "SeBackupPrivilege"
SeRestorePrivilege = "SeRestorePrivilege"
SeBackupPrivilege = "SeBackupPrivilege"
SeRestorePrivilege = "SeRestorePrivilege"
SeSecurityPrivilege = "SeSecurityPrivilege"
)
const (

View File

@@ -1,3 +1,3 @@
package winio
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go

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