From d514afdb204befbd64ea63fcc1f4e4e2f0e2b195 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Wed, 16 Jan 2019 18:06:03 -0800 Subject: [PATCH] remotecache: support createdat and fix order Signed-off-by: Tonis Tiigi --- cache/remotecache/import.go | 50 ++++++++++++++++++++++++++---- cache/remotecache/inline/inline.go | 26 ++++++++++++++-- exporter/containerimage/writer.go | 6 +++- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/cache/remotecache/import.go b/cache/remotecache/import.go index af6e2418b..5843d4fe2 100644 --- a/cache/remotecache/import.go +++ b/cache/remotecache/import.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io" "sync" + "time" "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" @@ -131,12 +132,7 @@ func (ci *contentCacheImporter) importInlineCache(ctx context.Context, dt []byte return err } - var img struct { - Rootfs struct { - DiffIDs []digest.Digest `json:"diff_ids"` - } `json:"rootfs"` - Cache json.RawMessage `json:"moby.buildkit.cache.v0"` - } + var img image if err := json.Unmarshal(p, &img); err != nil { return err @@ -156,11 +152,19 @@ func (ci *contentCacheImporter) importInlineCache(ctx context.Context, dt []byte return err } + createdDates, err := parseCreatedLayerDates(img) + if err != nil { + return err + } + layers := v1.DescriptorProvider{} for i, m := range m.Layers { if m.Annotations == nil { m.Annotations = map[string]string{} } + if createdAt := createdDates[i]; createdAt != "" { + m.Annotations["buildkit/createdat"] = createdAt + } m.Annotations["containerd.io/uncompressed"] = img.Rootfs.DiffIDs[i].String() layers[m.Digest] = v1.DescriptorProviderPair{ Descriptor: m, @@ -172,6 +176,11 @@ func (ci *contentCacheImporter) importInlineCache(ctx context.Context, dt []byte }) } + dt, err := json.Marshal(config) + if err != nil { + return err + } + mu.Lock() if err := v1.ParseConfig(config, layers, cc); err != nil { return err @@ -224,3 +233,32 @@ func (ci *contentCacheImporter) allDistributionManifests(ctx context.Context, dt return nil } + +type image struct { + Rootfs struct { + DiffIDs []digest.Digest `json:"diff_ids"` + } `json:"rootfs"` + Cache []byte `json:"moby.buildkit.cache.v0"` + History []struct { + Created *time.Time `json:"created,omitempty"` + EmptyLayer bool `json:"empty_layer,omitempty"` + } `json:"history,omitempty"` +} + +func parseCreatedLayerDates(img image) ([]string, error) { + dates := make([]string, 0, len(img.Rootfs.DiffIDs)) + for _, h := range img.History { + if !h.EmptyLayer { + str := "" + if h.Created != nil { + dt, err := h.Created.MarshalText() + if err != nil { + return nil, err + } + str = string(dt) + } + dates = append(dates, str) + } + } + return dates, nil +} diff --git a/cache/remotecache/inline/inline.go b/cache/remotecache/inline/inline.go index 59a79ea6c..39ca35355 100644 --- a/cache/remotecache/inline/inline.go +++ b/cache/remotecache/inline/inline.go @@ -45,7 +45,7 @@ func (ce *exporter) ExportForLayers(layers []digest.Digest) ([]byte, error) { } cc := v1.NewCacheChains() - if err := v1.ParseConfig(*config, descs, cc); err != nil { + if err := v1.ParseConfig(*config, descs2, cc); err != nil { return nil, err } @@ -59,7 +59,17 @@ func (ce *exporter) ExportForLayers(layers []digest.Digest) ([]byte, error) { return nil, nil } - // TODO: are the layers always ordered already or should we check? + cache := map[digest.Digest]int{} + + // reorder layers based on the order in the image + for i, r := range cfg.Records { + for j, rr := range r.Results { + n := getSortedLayerIndex(rr.LayerIndex, cfg.Layers, cache) + rr.LayerIndex = n + r.Results[j] = rr + cfg.Records[i] = r + } + } dt, err := json.Marshal(cfg.Records) if err != nil { @@ -68,3 +78,15 @@ func (ce *exporter) ExportForLayers(layers []digest.Digest) ([]byte, error) { return dt, nil } + +func getSortedLayerIndex(idx int, layers []v1.CacheLayer, cache map[digest.Digest]int) int { + if idx == -1 { + return -1 + } + l := layers[idx] + if i, ok := cache[l.Blob]; ok { + return i + } + cache[l.Blob] = getSortedLayerIndex(l.ParentIndex, layers, cache) + 1 + return cache[l.Blob] +} diff --git a/exporter/containerimage/writer.go b/exporter/containerimage/writer.go index 5684cba3c..f980afdc0 100644 --- a/exporter/containerimage/writer.go +++ b/exporter/containerimage/writer.go @@ -350,7 +350,11 @@ func patchImageConfig(dt []byte, dps []blobs.DiffPair, history []ocispec.History } if cache != nil { - m["moby.buildkit.cache.v0"] = cache + dt, err := json.Marshal(cache) + if err != nil { + return nil, err + } + m["moby.buildkit.cache.v0"] = dt } dt, err = json.Marshal(m)