diff --git a/container/src/libcfcontainer/cuttlefish_container.go b/container/src/libcfcontainer/cuttlefish_container.go index 5a09813c909..69c518d6d10 100644 --- a/container/src/libcfcontainer/cuttlefish_container.go +++ b/container/src/libcfcontainer/cuttlefish_container.go @@ -184,7 +184,10 @@ func (m *CuttlefishContainerManagerImpl) ExecOnContainer(ctx context.Context, ct } defer attachRes.Close() if stdin != nil { - go io.Copy(attachRes.Conn, stdin) + go func() { + io.Copy(attachRes.Conn, stdin) + attachRes.CloseWrite() + }() } stdcopy.StdCopy(stdout, stderr, attachRes.Reader) diff --git a/container/src/podcvd/internal/main.go b/container/src/podcvd/internal/main.go index 9b20818a487..84ca5511991 100644 --- a/container/src/podcvd/internal/main.go +++ b/container/src/podcvd/internal/main.go @@ -46,46 +46,38 @@ func Main(args []string) error { subcommand := cvdArgs.SubCommandArgs[0] if cvdArgs.HasHelpFlagOnSubCommandArgs() { - switch subcommand { - case "bugreport", "cache", "clear", "create", "display", "env", "fetch", "fleet", "help", "lint", "load", "login", "logs", "powerbtn", "powerwash", "remove", "reset", "restart", "resume", "screen_recording", "snapshot_take", "start", "status", "stop", "suspend", "version": - cvdArgs.SubCommandArgs = []string{subcommand, "--help"} - if err := handleToolingSubcommands(ccm, cvdArgs); err != nil { - return err - } - default: - return fmt.Errorf("unknown subcommand %q", subcommand) + cvdArgs.SubCommandArgs = []string{subcommand, "--help"} + return handleToolingSubcommands(ccm, cvdArgs) + } + if err := CheckDeviceAccessible(); err != nil { + return err + } + switch subcommand { + case "bugreport", "create", "display", "env", "logs", "powerbtn", "powerwash", "remove", "restart", "resume", "screen_recording", "snapshot_take", "start", "status", "stop", "suspend": + if err := handleSubcommandsForSingleInstanceGroup(ccm, cvdArgs); err != nil { + return err } - } else { - if err := CheckDeviceAccessible(); err != nil { + case "clear", "reset": + if err := clearAllCuttlefishHosts(ccm); err != nil { return err } - switch subcommand { - case "bugreport", "create", "display", "env", "logs", "powerbtn", "powerwash", "remove", "restart", "resume", "screen_recording", "snapshot_take", "start", "status", "stop", "suspend": - if err := handleSubcommandsForSingleInstanceGroup(ccm, cvdArgs); err != nil { - return err - } - case "clear", "reset": - if err := clearAllCuttlefishHosts(ccm); err != nil { - return err - } - case "fleet": - if err := fleetAllCuttlefishHosts(ccm); err != nil { - return err - } - case "help", "login", "version": - if err := handleToolingSubcommands(ccm, cvdArgs); err != nil { - return err - } - case "fetch": - if err := ExecFetchCmdOnDisposableHost(ccm, cvdArgs); err != nil { - return err - } - case "cache", "lint": - // TODO(seungjaeyoo): Support other subcommands of cvd as well. - return fmt.Errorf("subcommand %q is not implemented yet", subcommand) - default: - return fmt.Errorf("unknown subcommand %q", subcommand) + case "fleet": + if err := fleetAllCuttlefishHosts(ccm); err != nil { + return err + } + case "help", "lint", "login", "version": + if err := handleToolingSubcommands(ccm, cvdArgs); err != nil { + return err } + case "fetch": + if err := ExecFetchCmdOnDisposableHost(ccm, cvdArgs); err != nil { + return err + } + case "cache", "load", "monitor", "setup": + // TODO(seungjaeyoo): Support other subcommands of cvd as well. + return fmt.Errorf("subcommand %q is not implemented yet", subcommand) + default: + return fmt.Errorf("unknown subcommand %q", subcommand) } return nil } @@ -372,10 +364,39 @@ func handleToolingSubcommands(ccm libcfcontainer.CuttlefishContainerManager, cvd if err := CreateToolingHost(ccm); err != nil { return err } + subcommand := cvdArgs.SubCommandArgs[0] + switch subcommand { + case "lint": + if err := handleLintExecution(ccm, cvdArgs); err != nil { + return err + } + default: + args := append([]string{"cvd"}, cvdArgs.SerializeCommonArgs()...) + args = append(args, cvdArgs.SubCommandArgs...) + if err := ccm.ExecOnContainer(context.Background(), ToolingContainerName, args, os.Stdin, os.Stdout, os.Stderr); err != nil { + return err + } + } + return nil +} + +func handleLintExecution(ccm libcfcontainer.CuttlefishContainerManager, cvdArgs *CvdArgs) error { + if len(cvdArgs.SubCommandArgs) < 2 { + return fmt.Errorf("missing JSON config file path") + } + configPath := cvdArgs.SubCommandArgs[1] + file, err := os.Open(configPath) + if err != nil { + return fmt.Errorf("failed to open config file %q: %w", configPath, err) + } + defer file.Close() args := append([]string{"cvd"}, cvdArgs.SerializeCommonArgs()...) - args = append(args, cvdArgs.SubCommandArgs...) - if err := ccm.ExecOnContainer(context.Background(), ToolingContainerName, args, os.Stdin, os.Stdout, os.Stderr); err != nil { + args = append(args, "lint", "/dev/stdin") + var stdoutBuf bytes.Buffer + if err := ccm.ExecOnContainer(context.Background(), ToolingContainerName, args, file, &stdoutBuf, os.Stderr); err != nil { return err } + output := strings.ReplaceAll(stdoutBuf.String(), "/dev/stdin", configPath) + os.Stdout.WriteString(output) return nil }