mirror of
https://github.com/docker/buildx.git
synced 2024-11-22 15:37:16 +08:00
invoke: add messages
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
This commit is contained in:
parent
7b660c4e30
commit
2f9d46ce27
@ -709,10 +709,10 @@ func Invoke(ctx context.Context, cfg ContainerConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker DockerAPI, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
|
func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker DockerAPI, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
|
||||||
return BuildWithResultHandler(ctx, drivers, opt, docker, configDir, w, nil)
|
return BuildWithResultHandler(ctx, drivers, opt, docker, configDir, w, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker DockerAPI, configDir string, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultContext)) (resp map[string]*client.SolveResponse, err error) {
|
func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker DockerAPI, configDir string, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultContext), allowNoOutput bool) (resp map[string]*client.SolveResponse, err error) {
|
||||||
if len(drivers) == 0 {
|
if len(drivers) == 0 {
|
||||||
return nil, errors.Errorf("driver required for build")
|
return nil, errors.Errorf("driver required for build")
|
||||||
}
|
}
|
||||||
@ -737,7 +737,7 @@ func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[s
|
|||||||
noOutputTargets = append(noOutputTargets, name)
|
noOutputTargets = append(noOutputTargets, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(noOutputTargets) > 0 {
|
if len(noOutputTargets) > 0 && !allowNoOutput {
|
||||||
var warnNoOutputBuf bytes.Buffer
|
var warnNoOutputBuf bytes.Buffer
|
||||||
warnNoOutputBuf.WriteString("No output specified ")
|
warnNoOutputBuf.WriteString("No output specified ")
|
||||||
if len(noOutputTargets) == 1 && noOutputTargets[0] == "default" {
|
if len(noOutputTargets) == 1 && noOutputTargets[0] == "default" {
|
||||||
|
@ -233,7 +233,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
|
|||||||
contextPathHash = in.contextPath
|
contextPathHash = in.contextPath
|
||||||
}
|
}
|
||||||
|
|
||||||
imageID, res, err := buildTargets(ctx, dockerCli, map[string]build.Options{defaultTargetName: opts}, in.progress, contextPathHash, in.builder, in.metadataFile)
|
imageID, res, err := buildTargets(ctx, dockerCli, map[string]build.Options{defaultTargetName: opts}, in.progress, contextPathHash, in.builder, in.metadataFile, in.invoke != "")
|
||||||
err = wrapBuildError(err, false)
|
err = wrapBuildError(err, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -250,7 +250,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
|
|||||||
return errors.Errorf("failed to configure terminal: %v", err)
|
return errors.Errorf("failed to configure terminal: %v", err)
|
||||||
}
|
}
|
||||||
err = monitor.RunMonitor(ctx, cfg, func(ctx context.Context) (*build.ResultContext, error) {
|
err = monitor.RunMonitor(ctx, cfg, func(ctx context.Context) (*build.ResultContext, error) {
|
||||||
_, rr, err := buildTargets(ctx, dockerCli, map[string]build.Options{defaultTargetName: opts}, in.progress, contextPathHash, in.builder, in.metadataFile)
|
_, rr, err := buildTargets(ctx, dockerCli, map[string]build.Options{defaultTargetName: opts}, in.progress, contextPathHash, in.builder, in.metadataFile, true)
|
||||||
return rr, err
|
return rr, err
|
||||||
}, io.NopCloser(os.Stdin), nopCloser{os.Stdout}, nopCloser{os.Stderr})
|
}, io.NopCloser(os.Stdin), nopCloser{os.Stdout}, nopCloser{os.Stderr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -271,7 +271,7 @@ type nopCloser struct {
|
|||||||
|
|
||||||
func (c nopCloser) Close() error { return nil }
|
func (c nopCloser) Close() error { return nil }
|
||||||
|
|
||||||
func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]build.Options, progressMode, contextPathHash, instance string, metadataFile string) (imageID string, res *build.ResultContext, err error) {
|
func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]build.Options, progressMode, contextPathHash, instance string, metadataFile string, allowNoOutput bool) (imageID string, res *build.ResultContext, err error) {
|
||||||
dis, err := getInstanceOrDefault(ctx, dockerCli, instance, contextPathHash)
|
dis, err := getInstanceOrDefault(ctx, dockerCli, instance, contextPathHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
@ -290,7 +290,7 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu
|
|||||||
if res == nil || driverIndex < idx {
|
if res == nil || driverIndex < idx {
|
||||||
idx, res = driverIndex, gotRes
|
idx, res = driverIndex, gotRes
|
||||||
}
|
}
|
||||||
})
|
}, allowNoOutput)
|
||||||
err1 := printer.Wait()
|
err1 := printer.Wait()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = err1
|
err = err1
|
||||||
|
@ -13,6 +13,14 @@ import (
|
|||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const helpMessage = `
|
||||||
|
Available commads are:
|
||||||
|
reload reloads the context and build it.
|
||||||
|
rollback re-runs the interactive container with initial rootfs contents.
|
||||||
|
exit exits monitor.
|
||||||
|
help shows this message.
|
||||||
|
`
|
||||||
|
|
||||||
// RunMonitor provides an interactive session for running and managing containers via specified IO.
|
// RunMonitor provides an interactive session for running and managing containers via specified IO.
|
||||||
func RunMonitor(ctx context.Context, containerConfig build.ContainerConfig, reloadFunc func(context.Context) (*build.ResultContext, error), stdin io.ReadCloser, stdout, stderr io.WriteCloser) error {
|
func RunMonitor(ctx context.Context, containerConfig build.ContainerConfig, reloadFunc func(context.Context) (*build.ResultContext, error), stdin io.ReadCloser, stdout, stderr io.WriteCloser) error {
|
||||||
monitorIn, monitorOut := ioSetPipe()
|
monitorIn, monitorOut := ioSetPipe()
|
||||||
@ -34,11 +42,18 @@ func RunMonitor(ctx context.Context, containerConfig build.ContainerConfig, relo
|
|||||||
|
|
||||||
m := &monitor{
|
m := &monitor{
|
||||||
invokeIO: newIOForwarder(containerIn),
|
invokeIO: newIOForwarder(containerIn),
|
||||||
muxIO: newMuxIO(ioSetIn{stdin, stdout, stderr}, []ioSetOutContext{monitorOutCtx, containerOutCtx}, 1, "Switched IO\n"),
|
muxIO: newMuxIO(ioSetIn{stdin, stdout, stderr}, []ioSetOutContext{monitorOutCtx, containerOutCtx}, 1, func(prev int, res int) string {
|
||||||
|
if prev == 0 && res == 0 {
|
||||||
|
// No toggle happened because container I/O isn't enabled.
|
||||||
|
return "No running interactive containers. You can start one by issuing rollback command\n"
|
||||||
|
}
|
||||||
|
return "Switched IO\n"
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start container automatically
|
// Start container automatically
|
||||||
go func() {
|
go func() {
|
||||||
|
fmt.Fprintf(stdout, "Launching interactive container. Press Ctrl-a-c to switch to monitor console\n")
|
||||||
m.rollback(ctx, containerConfig)
|
m.rollback(ctx, containerConfig)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -73,13 +88,18 @@ func RunMonitor(ctx context.Context, containerConfig build.ContainerConfig, relo
|
|||||||
// rollback the running container with the new result
|
// rollback the running container with the new result
|
||||||
containerConfig.ResultCtx = res
|
containerConfig.ResultCtx = res
|
||||||
m.rollback(ctx, containerConfig)
|
m.rollback(ctx, containerConfig)
|
||||||
|
fmt.Fprint(stdout, "Interactive container was restarted. Press Ctrl-a-c to switch to the new container\n")
|
||||||
}
|
}
|
||||||
case "rollback":
|
case "rollback":
|
||||||
m.rollback(ctx, containerConfig)
|
m.rollback(ctx, containerConfig)
|
||||||
|
fmt.Fprint(stdout, "Interactive container was restarted. Press Ctrl-a-c to switch to the new container\n")
|
||||||
case "exit":
|
case "exit":
|
||||||
return
|
return
|
||||||
|
case "help":
|
||||||
|
fmt.Fprint(stdout, helpMessage)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("unknown command: %q\n", l)
|
fmt.Printf("unknown command: %q\n", l)
|
||||||
|
fmt.Fprint(stdout, helpMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -227,7 +247,7 @@ type ioSetOutContext struct {
|
|||||||
// newMuxIO forwards IO stream to/from "in" and "outs".
|
// newMuxIO forwards IO stream to/from "in" and "outs".
|
||||||
// "outs" are closed automatically when "in" reaches EOF.
|
// "outs" are closed automatically when "in" reaches EOF.
|
||||||
// "in" doesn't closed automatically so the caller needs to explicitly close it.
|
// "in" doesn't closed automatically so the caller needs to explicitly close it.
|
||||||
func newMuxIO(in ioSetIn, out []ioSetOutContext, initIdx int, toggleMessage string) *muxIO {
|
func newMuxIO(in ioSetIn, out []ioSetOutContext, initIdx int, toggleMessage func(prev int, res int) string) *muxIO {
|
||||||
m := &muxIO{
|
m := &muxIO{
|
||||||
enabled: make(map[int]struct{}),
|
enabled: make(map[int]struct{}),
|
||||||
in: in,
|
in: in,
|
||||||
@ -327,7 +347,7 @@ type muxIO struct {
|
|||||||
in ioSetIn
|
in ioSetIn
|
||||||
out []ioSetOutContext
|
out []ioSetOutContext
|
||||||
closedCh chan struct{}
|
closedCh chan struct{}
|
||||||
toggleMessage string
|
toggleMessage func(prev int, res int) string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *muxIO) waitClosed() {
|
func (m *muxIO) waitClosed() {
|
||||||
@ -357,6 +377,7 @@ func (m *muxIO) toggleIO() {
|
|||||||
if m.out[m.cur].disableHook != nil {
|
if m.out[m.cur].disableHook != nil {
|
||||||
m.out[m.cur].disableHook()
|
m.out[m.cur].disableHook()
|
||||||
}
|
}
|
||||||
|
prev := m.cur
|
||||||
for {
|
for {
|
||||||
if m.cur+1 >= m.maxCur {
|
if m.cur+1 >= m.maxCur {
|
||||||
m.cur = 0
|
m.cur = 0
|
||||||
@ -368,10 +389,11 @@ func (m *muxIO) toggleIO() {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
res := m.cur
|
||||||
if m.out[m.cur].enableHook != nil {
|
if m.out[m.cur].enableHook != nil {
|
||||||
m.out[m.cur].enableHook()
|
m.out[m.cur].enableHook()
|
||||||
}
|
}
|
||||||
fmt.Fprintf(m.in.stdout, m.toggleMessage)
|
fmt.Fprint(m.in.stdout, m.toggleMessage(prev, res))
|
||||||
}
|
}
|
||||||
|
|
||||||
func traceReader(r io.ReadCloser, f func(rune) (bool, error)) io.ReadCloser {
|
func traceReader(r io.ReadCloser, f func(rune) (bool, error)) io.ReadCloser {
|
||||||
|
@ -131,7 +131,7 @@ func TestMuxIO(t *testing.T) {
|
|||||||
outBufs = append(outBufs, outBuf)
|
outBufs = append(outBufs, outBuf)
|
||||||
outs = append(outs, ioSetOutContext{out, nil, nil})
|
outs = append(outs, ioSetOutContext{out, nil, nil})
|
||||||
}
|
}
|
||||||
mio := newMuxIO(in, outs, tt.initIdx, "")
|
mio := newMuxIO(in, outs, tt.initIdx, func(prev int, res int) string { return "" })
|
||||||
for _, i := range tt.inputs {
|
for _, i := range tt.inputs {
|
||||||
// Add input to muxIO
|
// Add input to muxIO
|
||||||
istr, writeback := i(mio)
|
istr, writeback := i(mio)
|
||||||
|
Loading…
Reference in New Issue
Block a user