mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
monitor: Enable to exec into the container
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
This commit is contained in:
145
build/build.go
145
build/build.go
@ -660,151 +660,6 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
|
||||
return &so, releaseF, nil
|
||||
}
|
||||
|
||||
// ContainerConfig is configuration for a container to run.
|
||||
type ContainerConfig struct {
|
||||
ResultCtx *ResultContext
|
||||
|
||||
Stdin io.ReadCloser
|
||||
Stdout io.WriteCloser
|
||||
Stderr io.WriteCloser
|
||||
Tty bool
|
||||
|
||||
Entrypoint []string
|
||||
Cmd []string
|
||||
Env []string
|
||||
User *string
|
||||
Cwd *string
|
||||
}
|
||||
|
||||
// ResultContext is a build result with the client that built it.
|
||||
type ResultContext struct {
|
||||
Client *client.Client
|
||||
Res *gateway.Result
|
||||
}
|
||||
|
||||
// Invoke invokes a build result as a container.
|
||||
func Invoke(ctx context.Context, cfg ContainerConfig) error {
|
||||
if cfg.ResultCtx == nil {
|
||||
return errors.Errorf("result must be provided")
|
||||
}
|
||||
c, res := cfg.ResultCtx.Client, cfg.ResultCtx.Res
|
||||
|
||||
mainCtx := ctx
|
||||
|
||||
_, err := c.Build(context.TODO(), client.SolveOpt{}, "buildx", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
go func() {
|
||||
<-mainCtx.Done()
|
||||
cancel()
|
||||
}()
|
||||
|
||||
if res.Ref == nil {
|
||||
return nil, errors.Errorf("no reference is registered")
|
||||
}
|
||||
st, err := res.Ref.ToState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
def, err := st.Marshal(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imgRef, err := c.Solve(ctx, gateway.SolveRequest{
|
||||
Definition: def.ToPB(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr, err := c.NewContainer(ctx, gateway.NewContainerRequest{
|
||||
Mounts: []gateway.Mount{
|
||||
{
|
||||
Dest: "/",
|
||||
MountType: pb.MountType_BIND,
|
||||
Ref: imgRef.Ref,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer ctr.Release(context.TODO())
|
||||
|
||||
imgData := res.Metadata[exptypes.ExporterImageConfigKey]
|
||||
var img *specs.Image
|
||||
if len(imgData) > 0 {
|
||||
img = &specs.Image{}
|
||||
if err := json.Unmarshal(imgData, img); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
user := ""
|
||||
if cfg.User != nil {
|
||||
user = *cfg.User
|
||||
} else if img != nil {
|
||||
user = img.Config.User
|
||||
}
|
||||
|
||||
cwd := ""
|
||||
if cfg.Cwd != nil {
|
||||
cwd = *cfg.Cwd
|
||||
} else if img != nil {
|
||||
cwd = img.Config.WorkingDir
|
||||
}
|
||||
|
||||
env := []string{}
|
||||
if img != nil {
|
||||
env = append(env, img.Config.Env...)
|
||||
}
|
||||
env = append(env, cfg.Env...)
|
||||
|
||||
args := []string{}
|
||||
if cfg.Entrypoint != nil {
|
||||
args = append(args, cfg.Entrypoint...)
|
||||
} else if img != nil {
|
||||
args = append(args, img.Config.Entrypoint...)
|
||||
}
|
||||
if cfg.Cmd != nil {
|
||||
args = append(args, cfg.Cmd...)
|
||||
} else if img != nil {
|
||||
args = append(args, img.Config.Cmd...)
|
||||
}
|
||||
|
||||
proc, err := ctr.Start(ctx, gateway.StartRequest{
|
||||
Args: args,
|
||||
Env: env,
|
||||
User: user,
|
||||
Cwd: cwd,
|
||||
Tty: cfg.Tty,
|
||||
Stdin: cfg.Stdin,
|
||||
Stdout: cfg.Stdout,
|
||||
Stderr: cfg.Stderr,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("failed to start container: %v", err)
|
||||
}
|
||||
errCh := make(chan error)
|
||||
doneCh := make(chan struct{})
|
||||
go func() {
|
||||
if err := proc.Wait(); err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
close(doneCh)
|
||||
}()
|
||||
select {
|
||||
case <-doneCh:
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case err := <-errCh:
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
}, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func Build(ctx context.Context, nodes []builder.Node, opt map[string]Options, docker *dockerutil.Client, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
|
||||
return BuildWithResultHandler(ctx, nodes, opt, docker, configDir, w, nil)
|
||||
}
|
||||
|
Reference in New Issue
Block a user