Skip to content

Commit dbb57d8

Browse files
committed
debug: allow debug from remote cache config
Signed-off-by: Tonis Tiigi <[email protected]>
1 parent 63874fc commit dbb57d8

File tree

4 files changed

+100
-16
lines changed

4 files changed

+100
-16
lines changed

cache/remotecache/v1/cachestorage.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,12 @@ func (cs *cacheKeyStorage) Exists(id string) bool {
106106
return ok
107107
}
108108

109-
func (cs *cacheKeyStorage) Walk(func(id string) error) error {
109+
func (cs *cacheKeyStorage) Walk(cb func(id string) error) error {
110+
for id := range cs.byID {
111+
if err := cb(id); err != nil {
112+
return err
113+
}
114+
}
110115
return nil
111116
}
112117

@@ -142,6 +147,26 @@ func (cs *cacheKeyStorage) Release(resultID string) error {
142147
func (cs *cacheKeyStorage) AddLink(id string, link solver.CacheInfoLink, target string) error {
143148
return nil
144149
}
150+
151+
func (cs *cacheKeyStorage) WalkLinksAll(id string, fn func(id string, link solver.CacheInfoLink) error) error {
152+
it, ok := cs.byID[id]
153+
if !ok {
154+
return nil
155+
}
156+
for nl, ids := range it.links {
157+
for _, id2 := range ids {
158+
if err := fn(id2, solver.CacheInfoLink{
159+
Input: solver.Index(nl.input),
160+
Selector: digest.Digest(nl.selector),
161+
Digest: nl.dgst,
162+
}); err != nil {
163+
return err
164+
}
165+
}
166+
}
167+
return nil
168+
}
169+
145170
func (cs *cacheKeyStorage) WalkLinks(id string, link solver.CacheInfoLink, fn func(id string) error) error {
146171
it, ok := cs.byID[id]
147172
if !ok {

cmd/buildkitd/debug.go

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"encoding/binary"
56
"encoding/json"
67
"expvar"
78
"fmt"
@@ -15,6 +16,7 @@ import (
1516
"strings"
1617
"time"
1718

19+
cacheimport "github.com/moby/buildkit/cache/remotecache/v1"
1820
"github.com/moby/buildkit/solver"
1921
"github.com/moby/buildkit/util/bklog"
2022
"github.com/moby/buildkit/util/cachedigest"
@@ -40,6 +42,7 @@ func setupDebugHandlers(addr string) error {
4042
m.Handle("/debug/cache/all", http.HandlerFunc(handleCacheAll))
4143
m.Handle("/debug/cache/lookup", http.HandlerFunc(handleCacheLookup))
4244
m.Handle("/debug/cache/store", http.HandlerFunc(handleDebugCacheStore))
45+
m.Handle("POST /debug/cache/load", http.HandlerFunc(handleCacheLoad))
4346

4447
m.Handle("/debug/gc", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
4548
runtime.GC()
@@ -139,9 +142,13 @@ func printCacheRecord(record *cachedigest.Record, w io.Writer) {
139142
case cachedigest.FrameIDData:
140143
w.Write([]byte(" " + frame.ID.String() + ": " + string(frame.Data) + "\n"))
141144
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))
143146
}
144147
}
148+
for _, subRec := range record.SubRecords {
149+
w.Write([]byte("\n"))
150+
printCacheRecord(subRec, w)
151+
}
145152
}
146153

147154
func cacheRecordLookup(ctx context.Context, dgst digest.Digest) (*cachedigest.Record, error) {
@@ -216,18 +223,70 @@ func loadCacheAll(ctx context.Context) ([]*cachedigest.Record, error) {
216223
return records, nil
217224
}
218225

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+
219270
func handleDebugCacheStore(w http.ResponseWriter, r *http.Request) {
220271
if r.Method != http.MethodGet {
221272
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
222273
return
223274
}
224275

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)
226282
if err != nil {
227283
http.Error(w, "Failed to debug cache store: "+err.Error(), http.StatusInternalServerError)
228284
return
229285
}
286+
writeCacheRecordsResponse(w, r, recs)
287+
}
230288

289+
func writeCacheRecordsResponse(w http.ResponseWriter, r *http.Request, recs []*recordWithDebug) {
231290
w.WriteHeader(http.StatusOK)
232291

233292
switch r.Header.Get("Accept") {
@@ -287,12 +346,7 @@ type recordWithDebug struct {
287346
Debug []*cachedigest.Record `json:"debug,omitempty"`
288347
}
289348

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) {
296350
recs, err := cachestore.Records(ctx, store)
297351
if err != nil {
298352
return nil, errors.Wrap(err, "failed to get cache records")

util/cachedigest/digest.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ func (h *Hash) WriteNoDebug(p []byte) (n int, err error) {
6767
if n > 0 && h.db != nil {
6868
if len(h.frames) > 0 && h.frames[len(h.frames)-1].ID == FrameIDSkip {
6969
last := &h.frames[len(h.frames)-1]
70-
prevLen := binary.BigEndian.Uint32(last.Data)
71-
binary.BigEndian.PutUint32(last.Data, prevLen+uint32(n))
70+
prevLen := binary.LittleEndian.Uint32(last.Data)
71+
binary.LittleEndian.PutUint32(last.Data, prevLen+uint32(n))
7272
} else {
7373
lenBytes := make([]byte, 4)
74-
binary.BigEndian.PutUint32(lenBytes, uint32(n))
74+
binary.LittleEndian.PutUint32(lenBytes, uint32(n))
7575
h.frames = append(h.frames, Frame{ID: FrameIDSkip, Data: lenBytes})
7676
}
7777
}
@@ -94,7 +94,7 @@ type Record struct {
9494
Digest digest.Digest `json:"digest"`
9595
Type Type `json:"type"`
9696
Data []Frame `json:"data,omitempty"`
97-
SubRecords []Record `json:"subRecords,omitempty"`
97+
SubRecords []*Record `json:"subRecords,omitempty"`
9898
}
9999

100100
var shaRegexpOnce = sync.OnceValue(func() *regexp.Regexp {
@@ -149,11 +149,16 @@ func (r *Record) LoadSubRecords(loader func(d digest.Digest) (Type, []Frame, err
149149
bklog.L.Warnf("failed to load sub-record for %s: %v", dgst, err)
150150
continue
151151
}
152-
r.SubRecords = append(r.SubRecords, Record{
152+
rr := &Record{
153153
Digest: digest.Digest(dgst),
154154
Type: typ,
155155
Data: frames,
156-
})
156+
}
157+
if err := rr.LoadSubRecords(loader); err != nil {
158+
return err
159+
}
160+
161+
r.SubRecords = append(r.SubRecords, rr)
157162
}
158163
return nil
159164
}

util/cachestore/store.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type storeWithLinks interface {
3535
func Records(ctx context.Context, store solver.CacheKeyStorage) ([]*Record, error) {
3636
swl, ok := store.(storeWithLinks)
3737
if !ok {
38-
return nil, errors.New("cache store does not support walkin all links")
38+
return nil, errors.New("cache store does not support walking all links")
3939
}
4040

4141
roots := []string{}

0 commit comments

Comments
 (0)