mirror of
https://github.com/containers/skopeo.git
synced 2025-09-16 15:00:14 +00:00
Add dry-run mode to copy skopeo-copy
Dry-run functionality was merged into the sync command in #1608. Here, the same sort of functionality is added to the copy command as well. Signed-off-by: Ryan Egesdahl <deriamis@gmail.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
enchelpers "github.com/containers/ocicrypt/helpers"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -39,6 +40,7 @@ type copyOptions struct {
|
||||
format commonFlag.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
|
||||
dryRun bool // Don't actually copy anything, just output what it would have done
|
||||
multiArch commonFlag.OptionalString // How to handle multi architecture images
|
||||
preserveDigests bool // Preserve digests during copy
|
||||
encryptLayer []int // The list of layers to encrypt
|
||||
@@ -82,6 +84,7 @@ See skopeo(1) section "IMAGE NAMES" for the expected format
|
||||
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.dryRun, "dry-run", false, "Run without actually copying images")
|
||||
flags.Var(commonFlag.NewOptionalStringValue(&opts.multiArch), "multi-arch", `How to handle multi-architecture images (system, all, or index-only)`)
|
||||
flags.BoolVar(&opts.preserveDigests, "preserve-digests", false, "Preserve digests of images and lists")
|
||||
flags.BoolVar(&opts.removeSignatures, "remove-signatures", false, "Do not copy signatures from SOURCE-IMAGE")
|
||||
@@ -126,6 +129,10 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) (retErr error) {
|
||||
opts.deprecatedTLSVerify.warnIfUsed([]string{"--src-tls-verify", "--dest-tls-verify"})
|
||||
imageNames := args
|
||||
|
||||
if opts.dryRun {
|
||||
logrus.Warn("Running in dry-run mode")
|
||||
}
|
||||
|
||||
if err := reexecIfNecessaryForImages(imageNames...); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -282,6 +289,11 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) (retErr error) {
|
||||
|
||||
opts.destImage.warnAboutIneffectiveOptions(destRef.Transport())
|
||||
|
||||
if opts.dryRun {
|
||||
logrus.Info(fmt.Sprintf("Would have copied from=%s to=%s", imageNames[0], imageNames[1]))
|
||||
return nil
|
||||
}
|
||||
|
||||
return retry.IfNecessary(ctx, func() error {
|
||||
manifestBytes, err := copy.Image(ctx, policyContext, destRef, srcRef, ©.Options{
|
||||
RemoveSignatures: opts.removeSignatures,
|
||||
|
@@ -32,6 +32,10 @@ If _source-image_ refers to a list of images, instead of copying just the image
|
||||
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.
|
||||
|
||||
**--dry-run**
|
||||
|
||||
Run the sync without actually copying data to the destination.
|
||||
|
||||
**--authfile** _path_
|
||||
|
||||
Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `skopeo login`.
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -127,6 +128,13 @@ func (s *copySuite) TestCopyAllWithManifestListRoundTrip() {
|
||||
assert.Equal(t, "", out)
|
||||
}
|
||||
|
||||
func (s *copySuite) TestCopyDryRun() {
|
||||
t := s.T()
|
||||
dir := t.TempDir()
|
||||
assertSkopeoSucceeds(t, "", "copy", "--dry-run", knownListImage, "dir:"+dir)
|
||||
assertDirIsEmpty(t, dir)
|
||||
}
|
||||
|
||||
func (s *copySuite) TestCopyAllWithManifestListConverge() {
|
||||
t := s.T()
|
||||
oci1 := t.TempDir()
|
||||
@@ -662,6 +670,14 @@ func assertSchema1DirImagesAreEqualExceptNames(t *testing.T, dir1, ref1, dir2, r
|
||||
assert.Equal(t, "", out)
|
||||
}
|
||||
|
||||
func assertDirIsEmpty(t *testing.T, dir string) {
|
||||
d, err := os.Open(dir)
|
||||
require.NoError(t, err)
|
||||
defer d.Close()
|
||||
_, err = d.Readdirnames(1)
|
||||
assert.Equal(t, err, io.EOF)
|
||||
}
|
||||
|
||||
// Streaming (skopeo copy)
|
||||
func (s *copySuite) TestCopyStreaming() {
|
||||
t := s.T()
|
||||
|
@@ -158,6 +158,15 @@ function setup() {
|
||||
expect_output "amd64"
|
||||
}
|
||||
|
||||
@test "copy: --dry-run" {
|
||||
local remote_image=docker://quay.io/libpod/busybox:latest
|
||||
local dir=$TESTDIR/dir
|
||||
|
||||
run_skopeo copy --dry-run $remote_image oci:$dir:latest
|
||||
expect_output --substring "Running in dry-run mode"
|
||||
expect_output --substring "Would have copied from=${remote_image} to=oci:${dir}:latest"
|
||||
}
|
||||
|
||||
teardown() {
|
||||
podman rm -f reg
|
||||
|
||||
|
Reference in New Issue
Block a user