mirror of
https://github.com/containers/skopeo.git
synced 2025-07-10 21:23:52 +00:00
Add a "copy" command for copying images
This copies an image from ImageSource to ImageDestination, e.g. skopeo copy atomic:mitr/busybox:latest dir:t-down # pull skopeo copy dir:t-up atomic:mitr/busybox:latest # push
This commit is contained in:
parent
56f9c987a2
commit
2e48975b8b
80
copy.go
Normal file
80
copy.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FIXME: Also handle schema2, and put this elsewhere:
|
||||||
|
// docker.go contains similar code, more sophisticated
|
||||||
|
// (at the very least the deduplication should be reused from there).
|
||||||
|
func manifestLayers(manifest []byte) ([]string, error) {
|
||||||
|
man := manifestSchema1{}
|
||||||
|
if err := json.Unmarshal(manifest, &man); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
layers := []string{}
|
||||||
|
for _, layer := range man.FSLayers {
|
||||||
|
layers = append(layers, layer.BlobSum)
|
||||||
|
}
|
||||||
|
return layers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyHandler(context *cli.Context) {
|
||||||
|
if len(context.Args()) != 2 {
|
||||||
|
logrus.Fatal("Usage: copy source destination")
|
||||||
|
}
|
||||||
|
|
||||||
|
src, err := parseImageSource(context, context.Args()[0])
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Error initializing %s: %s", context.Args()[0], err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
dest, err := parseImageDestination(context, context.Args()[1])
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Error initializing %s: %s", context.Args()[1], err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest, digest, err := src.GetManifest()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Error reading manifest: %s", err.Error())
|
||||||
|
}
|
||||||
|
fmt.Printf("Canonical manifest digest: %s\n", digest)
|
||||||
|
|
||||||
|
layers, err := manifestLayers(manifest)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Error parsing manifest: %s", err.Error())
|
||||||
|
}
|
||||||
|
for _, layer := range layers {
|
||||||
|
stream, err := src.GetLayer(layer)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Error reading layer %s: %s", layer, err.Error())
|
||||||
|
}
|
||||||
|
defer stream.Close()
|
||||||
|
if err := dest.PutLayer(layer, stream); err != nil {
|
||||||
|
logrus.Fatalf("Error writing layer: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sigs, err := src.GetSignatures()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Error reading signatures: %s", err.Error())
|
||||||
|
}
|
||||||
|
if err := dest.PutSignatures(sigs); err != nil {
|
||||||
|
logrus.Fatalf("Error writing signatures: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: We need to call PutManifest after PutLayer and PutSignatures. This seems ugly; move to a "set properties" + "commit" model?
|
||||||
|
if err := dest.PutManifest(manifest); err != nil {
|
||||||
|
logrus.Fatalf("Error writing manifest: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var copyCmd = cli.Command{
|
||||||
|
Name: "copy",
|
||||||
|
Action: copyHandler,
|
||||||
|
}
|
1
main.go
1
main.go
@ -60,6 +60,7 @@ func main() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
|
copyCmd,
|
||||||
inspectCmd,
|
inspectCmd,
|
||||||
layersCmd,
|
layersCmd,
|
||||||
standaloneSignCmd,
|
standaloneSignCmd,
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
.SH NAME
|
.SH NAME
|
||||||
skopeo \(em Inspect Docker images and repositories on registries
|
skopeo \(em Inspect Docker images and repositories on registries
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
\fBskopeo copy\fR source-location destination-location
|
||||||
|
.PP
|
||||||
\fBskopeo inspect\fR image-name [\fB--raw\fR]
|
\fBskopeo inspect\fR image-name [\fB--raw\fR]
|
||||||
.PP
|
.PP
|
||||||
\fBskopeo layers\fR image-name
|
\fBskopeo layers\fR image-name
|
||||||
@ -45,6 +47,15 @@ Show help
|
|||||||
.B "--version, -v"
|
.B "--version, -v"
|
||||||
print the version number
|
print the version number
|
||||||
.SH COMMANDS
|
.SH COMMANDS
|
||||||
|
.TP
|
||||||
|
.B copy
|
||||||
|
Copy an image (manifest, filesystem layers, signatures) from one location to another.
|
||||||
|
.sp
|
||||||
|
.B source-location
|
||||||
|
and
|
||||||
|
.B destination-location
|
||||||
|
can be \fBdocker://\fRdocker-reference, \fBdir:\fRlocal-path, or \fBatomic:\fRimagestream-name\fB:\fRtag .
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B inspect
|
.B inspect
|
||||||
Return low-level information on images in a registry
|
Return low-level information on images in a registry
|
||||||
|
Loading…
Reference in New Issue
Block a user