From f7bd5b99da0a847cf5aaabc00da3b6e1f9cadc1b Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Mon, 9 Jan 2023 16:46:40 +0000 Subject: [PATCH] build: use copy for BuildWithResultHandler loop vars Signed-off-by: Justin Chadwell (cherry picked from commit 347417ee123fa9673faa11347d0f079c49810aa1) --- build/build.go | 227 ++++++++++++++++++++++++------------------------- 1 file changed, 112 insertions(+), 115 deletions(-) diff --git a/build/build.go b/build/build.go index 024da1f3..76bad2f6 100644 --- a/build/build.go +++ b/build/build.go @@ -1078,7 +1078,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s }) for i, dp := range dps { - so := *dp.so + i, dp, so := i, dp, *dp.so if multiDriver { for i, e := range so.Exports { switch e.Type { @@ -1107,144 +1107,141 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s } } - func(i int, dp driverPair, so client.SolveOpt) { - pw := progress.WithPrefix(w, k, multiTarget) + pw := progress.WithPrefix(w, k, multiTarget) - c := clients[dp.driverIndex] - eg.Go(func() error { - pw = progress.ResetTime(pw) - defer wg.Done() + c := clients[dp.driverIndex] + eg.Go(func() error { + pw = progress.ResetTime(pw) + defer wg.Done() - if err := waitContextDeps(ctx, dp.driverIndex, results, &so); err != nil { + if err := waitContextDeps(ctx, dp.driverIndex, results, &so); err != nil { + return err + } + + frontendInputs := make(map[string]*pb.Definition) + for key, st := range so.FrontendInputs { + def, err := st.Marshal(ctx) + if err != nil { return err } + frontendInputs[key] = def.ToPB() + } - frontendInputs := make(map[string]*pb.Definition) - for key, st := range so.FrontendInputs { - def, err := st.Marshal(ctx) - if err != nil { - return err + req := gateway.SolveRequest{ + Frontend: so.Frontend, + FrontendInputs: frontendInputs, + FrontendOpt: make(map[string]string), + } + for k, v := range so.FrontendAttrs { + req.FrontendOpt[k] = v + } + so.Frontend = "" + so.FrontendInputs = nil + + ch, done := progress.NewChannel(pw) + defer func() { <-done }() + + cc := c + var printRes map[string][]byte + rr, err := c.Build(ctx, so, "buildx", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + var isFallback bool + var origErr error + for { + if opt.PrintFunc != nil { + if _, ok := req.FrontendOpt["frontend.caps"]; !ok { + req.FrontendOpt["frontend.caps"] = "moby.buildkit.frontend.subrequests+forward" + } else { + req.FrontendOpt["frontend.caps"] += ",moby.buildkit.frontend.subrequests+forward" + } + req.FrontendOpt["requestid"] = "frontend." + opt.PrintFunc.Name + if isFallback { + req.FrontendOpt["build-arg:BUILDKIT_SYNTAX"] = printFallbackImage + } } - frontendInputs[key] = def.ToPB() - } - - req := gateway.SolveRequest{ - Frontend: so.Frontend, - FrontendInputs: frontendInputs, - FrontendOpt: make(map[string]string), - } - for k, v := range so.FrontendAttrs { - req.FrontendOpt[k] = v - } - so.Frontend = "" - so.FrontendInputs = nil - - ch, done := progress.NewChannel(pw) - defer func() { <-done }() - - cc := c - var printRes map[string][]byte - rr, err := c.Build(ctx, so, "buildx", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { - var isFallback bool - var origErr error - for { - if opt.PrintFunc != nil { - if _, ok := req.FrontendOpt["frontend.caps"]; !ok { - req.FrontendOpt["frontend.caps"] = "moby.buildkit.frontend.subrequests+forward" - } else { - req.FrontendOpt["frontend.caps"] += ",moby.buildkit.frontend.subrequests+forward" - } - req.FrontendOpt["requestid"] = "frontend." + opt.PrintFunc.Name - if isFallback { - req.FrontendOpt["build-arg:BUILDKIT_SYNTAX"] = printFallbackImage - } + res, err := c.Solve(ctx, req) + if err != nil { + if origErr != nil { + return nil, err } - res, err := c.Solve(ctx, req) - if err != nil { - if origErr != nil { - return nil, err - } - var reqErr *errdefs.UnsupportedSubrequestError - if !isFallback { - if errors.As(err, &reqErr) { - switch reqErr.Name { - case "frontend.outline", "frontend.targets": - isFallback = true - origErr = err - continue - } - return nil, err - } - // buildkit v0.8 vendored in Docker 20.10 does not support typed errors - if strings.Contains(err.Error(), "unsupported request frontend.outline") || strings.Contains(err.Error(), "unsupported request frontend.targets") { + var reqErr *errdefs.UnsupportedSubrequestError + if !isFallback { + if errors.As(err, &reqErr) { + switch reqErr.Name { + case "frontend.outline", "frontend.targets": isFallback = true origErr = err continue } + return nil, err + } + // buildkit v0.8 vendored in Docker 20.10 does not support typed errors + if strings.Contains(err.Error(), "unsupported request frontend.outline") || strings.Contains(err.Error(), "unsupported request frontend.targets") { + isFallback = true + origErr = err + continue } - return nil, err - } - if opt.PrintFunc != nil { - printRes = res.Metadata - } - results.Set(resultKey(dp.driverIndex, k), res) - if resultHandleFunc != nil { - resultHandleFunc(dp.driverIndex, &ResultContext{cc, res}) } - return res, nil + return nil, err } - }, ch) - if err != nil { - return err + if opt.PrintFunc != nil { + printRes = res.Metadata + } + results.Set(resultKey(dp.driverIndex, k), res) + if resultHandleFunc != nil { + resultHandleFunc(dp.driverIndex, &ResultContext{cc, res}) + } + return res, nil } - res[i] = rr + }, ch) + if err != nil { + return err + } + res[i] = rr - if rr.ExporterResponse == nil { - rr.ExporterResponse = map[string]string{} - } - for k, v := range printRes { - rr.ExporterResponse[k] = string(v) - } + if rr.ExporterResponse == nil { + rr.ExporterResponse = map[string]string{} + } + for k, v := range printRes { + rr.ExporterResponse[k] = string(v) + } - node := nodes[dp.driverIndex].Driver - if node.IsMobyDriver() { - for _, e := range so.Exports { - if e.Type == "moby" && e.Attrs["push"] != "" { - if ok, _ := strconv.ParseBool(e.Attrs["push"]); ok { - pushNames = e.Attrs["name"] - if pushNames == "" { - return errors.Errorf("tag is needed when pushing to registry") - } - pw := progress.ResetTime(pw) - pushList := strings.Split(pushNames, ",") - for _, name := range pushList { - if err := progress.Wrap(fmt.Sprintf("pushing %s with docker", name), pw.Write, func(l progress.SubLogger) error { - return pushWithMoby(ctx, node, name, l) - }); err != nil { - return err - } + node := nodes[dp.driverIndex].Driver + if node.IsMobyDriver() { + for _, e := range so.Exports { + if e.Type == "moby" && e.Attrs["push"] != "" { + if ok, _ := strconv.ParseBool(e.Attrs["push"]); ok { + pushNames = e.Attrs["name"] + if pushNames == "" { + return errors.Errorf("tag is needed when pushing to registry") + } + pw := progress.ResetTime(pw) + pushList := strings.Split(pushNames, ",") + for _, name := range pushList { + if err := progress.Wrap(fmt.Sprintf("pushing %s with docker", name), pw.Write, func(l progress.SubLogger) error { + return pushWithMoby(ctx, node, name, l) + }); err != nil { + return err } - remoteDigest, err := remoteDigestWithMoby(ctx, node, pushList[0]) - if err == nil && remoteDigest != "" { - // old daemons might not have containerimage.config.digest set - // in response so use containerimage.digest value for it if available - if _, ok := rr.ExporterResponse[exptypes.ExporterImageConfigDigestKey]; !ok { - if v, ok := rr.ExporterResponse[exptypes.ExporterImageDigestKey]; ok { - rr.ExporterResponse[exptypes.ExporterImageConfigDigestKey] = v - } + } + remoteDigest, err := remoteDigestWithMoby(ctx, node, pushList[0]) + if err == nil && remoteDigest != "" { + // old daemons might not have containerimage.config.digest set + // in response so use containerimage.digest value for it if available + if _, ok := rr.ExporterResponse[exptypes.ExporterImageConfigDigestKey]; !ok { + if v, ok := rr.ExporterResponse[exptypes.ExporterImageDigestKey]; ok { + rr.ExporterResponse[exptypes.ExporterImageConfigDigestKey] = v } - rr.ExporterResponse[exptypes.ExporterImageDigestKey] = remoteDigest - } else if err != nil { - return err } + rr.ExporterResponse[exptypes.ExporterImageDigestKey] = remoteDigest + } else if err != nil { + return err } } } } - return nil - }) - - }(i, dp, so) + } + return nil + }) } return nil