client: Allow setting image labels on Pull() and Import()

Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
Kenfe-Mickael Laventure 2017-09-19 20:47:00 -07:00
parent b24acea276
commit df82159f4d
No known key found for this signature in database
GPG Key ID: 40CF16616B361216
7 changed files with 84 additions and 13 deletions

View File

@ -178,6 +178,9 @@ type RemoteContext struct {
// Snapshotter used for unpacking // Snapshotter used for unpacking
Snapshotter string Snapshotter string
// Labels to be applied to the created image
Labels map[string]string
// BaseHandlers are a set of handlers which get are called on dispatch. // BaseHandlers are a set of handlers which get are called on dispatch.
// These handlers always get called before any operation specific // These handlers always get called before any operation specific
// handlers. // handlers.
@ -199,7 +202,7 @@ func defaultRemoteContext() *RemoteContext {
} }
// Pull downloads the provided content into containerd's content store // Pull downloads the provided content into containerd's content store
func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Image, error) { func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) {
pullCtx := defaultRemoteContext() pullCtx := defaultRemoteContext()
for _, o := range opts { for _, o := range opts {
if err := o(c, pullCtx); err != nil { if err := o(c, pullCtx); err != nil {
@ -244,6 +247,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
imgrec := images.Image{ imgrec := images.Image{
Name: name, Name: name,
Target: desc, Target: desc,
Labels: pullCtx.Labels,
} }
is := c.ImageService() is := c.ImageService()
@ -275,7 +279,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
} }
// Push uploads the provided content to a remote resource // Push uploads the provided content to a remote resource
func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor, opts ...RemoteOpts) error { func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor, opts ...RemoteOpt) error {
pushCtx := defaultRemoteContext() pushCtx := defaultRemoteContext()
for _, o := range opts { for _, o := range opts {
if err := o(c, pushCtx); err != nil { if err := o(c, pushCtx); err != nil {
@ -485,11 +489,38 @@ const (
type importOpts struct { type importOpts struct {
format imageFormat format imageFormat
refObject string refObject string
labels map[string]string
} }
// ImportOpt allows the caller to specify import specific options // ImportOpt allows the caller to specify import specific options
type ImportOpt func(c *importOpts) error type ImportOpt func(c *importOpts) error
// WithImportLabel sets a label to be associated with an imported image
func WithImportLabel(key, value string) ImportOpt {
return func(opts *importOpts) error {
if opts.labels == nil {
opts.labels = make(map[string]string)
}
opts.labels[key] = value
return nil
}
}
// WithImportLabels associates a set of labels to an imported image
func WithImportLabels(labels map[string]string) ImportOpt {
return func(opts *importOpts) error {
if opts.labels == nil {
opts.labels = make(map[string]string)
}
for k, v := range labels {
opts.labels[k] = v
}
return nil
}
}
// WithOCIImportFormat sets the import format for an OCI image format // WithOCIImportFormat sets the import format for an OCI image format
func WithOCIImportFormat() ImportOpt { func WithOCIImportFormat() ImportOpt {
return func(c *importOpts) error { return func(c *importOpts) error {

View File

@ -33,25 +33,51 @@ func WithDialOpts(opts []grpc.DialOption) ClientOpt {
} }
} }
// RemoteOpts allows the caller to set distribution options for a remote // RemoteOpt allows the caller to set distribution options for a remote
type RemoteOpts func(*Client, *RemoteContext) error type RemoteOpt func(*Client, *RemoteContext) error
// WithPullUnpack is used to unpack an image after pull. This // WithPullUnpack is used to unpack an image after pull. This
// uses the snapshotter, content store, and diff service // uses the snapshotter, content store, and diff service
// configured for the client. // configured for the client.
func WithPullUnpack(client *Client, c *RemoteContext) error { func WithPullUnpack(_ *Client, c *RemoteContext) error {
c.Unpack = true c.Unpack = true
return nil return nil
} }
// WithPullSnapshotter specifies snapshotter name used for unpacking // WithPullSnapshotter specifies snapshotter name used for unpacking
func WithPullSnapshotter(snapshotterName string) RemoteOpts { func WithPullSnapshotter(snapshotterName string) RemoteOpt {
return func(client *Client, c *RemoteContext) error { return func(_ *Client, c *RemoteContext) error {
c.Snapshotter = snapshotterName c.Snapshotter = snapshotterName
return nil return nil
} }
} }
// WithPullLabel sets a label to be associated with a pulled reference
func WithPullLabel(key, value string) RemoteOpt {
return func(_ *Client, rc *RemoteContext) error {
if rc.Labels == nil {
rc.Labels = make(map[string]string)
}
rc.Labels[key] = value
return nil
}
}
// WithPullLabels associates a set of labels to a pulled reference
func WithPullLabels(labels map[string]string) RemoteOpt {
return func(_ *Client, rc *RemoteContext) error {
if rc.Labels == nil {
rc.Labels = make(map[string]string)
}
for k, v := range labels {
rc.Labels[k] = v
}
return nil
}
}
// WithSchema1Conversion is used to convert Docker registry schema 1 // WithSchema1Conversion is used to convert Docker registry schema 1
// manifests to oci manifests on pull. Without this option schema 1 // manifests to oci manifests on pull. Without this option schema 1
// manifests will return a not supported error. // manifests will return a not supported error.
@ -61,7 +87,7 @@ func WithSchema1Conversion(client *Client, c *RemoteContext) error {
} }
// WithResolver specifies the resolver to use. // WithResolver specifies the resolver to use.
func WithResolver(resolver remotes.Resolver) RemoteOpts { func WithResolver(resolver remotes.Resolver) RemoteOpt {
return func(client *Client, c *RemoteContext) error { return func(client *Client, c *RemoteContext) error {
c.Resolver = resolver c.Resolver = resolver
return nil return nil
@ -69,7 +95,7 @@ func WithResolver(resolver remotes.Resolver) RemoteOpts {
} }
// WithImageHandler adds a base handler to be called on dispatch. // WithImageHandler adds a base handler to be called on dispatch.
func WithImageHandler(h images.Handler) RemoteOpts { func WithImageHandler(h images.Handler) RemoteOpt {
return func(client *Client, c *RemoteContext) error { return func(client *Client, c *RemoteContext) error {
c.BaseHandlers = append(c.BaseHandlers, h) c.BaseHandlers = append(c.BaseHandlers, h)
return nil return nil

View File

@ -39,7 +39,7 @@ not use this implementation as a guide. The end goal should be having metadata,
content and snapshots ready for a direct use via the 'ctr run'. content and snapshots ready for a direct use via the 'ctr run'.
Most of this is experimental and there are few leaps to make this work.`, Most of this is experimental and there are few leaps to make this work.`,
Flags: registryFlags, Flags: append(registryFlags, labelFlag),
Action: func(clicontext *cli.Context) error { Action: func(clicontext *cli.Context) error {
var ( var (
ref = clicontext.Args().First() ref = clicontext.Args().First()
@ -84,8 +84,13 @@ func fetch(ctx context.Context, ref string, clicontext *cli.Context) (containerd
}) })
log.G(pctx).WithField("image", ref).Debug("fetching") log.G(pctx).WithField("image", ref).Debug("fetching")
labels := labelArgs(clicontext.StringSlice("label"))
img, err := client.Pull(pctx, ref, containerd.WithResolver(resolver), containerd.WithImageHandler(h), containerd.WithSchema1Conversion) img, err := client.Pull(pctx, ref,
containerd.WithPullLabels(labels),
containerd.WithResolver(resolver),
containerd.WithImageHandler(h),
containerd.WithSchema1Conversion,
)
stopProgress() stopProgress()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -21,12 +21,14 @@ var imagesImportCommand = cli.Command{
Value: "", Value: "",
Usage: "reference object e.g. tag@digest (default: use the object specified in ref)", Usage: "reference object e.g. tag@digest (default: use the object specified in ref)",
}, },
labelFlag,
}, },
Action: func(clicontext *cli.Context) error { Action: func(clicontext *cli.Context) error {
var ( var (
ref = clicontext.Args().First() ref = clicontext.Args().First()
in = clicontext.Args().Get(1) in = clicontext.Args().Get(1)
refObject = clicontext.String("ref-object") refObject = clicontext.String("ref-object")
labels = labelArgs(clicontext.StringSlice("label"))
) )
ctx, cancel := appContext(clicontext) ctx, cancel := appContext(clicontext)
@ -50,6 +52,7 @@ var imagesImportCommand = cli.Command{
ref, ref,
r, r,
containerd.WithRefObject(refObject), containerd.WithRefObject(refObject),
containerd.WithImportLabels(labels),
) )
if err != nil { if err != nil {
return err return err

View File

@ -20,7 +20,7 @@ command. As part of this process, we do the following:
2. Prepare the snapshot filesystem with the pulled resources. 2. Prepare the snapshot filesystem with the pulled resources.
3. Register metadata for the image. 3. Register metadata for the image.
`, `,
Flags: append(registryFlags, snapshotterFlags...), Flags: append(registryFlags, append(snapshotterFlags, labelFlag)...),
Action: func(clicontext *cli.Context) error { Action: func(clicontext *cli.Context) error {
var ( var (
ref = clicontext.Args().First() ref = clicontext.Args().First()

View File

@ -57,6 +57,11 @@ var (
}, },
} }
labelFlag = cli.StringSliceFlag{
Name: "label",
Usage: "labels to attach to the pulled image",
}
registryFlags = []cli.Flag{ registryFlags = []cli.Flag{
cli.BoolFlag{ cli.BoolFlag{
Name: "skip-verify,k", Name: "skip-verify,k",

View File

@ -68,6 +68,7 @@ func (c *Client) importFromOCITar(ctx context.Context, ref string, reader io.Rea
imgrec := images.Image{ imgrec := images.Image{
Name: ref, Name: ref,
Target: *desc, Target: *desc,
Labels: iopts.labels,
} }
is := c.ImageService() is := c.ImageService()
if updated, err := is.Update(ctx, imgrec, "target"); err != nil { if updated, err := is.Update(ctx, imgrec, "target"); err != nil {