feat: export images using Transfer api
Signed-off-by: Jian Zeng <anonymousknight96@gmail.com>
This commit is contained in:
@@ -22,11 +22,15 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
"github.com/containerd/containerd/pkg/transfer"
|
||||
tarchive "github.com/containerd/containerd/pkg/transfer/archive"
|
||||
"github.com/containerd/containerd/pkg/transfer/image"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
)
|
||||
|
||||
var exportCommand = cli.Command{
|
||||
@@ -58,6 +62,10 @@ When '--all-platforms' is given all images in a manifest list must be available.
|
||||
Name: "all-platforms",
|
||||
Usage: "Exports content from all platforms",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "local",
|
||||
Usage: "run export locally rather than through transfer API",
|
||||
},
|
||||
},
|
||||
Action: func(context *cli.Context) error {
|
||||
var (
|
||||
@@ -69,6 +77,56 @@ When '--all-platforms' is given all images in a manifest list must be available.
|
||||
return errors.New("please provide both an output filename and an image reference to export")
|
||||
}
|
||||
|
||||
client, ctx, cancel, err := commands.NewClient(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
var w io.WriteCloser
|
||||
if out == "-" {
|
||||
w = os.Stdout
|
||||
} else {
|
||||
w, err = os.Create(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
if !context.BoolT("local") {
|
||||
pf, done := ProgressHandler(ctx, os.Stdout)
|
||||
defer done()
|
||||
|
||||
var specified []ocispec.Platform
|
||||
if pss := context.StringSlice("platform"); len(pss) > 0 {
|
||||
for _, ps := range pss {
|
||||
p, err := platforms.Parse(ps)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid platform %q: %w", ps, err)
|
||||
}
|
||||
specified = append(specified, p)
|
||||
}
|
||||
}
|
||||
|
||||
err := client.Transfer(ctx,
|
||||
image.NewStore(""), // a dummy image store
|
||||
tarchive.NewImageExportStream(w, "", tarchive.ExportOptions{
|
||||
Images: images,
|
||||
Platforms: specified,
|
||||
AllPlatforms: context.Bool("all-platforms"),
|
||||
SkipNonDistributable: context.Bool("skip-non-distributable"),
|
||||
SkipDockerManifest: context.Bool("skip-manifest-json"),
|
||||
}),
|
||||
transfer.WithProgress(pf),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if pss := context.StringSlice("platform"); len(pss) > 0 {
|
||||
var all []ocispec.Platform
|
||||
for _, ps := range pss {
|
||||
@@ -95,28 +153,11 @@ When '--all-platforms' is given all images in a manifest list must be available.
|
||||
exportOpts = append(exportOpts, archive.WithSkipNonDistributableBlobs())
|
||||
}
|
||||
|
||||
client, ctx, cancel, err := commands.NewClient(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
is := client.ImageService()
|
||||
for _, img := range images {
|
||||
exportOpts = append(exportOpts, archive.WithImage(is, img))
|
||||
}
|
||||
|
||||
var w io.WriteCloser
|
||||
if out == "-" {
|
||||
w = os.Stdout
|
||||
} else {
|
||||
w, err = os.Create(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
return client.Export(ctx, w, exportOpts...)
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user