1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package cache
17
18 import (
19 "errors"
20 "io"
21
22 "github.com/google/go-containerregistry/pkg/logs"
23 v1 "github.com/google/go-containerregistry/pkg/v1"
24 "github.com/google/go-containerregistry/pkg/v1/types"
25 )
26
27
28 type Cache interface {
29
30
31
32
33
34
35
36
37
38 Put(v1.Layer) (v1.Layer, error)
39
40
41
42 Get(v1.Hash) (v1.Layer, error)
43
44
45 Delete(v1.Hash) error
46 }
47
48
49 var ErrNotFound = errors.New("layer was not found")
50
51
52
53
54 func Image(i v1.Image, c Cache) v1.Image {
55 return &image{
56 Image: i,
57 c: c,
58 }
59 }
60
61 type image struct {
62 v1.Image
63 c Cache
64 }
65
66 func (i *image) Layers() ([]v1.Layer, error) {
67 ls, err := i.Image.Layers()
68 if err != nil {
69 return nil, err
70 }
71
72 out := make([]v1.Layer, len(ls))
73 for idx, l := range ls {
74 out[idx] = &lazyLayer{inner: l, c: i.c}
75 }
76 return out, nil
77 }
78
79 type lazyLayer struct {
80 inner v1.Layer
81 c Cache
82 }
83
84 func (l *lazyLayer) Compressed() (io.ReadCloser, error) {
85 digest, err := l.inner.Digest()
86 if err != nil {
87 return nil, err
88 }
89
90 if cl, err := l.c.Get(digest); err == nil {
91
92 logs.Progress.Printf("Layer %s found (compressed) in cache", digest)
93 return cl.Compressed()
94 } else if !errors.Is(err, ErrNotFound) {
95 return nil, err
96 }
97
98
99 logs.Progress.Printf("Layer %s not found (compressed) in cache, getting", digest)
100 rl, err := l.c.Put(l.inner)
101 if err != nil {
102 return nil, err
103 }
104 return rl.Compressed()
105 }
106
107 func (l *lazyLayer) Uncompressed() (io.ReadCloser, error) {
108 diffID, err := l.inner.DiffID()
109 if err != nil {
110 return nil, err
111 }
112 if cl, err := l.c.Get(diffID); err == nil {
113
114 logs.Progress.Printf("Layer %s found (uncompressed) in cache", diffID)
115 return cl.Uncompressed()
116 } else if !errors.Is(err, ErrNotFound) {
117 return nil, err
118 }
119
120
121 logs.Progress.Printf("Layer %s not found (uncompressed) in cache, getting", diffID)
122 rl, err := l.c.Put(l.inner)
123 if err != nil {
124 return nil, err
125 }
126 return rl.Uncompressed()
127 }
128
129 func (l *lazyLayer) Size() (int64, error) { return l.inner.Size() }
130 func (l *lazyLayer) DiffID() (v1.Hash, error) { return l.inner.DiffID() }
131 func (l *lazyLayer) Digest() (v1.Hash, error) { return l.inner.Digest() }
132 func (l *lazyLayer) MediaType() (types.MediaType, error) { return l.inner.MediaType() }
133
134 func (i *image) LayerByDigest(h v1.Hash) (v1.Layer, error) {
135 l, err := i.c.Get(h)
136 if errors.Is(err, ErrNotFound) {
137
138 l, err := i.Image.LayerByDigest(h)
139 if err != nil {
140 return nil, err
141 }
142 return i.c.Put(l)
143 }
144 return l, err
145 }
146
147 func (i *image) LayerByDiffID(h v1.Hash) (v1.Layer, error) {
148 l, err := i.c.Get(h)
149 if errors.Is(err, ErrNotFound) {
150
151 l, err := i.Image.LayerByDiffID(h)
152 if err != nil {
153 return nil, err
154 }
155 return i.c.Put(l)
156 }
157 return l, err
158 }
159
160
161
162 func ImageIndex(ii v1.ImageIndex, c Cache) v1.ImageIndex {
163 return &imageIndex{
164 inner: ii,
165 c: c,
166 }
167 }
168
169 type imageIndex struct {
170 inner v1.ImageIndex
171 c Cache
172 }
173
174 func (ii *imageIndex) MediaType() (types.MediaType, error) { return ii.inner.MediaType() }
175 func (ii *imageIndex) Digest() (v1.Hash, error) { return ii.inner.Digest() }
176 func (ii *imageIndex) Size() (int64, error) { return ii.inner.Size() }
177 func (ii *imageIndex) IndexManifest() (*v1.IndexManifest, error) { return ii.inner.IndexManifest() }
178 func (ii *imageIndex) RawManifest() ([]byte, error) { return ii.inner.RawManifest() }
179
180 func (ii *imageIndex) Image(h v1.Hash) (v1.Image, error) {
181 i, err := ii.inner.Image(h)
182 if err != nil {
183 return nil, err
184 }
185 return Image(i, ii.c), nil
186 }
187
188 func (ii *imageIndex) ImageIndex(h v1.Hash) (v1.ImageIndex, error) {
189 idx, err := ii.inner.ImageIndex(h)
190 if err != nil {
191 return nil, err
192 }
193 return ImageIndex(idx, ii.c), nil
194 }
195
View as plain text