瀏覽代碼

restore TTY auto-detection using dockerCli.Out.IsTerminal

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 3 年之前
父節點
當前提交
c843d373de
共有 8 個文件被更改,包括 25 次插入18 次删除
  1. 4 3
      cmd/compose/compose.go
  2. 3 2
      cmd/compose/exec.go
  3. 3 2
      cmd/compose/run.go
  4. 1 1
      cmd/main.go
  5. 1 1
      docs/yaml/main/generate.go
  6. 5 0
      pkg/compose/run.go
  7. 8 8
      pkg/e2e/compose_run_test.go
  8. 0 1
      pkg/e2e/toto.sh

+ 4 - 3
cmd/compose/compose.go

@@ -29,6 +29,7 @@ import (
 	"github.com/compose-spec/compose-go/types"
 	"github.com/compose-spec/compose-go/types"
 	dockercli "github.com/docker/cli/cli"
 	dockercli "github.com/docker/cli/cli"
 	"github.com/docker/cli/cli-plugins/manager"
 	"github.com/docker/cli/cli-plugins/manager"
+	"github.com/docker/cli/cli/command"
 	"github.com/morikuni/aec"
 	"github.com/morikuni/aec"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
@@ -224,7 +225,7 @@ func RunningAsStandalone() bool {
 }
 }
 
 
 // RootCommand returns the compose command with its child commands
 // RootCommand returns the compose command with its child commands
-func RootCommand(backend api.Service) *cobra.Command {
+func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 	opts := projectOptions{}
 	opts := projectOptions{}
 	var (
 	var (
 		ansi    string
 		ansi    string
@@ -300,9 +301,9 @@ func RootCommand(backend api.Service) *cobra.Command {
 		logsCommand(&opts, backend),
 		logsCommand(&opts, backend),
 		convertCommand(&opts, backend),
 		convertCommand(&opts, backend),
 		killCommand(&opts, backend),
 		killCommand(&opts, backend),
-		runCommand(&opts, backend),
+		runCommand(&opts, dockerCli, backend),
 		removeCommand(&opts, backend),
 		removeCommand(&opts, backend),
-		execCommand(&opts, backend),
+		execCommand(&opts, dockerCli, backend),
 		pauseCommand(&opts, backend),
 		pauseCommand(&opts, backend),
 		unpauseCommand(&opts, backend),
 		unpauseCommand(&opts, backend),
 		topCommand(&opts, backend),
 		topCommand(&opts, backend),

+ 3 - 2
cmd/compose/exec.go

@@ -21,6 +21,7 @@ import (
 
 
 	"github.com/compose-spec/compose-go/types"
 	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli"
+	"github.com/docker/cli/cli/command"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/compose"
 	"github.com/docker/compose/v2/pkg/compose"
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
@@ -41,7 +42,7 @@ type execOpts struct {
 	privileged bool
 	privileged bool
 }
 }
 
 
-func execCommand(p *projectOptions, backend api.Service) *cobra.Command {
+func execCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
 	opts := execOpts{
 	opts := execOpts{
 		composeOptions: &composeOptions{
 		composeOptions: &composeOptions{
 			projectOptions: p,
 			projectOptions: p,
@@ -67,7 +68,7 @@ func execCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	runCmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if there are multiple instances of a service [default: 1].")
 	runCmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if there are multiple instances of a service [default: 1].")
 	runCmd.Flags().BoolVarP(&opts.privileged, "privileged", "", false, "Give extended privileges to the process.")
 	runCmd.Flags().BoolVarP(&opts.privileged, "privileged", "", false, "Give extended privileges to the process.")
 	runCmd.Flags().StringVarP(&opts.user, "user", "u", "", "Run the command as this user.")
 	runCmd.Flags().StringVarP(&opts.user, "user", "u", "", "Run the command as this user.")
-	runCmd.Flags().BoolVarP(&opts.noTty, "no-TTY", "T", false, "Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.")
+	runCmd.Flags().BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.")
 	runCmd.Flags().StringVarP(&opts.workingDir, "workdir", "w", "", "Path to workdir directory for this command.")
 	runCmd.Flags().StringVarP(&opts.workingDir, "workdir", "w", "", "Path to workdir directory for this command.")
 
 
 	runCmd.Flags().BoolP("interactive", "i", true, "Keep STDIN open even if not attached.")
 	runCmd.Flags().BoolP("interactive", "i", true, "Keep STDIN open even if not attached.")

+ 3 - 2
cmd/compose/run.go

@@ -24,6 +24,7 @@ import (
 	cgo "github.com/compose-spec/compose-go/cli"
 	cgo "github.com/compose-spec/compose-go/cli"
 	"github.com/compose-spec/compose-go/loader"
 	"github.com/compose-spec/compose-go/loader"
 	"github.com/compose-spec/compose-go/types"
 	"github.com/compose-spec/compose-go/types"
+	"github.com/docker/cli/cli/command"
 	"github.com/mattn/go-shellwords"
 	"github.com/mattn/go-shellwords"
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
 	"github.com/spf13/pflag"
@@ -106,7 +107,7 @@ func (opts runOptions) apply(project *types.Project) error {
 	return nil
 	return nil
 }
 }
 
 
-func runCommand(p *projectOptions, backend api.Service) *cobra.Command {
+func runCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
 	opts := runOptions{
 	opts := runOptions{
 		composeOptions: &composeOptions{
 		composeOptions: &composeOptions{
 			projectOptions: p,
 			projectOptions: p,
@@ -149,7 +150,7 @@ func runCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	flags.StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
 	flags.StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
 	flags.StringArrayVarP(&opts.labels, "label", "l", []string{}, "Add or override a label")
 	flags.StringArrayVarP(&opts.labels, "label", "l", []string{}, "Add or override a label")
 	flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
 	flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
-	flags.BoolVarP(&opts.noTty, "no-TTY", "T", false, "Disable pseudo-noTty allocation. By default docker compose run allocates a TTY")
+	flags.BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-noTty allocation. By default docker compose run allocates a TTY")
 	flags.StringVar(&opts.name, "name", "", " Assign a name to the container")
 	flags.StringVar(&opts.name, "name", "", " Assign a name to the container")
 	flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
 	flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
 	flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
 	flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")

+ 1 - 1
cmd/main.go

@@ -40,7 +40,7 @@ func init() {
 func pluginMain() {
 func pluginMain() {
 	plugin.Run(func(dockerCli command.Cli) *cobra.Command {
 	plugin.Run(func(dockerCli command.Cli) *cobra.Command {
 		lazyInit := api.NewServiceProxy()
 		lazyInit := api.NewServiceProxy()
-		cmd := commands.RootCommand(lazyInit)
+		cmd := commands.RootCommand(dockerCli, lazyInit)
 		originalPreRun := cmd.PersistentPreRunE
 		originalPreRun := cmd.PersistentPreRunE
 		cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
 		cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
 			if err := plugin.PersistentPreRunE(cmd, args); err != nil {
 			if err := plugin.PersistentPreRunE(cmd, args); err != nil {

+ 1 - 1
docs/yaml/main/generate.go

@@ -31,7 +31,7 @@ func generateDocs(opts *options) error {
 		Use:               "docker",
 		Use:               "docker",
 		DisableAutoGenTag: true,
 		DisableAutoGenTag: true,
 	}
 	}
-	cmd.AddCommand(compose.RootCommand(nil))
+	cmd.AddCommand(compose.RootCommand(nil, nil))
 	disableFlagsInUseLine(cmd)
 	disableFlagsInUseLine(cmd)
 
 
 	tool, err := clidocstool.New(clidocstool.Options{
 	tool, err := clidocstool.New(clidocstool.Options{

+ 5 - 0
pkg/compose/run.go

@@ -19,6 +19,7 @@ package compose
 import (
 import (
 	"context"
 	"context"
 	"fmt"
 	"fmt"
+
 	"github.com/compose-spec/compose-go/types"
 	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli"
 	cmd "github.com/docker/cli/cli/command/container"
 	cmd "github.com/docker/cli/cli/command/container"
@@ -55,6 +56,10 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
 
 
 	applyRunOptions(project, &service, opts)
 	applyRunOptions(project, &service, opts)
 
 
+	if err := s.dockerCli.In().CheckTty(opts.Interactive, service.Tty); err != nil {
+		return "", err
+	}
+
 	slug := stringid.GenerateRandomID()
 	slug := stringid.GenerateRandomID()
 	if service.ContainerName == "" {
 	if service.ContainerName == "" {
 		service.ContainerName = fmt.Sprintf("%s_%s_run_%s", project.Name, service.Name, stringid.TruncateID(slug))
 		service.ContainerName = fmt.Sprintf("%s_%s_run_%s", project.Name, service.Name, stringid.TruncateID(slug))

+ 8 - 8
pkg/e2e/compose_run_test.go

@@ -29,11 +29,11 @@ func TestLocalComposeRun(t *testing.T) {
 	c := NewParallelE2eCLI(t, binDir)
 	c := NewParallelE2eCLI(t, binDir)
 
 
 	t.Run("compose run", func(t *testing.T) {
 	t.Run("compose run", func(t *testing.T) {
-		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "-T", "back")
+		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "back")
 		lines := Lines(res.Stdout())
 		lines := Lines(res.Stdout())
 		assert.Equal(t, lines[len(lines)-1], "Hello there!!", res.Stdout())
 		assert.Equal(t, lines[len(lines)-1], "Hello there!!", res.Stdout())
 		assert.Assert(t, !strings.Contains(res.Combined(), "orphan"))
 		assert.Assert(t, !strings.Contains(res.Combined(), "orphan"))
-		res = c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "-T", "back", "echo", "Hello one more time")
+		res = c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "back", "echo", "Hello one more time")
 		lines = Lines(res.Stdout())
 		lines = Lines(res.Stdout())
 		assert.Equal(t, lines[len(lines)-1], "Hello one more time", res.Stdout())
 		assert.Equal(t, lines[len(lines)-1], "Hello one more time", res.Stdout())
 		assert.Assert(t, !strings.Contains(res.Combined(), "orphan"))
 		assert.Assert(t, !strings.Contains(res.Combined(), "orphan"))
@@ -68,7 +68,7 @@ func TestLocalComposeRun(t *testing.T) {
 	})
 	})
 
 
 	t.Run("compose run --rm", func(t *testing.T) {
 	t.Run("compose run --rm", func(t *testing.T) {
-		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "-T", "--rm", "back", "echo", "Hello again")
+		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "--rm", "back", "echo", "Hello again")
 		lines := Lines(res.Stdout())
 		lines := Lines(res.Stdout())
 		assert.Equal(t, lines[len(lines)-1], "Hello again", res.Stdout())
 		assert.Equal(t, lines[len(lines)-1], "Hello again", res.Stdout())
 
 
@@ -85,7 +85,7 @@ func TestLocalComposeRun(t *testing.T) {
 	t.Run("compose run --volumes", func(t *testing.T) {
 	t.Run("compose run --volumes", func(t *testing.T) {
 		wd, err := os.Getwd()
 		wd, err := os.Getwd()
 		assert.NilError(t, err)
 		assert.NilError(t, err)
-		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "-T", "--volumes", wd+":/foo", "back", "/bin/sh", "-c", "ls /foo")
+		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "--volumes", wd+":/foo", "back", "/bin/sh", "-c", "ls /foo")
 		res.Assert(t, icmd.Expected{Out: "compose_run_test.go"})
 		res.Assert(t, icmd.Expected{Out: "compose_run_test.go"})
 
 
 		res = c.RunDockerCmd("ps", "--all")
 		res = c.RunDockerCmd("ps", "--all")
@@ -93,18 +93,18 @@ func TestLocalComposeRun(t *testing.T) {
 	})
 	})
 
 
 	t.Run("compose run --publish", func(t *testing.T) {
 	t.Run("compose run --publish", func(t *testing.T) {
-		c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "-T", "--publish", "8081:80", "-d", "back", "/bin/sh", "-c", "sleep 1")
+		c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "--publish", "8081:80", "-d", "back", "/bin/sh", "-c", "sleep 1")
 		res := c.RunDockerCmd("ps")
 		res := c.RunDockerCmd("ps")
 		assert.Assert(t, strings.Contains(res.Stdout(), "8081->80/tcp"), res.Stdout())
 		assert.Assert(t, strings.Contains(res.Stdout(), "8081->80/tcp"), res.Stdout())
 	})
 	})
 
 
 	t.Run("compose run orphan", func(t *testing.T) {
 	t.Run("compose run orphan", func(t *testing.T) {
 		// Use different compose files to get an orphan container
 		// Use different compose files to get an orphan container
-		c.RunDockerComposeCmd("-f", "./fixtures/run-test/orphan.yaml", "run", "-T", "simple")
-		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "-T", "back", "echo", "Hello")
+		c.RunDockerComposeCmd("-f", "./fixtures/run-test/orphan.yaml", "run", "simple")
+		res := c.RunDockerComposeCmd("-f", "./fixtures/run-test/compose.yaml", "run", "back", "echo", "Hello")
 		assert.Assert(t, strings.Contains(res.Combined(), "orphan"))
 		assert.Assert(t, strings.Contains(res.Combined(), "orphan"))
 
 
-		cmd := c.NewDockerCmd("compose", "-f", "./fixtures/run-test/compose.yaml", "run", "-T", "back", "echo", "Hello")
+		cmd := c.NewDockerCmd("compose", "-f", "./fixtures/run-test/compose.yaml", "run", "back", "echo", "Hello")
 		res = icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
 		res = icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
 			cmd.Env = append(cmd.Env, "COMPOSE_IGNORE_ORPHANS=True")
 			cmd.Env = append(cmd.Env, "COMPOSE_IGNORE_ORPHANS=True")
 		})
 		})

+ 0 - 1
pkg/e2e/toto.sh

@@ -1 +0,0 @@
-../../bin/docker-compose -f ./fixtures/run-test/compose.yaml run --volumes $(pwd):/foo back ls /foo