...
1 package cache
2
3 import (
4 "errors"
5 "fmt"
6 "io"
7
8 v1 "github.com/google/go-containerregistry/pkg/v1"
9
10 "edge-infra.dev/pkg/f8n/warehouse/oci/layer"
11 )
12
13
14 type cachingImage struct {
15 v1.Image
16 cache *LazyCache
17 }
18
19
20
21
22 func Image(i v1.Image, c *LazyCache) v1.Image {
23 return &cachingImage{
24 Image: i,
25 cache: c,
26 }
27 }
28
29 func (c *cachingImage) Layers() ([]v1.Layer, error) {
30 m, err := c.Image.Manifest()
31 if err != nil {
32 return nil, err
33 }
34 layers := make([]v1.Layer, 0, len(m.Layers))
35 for _, desc := range m.Layers {
36 l, err := c.LayerByDigest(desc.Digest)
37 if err != nil {
38 return nil, err
39 }
40 layers = append(layers, l)
41 }
42 return layers, nil
43 }
44
45 func (c *cachingImage) RawConfigFile() ([]byte, error) {
46 manifest, err := c.Image.Manifest()
47 if err != nil {
48 return nil, err
49 }
50
51 h := manifest.Config.Digest
52 if cached, err := c.cache.getLayer(h); err == nil {
53 rc, err := cached.Uncompressed()
54 if err != nil {
55 return nil, err
56 }
57 defer rc.Close()
58 return io.ReadAll(rc)
59 } else if !errors.Is(err, ErrNotFound) {
60 return nil, err
61 }
62
63 raw, err := c.Image.RawConfigFile()
64 if err != nil {
65 return nil, err
66 }
67 c.cache.putBlob(h, raw)
68 return raw, nil
69 }
70
71
72
73 func (c *cachingImage) LayerByDigest(h v1.Hash) (v1.Layer, error) {
74 if cached, err := c.cache.getLayer(h); err == nil {
75 return cached, nil
76 } else if !errors.Is(err, ErrNotFound) {
77 return nil, err
78 }
79
80 l, err := c.Image.LayerByDigest(h)
81 if err != nil {
82 return nil, err
83 }
84
85 ll, err := layer.FromOCILayer(l)
86 if err != nil {
87 return nil, fmt.Errorf("failed to convert OCI Layer to Warehouse Layer. error: %v", err)
88 }
89 return c.cache.putLayer(ll)
90 }
91
92
93 func (c *cachingImage) LayerByDiffID(h v1.Hash) (v1.Layer, error) {
94 return c.LayerByDigest(h)
95 }
96
View as plain text