Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

copy: add a --all/-a flag #741

Merged
merged 1 commit into from
Oct 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion cmd/skopeo/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type copyOptions struct {
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
}

func copyCmd(global *globalOptions) cli.Command {
Expand Down Expand Up @@ -62,6 +62,11 @@ func copyCmd(global *globalOptions) cli.Command {
Usage: "Suppress output information when copying images",
Destination: &opts.quiet,
},
cli.BoolFlag{
Name: "all, a",
Usage: "Copy all images if SOURCE-IMAGE is a list",
Destination: &opts.all,
},
cli.BoolFlag{
Name: "remove-signatures",
Usage: "Do not copy signatures from SOURCE-IMAGE",
Expand Down Expand Up @@ -147,13 +152,18 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error {
if opts.quiet {
stdout = nil
}
imageListSelection := copy.CopySystemImage
if opts.all {
imageListSelection = copy.CopyAllImages
}
_, 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,
})
return err
}
4 changes: 2 additions & 2 deletions cmd/skopeo/layers.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) {
if err != nil {
return err
}
if err := dest.PutManifest(ctx, manifest); err != nil {
if err := dest.PutManifest(ctx, manifest, nil); err != nil {
return err
}

return dest.Commit(ctx)
return dest.Commit(ctx, image.UnparsedInstance(rawSource, nil))
}
1 change: 1 addition & 0 deletions completions/bash/skopeo
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ _skopeo_copy() {
"

local boolean_options="
--all
--dest-compress
--remove-signatures
--src-no-creds
Expand Down
6 changes: 6 additions & 0 deletions docs/skopeo-copy.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ Uses the system's trust policy to validate images, rejects images not trusted by

## OPTIONS

**--all**

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 and --override-arch 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 `podman login`.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.12

require (
github.com/containers/buildah v1.8.4
github.com/containers/image/v4 v4.0.1
github.com/containers/image/v4 v4.0.2-0.20191021195858-69340234bfc6
github.com/containers/storage v1.13.4
github.com/docker/docker v0.0.0-20180522102801-da99009bbb11
github.com/dsnet/compress v0.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ github.com/containers/buildah v1.8.4 h1:06c+UNeEWMa2wA1Z7muZ0ZqUzE91sDuZJbB0BiZa
github.com/containers/buildah v1.8.4/go.mod h1:1CsiLJvyU+h+wOjnqJJOWuJCVcMxZOr5HN/gHGdzJxY=
github.com/containers/image/v4 v4.0.1 h1:idNGHChj0Pyv3vLrxul2oSVMZLeFqpoq3CjLeVgapSQ=
github.com/containers/image/v4 v4.0.1/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
github.com/containers/image/v4 v4.0.2-0.20191021195858-69340234bfc6 h1:sFL2cwC0xjphJHpa6DXhka2jTLGI5HwbnAUSAKFhg2M=
github.com/containers/image/v4 v4.0.2-0.20191021195858-69340234bfc6/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/storage v1.13.4 h1:j0bBaJDKbUHtAW1MXPFnwXJtqcH+foWeuXK1YaBV5GA=
Expand Down
380 changes: 377 additions & 3 deletions integration/copy_test.go

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions integration/decompress-dirs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash -e
# Account for differences between dir: images that are solely due to one being
# compressed (fresh from a registry) and the other not being compressed (read
# from storage, which decompressed it and had to reassemble the layer blobs).
for dir in "$@" ; do
# Updating the manifest's blob digests may change the formatting, so
# use jq to get them into similar shape.
jq -M . "${dir}"/manifest.json > "${dir}"/manifest.json.tmp && mv "${dir}"/manifest.json.tmp "${dir}"/manifest.json
for candidate in "${dir}"/???????????????????????????????????????????????????????????????? ; do
# If a digest-identified file looks like it was compressed,
# decompress it, and replace its hash and size in the manifest
# with the values for their decompressed versions.
uncompressed=`zcat "${candidate}" 2> /dev/null | sha256sum | cut -c1-64`
if test $? -eq 0 ; then
if test "$uncompressed" != e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 ; then
zcat "${candidate}" > "${dir}"/${uncompressed}
sed -r -i -e "s#sha256:$(basename ${candidate})#sha256:${uncompressed}#g" "${dir}"/manifest.json
sed -r -i -e "s#\"size\": $(wc -c < ${candidate}),#\"size\": $(wc -c < ${dir}/${uncompressed}),#g" "${dir}"/manifest.json
rm -f "${candidate}"
fi
fi
done
done
26 changes: 26 additions & 0 deletions integration/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import (
"io/ioutil"
"net"
"os/exec"
"path/filepath"
"strings"
"time"

"github.com/go-check/check"
)

const skopeoBinary = "skopeo"
const decompressDirsBinary = "./decompress-dirs.sh"

// 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) {
Expand Down Expand Up @@ -174,3 +176,27 @@ func fileFromFixture(c *check.C, inputPath string, edits map[string]string) stri
c.Assert(err, check.IsNil)
return path
}

// runDecompressDirs runs decompress-dirs.sh using exec.Command().CombinedOutput, verifies that the exit status is 0,
// and optionally that the output matches a multi-line regexp if it is nonempty; or terminates c on failure
func runDecompressDirs(c *check.C, regexp string, args ...string) {
c.Logf("Running %s %s", decompressDirsBinary, strings.Join(args, " "))
for i, dir := range args {
m, err := ioutil.ReadFile(filepath.Join(dir, "manifest.json"))
c.Assert(err, check.IsNil)
c.Logf("manifest %d before: %s", i+1, string(m))
}
out, err := exec.Command(decompressDirsBinary, args...).CombinedOutput()
c.Assert(err, check.IsNil, check.Commentf("%s", out))
for i, dir := range args {
if len(out) > 0 {
c.Logf("output: %s", out)
}
m, err := ioutil.ReadFile(filepath.Join(dir, "manifest.json"))
c.Assert(err, check.IsNil)
c.Logf("manifest %d after: %s", i+1, string(m))
}
if regexp != "" {
c.Assert(string(out), check.Matches, "(?s)"+regexp) // (?s) : '.' will also match newlines
}
}
Loading