github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/integration-cli/docker_cli_run_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "bufio" 7 "fmt" 8 "io/ioutil" 9 "os" 10 "os/exec" 11 "path" 12 "path/filepath" 13 "strings" 14 "time" 15 16 "github.com/docker/docker/pkg/mount" 17 "github.com/go-check/check" 18 "github.com/kr/pty" 19 ) 20 21 // #6509 22 func (s *DockerSuite) TestRunRedirectStdout(c *check.C) { 23 checkRedirect := func(command string) { 24 _, tty, err := pty.Open() 25 if err != nil { 26 c.Fatalf("Could not open pty: %v", err) 27 } 28 cmd := exec.Command("sh", "-c", command) 29 cmd.Stdin = tty 30 cmd.Stdout = tty 31 cmd.Stderr = tty 32 ch := make(chan struct{}) 33 if err := cmd.Start(); err != nil { 34 c.Fatalf("start err: %v", err) 35 } 36 go func() { 37 if err := cmd.Wait(); err != nil { 38 c.Fatalf("wait err=%v", err) 39 } 40 close(ch) 41 }() 42 43 select { 44 case <-time.After(10 * time.Second): 45 c.Fatal("command timeout") 46 case <-ch: 47 } 48 } 49 50 checkRedirect(dockerBinary + " run -i busybox cat /etc/passwd | grep -q root") 51 checkRedirect(dockerBinary + " run busybox cat /etc/passwd | grep -q root") 52 } 53 54 // Test recursive bind mount works by default 55 func (s *DockerSuite) TestRunWithVolumesIsRecursive(c *check.C) { 56 tmpDir, err := ioutil.TempDir("", "docker_recursive_mount_test") 57 if err != nil { 58 c.Fatal(err) 59 } 60 61 defer os.RemoveAll(tmpDir) 62 63 // Create a temporary tmpfs mount. 64 tmpfsDir := filepath.Join(tmpDir, "tmpfs") 65 if err := os.MkdirAll(tmpfsDir, 0777); err != nil { 66 c.Fatalf("failed to mkdir at %s - %s", tmpfsDir, err) 67 } 68 if err := mount.Mount("tmpfs", tmpfsDir, "tmpfs", ""); err != nil { 69 c.Fatalf("failed to create a tmpfs mount at %s - %s", tmpfsDir, err) 70 } 71 72 f, err := ioutil.TempFile(tmpfsDir, "touch-me") 73 if err != nil { 74 c.Fatal(err) 75 } 76 defer f.Close() 77 78 runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox:latest", "ls", "/tmp/tmpfs") 79 out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd) 80 if err != nil && exitCode != 0 { 81 c.Fatal(out, stderr, err) 82 } 83 if !strings.Contains(out, filepath.Base(f.Name())) { 84 c.Fatal("Recursive bind mount test failed. Expected file not found") 85 } 86 } 87 88 func (s *DockerSuite) TestRunWithUlimits(c *check.C) { 89 testRequires(c, NativeExecDriver) 90 out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name=testulimits", "--ulimit", "nofile=42", "busybox", "/bin/sh", "-c", "ulimit -n")) 91 if err != nil { 92 c.Fatal(err, out) 93 } 94 95 ul := strings.TrimSpace(out) 96 if ul != "42" { 97 c.Fatalf("expected `ulimit -n` to be 42, got %s", ul) 98 } 99 } 100 101 func (s *DockerSuite) TestRunContainerWithCgroupParent(c *check.C) { 102 testRequires(c, NativeExecDriver) 103 104 cgroupParent := "test" 105 data, err := ioutil.ReadFile("/proc/self/cgroup") 106 if err != nil { 107 c.Fatalf("failed to read '/proc/self/cgroup - %v", err) 108 } 109 selfCgroupPaths := parseCgroupPaths(string(data)) 110 selfCpuCgroup, found := selfCgroupPaths["memory"] 111 if !found { 112 c.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths) 113 } 114 115 out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--cgroup-parent", cgroupParent, "--rm", "busybox", "cat", "/proc/self/cgroup")) 116 if err != nil { 117 c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err) 118 } 119 cgroupPaths := parseCgroupPaths(string(out)) 120 if len(cgroupPaths) == 0 { 121 c.Fatalf("unexpected output - %q", string(out)) 122 } 123 found = false 124 expectedCgroupPrefix := path.Join(selfCpuCgroup, cgroupParent) 125 for _, path := range cgroupPaths { 126 if strings.HasPrefix(path, expectedCgroupPrefix) { 127 found = true 128 break 129 } 130 } 131 if !found { 132 c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", expectedCgroupPrefix, cgroupPaths) 133 } 134 } 135 136 func (s *DockerSuite) TestRunContainerWithCgroupParentAbsPath(c *check.C) { 137 testRequires(c, NativeExecDriver) 138 139 cgroupParent := "/cgroup-parent/test" 140 141 out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--cgroup-parent", cgroupParent, "--rm", "busybox", "cat", "/proc/self/cgroup")) 142 if err != nil { 143 c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err) 144 } 145 cgroupPaths := parseCgroupPaths(string(out)) 146 if len(cgroupPaths) == 0 { 147 c.Fatalf("unexpected output - %q", string(out)) 148 } 149 found := false 150 for _, path := range cgroupPaths { 151 if strings.HasPrefix(path, cgroupParent) { 152 found = true 153 break 154 } 155 } 156 if !found { 157 c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", cgroupParent, cgroupPaths) 158 } 159 } 160 161 func (s *DockerSuite) TestRunDeviceDirectory(c *check.C) { 162 testRequires(c, NativeExecDriver) 163 cmd := exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/snd", "busybox", "sh", "-c", "ls /dev/snd/") 164 165 out, _, err := runCommandWithOutput(cmd) 166 if err != nil { 167 c.Fatal(err, out) 168 } 169 170 if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "timer") { 171 c.Fatalf("expected output /dev/snd/timer, received %s", actual) 172 } 173 174 cmd = exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/othersnd", "busybox", "sh", "-c", "ls /dev/othersnd/") 175 176 out, _, err = runCommandWithOutput(cmd) 177 if err != nil { 178 c.Fatal(err, out) 179 } 180 181 if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "seq") { 182 c.Fatalf("expected output /dev/othersnd/seq, received %s", actual) 183 } 184 } 185 186 // TestRunDetach checks attaching and detaching with the escape sequence. 187 func (s *DockerSuite) TestRunAttachDetach(c *check.C) { 188 name := "attach-detach" 189 cmd := exec.Command(dockerBinary, "run", "--name", name, "-it", "busybox", "cat") 190 stdout, err := cmd.StdoutPipe() 191 if err != nil { 192 c.Fatal(err) 193 } 194 cpty, tty, err := pty.Open() 195 if err != nil { 196 c.Fatal(err) 197 } 198 defer cpty.Close() 199 cmd.Stdin = tty 200 if err := cmd.Start(); err != nil { 201 c.Fatal(err) 202 } 203 if err := waitRun(name); err != nil { 204 c.Fatal(err) 205 } 206 207 if _, err := cpty.Write([]byte("hello\n")); err != nil { 208 c.Fatal(err) 209 } 210 211 out, err := bufio.NewReader(stdout).ReadString('\n') 212 if err != nil { 213 c.Fatal(err) 214 } 215 if strings.TrimSpace(out) != "hello" { 216 c.Fatalf("expected 'hello', got %q", out) 217 } 218 219 // escape sequence 220 if _, err := cpty.Write([]byte{16}); err != nil { 221 c.Fatal(err) 222 } 223 time.Sleep(100 * time.Millisecond) 224 if _, err := cpty.Write([]byte{17}); err != nil { 225 c.Fatal(err) 226 } 227 228 ch := make(chan struct{}) 229 go func() { 230 cmd.Wait() 231 ch <- struct{}{} 232 }() 233 234 running, err := inspectField(name, "State.Running") 235 if err != nil { 236 c.Fatal(err) 237 } 238 if running != "true" { 239 c.Fatal("expected container to still be running") 240 } 241 242 go func() { 243 exec.Command(dockerBinary, "kill", name).Run() 244 }() 245 246 select { 247 case <-ch: 248 case <-time.After(10 * time.Millisecond): 249 c.Fatal("timed out waiting for container to exit") 250 } 251 }