mirror of
https://github.com/moby/moby.git
synced 2026-07-26 03:07:42 +00:00
When image is built with buildkit with containerd integration the image service has no way of knowing that the image was tagged because buildkit creates the image directly in containerd image store. Add a callback that is called by the exporter wrapper. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
103 lines
3.2 KiB
Go
103 lines
3.2 KiB
Go
package exporter
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/containerd/log"
|
|
"github.com/distribution/reference"
|
|
"github.com/docker/docker/builder/builder-next/exporter/overrides"
|
|
"github.com/moby/buildkit/exporter"
|
|
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
|
|
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
)
|
|
|
|
type BuildkitCallbacks struct {
|
|
// Exported is a Called when an image is exported by buildkit.
|
|
Exported func(ctx context.Context, id string, desc ocispec.Descriptor)
|
|
|
|
// Named is a callback that is called when an image is created in the
|
|
// containerd image store by buildkit.
|
|
Named func(ctx context.Context, ref reference.NamedTagged, desc ocispec.Descriptor)
|
|
}
|
|
|
|
// Wraps the containerimage exporter's Resolve method to apply moby-specific
|
|
// overrides to the exporter attributes.
|
|
type imageExporterMobyWrapper struct {
|
|
exp exporter.Exporter
|
|
callbacks BuildkitCallbacks
|
|
}
|
|
|
|
// NewWrapper returns an exporter wrapper that applies moby specific attributes
|
|
// and hooks the export process.
|
|
func NewWrapper(exp exporter.Exporter, callbacks BuildkitCallbacks) (exporter.Exporter, error) {
|
|
return &imageExporterMobyWrapper{
|
|
exp: exp,
|
|
callbacks: callbacks,
|
|
}, nil
|
|
}
|
|
|
|
// Resolve applies moby specific attributes to the request.
|
|
func (e *imageExporterMobyWrapper) Resolve(ctx context.Context, id int, exporterAttrs map[string]string) (exporter.ExporterInstance, error) {
|
|
if exporterAttrs == nil {
|
|
exporterAttrs = make(map[string]string)
|
|
}
|
|
reposAndTags, err := overrides.SanitizeRepoAndTags(strings.Split(exporterAttrs[string(exptypes.OptKeyName)], ","))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
exporterAttrs[string(exptypes.OptKeyName)] = strings.Join(reposAndTags, ",")
|
|
exporterAttrs[string(exptypes.OptKeyUnpack)] = "true"
|
|
if _, has := exporterAttrs[string(exptypes.OptKeyDanglingPrefix)]; !has {
|
|
exporterAttrs[string(exptypes.OptKeyDanglingPrefix)] = "moby-dangling"
|
|
}
|
|
|
|
inst, err := e.exp.Resolve(ctx, id, exporterAttrs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &imageExporterInstanceWrapper{
|
|
ExporterInstance: inst,
|
|
callbacks: e.callbacks,
|
|
}, nil
|
|
}
|
|
|
|
type imageExporterInstanceWrapper struct {
|
|
exporter.ExporterInstance
|
|
callbacks BuildkitCallbacks
|
|
}
|
|
|
|
func (i *imageExporterInstanceWrapper) Export(ctx context.Context, src *exporter.Source, inlineCache exptypes.InlineCache, sessionID string) (map[string]string, exporter.DescriptorReference, error) {
|
|
out, ref, err := i.ExporterInstance.Export(ctx, src, inlineCache, sessionID)
|
|
if err != nil {
|
|
return out, ref, err
|
|
}
|
|
|
|
desc := ref.Descriptor()
|
|
imageID := out[exptypes.ExporterImageDigestKey]
|
|
if i.callbacks.Exported != nil {
|
|
i.callbacks.Exported(ctx, imageID, desc)
|
|
}
|
|
|
|
if i.callbacks.Named != nil {
|
|
for _, name := range strings.Split(out[string(exptypes.OptKeyName)], ",") {
|
|
ref, err := reference.ParseNormalizedNamed(name)
|
|
if err != nil {
|
|
// Shouldn't happen, but log if it does and continue.
|
|
log.G(ctx).WithFields(log.Fields{
|
|
"name": name,
|
|
"error": err,
|
|
}).Warn("image named with invalid reference produced by buildkit")
|
|
continue
|
|
}
|
|
|
|
namedTagged := reference.TagNameOnly(ref).(reference.NamedTagged)
|
|
i.callbacks.Named(ctx, namedTagged, desc)
|
|
}
|
|
}
|
|
|
|
return out, ref, nil
|
|
}
|