vendor: update buildkit to v0.14.0-rc1

Update buildkit dependency to v0.14.0-rc1. Update the tracing
infrastructure to use the new detect API which updates how the delegated
exporter is configured.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
Jonathan A. Sternberg
2024-05-31 16:11:33 -05:00
parent 9b6c4103af
commit b1cb658a31
80 changed files with 2583 additions and 1597 deletions

View File

@ -210,13 +210,23 @@ func (cli *GitCLI) Run(ctx context.Context, args ...string) (_ []byte, err error
}
if err != nil {
select {
case <-ctx.Done():
cerr := context.Cause(ctx)
if cerr != nil {
return buf.Bytes(), errors.Wrapf(cerr, "context completed: git stderr:\n%s", errbuf.String())
}
default:
}
if strings.Contains(errbuf.String(), "--depth") || strings.Contains(errbuf.String(), "shallow") {
if newArgs := argsNoDepth(args); len(args) > len(newArgs) {
args = newArgs
continue
}
}
return buf.Bytes(), errors.Errorf("git error: %s\nstderr:\n%s", err, errbuf.String())
return buf.Bytes(), errors.Wrapf(err, "git stderr:\n%s", errbuf.String())
}
return buf.Bytes(), nil
}

View File

@ -95,6 +95,7 @@ func (mr *MultiReader) Reader(ctx context.Context) Reader {
mr.mu.Lock()
defer mr.mu.Unlock()
delete(mr.writers, w)
closeWriter(context.Cause(ctx))
}()
if !mr.initialized {

View File

@ -285,7 +285,6 @@ type rawJSONDisplay struct {
// output of status update events.
func newRawJSONDisplay(w io.Writer) Display {
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
return Display{
disp: &rawJSONDisplay{
enc: enc,
@ -744,6 +743,7 @@ func (t *trace) update(s *client.SolveStatus, termWidth int) {
v.jobCached = false
if v.term != nil {
if v.term.Width != termWidth {
termHeight = max(termHeightMin, min(termHeightInitial, v.term.Height-termHeightMin-1))
v.term.Resize(termHeight, termWidth-termPad)
}
v.termBytes += len(l.Data)
@ -823,7 +823,7 @@ func (t *trace) displayInfo() (d displayInfo) {
}
var jobs []*job
j := &job{
name: strings.Replace(v.Name, "\t", " ", -1),
name: strings.ReplaceAll(v.Name, "\t", " "),
vertex: v,
isCompleted: true,
}
@ -913,7 +913,7 @@ func addTime(tm *time.Time, d time.Duration) *time.Time {
if tm == nil {
return nil
}
t := (*tm).Add(d)
t := tm.Add(d)
return &t
}
@ -957,6 +957,7 @@ func setupTerminals(jobs []*job, height int, all bool) []*job {
numFree := height - 2 - numInUse
numToHide := 0
termHeight = max(termHeightMin, min(termHeightInitial, height-termHeightMin-1))
termLimit := termHeight + 3
for i := 0; numFree > termLimit && i < len(candidates); i++ {

View File

@ -13,7 +13,10 @@ var colorCancel aec.ANSI
var colorWarning aec.ANSI
var colorError aec.ANSI
var termHeight = 6
const termHeightMin = 6
var termHeightInitial = termHeightMin
var termHeight = termHeightMin
func init() {
// As recommended on https://no-color.org/
@ -43,6 +46,7 @@ func init() {
if termHeightStr != "" {
termHeightVal, err := strconv.Atoi(termHeightStr)
if err == nil && termHeightVal > 0 {
termHeightInitial = termHeightVal
termHeight = termHeightVal
}
}

View File

@ -89,7 +89,7 @@ func ToSlash(inputPath, inputOS string) string {
if inputOS != "windows" {
return inputPath
}
return strings.Replace(inputPath, "\\", "/", -1)
return strings.ReplaceAll(inputPath, "\\", "/")
}
func FromSlash(inputPath, inputOS string) string {
@ -97,7 +97,7 @@ func FromSlash(inputPath, inputOS string) string {
if inputOS == "windows" {
separator = "\\"
}
return strings.Replace(inputPath, "/", separator, -1)
return strings.ReplaceAll(inputPath, "/", separator)
}
// NormalizeWorkdir will return a normalized version of the new workdir, given

View File

@ -21,6 +21,7 @@ import (
"github.com/moby/buildkit/util/appcontext"
"github.com/moby/buildkit/util/contentutil"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"golang.org/x/sync/semaphore"
)
@ -197,6 +198,9 @@ func Run(t *testing.T, testCases []Test, opt ...TestOpt) {
require.NoError(t, sandboxLimiter.Acquire(context.TODO(), 1))
defer sandboxLimiter.Release(1)
ctx, cancel := context.WithCancelCause(ctx)
defer cancel(errors.WithStack(context.Canceled))
sb, closer, err := newSandbox(ctx, br, mirror, mv)
require.NoError(t, err)
t.Cleanup(func() { _ = closer() })

View File

@ -7,6 +7,7 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
@ -65,6 +66,10 @@ func (sb *sandbox) Cmd(args ...string) *exec.Cmd {
cmd := exec.Command("buildctl", args...)
cmd.Env = append(cmd.Env, os.Environ()...)
cmd.Env = append(cmd.Env, "BUILDKIT_HOST="+sb.Address())
if v := os.Getenv("GO_TEST_COVERPROFILE"); v != "" {
coverDir := filepath.Join(filepath.Dir(v), "helpers")
cmd.Env = append(cmd.Env, "GOCOVERDIR="+coverDir)
}
return cmd
}

View File

@ -79,6 +79,10 @@ func runBuildkitd(
"BUILDKIT_DEBUG_EXEC_OUTPUT=1",
"BUILDKIT_DEBUG_PANIC_ON_ERROR=1",
"TMPDIR="+filepath.Join(tmpdir, "tmp"))
if v := os.Getenv("GO_TEST_COVERPROFILE"); v != "" {
coverDir := filepath.Join(filepath.Dir(v), "helpers")
cmd.Env = append(cmd.Env, "GOCOVERDIR="+coverDir)
}
cmd.Env = append(cmd.Env, extraEnv...)
cmd.SysProcAttr = getSysProcAttr()

View File

@ -4,19 +4,13 @@ import (
"context"
"sync"
"github.com/moby/buildkit/util/tracing/detect"
"github.com/moby/buildkit/client"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
const maxBuffer = 256
var exp = &Exporter{}
func init() {
detect.Register("delegated", detect.TraceExporterDetector(func() (sdktrace.SpanExporter, error) {
return exp, nil
}), 100)
}
var DefaultExporter = &Exporter{}
type Exporter struct {
mu sync.Mutex
@ -24,7 +18,10 @@ type Exporter struct {
buffer []sdktrace.ReadOnlySpan
}
var _ sdktrace.SpanExporter = &Exporter{}
var (
_ sdktrace.SpanExporter = (*Exporter)(nil)
_ client.TracerDelegate = (*Exporter)(nil)
)
func (e *Exporter) ExportSpans(ctx context.Context, ss []sdktrace.ReadOnlySpan) error {
e.mu.Lock()

View File

@ -3,22 +3,13 @@ package detect
import (
"context"
"os"
"path/filepath"
"sort"
"strconv"
"sync"
"github.com/moby/buildkit/util/bklog"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/metric"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
)
type ExporterDetector interface {
@ -31,18 +22,7 @@ type detector struct {
priority int
}
var ServiceName string
var detectors map[string]detector
var once sync.Once
var tp trace.TracerProvider
var mp metric.MeterProvider
var exporter struct {
SpanExporter sdktrace.SpanExporter
MetricExporter sdkmetric.Exporter
}
var closers []func(context.Context) error
var err error
func Register(name string, exp ExporterDetector, priority int) {
if detectors == nil {
@ -64,32 +44,21 @@ func (fn TraceExporterDetector) DetectMetricExporter() (sdkmetric.Exporter, erro
return nil, nil
}
func detectExporters() (texp sdktrace.SpanExporter, mexp sdkmetric.Exporter, err error) {
texp, err = detectExporter("OTEL_TRACES_EXPORTER", func(d ExporterDetector) (sdktrace.SpanExporter, bool, error) {
exp, err := d.DetectTraceExporter()
return exp, exp != nil, err
})
if err != nil {
return nil, nil, err
}
mexp, err = detectExporter("OTEL_METRICS_EXPORTER", func(d ExporterDetector) (sdkmetric.Exporter, bool, error) {
exp, err := d.DetectMetricExporter()
return exp, exp != nil, err
})
if err != nil {
return nil, nil, err
}
return texp, mexp, nil
}
func detectExporter[T any](envVar string, fn func(d ExporterDetector) (T, bool, error)) (exp T, err error) {
ignoreErrors, _ := strconv.ParseBool("OTEL_IGNORE_ERROR")
if n := os.Getenv(envVar); n != "" {
d, ok := detectors[n]
if !ok {
return exp, errors.Errorf("unsupported opentelemetry exporter %v", n)
if !ignoreErrors {
err = errors.Errorf("unsupported opentelemetry exporter %v", n)
}
return exp, err
}
exp, _, err = fn(d.f)
if err != nil && ignoreErrors {
err = nil
}
return exp, err
}
@ -104,7 +73,7 @@ func detectExporter[T any](envVar string, fn func(d ExporterDetector) (T, bool,
var ok bool
for _, d := range arr {
exp, ok, err = fn(d.f)
if err != nil {
if err != nil && !ignoreErrors {
return exp, err
}
@ -115,164 +84,70 @@ func detectExporter[T any](envVar string, fn func(d ExporterDetector) (T, bool,
return exp, nil
}
func detect() error {
tp = noop.NewTracerProvider()
mp = sdkmetric.NewMeterProvider()
texp, mexp, err := detectExporters()
if err != nil || (texp == nil && mexp == nil) {
return err
}
res := Resource()
if texp != nil || Recorder != nil {
// enable log with traceID when a valid exporter is used
bklog.EnableLogWithTraceID(true)
sdktpopts := []sdktrace.TracerProviderOption{
sdktrace.WithResource(res),
}
if texp != nil {
sdktpopts = append(sdktpopts, sdktrace.WithBatcher(texp))
}
if Recorder != nil {
sp := sdktrace.NewSimpleSpanProcessor(Recorder)
sdktpopts = append(sdktpopts, sdktrace.WithSpanProcessor(sp))
}
sdktp := sdktrace.NewTracerProvider(sdktpopts...)
closers = append(closers, sdktp.Shutdown)
exporter.SpanExporter = texp
tp = sdktp
}
var readers []sdkmetric.Reader
if mexp != nil {
// Create a new periodic reader using any configured metric exporter.
readers = append(readers, sdkmetric.NewPeriodicReader(mexp))
}
if r, err := prometheus.New(); err != nil {
// Log the error but do not fail if we could not configure the prometheus metrics.
bklog.G(context.Background()).
WithError(err).
Error("failed prometheus metrics configuration")
} else {
// Register the prometheus reader if there was no error.
readers = append(readers, r)
}
if len(readers) > 0 {
opts := make([]sdkmetric.Option, 0, len(readers)+1)
opts = append(opts, sdkmetric.WithResource(res))
for _, r := range readers {
opts = append(opts, sdkmetric.WithReader(r))
}
sdkmp := sdkmetric.NewMeterProvider(opts...)
closers = append(closers, sdkmp.Shutdown)
exporter.MetricExporter = mexp
mp = sdkmp
}
return nil
}
func TracerProvider() (trace.TracerProvider, error) {
if err := detectOnce(); err != nil {
return nil, err
}
return tp, nil
}
func MeterProvider() (metric.MeterProvider, error) {
if err := detectOnce(); err != nil {
return nil, err
}
return mp, nil
}
func detectOnce() error {
once.Do(func() {
if err1 := detect(); err1 != nil {
b, _ := strconv.ParseBool(os.Getenv("OTEL_IGNORE_ERROR"))
if !b {
err = err1
}
}
})
return err
}
func Exporter() (sdktrace.SpanExporter, sdkmetric.Exporter, error) {
_, err := TracerProvider()
if err != nil {
return nil, nil, err
}
return exporter.SpanExporter, exporter.MetricExporter, nil
}
func Shutdown(ctx context.Context) error {
for _, c := range closers {
if err := c(ctx); err != nil {
return err
}
}
return nil
}
var (
detectedResource *resource.Resource
detectedResourceOnce sync.Once
)
func Resource() *resource.Resource {
detectedResourceOnce.Do(func() {
res, err := resource.New(context.Background(),
resource.WithDetectors(serviceNameDetector{}),
resource.WithFromEnv(),
resource.WithTelemetrySDK(),
)
if err != nil {
otel.Handle(err)
}
detectedResource = res
})
return detectedResource
}
// OverrideResource overrides the resource returned from Resource.
//
// This must be invoked before Resource is called otherwise it is a no-op.
func OverrideResource(res *resource.Resource) {
detectedResourceOnce.Do(func() {
detectedResource = res
func NewSpanExporter(_ context.Context) (sdktrace.SpanExporter, error) {
return detectExporter("OTEL_TRACES_EXPORTER", func(d ExporterDetector) (sdktrace.SpanExporter, bool, error) {
exp, err := d.DetectTraceExporter()
return exp, exp != nil, err
})
}
type serviceNameDetector struct{}
func (serviceNameDetector) Detect(ctx context.Context) (*resource.Resource, error) {
return resource.StringDetector(
semconv.SchemaURL,
semconv.ServiceNameKey,
func() (string, error) {
if ServiceName != "" {
return ServiceName, nil
}
return filepath.Base(os.Args[0]), nil
},
).Detect(ctx)
func NewMetricExporter(_ context.Context) (sdkmetric.Exporter, error) {
return detectExporter("OTEL_METRICS_EXPORTER", func(d ExporterDetector) (sdkmetric.Exporter, bool, error) {
exp, err := d.DetectMetricExporter()
return exp, exp != nil, err
})
}
type noneDetector struct{}
func (n noneDetector) DetectTraceExporter() (sdktrace.SpanExporter, error) {
return nil, nil
return noneSpanExporter{}, nil
}
func (n noneDetector) DetectMetricExporter() (sdkmetric.Exporter, error) {
return nil, nil
return noneMetricExporter{}, nil
}
type noneSpanExporter struct{}
func (n noneSpanExporter) ExportSpans(_ context.Context, _ []sdktrace.ReadOnlySpan) error {
return nil
}
func (n noneSpanExporter) Shutdown(_ context.Context) error {
return nil
}
func IsNoneSpanExporter(exp sdktrace.SpanExporter) bool {
_, ok := exp.(noneSpanExporter)
return ok
}
type noneMetricExporter struct{}
func (n noneMetricExporter) Temporality(kind sdkmetric.InstrumentKind) metricdata.Temporality {
return sdkmetric.DefaultTemporalitySelector(kind)
}
func (n noneMetricExporter) Aggregation(kind sdkmetric.InstrumentKind) sdkmetric.Aggregation {
return sdkmetric.DefaultAggregationSelector(kind)
}
func (n noneMetricExporter) Export(_ context.Context, _ *metricdata.ResourceMetrics) error {
return nil
}
func (n noneMetricExporter) ForceFlush(_ context.Context) error {
return nil
}
func (n noneMetricExporter) Shutdown(_ context.Context) error {
return nil
}
func IsNoneMetricExporter(exp sdkmetric.Exporter) bool {
_, ok := exp.(noneMetricExporter)
return ok
}
func init() {

View File

@ -0,0 +1,58 @@
package detect
import (
"context"
"os"
"path/filepath"
"sync"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
)
var (
ServiceName string
detectedResource *resource.Resource
detectedResourceOnce sync.Once
)
func Resource() *resource.Resource {
detectedResourceOnce.Do(func() {
res, err := resource.New(context.Background(),
resource.WithDetectors(serviceNameDetector{}),
resource.WithFromEnv(),
resource.WithTelemetrySDK(),
)
if err != nil {
otel.Handle(err)
}
detectedResource = res
})
return detectedResource
}
// OverrideResource overrides the resource returned from Resource.
//
// This must be invoked before Resource is called otherwise it is a no-op.
func OverrideResource(res *resource.Resource) {
detectedResourceOnce.Do(func() {
detectedResource = res
})
}
type serviceNameDetector struct{}
func (serviceNameDetector) Detect(ctx context.Context) (*resource.Resource, error) {
return resource.StringDetector(
semconv.SchemaURL,
semconv.ServiceNameKey,
func() (string, error) {
if ServiceName != "" {
return ServiceName, nil
}
return filepath.Base(os.Args[0]), nil
},
).Detect(ctx)
}

View File

@ -0,0 +1,36 @@
package tracing
import (
"context"
"github.com/hashicorp/go-multierror"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
type MultiSpanExporter []sdktrace.SpanExporter
func (m MultiSpanExporter) ExportSpans(ctx context.Context, spans []sdktrace.ReadOnlySpan) (err error) {
for _, exp := range m {
if e := exp.ExportSpans(ctx, spans); e != nil {
if err != nil {
err = multierror.Append(err, e)
continue
}
err = e
}
}
return err
}
func (m MultiSpanExporter) Shutdown(ctx context.Context) (err error) {
for _, exp := range m {
if e := exp.Shutdown(ctx); e != nil {
if err != nil {
err = multierror.Append(err, e)
continue
}
err = e
}
}
return err
}