mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-10-31 08:03:43 +08:00 
			
		
		
		
	invoke: add messages
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
This commit is contained in:
		| @@ -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) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Kohei Tokunaga
					Kohei Tokunaga