@@ -2,6 +2,7 @@ package main
2
2
3
3
import (
4
4
"context"
5
+ "encoding/binary"
5
6
"encoding/json"
6
7
"expvar"
7
8
"fmt"
@@ -15,6 +16,7 @@ import (
15
16
"strings"
16
17
"time"
17
18
19
+ cacheimport "github.com/moby/buildkit/cache/remotecache/v1"
18
20
"github.com/moby/buildkit/solver"
19
21
"github.com/moby/buildkit/util/bklog"
20
22
"github.com/moby/buildkit/util/cachedigest"
@@ -40,6 +42,7 @@ func setupDebugHandlers(addr string) error {
40
42
m .Handle ("/debug/cache/all" , http .HandlerFunc (handleCacheAll ))
41
43
m .Handle ("/debug/cache/lookup" , http .HandlerFunc (handleCacheLookup ))
42
44
m .Handle ("/debug/cache/store" , http .HandlerFunc (handleDebugCacheStore ))
45
+ m .Handle ("POST /debug/cache/load" , http .HandlerFunc (handleCacheLoad ))
43
46
44
47
m .Handle ("/debug/gc" , http .HandlerFunc (func (rw http.ResponseWriter , req * http.Request ) {
45
48
runtime .GC ()
@@ -139,9 +142,13 @@ func printCacheRecord(record *cachedigest.Record, w io.Writer) {
139
142
case cachedigest .FrameIDData :
140
143
w .Write ([]byte (" " + frame .ID .String () + ": " + string (frame .Data ) + "\n " ))
141
144
case cachedigest .FrameIDSkip :
142
- w . Write ([] byte ( " skipping " + string (frame .Data ) + " bytes \n " ))
145
+ fmt . Fprintf ( w , " skipping %d bytes \n " , binary . LittleEndian . Uint32 (frame .Data ))
143
146
}
144
147
}
148
+ for _ , subRec := range record .SubRecords {
149
+ w .Write ([]byte ("\n " ))
150
+ printCacheRecord (subRec , w )
151
+ }
145
152
}
146
153
147
154
func cacheRecordLookup (ctx context.Context , dgst digest.Digest ) (* cachedigest.Record , error ) {
@@ -216,18 +223,70 @@ func loadCacheAll(ctx context.Context) ([]*cachedigest.Record, error) {
216
223
return records , nil
217
224
}
218
225
226
+ func handleCacheLoad (w http.ResponseWriter , r * http.Request ) {
227
+ if r .Method != http .MethodPost {
228
+ http .Error (w , "method not allowed" , http .StatusMethodNotAllowed )
229
+ return
230
+ }
231
+ if r .Body == nil {
232
+ http .Error (w , "body is required" , http .StatusBadRequest )
233
+ return
234
+ }
235
+ defer r .Body .Close ()
236
+
237
+ recs , err := loadCacheFromReader (r .Context (), r .Body )
238
+ if err != nil {
239
+ http .Error (w , "failed to load cache: " + err .Error (), http .StatusInternalServerError )
240
+ return
241
+ }
242
+ writeCacheRecordsResponse (w , r , recs )
243
+ }
244
+
245
+ func loadCacheFromReader (ctx context.Context , rdr io.Reader ) ([]* recordWithDebug , error ) {
246
+ dt , err := io .ReadAll (rdr )
247
+ if err != nil {
248
+ return nil , errors .Wrap (err , "failed to read body" )
249
+ }
250
+
251
+ allLayers := cacheimport.DescriptorProvider {}
252
+ cc := cacheimport .NewCacheChains ()
253
+ if err := cacheimport .Parse (dt , allLayers , cc ); err != nil {
254
+ return nil , err
255
+ }
256
+
257
+ keyStorage , _ , err := cacheimport .NewCacheKeyStorage (cc , nil )
258
+ if err != nil {
259
+ return nil , err
260
+ }
261
+
262
+ recs , err := debugCacheStore (ctx , keyStorage )
263
+ if err != nil {
264
+ return nil , errors .Wrap (err , "failed to debug cache store" )
265
+ }
266
+
267
+ return recs , nil
268
+ }
269
+
219
270
func handleDebugCacheStore (w http.ResponseWriter , r * http.Request ) {
220
271
if r .Method != http .MethodGet {
221
272
http .Error (w , "Method not allowed" , http .StatusMethodNotAllowed )
222
273
return
223
274
}
224
275
225
- recs , err := debugCacheStore (r .Context ())
276
+ store := cacheStoreForDebug
277
+ if store == nil {
278
+ http .Error (w , "Cache store is not initialized for debug" , http .StatusInternalServerError )
279
+ }
280
+
281
+ recs , err := debugCacheStore (r .Context (), store )
226
282
if err != nil {
227
283
http .Error (w , "Failed to debug cache store: " + err .Error (), http .StatusInternalServerError )
228
284
return
229
285
}
286
+ writeCacheRecordsResponse (w , r , recs )
287
+ }
230
288
289
+ func writeCacheRecordsResponse (w http.ResponseWriter , r * http.Request , recs []* recordWithDebug ) {
231
290
w .WriteHeader (http .StatusOK )
232
291
233
292
switch r .Header .Get ("Accept" ) {
@@ -287,12 +346,7 @@ type recordWithDebug struct {
287
346
Debug []* cachedigest.Record `json:"debug,omitempty"`
288
347
}
289
348
290
- func debugCacheStore (ctx context.Context ) ([]* recordWithDebug , error ) {
291
- store := cacheStoreForDebug
292
- if store == nil {
293
- return nil , errors .New ("cache store is not initialized for debug" )
294
- }
295
-
349
+ func debugCacheStore (ctx context.Context , store solver.CacheKeyStorage ) ([]* recordWithDebug , error ) {
296
350
recs , err := cachestore .Records (ctx , store )
297
351
if err != nil {
298
352
return nil , errors .Wrap (err , "failed to get cache records" )
0 commit comments