Skip to content

Commit 0b432cc

Browse files
authored
Merge pull request #1640 from ktock/monitor-invoke-mode-restore
monitor: add `debug-shell` and `on-error`
2 parents b716e48 + fd5d90c commit 0b432cc

File tree

23 files changed

+1124
-316
lines changed

23 files changed

+1124
-316
lines changed

build/build.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,12 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
920920
}
921921
results.Set(resultKey(dp.driverIndex, k), res)
922922
if resultHandleFunc != nil {
923-
resultHandleFunc(dp.driverIndex, &ResultContext{cc, res})
923+
resultCtx, err := NewResultContext(cc, so, res)
924+
if err == nil {
925+
resultHandleFunc(dp.driverIndex, resultCtx)
926+
} else {
927+
logrus.Warnf("failed to record result: %s", err)
928+
}
924929
}
925930
return res, nil
926931
}

build/invoke.go

Lines changed: 23 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -3,110 +3,68 @@ package build
33
import (
44
"context"
55
_ "crypto/sha256" // ensure digests can be computed
6-
"encoding/json"
7-
"fmt"
86
"io"
97
"sync"
108
"sync/atomic"
119
"syscall"
1210

1311
controllerapi "github.com/docker/buildx/controller/pb"
14-
"github.com/moby/buildkit/client"
15-
"github.com/moby/buildkit/exporter/containerimage/exptypes"
1612
gateway "github.com/moby/buildkit/frontend/gateway/client"
17-
"github.com/moby/buildkit/solver/pb"
18-
specs "github.com/opencontainers/image-spec/specs-go/v1"
1913
"github.com/pkg/errors"
2014
"github.com/sirupsen/logrus"
2115
)
2216

23-
// ResultContext is a build result with the client that built it.
24-
type ResultContext struct {
25-
Client *client.Client
26-
Res *gateway.Result
27-
}
28-
2917
type Container struct {
3018
cancelOnce sync.Once
3119
containerCancel func()
32-
33-
isUnavailable atomic.Bool
34-
35-
initStarted atomic.Bool
36-
37-
container gateway.Container
38-
image *specs.Image
39-
40-
releaseCh chan struct{}
20+
isUnavailable atomic.Bool
21+
initStarted atomic.Bool
22+
container gateway.Container
23+
releaseCh chan struct{}
24+
resultCtx *ResultContext
4125
}
4226

43-
func NewContainer(ctx context.Context, resultCtx *ResultContext) (*Container, error) {
44-
c, res := resultCtx.Client, resultCtx.Res
45-
27+
func NewContainer(ctx context.Context, resultCtx *ResultContext, cfg *controllerapi.InvokeConfig) (*Container, error) {
4628
mainCtx := ctx
4729

4830
ctrCh := make(chan *Container)
4931
errCh := make(chan error)
5032
go func() {
51-
_, err := c.Build(context.TODO(), client.SolveOpt{}, "buildx", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
33+
err := resultCtx.build(func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
5234
ctx, cancel := context.WithCancel(ctx)
5335
go func() {
5436
<-mainCtx.Done()
5537
cancel()
5638
}()
5739

58-
if res.Ref == nil {
59-
return nil, errors.Errorf("no reference is registered")
60-
}
61-
st, err := res.Ref.ToState()
62-
if err != nil {
63-
return nil, err
64-
}
65-
def, err := st.Marshal(ctx)
66-
if err != nil {
67-
return nil, err
68-
}
69-
imgRef, err := c.Solve(ctx, gateway.SolveRequest{
70-
Definition: def.ToPB(),
71-
})
40+
containerCfg, err := resultCtx.getContainerConfig(ctx, c, cfg)
7241
if err != nil {
7342
return nil, err
7443
}
7544
containerCtx, containerCancel := context.WithCancel(ctx)
7645
defer containerCancel()
77-
bkContainer, err := c.NewContainer(containerCtx, gateway.NewContainerRequest{
78-
Mounts: []gateway.Mount{
79-
{
80-
Dest: "/",
81-
MountType: pb.MountType_BIND,
82-
Ref: imgRef.Ref,
83-
},
84-
},
85-
})
46+
bkContainer, err := c.NewContainer(containerCtx, containerCfg)
8647
if err != nil {
8748
return nil, err
8849
}
89-
imgData := res.Metadata[exptypes.ExporterImageConfigKey]
90-
var img *specs.Image
91-
if len(imgData) > 0 {
92-
img = &specs.Image{}
93-
if err := json.Unmarshal(imgData, img); err != nil {
94-
fmt.Println(err)
95-
return nil, err
96-
}
97-
}
9850
releaseCh := make(chan struct{})
9951
container := &Container{
10052
containerCancel: containerCancel,
10153
container: bkContainer,
102-
image: img,
10354
releaseCh: releaseCh,
55+
resultCtx: resultCtx,
10456
}
57+
doneCh := make(chan struct{})
58+
defer close(doneCh)
59+
resultCtx.registerCleanup(func() {
60+
container.Cancel()
61+
<-doneCh
62+
})
10563
ctrCh <- container
10664
<-container.releaseCh
10765

10866
return nil, bkContainer.Release(ctx)
109-
}, nil)
67+
})
11068
if err != nil {
11169
errCh <- err
11270
}
@@ -146,56 +104,20 @@ func (c *Container) Exec(ctx context.Context, cfg *controllerapi.InvokeConfig, s
146104
c.markUnavailable()
147105
}()
148106
}
149-
err := exec(ctx, cfg, c.container, c.image, stdin, stdout, stderr)
107+
err := exec(ctx, c.resultCtx, cfg, c.container, stdin, stdout, stderr)
150108
if err != nil {
151109
// Container becomes unavailable if one of the processes fails in it.
152110
c.markUnavailable()
153111
}
154112
return err
155113
}
156114

157-
func exec(ctx context.Context, cfg *controllerapi.InvokeConfig, ctr gateway.Container, img *specs.Image, stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
158-
user := ""
159-
if !cfg.NoUser {
160-
user = cfg.User
161-
} else if img != nil {
162-
user = img.Config.User
163-
}
164-
165-
cwd := ""
166-
if !cfg.NoCwd {
167-
cwd = cfg.Cwd
168-
} else if img != nil {
169-
cwd = img.Config.WorkingDir
170-
}
171-
172-
env := []string{}
173-
if img != nil {
174-
env = append(env, img.Config.Env...)
175-
}
176-
env = append(env, cfg.Env...)
177-
178-
args := []string{}
179-
if cfg.Entrypoint != nil {
180-
args = append(args, cfg.Entrypoint...)
181-
}
182-
if cfg.Cmd != nil {
183-
args = append(args, cfg.Cmd...)
184-
}
185-
// caller should always set args
186-
if len(args) == 0 {
187-
return errors.Errorf("specify args to execute")
115+
func exec(ctx context.Context, resultCtx *ResultContext, cfg *controllerapi.InvokeConfig, ctr gateway.Container, stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
116+
processCfg, err := resultCtx.getProcessConfig(cfg, stdin, stdout, stderr)
117+
if err != nil {
118+
return err
188119
}
189-
proc, err := ctr.Start(ctx, gateway.StartRequest{
190-
Args: args,
191-
Env: env,
192-
User: user,
193-
Cwd: cwd,
194-
Tty: cfg.Tty,
195-
Stdin: stdin,
196-
Stdout: stdout,
197-
Stderr: stderr,
198-
})
120+
proc, err := ctr.Start(ctx, processCfg)
199121
if err != nil {
200122
return errors.Errorf("failed to start container: %v", err)
201123
}

0 commit comments

Comments
 (0)