Преглед на файлове

Merge pull request #326 from docker/run_follow_logs

Run containers and attach to logs by default, detach with -d option
Guillaume Tardif преди 5 години
родител
ревизия
4a1b50a9cd
променени са 7 файла, в които са добавени 76 реда и са изтрити 12 реда
  1. 1 3
      cli/cmd/logs.go
  2. 23 4
      cli/cmd/run/run.go
  3. 1 1
      cli/cmd/run/testdata/run-help.golden
  4. 1 0
      cli/options/run/opts.go
  5. 2 2
      local/e2e/backend_test.go
  6. 47 1
      tests/aci-e2e/e2e-aci_test.go
  7. 1 1
      tests/e2e/e2e_test.go

+ 1 - 3
cli/cmd/logs.go

@@ -57,9 +57,7 @@ func runLogs(ctx context.Context, containerName string, opts logsOpts) error {
 	if err != nil {
 	if err != nil {
 		return errors.Wrap(err, "cannot connect to backend")
 		return errors.Wrap(err, "cannot connect to backend")
 	}
 	}
-	var con io.Writer
-
-	con = os.Stdout
+	var con io.Writer = os.Stdout
 	if c, err := console.ConsoleFromFile(os.Stdout); err == nil {
 	if c, err := console.ConsoleFromFile(os.Stdout); err == nil {
 		con = c
 		con = c
 	}
 	}

+ 23 - 4
cli/cmd/run/run.go

@@ -19,9 +19,14 @@ package run
 import (
 import (
 	"context"
 	"context"
 	"fmt"
 	"fmt"
+	"io"
+	"os"
 
 
+	"github.com/containerd/console"
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
 
 
+	"github.com/docker/api/containers"
+
 	"github.com/docker/api/cli/options/run"
 	"github.com/docker/api/cli/options/run"
 	"github.com/docker/api/client"
 	"github.com/docker/api/client"
 	"github.com/docker/api/progress"
 	"github.com/docker/api/progress"
@@ -43,7 +48,7 @@ func Command() *cobra.Command {
 	cmd.Flags().StringVar(&opts.Name, "name", "", "Assign a name to the container")
 	cmd.Flags().StringVar(&opts.Name, "name", "", "Assign a name to the container")
 	cmd.Flags().StringArrayVarP(&opts.Labels, "label", "l", []string{}, "Set meta data on a container")
 	cmd.Flags().StringArrayVarP(&opts.Labels, "label", "l", []string{}, "Set meta data on a container")
 	cmd.Flags().StringArrayVarP(&opts.Volumes, "volume", "v", []string{}, "Volume. Ex: user:key@my_share:/absolute/path/to/target")
 	cmd.Flags().StringArrayVarP(&opts.Volumes, "volume", "v", []string{}, "Volume. Ex: user:key@my_share:/absolute/path/to/target")
-	cmd.Flags().BoolP("detach", "d", true, "Run container in background and print container ID")
+	cmd.Flags().BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")
 	cmd.Flags().Float64Var(&opts.Cpus, "cpus", 1., "Number of CPUs")
 	cmd.Flags().Float64Var(&opts.Cpus, "cpus", 1., "Number of CPUs")
 	cmd.Flags().VarP(&opts.Memory, "memory", "m", "Memory limit")
 	cmd.Flags().VarP(&opts.Memory, "memory", "m", "Memory limit")
 
 
@@ -64,8 +69,22 @@ func runRun(ctx context.Context, image string, opts run.Opts) error {
 	err = progress.Run(ctx, func(ctx context.Context) error {
 	err = progress.Run(ctx, func(ctx context.Context) error {
 		return c.ContainerService().Run(ctx, containerConfig)
 		return c.ContainerService().Run(ctx, containerConfig)
 	})
 	})
-	if err == nil {
-		fmt.Println(opts.Name)
+	if err != nil {
+		return err
+	}
+	if !opts.Detach {
+		var con io.Writer = os.Stdout
+		if c, err := console.ConsoleFromFile(os.Stdout); err == nil {
+			con = c
+		}
+
+		req := containers.LogsRequest{
+			Follow: true,
+			Writer: con,
+		}
+
+		return c.ContainerService().Logs(ctx, opts.Name, req)
 	}
 	}
-	return err
+	fmt.Println(opts.Name)
+	return nil
 }
 }

+ 1 - 1
cli/cmd/run/testdata/run-help.golden

@@ -5,7 +5,7 @@ Usage:
 
 
 Flags:
 Flags:
       --cpus float            Number of CPUs (default 1)
       --cpus float            Number of CPUs (default 1)
-  -d, --detach                Run container in background and print container ID (default true)
+  -d, --detach                Run container in background and print container ID
   -l, --label stringArray     Set meta data on a container
   -l, --label stringArray     Set meta data on a container
   -m, --memory bytes          Memory limit
   -m, --memory bytes          Memory limit
       --name string           Assign a name to the container
       --name string           Assign a name to the container

+ 1 - 0
cli/options/run/opts.go

@@ -36,6 +36,7 @@ type Opts struct {
 	Volumes []string
 	Volumes []string
 	Cpus    float64
 	Cpus    float64
 	Memory  formatter.MemBytes
 	Memory  formatter.MemBytes
+	Detach  bool
 }
 }
 
 
 // ToContainerConfig convert run options to a container configuration
 // ToContainerConfig convert run options to a container configuration

+ 2 - 2
local/e2e/backend_test.go

@@ -45,7 +45,7 @@ func (m *LocalBackendTestSuite) TestPs() {
 }
 }
 
 
 func (m *LocalBackendTestSuite) TestRun() {
 func (m *LocalBackendTestSuite) TestRun() {
-	_, err := m.NewDockerCommand("run", "--name", "nginx", "nginx").Exec()
+	_, err := m.NewDockerCommand("run", "-d", "--name", "nginx", "nginx").Exec()
 	require.Nil(m.T(), err)
 	require.Nil(m.T(), err)
 	out := m.NewDockerCommand("ps").ExecOrDie()
 	out := m.NewDockerCommand("ps").ExecOrDie()
 	defer func() {
 	defer func() {
@@ -55,7 +55,7 @@ func (m *LocalBackendTestSuite) TestRun() {
 }
 }
 
 
 func (m *LocalBackendTestSuite) TestRunWithPorts() {
 func (m *LocalBackendTestSuite) TestRunWithPorts() {
-	_, err := m.NewDockerCommand("run", "--name", "nginx", "-p", "8080:80", "nginx").Exec()
+	_, err := m.NewDockerCommand("run", "-d", "--name", "nginx", "-p", "8080:80", "nginx").Exec()
 	require.Nil(m.T(), err)
 	require.Nil(m.T(), err)
 	out := m.NewDockerCommand("ps").ExecOrDie()
 	out := m.NewDockerCommand("ps").ExecOrDie()
 	defer func() {
 	defer func() {

+ 47 - 1
tests/aci-e2e/e2e-aci_test.go

@@ -125,7 +125,7 @@ func (s *E2eACISuite) TestACIBackend() {
 		uploadFile(credential, u.String(), testFileName, testFileContent)
 		uploadFile(credential, u.String(), testFileName, testFileContent)
 
 
 		mountTarget := "/usr/share/nginx/html"
 		mountTarget := "/usr/share/nginx/html"
-		output := s.NewDockerCommand("run", "nginx",
+		output := s.NewDockerCommand("run", "-d", "nginx",
 			"-v", fmt.Sprintf("%s:%s@%s:%s",
 			"-v", fmt.Sprintf("%s:%s@%s:%s",
 				testStorageAccountName, firstKey, testShareName, mountTarget),
 				testStorageAccountName, firstKey, testShareName, mountTarget),
 			"-p", "80:80",
 			"-p", "80:80",
@@ -177,6 +177,52 @@ func (s *E2eACISuite) TestACIBackend() {
 		Expect(Lines(output)[0]).To(Equal(testContainerName))
 		Expect(Lines(output)[0]).To(Equal(testContainerName))
 	})
 	})
 
 
+	s.T().Run("re-run nginx with modified cpu/mem, and without --detach and follow logs", func(t *testing.T) {
+		shutdown := make(chan time.Time)
+		errs := make(chan error)
+		outChan := make(chan string)
+		cmd := s.NewDockerCommand("run", "nginx", "--memory", "0.1G", "--cpus", "0.1", "-p", "80:80", "--name", testContainerName).WithTimeout(shutdown)
+		go func() {
+			output, err := cmd.Exec()
+			outChan <- output
+			errs <- err
+		}()
+		var containerID string
+		err := WaitFor(time.Second, 100*time.Second, errs, func() bool {
+			output := s.NewDockerCommand("ps").ExecOrDie()
+			lines := Lines(output)
+			if len(lines) != 2 {
+				return false
+			}
+			containerFields := Columns(lines[1])
+			if containerFields[2] != "Running" {
+				return false
+			}
+			containerID = containerFields[0]
+			nginxExposedURL = strings.ReplaceAll(containerFields[3], "->80/tcp", "")
+			return true
+		})
+		Expect(err).NotTo(HaveOccurred())
+
+		s.NewCommand("curl", nginxExposedURL+"/test").ExecOrDie()
+		inspect := s.NewDockerCommand("inspect", containerID).ExecOrDie()
+		Expect(inspect).To(ContainSubstring("\"CPULimit\": 0.1"))
+		Expect(inspect).To(ContainSubstring("\"MemoryLimit\": 107374182"))
+
+		// Give a little time to get logs of the curl call
+		time.Sleep(5 * time.Second)
+		// Kill
+		close(shutdown)
+
+		output := <-outChan
+		Expect(output).To(ContainSubstring("/test"))
+	})
+
+	s.T().Run("removes container nginx", func(t *testing.T) {
+		output := s.NewDockerCommand("rm", testContainerName).ExecOrDie()
+		Expect(Lines(output)[0]).To(Equal(testContainerName))
+	})
+
 	var exposedURL string
 	var exposedURL string
 	const composeFile = "../composefiles/aci-demo/aci_demo_port.yaml"
 	const composeFile = "../composefiles/aci-demo/aci_demo_port.yaml"
 	const composeFileMultiplePorts = "../composefiles/aci-demo/aci_demo_multi_port.yaml"
 	const composeFileMultiplePorts = "../composefiles/aci-demo/aci_demo_multi_port.yaml"

+ 1 - 1
tests/e2e/e2e_test.go

@@ -288,7 +288,7 @@ func (s *E2eSuite) TestMockBackend() {
 	})
 	})
 
 
 	It("can run 'run' command", func() {
 	It("can run 'run' command", func() {
-		output := s.NewDockerCommand("run", "nginx", "-p", "80:80").ExecOrDie()
+		output := s.NewDockerCommand("run", "-d", "nginx", "-p", "80:80").ExecOrDie()
 		Expect(output).To(ContainSubstring("Running container \"nginx\" with name"))
 		Expect(output).To(ContainSubstring("Running container \"nginx\" with name"))
 	})
 	})
 }
 }