fix ctr image export not found error
Signed-off-by: Jie Zhang <iamkadisi@163.com>
This commit is contained in:
parent
1a9b010de0
commit
40267382c5
@ -21,7 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||||
oci "github.com/containerd/containerd/images/oci"
|
"github.com/containerd/containerd/images/oci"
|
||||||
"github.com/containerd/containerd/reference"
|
"github.com/containerd/containerd/reference"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -52,6 +52,10 @@ Currently, only OCI format is supported.
|
|||||||
Usage: "media type of manifest digest",
|
Usage: "media type of manifest digest",
|
||||||
Value: ocispec.MediaTypeImageManifest,
|
Value: ocispec.MediaTypeImageManifest,
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "all-platforms",
|
||||||
|
Usage: "exports content from all platforms",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(context *cli.Context) error {
|
Action: func(context *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
@ -101,7 +105,14 @@ Currently, only OCI format is supported.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r, err := client.Export(ctx, &oci.V1Exporter{}, desc)
|
|
||||||
|
var (
|
||||||
|
exportOpts []oci.V1ExporterOpt
|
||||||
|
)
|
||||||
|
|
||||||
|
exportOpts = append(exportOpts, oci.WithAllPlatforms(context.Bool("all-platforms")))
|
||||||
|
|
||||||
|
r, err := client.Export(ctx, desc, exportOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
25
export.go
25
export.go
@ -20,36 +20,23 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images/oci"
|
||||||
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type exportOpts struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExportOpt allows the caller to specify export-specific options
|
|
||||||
type ExportOpt func(c *exportOpts) error
|
|
||||||
|
|
||||||
func resolveExportOpt(opts ...ExportOpt) (exportOpts, error) {
|
|
||||||
var eopts exportOpts
|
|
||||||
for _, o := range opts {
|
|
||||||
if err := o(&eopts); err != nil {
|
|
||||||
return eopts, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return eopts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export exports an image to a Tar stream.
|
// Export exports an image to a Tar stream.
|
||||||
// OCI format is used by default.
|
// OCI format is used by default.
|
||||||
// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
|
// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
|
||||||
// TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream.
|
// TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream.
|
||||||
func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocispec.Descriptor, opts ...ExportOpt) (io.ReadCloser, error) {
|
func (c *Client) Export(ctx context.Context, desc ocispec.Descriptor, opts ...oci.V1ExporterOpt) (io.ReadCloser, error) {
|
||||||
_, err := resolveExportOpt(opts...) // unused now
|
|
||||||
|
exporter, err := oci.ResolveV1ExportOpt(opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
go func() {
|
go func() {
|
||||||
pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed"))
|
pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed"))
|
||||||
|
@ -21,8 +21,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd/images/oci"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestOCIExport exports testImage as a tar stream
|
// TestOCIExport exports testImage as a tar stream
|
||||||
@ -44,7 +42,7 @@ func TestOCIExport(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
exportedStream, err := client.Export(ctx, &oci.V1Exporter{}, pulled.Target)
|
exportedStream, err := client.Export(ctx, pulled.Target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
ocispecs "github.com/opencontainers/image-spec/specs-go"
|
ocispecs "github.com/opencontainers/image-spec/specs-go"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -37,6 +38,36 @@ import (
|
|||||||
// e.g. application/vnd.docker.image.rootfs.diff.tar.gzip
|
// e.g. application/vnd.docker.image.rootfs.diff.tar.gzip
|
||||||
// -> application/vnd.oci.image.layer.v1.tar+gzip
|
// -> application/vnd.oci.image.layer.v1.tar+gzip
|
||||||
type V1Exporter struct {
|
type V1Exporter struct {
|
||||||
|
AllPlatforms bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// V1ExporterOpt allows to set additional options to a newly V1Exporter
|
||||||
|
type V1ExporterOpt func(c *V1Exporter) error
|
||||||
|
|
||||||
|
// DefaultV1Exporter return a default V1Exporter pointer
|
||||||
|
func DefaultV1Exporter() *V1Exporter {
|
||||||
|
return &V1Exporter{
|
||||||
|
AllPlatforms: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveV1ExportOpt return a new V1Exporter with V1ExporterOpt
|
||||||
|
func ResolveV1ExportOpt(opts ...V1ExporterOpt) (*V1Exporter, error) {
|
||||||
|
exporter := DefaultV1Exporter()
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(exporter); err != nil {
|
||||||
|
return exporter, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exporter, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAllPlatforms set V1Exporter`s AllPlatforms option
|
||||||
|
func WithAllPlatforms(allPlatforms bool) V1ExporterOpt {
|
||||||
|
return func(c *V1Exporter) error {
|
||||||
|
c.AllPlatforms = allPlatforms
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export implements Exporter.
|
// Export implements Exporter.
|
||||||
@ -56,8 +87,19 @@ func (oe *V1Exporter) Export(ctx context.Context, store content.Provider, desc o
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
childrenHandler := images.ChildrenHandler(store)
|
||||||
|
|
||||||
|
if !oe.AllPlatforms {
|
||||||
|
// get local default platform to fetch image manifest
|
||||||
|
p, err := platforms.Parse(platforms.DefaultString())
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "invalid platform %s", platforms.DefaultString())
|
||||||
|
}
|
||||||
|
childrenHandler = images.FilterPlatforms(childrenHandler, platforms.Any(p))
|
||||||
|
}
|
||||||
|
|
||||||
handlers := images.Handlers(
|
handlers := images.Handlers(
|
||||||
images.ChildrenHandler(store),
|
childrenHandler,
|
||||||
images.HandlerFunc(exportHandler),
|
images.HandlerFunc(exportHandler),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ import (
|
|||||||
"github.com/containerd/containerd/archive/tartest"
|
"github.com/containerd/containerd/archive/tartest"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/images/archive"
|
"github.com/containerd/containerd/images/archive"
|
||||||
"github.com/containerd/containerd/images/oci"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go"
|
specs "github.com/opencontainers/image-spec/specs-go"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -56,7 +55,7 @@ func TestOCIExportAndImport(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
exported, err := client.Export(ctx, &oci.V1Exporter{}, pulled.Target)
|
exported, err := client.Export(ctx, pulled.Target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user