diff --git a/cache/not_nydus.go b/cache/compression.go similarity index 50% rename from cache/not_nydus.go rename to cache/compression.go index 187a2deea07da..bede8d932278e 100644 --- a/cache/not_nydus.go +++ b/cache/compression.go @@ -8,18 +8,9 @@ import ( "github.com/containerd/containerd/content" "github.com/moby/buildkit/cache/config" - "github.com/moby/buildkit/session" - "github.com/moby/buildkit/solver" - "github.com/moby/buildkit/util/compression" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) -var validAnnotations = append(compression.EStargzAnnotations, containerdUncompressed) - func needsForceCompression(ctx context.Context, cs content.Store, source ocispecs.Descriptor, refCfg config.RefConfig) bool { return refCfg.Compression.Force } - -func PatchLayers(ctx context.Context, ref ImmutableRef, refCfg config.RefConfig, remote *solver.Remote, sg session.Group) (*solver.Remote, error) { - return remote, nil -} diff --git a/cache/nydus.go b/cache/compression_nydus.go similarity index 82% rename from cache/nydus.go rename to cache/compression_nydus.go index 9acdef3441f4a..2f5f10bd172c9 100644 --- a/cache/nydus.go +++ b/cache/compression_nydus.go @@ -14,7 +14,6 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/moby/buildkit/cache/config" "github.com/moby/buildkit/session" - "github.com/moby/buildkit/solver" "github.com/moby/buildkit/util/compression" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" @@ -23,16 +22,32 @@ import ( nydusify "github.com/containerd/nydus-snapshotter/pkg/converter" ) -var validAnnotations = append( - compression.EStargzAnnotations, containerdUncompressed, - nydusify.LayerAnnotationNydusBlob, nydusify.LayerAnnotationNydusBootstrap, nydusify.LayerAnnotationNydusBlobIDs, -) +func init() { + additionalAnnotations = append( + additionalAnnotations, + nydusify.LayerAnnotationNydusBlob, nydusify.LayerAnnotationNydusBootstrap, nydusify.LayerAnnotationNydusBlobIDs, + ) +} -// mergeNydus does two steps: +// Nydus compression type can't be mixed with other compression types in the same image, +// so if `source` is this kind of layer, but the target is other compression type, we +// should do the forced compression. +func needsForceCompression(ctx context.Context, cs content.Store, source ocispecs.Descriptor, refCfg config.RefConfig) bool { + if refCfg.Compression.Force { + return true + } + isNydusBlob, _ := compression.Nydus.Is(ctx, cs, source) + if refCfg.Compression.Type == compression.Nydus { + return !isNydusBlob + } + return isNydusBlob +} + +// MergeNydus does two steps: // 1. Extracts nydus bootstrap from nydus format (nydus blob + nydus bootstrap) for each layer. // 2. Merge all nydus bootstraps into a final bootstrap (will as an extra layer). // The nydus bootstrap size is very small, so the merge operation is fast. -func mergeNydus(ctx context.Context, ref ImmutableRef, comp compression.Config, s session.Group) (*ocispecs.Descriptor, error) { +func MergeNydus(ctx context.Context, ref ImmutableRef, comp compression.Config, s session.Group) (*ocispecs.Descriptor, error) { iref, ok := ref.(*immutableRef) if !ok { return nil, fmt.Errorf("unsupported ref") @@ -131,34 +146,3 @@ func mergeNydus(ctx context.Context, ref ImmutableRef, comp compression.Config, return &desc, nil } - -// Nydus compression type can't be mixed with other compression types in the same image, -// so if `source` is this kind of layer, but the target is other compression type, we -// should do the forced compression. -func needsForceCompression(ctx context.Context, cs content.Store, source ocispecs.Descriptor, refCfg config.RefConfig) bool { - if refCfg.Compression.Force { - return true - } - isNydusBlob, _ := compression.Nydus.Is(ctx, cs, source) - if refCfg.Compression.Type == compression.Nydus { - return !isNydusBlob - } - return isNydusBlob -} - -// PatchLayers appends an extra nydus bootstrap layer -// to the manifest of nydus image, this layer represents the -// whole metadata of filesystem view for the entire image. -func PatchLayers(ctx context.Context, ref ImmutableRef, refCfg config.RefConfig, remote *solver.Remote, sg session.Group) (*solver.Remote, error) { - if refCfg.Compression.Type != compression.Nydus { - return remote, nil - } - - desc, err := mergeNydus(ctx, ref, refCfg.Compression, sg) - if err != nil { - return nil, errors.Wrap(err, "merge nydus layer") - } - remote.Descriptors = append(remote.Descriptors, *desc) - - return remote, nil -} diff --git a/cache/refs.go b/cache/refs.go index f027af96ea2c6..2bb0ba115b6ea 100644 --- a/cache/refs.go +++ b/cache/refs.go @@ -36,6 +36,8 @@ import ( "golang.org/x/sync/errgroup" ) +var additionalAnnotations = append(compression.EStargzAnnotations, containerdUncompressed) + // Ref is a reference to cacheable objects. type Ref interface { Mountable @@ -878,7 +880,7 @@ func filterAnnotationsForSave(a map[string]string) (b map[string]string) { if a == nil { return nil } - for _, k := range validAnnotations { + for _, k := range additionalAnnotations { v, ok := a[k] if !ok { continue diff --git a/exporter/containerimage/patch.go b/exporter/containerimage/patch.go new file mode 100644 index 0000000000000..3cfb1242f1622 --- /dev/null +++ b/exporter/containerimage/patch.go @@ -0,0 +1,17 @@ +//go:build !nydus +// +build !nydus + +package containerimage + +import ( + "context" + + "github.com/moby/buildkit/cache" + "github.com/moby/buildkit/session" + "github.com/moby/buildkit/solver" + ocispecs "github.com/opencontainers/image-spec/specs-go/v1" +) + +func patchImageLayers(ctx context.Context, remote *solver.Remote, history []ocispecs.History, ref cache.ImmutableRef, opts *ImageCommitOpts, sg session.Group) (*solver.Remote, []ocispecs.History, error) { + return normalizeLayersAndHistory(ctx, remote, history, ref, opts) +} diff --git a/exporter/containerimage/patch_nydus.go b/exporter/containerimage/patch_nydus.go new file mode 100644 index 0000000000000..78d55a0d7a438 --- /dev/null +++ b/exporter/containerimage/patch_nydus.go @@ -0,0 +1,33 @@ +//go:build nydus +// +build nydus + +package containerimage + +import ( + "context" + + "github.com/moby/buildkit/cache" + "github.com/moby/buildkit/session" + "github.com/moby/buildkit/solver" + "github.com/moby/buildkit/util/compression" + ocispecs "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" +) + +// patchImageLayers appends an extra nydus bootstrap layer +// to the manifest of nydus image, normalizes layers and +// history. The nydus bootstrap layer represents the whole +// metadata of filesystem view for the entire image. +func patchImageLayers(ctx context.Context, remote *solver.Remote, history []ocispecs.History, ref cache.ImmutableRef, opts *ImageCommitOpts, sg session.Group) (*solver.Remote, []ocispecs.History, error) { + if opts.RefCfg.Compression.Type != compression.Nydus { + return normalizeLayersAndHistory(ctx, remote, history, ref, opts) + } + + desc, err := cache.MergeNydus(ctx, ref, opts.RefCfg.Compression, sg) + if err != nil { + return nil, nil, errors.Wrap(err, "merge nydus layer") + } + remote.Descriptors = append(remote.Descriptors, *desc) + + return normalizeLayersAndHistory(ctx, remote, history, ref, opts) +} diff --git a/exporter/containerimage/writer.go b/exporter/containerimage/writer.go index 5303939d3aeab..e9085f534e824 100644 --- a/exporter/containerimage/writer.go +++ b/exporter/containerimage/writer.go @@ -432,13 +432,11 @@ func (ic *ImageWriter) commitDistributionManifest(ctx context.Context, opts *Ima return nil, nil, err } - remote, err = cache.PatchLayers(ctx, ref, opts.RefCfg, remote, sg) + remote, history, err = patchImageLayers(ctx, remote, history, ref, opts, sg) if err != nil { return nil, nil, err } - remote, history = normalizeLayersAndHistory(ctx, remote, history, ref, opts.OCITypes) - config, err = patchImageConfig(config, remote.Descriptors, history, inlineCache, buildInfo, epoch) if err != nil { return nil, nil, err @@ -765,7 +763,7 @@ func patchImageConfig(dt []byte, descs []ocispecs.Descriptor, history []ocispecs return dt, errors.Wrap(err, "failed to marshal config after patch") } -func normalizeLayersAndHistory(ctx context.Context, remote *solver.Remote, history []ocispecs.History, ref cache.ImmutableRef, oci bool) (*solver.Remote, []ocispecs.History) { +func normalizeLayersAndHistory(ctx context.Context, remote *solver.Remote, history []ocispecs.History, ref cache.ImmutableRef, opts *ImageCommitOpts) (*solver.Remote, []ocispecs.History, error) { refMeta := getRefMetadata(ref, len(remote.Descriptors)) var historyLayers int @@ -847,9 +845,9 @@ func normalizeLayersAndHistory(ctx context.Context, remote *solver.Remote, histo } // convert between oci and docker media types (or vice versa) if needed - remote.Descriptors = compression.ConvertAllLayerMediaTypes(oci, remote.Descriptors...) + remote.Descriptors = compression.ConvertAllLayerMediaTypes(opts.OCITypes, remote.Descriptors...) - return remote, history + return remote, history, nil } func removeInternalLayerAnnotations(desc *ocispecs.Descriptor, oci bool) { diff --git a/util/compression/not_nydus.go b/util/compression/parse.go similarity index 100% rename from util/compression/not_nydus.go rename to util/compression/parse.go