github.com/rish1988/moby@v25.0.2+incompatible/integration/build/build_traces_test.go (about) 1 package build 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 9 "github.com/docker/docker/client/buildkit" 10 "github.com/docker/docker/testutil" 11 moby_buildkit_v1 "github.com/moby/buildkit/api/services/control" 12 "github.com/moby/buildkit/client" 13 "github.com/moby/buildkit/client/llb" 14 "github.com/moby/buildkit/util/progress/progressui" 15 "go.opentelemetry.io/otel" 16 "golang.org/x/sync/errgroup" 17 "gotest.tools/v3/assert" 18 "gotest.tools/v3/poll" 19 "gotest.tools/v3/skip" 20 ) 21 22 type testWriter struct { 23 *testing.T 24 } 25 26 func (t *testWriter) Write(p []byte) (int, error) { 27 t.Log(string(p)) 28 return len(p), nil 29 } 30 31 func TestBuildkitHistoryTracePropagation(t *testing.T) { 32 skip.If(t, testEnv.DaemonInfo.OSType == "windows", "buildkit is not supported on Windows") 33 34 ctx := testutil.StartSpan(baseContext, t) 35 36 opts := buildkit.ClientOpts(testEnv.APIClient()) 37 bc, err := client.New(ctx, "", opts...) 38 assert.NilError(t, err) 39 defer bc.Close() 40 41 def, err := llb.Scratch().Marshal(ctx) 42 assert.NilError(t, err) 43 44 eg, ctxGo := errgroup.WithContext(ctx) 45 ch := make(chan *client.SolveStatus) 46 47 ctxHistory, cancel := context.WithCancel(ctx) 48 defer cancel() 49 50 sub, err := bc.ControlClient().ListenBuildHistory(ctxHistory, &moby_buildkit_v1.BuildHistoryRequest{ActiveOnly: true}) 51 assert.NilError(t, err) 52 sub.CloseSend() 53 54 defer func() { 55 cancel() 56 <-sub.Context().Done() 57 }() 58 59 eg.Go(func() error { 60 _, err := progressui.DisplaySolveStatus(ctxGo, nil, &testWriter{t}, ch, progressui.WithPhase("test")) 61 return err 62 }) 63 64 eg.Go(func() error { 65 _, err := bc.Solve(ctxGo, def, client.SolveOpt{}, ch) 66 return err 67 }) 68 assert.NilError(t, eg.Wait()) 69 70 he, err := sub.Recv() 71 assert.NilError(t, err) 72 assert.Assert(t, he != nil) 73 cancel() 74 75 // Traces for history records are recorded asynchronously, so we need to wait for it to be available. 76 if he.Record.Trace != nil { 77 return 78 } 79 80 // Split this into a new span so it doesn't clutter up the trace reporting GUI. 81 ctx, span := otel.Tracer("").Start(ctx, "Wait for trace to propagate to history record") 82 defer span.End() 83 84 t.Log("Waiting for trace to be available") 85 poll.WaitOn(t, func(logger poll.LogT) poll.Result { 86 ctx, cancel := context.WithCancel(ctx) 87 defer cancel() 88 89 sub, err := bc.ControlClient().ListenBuildHistory(ctx, &moby_buildkit_v1.BuildHistoryRequest{Ref: he.Record.Ref}) 90 if err != nil { 91 return poll.Error(err) 92 } 93 sub.CloseSend() 94 95 defer func() { 96 cancel() 97 <-sub.Context().Done() 98 }() 99 100 msg, err := sub.Recv() 101 if err != nil { 102 return poll.Error(err) 103 } 104 105 if msg.Record.Ref != he.Record.Ref { 106 return poll.Error(fmt.Errorf("got incorrect history record")) 107 } 108 if msg.Record.Trace != nil { 109 return poll.Success() 110 } 111 return poll.Continue("trace not available yet") 112 }, poll.WithDelay(time.Second), poll.WithTimeout(30*time.Second)) 113 114 }