diff --git a/cli/cmd/logs.go b/cli/cmd/logs.go index 548aa47f7..62e79ddff 100644 --- a/cli/cmd/logs.go +++ b/cli/cmd/logs.go @@ -57,9 +57,7 @@ func runLogs(ctx context.Context, containerName string, opts logsOpts) error { if err != nil { 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 { con = c } diff --git a/cli/cmd/run/run.go b/cli/cmd/run/run.go index 942a9b264..5bb6b0568 100644 --- a/cli/cmd/run/run.go +++ b/cli/cmd/run/run.go @@ -19,9 +19,14 @@ package run import ( "context" "fmt" + "io" + "os" + "github.com/containerd/console" "github.com/spf13/cobra" + "github.com/docker/api/containers" + "github.com/docker/api/cli/options/run" "github.com/docker/api/client" "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().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().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().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 { return c.ContainerService().Run(ctx, containerConfig) }) - if err == nil { - fmt.Println(opts.Name) + if err != nil { + return err } - 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) + } + fmt.Println(opts.Name) + return nil } diff --git a/cli/cmd/run/testdata/run-help.golden b/cli/cmd/run/testdata/run-help.golden index 3859e002e..c69e05c58 100644 --- a/cli/cmd/run/testdata/run-help.golden +++ b/cli/cmd/run/testdata/run-help.golden @@ -5,7 +5,7 @@ Usage: Flags: --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 -m, --memory bytes Memory limit --name string Assign a name to the container diff --git a/cli/options/run/opts.go b/cli/options/run/opts.go index 5e2563830..f1188e1c1 100644 --- a/cli/options/run/opts.go +++ b/cli/options/run/opts.go @@ -36,6 +36,7 @@ type Opts struct { Volumes []string Cpus float64 Memory formatter.MemBytes + Detach bool } // ToContainerConfig convert run options to a container configuration diff --git a/local/e2e/backend_test.go b/local/e2e/backend_test.go index ccfc9e301..b6120f670 100644 --- a/local/e2e/backend_test.go +++ b/local/e2e/backend_test.go @@ -45,7 +45,7 @@ func (m *LocalBackendTestSuite) TestPs() { } 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) out := m.NewDockerCommand("ps").ExecOrDie() defer func() { @@ -55,7 +55,7 @@ func (m *LocalBackendTestSuite) TestRun() { } 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) out := m.NewDockerCommand("ps").ExecOrDie() defer func() { diff --git a/tests/aci-e2e/e2e-aci_test.go b/tests/aci-e2e/e2e-aci_test.go index 29c6307bd..e09ff74c6 100644 --- a/tests/aci-e2e/e2e-aci_test.go +++ b/tests/aci-e2e/e2e-aci_test.go @@ -125,7 +125,7 @@ func (s *E2eACISuite) TestACIBackend() { uploadFile(credential, u.String(), testFileName, testFileContent) mountTarget := "/usr/share/nginx/html" - output := s.NewDockerCommand("run", "nginx", + output := s.NewDockerCommand("run", "-d", "nginx", "-v", fmt.Sprintf("%s:%s@%s:%s", testStorageAccountName, firstKey, testShareName, mountTarget), "-p", "80:80", @@ -177,6 +177,52 @@ func (s *E2eACISuite) TestACIBackend() { 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 const composeFile = "../composefiles/aci-demo/aci_demo_port.yaml" const composeFileMultiplePorts = "../composefiles/aci-demo/aci_demo_multi_port.yaml" diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 31b9034ff..280369570 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -288,7 +288,7 @@ func (s *E2eSuite) TestMockBackend() { }) 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")) }) }