2014-02-25 11:17:48 -05:00
package main
import (
2014-08-12 05:36:49 -04:00
"bufio"
2014-10-17 14:06:05 -04:00
"bytes"
2014-02-25 11:17:48 -05:00
"fmt"
2014-06-26 07:03:23 -04:00
"io/ioutil"
2014-09-05 21:59:31 -04:00
"net"
2014-04-17 22:53:08 -04:00
"os"
2014-02-25 11:17:48 -05:00
"os/exec"
2014-08-27 20:25:10 -04:00
"path"
2014-07-29 22:22:50 -04:00
"path/filepath"
2014-02-17 18:14:30 -05:00
"reflect"
2014-04-17 21:58:20 -04:00
"regexp"
2014-04-17 22:53:08 -04:00
"sort"
2014-09-16 21:08:30 -04:00
"strconv"
2014-02-25 11:17:48 -05:00
"strings"
2014-04-17 22:46:03 -04:00
"sync"
2014-08-12 05:36:49 -04:00
"time"
2014-06-26 07:03:23 -04:00
2015-06-30 12:41:01 -04:00
"github.com/docker/docker/pkg/nat"
2015-05-06 18:39:29 -04:00
"github.com/docker/libnetwork/resolvconf"
2015-04-18 12:46:47 -04:00
"github.com/go-check/check"
2014-02-25 11:17:48 -05:00
)
// "test123" should be printed by docker run
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEchoStdout ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "busybox" , "echo" , "test123" )
2014-02-25 11:17:48 -05:00
if out != "test123\n" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "container should've printed 'test123'" )
2014-02-25 11:17:48 -05:00
}
}
// "test" should be printed
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEchoStdoutWithMemoryLimit ( c * check . C ) {
2015-07-20 14:20:50 -04:00
out , _ , _ := dockerCmdWithStdoutStderr ( c , "run" , "-m" , "16m" , "busybox" , "echo" , "test" )
2014-09-01 20:09:52 -04:00
out = strings . Trim ( out , "\r\n" )
if expected := "test" ; out != expected {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "container should've printed %q but printed %q" , expected , out )
2014-02-25 11:17:48 -05:00
}
}
2015-02-08 21:36:49 -05:00
// should run without memory swap
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithoutMemoryswapLimit ( c * check . C ) {
2015-06-05 12:14:19 -04:00
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-m" , "16m" , "--memory-swap" , "-1" , "busybox" , "true" )
2015-02-08 21:36:49 -05:00
}
2015-07-12 03:46:33 -04:00
func ( s * DockerSuite ) TestRunWithSwappiness ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--memory-swappiness" , "0" , "busybox" , "true" )
2015-07-12 03:46:33 -04:00
}
func ( s * DockerSuite ) TestRunWithSwappinessInvalid ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--memory-swappiness" , "101" , "busybox" , "true" )
2015-07-12 03:46:33 -04:00
if err == nil {
c . Fatalf ( "failed. test was able to set invalid value, output: %q" , out )
}
}
2014-02-25 11:17:48 -05:00
// "test" should be printed
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEchoStdoutWitCPULimit ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-c" , "1000" , "busybox" , "echo" , "test" )
2014-02-25 11:17:48 -05:00
if out != "test\n" {
2015-04-18 12:46:47 -04:00
c . Errorf ( "container should've printed 'test'" )
2014-02-25 11:17:48 -05:00
}
}
// "test" should be printed
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEchoStdoutWithCPUAndMemoryLimit ( c * check . C ) {
2015-07-20 14:20:50 -04:00
out , _ , _ := dockerCmdWithStdoutStderr ( c , "run" , "-c" , "1000" , "-m" , "16m" , "busybox" , "echo" , "test" )
2014-02-25 11:17:48 -05:00
if out != "test\n" {
2015-04-18 12:46:47 -04:00
c . Errorf ( "container should've printed 'test', got %q instead" , out )
2014-02-25 11:17:48 -05:00
}
}
// "test" should be printed
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEchoNamedContainer ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--name" , "testfoonamedcontainer" , "busybox" , "echo" , "test" )
2014-02-25 11:17:48 -05:00
if out != "test\n" {
2015-04-18 12:46:47 -04:00
c . Errorf ( "container should've printed 'test'" )
2014-02-25 11:17:48 -05:00
}
}
2014-04-29 01:22:54 -04:00
// docker run should not leak file descriptors
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunLeakyFileDescriptors ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "busybox" , "ls" , "-C" , "/proc/self/fd" )
2014-04-29 01:22:54 -04:00
// normally, we should only get 0, 1, and 2, but 3 gets created by "ls" when it does "opendir" on the "fd" directory
if out != "0 1 2 3\n" {
2015-04-18 12:46:47 -04:00
c . Errorf ( "container should've printed '0 1 2 3', not: %s" , out )
2014-04-29 01:22:54 -04:00
}
}
2015-03-11 01:09:09 -04:00
// it should be possible to lookup Google DNS
2014-02-25 11:17:48 -05:00
// this will fail when Internet access is unavailable
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunLookupGoogleDns ( c * check . C ) {
testRequires ( c , Network )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "busybox" , "nslookup" , "google.com" )
2014-02-25 11:17:48 -05:00
}
// the exit code should be 0
// some versions of lxc might make this test fail
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunExitCodeZero ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "busybox" , "true" )
2014-02-25 11:17:48 -05:00
}
// the exit code should be 1
// some versions of lxc might make this test fail
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunExitCodeOne ( c * check . C ) {
2015-07-19 16:47:47 -04:00
_ , exitCode , err := dockerCmdWithError ( c , "run" , "busybox" , "false" )
2014-02-25 11:17:48 -05:00
if err != nil && ! strings . Contains ( "exit status 1" , fmt . Sprintf ( "%s" , err ) ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-02-25 11:17:48 -05:00
}
if exitCode != 1 {
2015-04-18 12:46:47 -04:00
c . Errorf ( "container should've exited with exit code 1" )
2014-02-25 11:17:48 -05:00
}
}
// it should be possible to pipe in data via stdin to a process running in a container
// some versions of lxc might make this test fail
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunStdinPipe ( c * check . C ) {
2015-05-16 14:04:25 -04:00
runCmd := exec . Command ( dockerBinary , "run" , "-i" , "-a" , "stdin" , "busybox" , "cat" )
runCmd . Stdin = strings . NewReader ( "blahblah" )
2014-02-25 11:17:48 -05:00
out , _ , _ , err := runCommandWithStdoutStderr ( runCmd )
2014-09-12 09:51:21 -04:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "failed to run container: %v, output: %q" , err , out )
2014-09-12 09:51:21 -04:00
}
2014-02-25 11:17:48 -05:00
2015-04-06 09:21:18 -04:00
out = strings . TrimSpace ( out )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "wait" , out )
2014-02-25 11:17:48 -05:00
2015-07-19 16:47:47 -04:00
logsOut , _ := dockerCmd ( c , "logs" , out )
2014-02-25 11:17:48 -05:00
2015-04-06 09:21:18 -04:00
containerLogs := strings . TrimSpace ( logsOut )
2014-02-25 11:17:48 -05:00
if containerLogs != "blahblah" {
2015-04-18 12:46:47 -04:00
c . Errorf ( "logs didn't print the container's logs %s" , containerLogs )
2014-02-25 11:17:48 -05:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "rm" , out )
2014-02-25 11:17:48 -05:00
}
// the container's ID should be printed when starting a container in detached mode
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunDetachedContainerIDPrinting ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "true" )
2014-02-25 11:17:48 -05:00
2015-04-06 09:21:18 -04:00
out = strings . TrimSpace ( out )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "wait" , out )
2014-02-25 11:17:48 -05:00
2015-07-19 16:47:47 -04:00
rmOut , _ := dockerCmd ( c , "rm" , out )
2014-02-25 11:17:48 -05:00
2015-04-06 09:21:18 -04:00
rmOut = strings . TrimSpace ( rmOut )
2014-02-25 11:17:48 -05:00
if rmOut != out {
2015-04-18 12:46:47 -04:00
c . Errorf ( "rm didn't print the container ID %s %s" , out , rmOut )
2014-02-25 11:17:48 -05:00
}
}
// the working directory should be set correctly
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWorkingDirectory ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-w" , "/root" , "busybox" , "pwd" )
2014-02-25 11:17:48 -05:00
2015-04-06 09:21:18 -04:00
out = strings . TrimSpace ( out )
2014-02-25 11:17:48 -05:00
if out != "/root" {
2015-04-18 12:46:47 -04:00
c . Errorf ( "-w failed to set working directory" )
2014-02-25 11:17:48 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "--workdir" , "/root" , "busybox" , "pwd" )
2015-04-06 09:21:18 -04:00
out = strings . TrimSpace ( out )
2014-02-25 11:17:48 -05:00
if out != "/root" {
2015-04-18 12:46:47 -04:00
c . Errorf ( "--workdir failed to set working directory" )
2014-02-25 11:17:48 -05:00
}
}
// pinging Google's DNS resolver should fail when we disable the networking
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithoutNetworking ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , exitCode , err := dockerCmdWithError ( c , "run" , "--net=none" , "busybox" , "ping" , "-c" , "1" , "8.8.8.8" )
2014-02-25 11:17:48 -05:00
if err != nil && exitCode != 1 {
2015-04-18 12:46:47 -04:00
c . Fatal ( out , err )
2014-02-25 11:17:48 -05:00
}
if exitCode != 1 {
2015-04-18 12:46:47 -04:00
c . Errorf ( "--net=none should've disabled the network; the container shouldn't have been able to ping 8.8.8.8" )
2014-02-25 11:17:48 -05:00
}
2015-07-19 16:47:47 -04:00
out , exitCode , err = dockerCmdWithError ( c , "run" , "-n=false" , "busybox" , "ping" , "-c" , "1" , "8.8.8.8" )
2014-02-25 11:17:48 -05:00
if err != nil && exitCode != 1 {
2015-04-18 12:46:47 -04:00
c . Fatal ( out , err )
2014-02-25 11:17:48 -05:00
}
if exitCode != 1 {
2015-04-18 12:46:47 -04:00
c . Errorf ( "-n=false should've disabled the network; the container shouldn't have been able to ping 8.8.8.8" )
2014-02-25 11:17:48 -05:00
}
}
2014-03-31 13:41:40 -04:00
2015-01-14 02:25:58 -05:00
//test --link use container name to link target
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunLinksContainerWithContainerName ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-i" , "-t" , "-d" , "--name" , "parent" , "busybox" )
2015-05-17 22:06:13 -04:00
ip , err := inspectField ( "parent" , "NetworkSettings.IPAddress" )
c . Assert ( err , check . IsNil )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--link" , "parent:test" , "busybox" , "/bin/cat" , "/etc/hosts" )
2015-01-14 02:25:58 -05:00
if ! strings . Contains ( out , ip + " test" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "use a container name to link target failed" )
2015-01-14 02:25:58 -05:00
}
}
//test --link use container id to link target
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunLinksContainerWithContainerId ( c * check . C ) {
2015-07-19 16:47:47 -04:00
cID , _ := dockerCmd ( c , "run" , "-i" , "-t" , "-d" , "busybox" )
2015-01-14 02:25:58 -05:00
cID = strings . TrimSpace ( cID )
2015-05-17 22:06:13 -04:00
ip , err := inspectField ( cID , "NetworkSettings.IPAddress" )
c . Assert ( err , check . IsNil )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--link" , cID + ":test" , "busybox" , "/bin/cat" , "/etc/hosts" )
2015-01-14 02:25:58 -05:00
if ! strings . Contains ( out , ip + " test" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "use a container id to link target failed" )
2015-01-14 02:25:58 -05:00
}
}
2015-05-01 10:00:43 -04:00
// Issue 9677.
func ( s * DockerSuite ) TestRunWithDaemonFlags ( c * check . C ) {
out , _ , err := dockerCmdWithError ( c , "--selinux-enabled" , "run" , "-i" , "-t" , "busybox" , "true" )
if err != nil {
if ! strings . Contains ( out , "must follow the 'docker daemon' command" ) && // daemon
! strings . Contains ( out , "flag provided but not defined: --selinux-enabled" ) { // no daemon (client-only)
c . Fatal ( err , out )
}
}
}
2014-04-03 10:27:07 -04:00
// Regression test for #4979
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithVolumesFromExited ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , exitCode := dockerCmd ( c , "run" , "--name" , "test-data" , "--volume" , "/some/dir" , "busybox" , "touch" , "/some/dir/file" )
if exitCode != 0 {
c . Fatal ( "1" , out , exitCode )
2014-04-03 10:27:07 -04:00
}
2015-07-19 16:47:47 -04:00
out , exitCode = dockerCmd ( c , "run" , "--volumes-from" , "test-data" , "busybox" , "cat" , "/some/dir/file" )
if exitCode != 0 {
c . Fatal ( "2" , out , exitCode )
2014-04-03 10:27:07 -04:00
}
}
2015-03-30 14:35:37 -04:00
// Volume path is a symlink which also exists on the host, and the host side is a file not a dir
// But the volume call is just a normal volume, not a bind mount
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCreateVolumesInSymlinkDir ( c * check . C ) {
testRequires ( c , SameHostDaemon )
testRequires ( c , NativeExecDriver )
2015-03-30 14:35:37 -04:00
name := "test-volume-symlink"
dir , err := ioutil . TempDir ( "" , name )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-03-29 01:35:36 -04:00
}
2015-03-30 14:35:37 -04:00
defer os . RemoveAll ( dir )
f , err := os . OpenFile ( filepath . Join ( dir , "test" ) , os . O_CREATE , 0700 )
2015-03-29 01:35:36 -04:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-03-30 14:35:37 -04:00
}
f . Close ( )
dockerFile := fmt . Sprintf ( "FROM busybox\nRUN mkdir -p %s\nRUN ln -s %s /test" , dir , dir )
if _ , err := buildImage ( name , dockerFile , false ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-03-30 14:35:37 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , "/test/test" , name )
2015-03-29 01:35:36 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunVolumesMountedAsReadonly ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code , err := dockerCmdWithError ( c , "run" , "-v" , "/test:/test:ro" , "busybox" , "touch" , "/test/somefile" ) ; err == nil || code == 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "run should fail because volume is ro: exit code %d" , code )
2014-04-07 21:23:22 -04:00
}
}
2014-04-08 05:26:09 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunVolumesFromInReadonlyMode ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , "/test" , "busybox" , "true" )
2014-04-08 05:26:09 -04:00
2015-07-19 16:47:47 -04:00
if _ , code , err := dockerCmdWithError ( c , "run" , "--volumes-from" , "parent:ro" , "busybox" , "touch" , "/test/file" ) ; err == nil || code == 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "run should fail because volume is ro: exit code %d" , code )
2014-04-08 05:26:09 -04:00
}
}
// Regression test for #1201
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunVolumesFromInReadWriteMode ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , "/test" , "busybox" , "true" )
dockerCmd ( c , "run" , "--volumes-from" , "parent:rw" , "busybox" , "touch" , "/test/file" )
2014-10-03 18:33:11 -04:00
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "run" , "--volumes-from" , "parent:bar" , "busybox" , "touch" , "/test/file" ) ; err == nil || ! strings . Contains ( out , "invalid mode for volumes-from: bar" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "running --volumes-from foo:bar should have failed with invalid mount mode: %q" , out )
2014-10-03 18:33:11 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--volumes-from" , "parent" , "busybox" , "touch" , "/test/file" )
2014-04-08 05:26:09 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestVolumesFromGetsProperMode ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , "/test:/test:ro" , "busybox" , "true" )
2015-04-20 13:54:47 -04:00
// Expect this "rw" mode to be be ignored since the inherited volume is "ro"
2015-07-19 16:47:47 -04:00
if _ , _ , err := dockerCmdWithError ( c , "run" , "--volumes-from" , "parent:rw" , "busybox" , "touch" , "/test/file" ) ; err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected volumes-from to inherit read-only volume even when passing in `rw`" )
2014-08-28 10:18:08 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "parent2" , "-v" , "/test:/test:ro" , "busybox" , "true" )
2014-08-28 10:18:08 -04:00
// Expect this to be read-only since both are "ro"
2015-07-19 16:47:47 -04:00
if _ , _ , err := dockerCmdWithError ( c , "run" , "--volumes-from" , "parent2:ro" , "busybox" , "touch" , "/test/file" ) ; err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected volumes-from to inherit read-only volume even when passing in `ro`" )
2014-08-21 17:57:46 -04:00
}
}
2015-02-06 17:00:53 -05:00
// Test for GH#10618
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunNoDupVolumes ( c * check . C ) {
2015-02-24 21:50:55 -05:00
mountstr1 := randomUnixTmpDirPath ( "test1" ) + ":/someplace"
mountstr2 := randomUnixTmpDirPath ( "test2" ) + ":/someplace"
2015-02-09 11:17:41 -05:00
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "run" , "-v" , mountstr1 , "-v" , mountstr2 , "busybox" , "true" ) ; err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected error about duplicate volume definitions" )
2015-02-06 17:00:53 -05:00
} else {
2015-05-19 16:05:25 -04:00
if ! strings . Contains ( out , "Duplicate bind mount" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Expected 'duplicate volume' error, got %v" , err )
2015-02-06 17:00:53 -05:00
}
}
}
2014-04-08 05:26:09 -04:00
// Test for #1351
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunApplyVolumesFromBeforeVolumes ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , "/test" , "busybox" , "touch" , "/test/foo" )
dockerCmd ( c , "run" , "--volumes-from" , "parent" , "-v" , "/test" , "busybox" , "cat" , "/test/foo" )
2014-04-08 05:26:09 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunMultipleVolumesFrom ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "parent1" , "-v" , "/test" , "busybox" , "touch" , "/test/foo" )
dockerCmd ( c , "run" , "--name" , "parent2" , "-v" , "/other" , "busybox" , "touch" , "/other/bar" )
dockerCmd ( c , "run" , "--volumes-from" , "parent1" , "--volumes-from" , "parent2" , "busybox" , "sh" , "-c" , "cat /test/foo && cat /other/bar" )
2014-04-08 05:26:09 -04:00
}
2014-04-17 21:58:20 -04:00
2014-04-18 17:35:16 -04:00
// this tests verifies the ID format for the container
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunVerifyContainerID ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , exit , err := dockerCmdWithError ( c , "run" , "-d" , "busybox" , "true" )
2014-04-18 17:35:16 -04:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-04-18 17:35:16 -04:00
}
if exit != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected exit code 0 received %d" , exit )
2014-04-18 17:35:16 -04:00
}
2015-07-19 16:47:47 -04:00
2014-04-18 17:35:16 -04:00
match , err := regexp . MatchString ( "^[0-9a-f]{64}$" , strings . TrimSuffix ( out , "\n" ) )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-04-18 17:35:16 -04:00
}
if ! match {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Invalid container ID: %s" , out )
2014-04-18 17:35:16 -04:00
}
}
// Test that creating a container with a volume doesn't crash. Regression test for #995.
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCreateVolume ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , "/var/lib/data" , "busybox" , "true" )
2014-04-18 17:35:16 -04:00
}
2014-04-24 21:22:22 -04:00
// Test that creating a volume with a symlink in its path works correctly. Test for #5152.
// Note that this bug happens only with symlinks with a target that starts with '/'.
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCreateVolumeWithSymlink ( c * check . C ) {
2015-02-20 01:56:02 -05:00
image := "docker-test-createvolumewithsymlink"
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , image , "-" )
2014-05-27 17:54:38 -04:00
buildCmd . Stdin = strings . NewReader ( ` FROM busybox
2015-01-23 07:17:05 -05:00
RUN ln - s home / bar ` )
2014-05-27 17:54:38 -04:00
buildCmd . Dir = workingDirectory
2014-04-24 21:22:22 -04:00
err := buildCmd . Run ( )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "could not build '%s': %v" , image , err )
2014-04-24 21:22:22 -04:00
}
2015-07-19 16:47:47 -04:00
_ , exitCode , err := dockerCmdWithError ( c , "run" , "-v" , "/bar/foo" , "--name" , "test-createvolumewithsymlink" , image , "sh" , "-c" , "mount | grep -q /home/foo" )
2014-04-24 21:22:22 -04:00
if err != nil || exitCode != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "[run] err: %v, exitcode: %d" , err , exitCode )
2014-04-24 21:22:22 -04:00
}
2015-07-23 18:11:06 -04:00
volPath , err := inspectMountSourceField ( "test-createvolumewithsymlink" , "/bar/foo" )
if err != nil {
c . Fatalf ( "[inspect] err: %v" , err )
2014-04-24 21:22:22 -04:00
}
2015-07-19 16:47:47 -04:00
_ , exitCode , err = dockerCmdWithError ( c , "rm" , "-v" , "test-createvolumewithsymlink" )
2014-04-24 21:22:22 -04:00
if err != nil || exitCode != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "[rm] err: %v, exitcode: %d" , err , exitCode )
2014-04-24 21:22:22 -04:00
}
2015-07-23 18:11:06 -04:00
_ , err = os . Stat ( volPath )
2014-04-24 21:22:22 -04:00
if ! os . IsNotExist ( err ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "[open] (expecting 'file does not exist' error) err: %v, volPath: %s" , err , volPath )
2014-04-24 21:22:22 -04:00
}
}
2014-05-27 17:49:43 -04:00
// Tests that a volume path that has a symlink exists in a container mounting it with `--volumes-from`.
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunVolumesFromSymlinkPath ( c * check . C ) {
2014-11-17 11:05:49 -05:00
name := "docker-test-volumesfromsymlinkpath"
2015-02-20 01:56:02 -05:00
2014-11-17 11:05:49 -05:00
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , name , "-" )
2014-05-27 17:49:43 -04:00
buildCmd . Stdin = strings . NewReader ( ` FROM busybox
2015-01-23 07:17:05 -05:00
RUN ln - s home / foo
2014-05-27 17:49:43 -04:00
VOLUME [ "/foo/bar" ] ` )
buildCmd . Dir = workingDirectory
err := buildCmd . Run ( )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "could not build 'docker-test-volumesfromsymlinkpath': %v" , err )
2014-05-27 17:49:43 -04:00
}
2015-07-19 16:47:47 -04:00
_ , exitCode , err := dockerCmdWithError ( c , "run" , "--name" , "test-volumesfromsymlinkpath" , name )
2014-05-27 17:49:43 -04:00
if err != nil || exitCode != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "[run] (volume) err: %v, exitcode: %d" , err , exitCode )
2014-05-27 17:49:43 -04:00
}
2015-07-19 16:47:47 -04:00
_ , exitCode , err = dockerCmdWithError ( c , "run" , "--volumes-from" , "test-volumesfromsymlinkpath" , "busybox" , "sh" , "-c" , "ls /foo | grep -q bar" )
2014-05-27 17:49:43 -04:00
if err != nil || exitCode != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "[run] err: %v, exitcode: %d" , err , exitCode )
2014-05-27 17:49:43 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunExitCode ( c * check . C ) {
2015-07-19 16:47:47 -04:00
_ , exit , err := dockerCmdWithError ( c , "run" , "busybox" , "/bin/sh" , "-c" , "exit 72" )
2014-04-18 17:35:16 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "should not have a non nil error" )
2014-04-18 17:35:16 -04:00
}
if exit != 72 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected exit code 72 received %d" , exit )
2014-04-18 17:35:16 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUserDefaultsToRoot ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "busybox" , "id" )
2014-04-18 17:35:16 -04:00
if ! strings . Contains ( out , "uid=0(root) gid=0(root)" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected root user got %s" , out )
2014-04-18 17:35:16 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUserByName ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-u" , "root" , "busybox" , "id" )
2014-04-18 17:35:16 -04:00
if ! strings . Contains ( out , "uid=0(root) gid=0(root)" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected root user got %s" , out )
2014-04-18 17:35:16 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUserByID ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-u" , "1" , "busybox" , "id" )
2014-04-18 17:35:16 -04:00
if ! strings . Contains ( out , "uid=1(daemon) gid=1(daemon)" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected daemon user got %s" , out )
2014-04-18 17:35:16 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUserByIDBig ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "-u" , "2147483648" , "busybox" , "id" )
2014-05-17 14:43:31 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "No error, but must be." , out )
2014-05-17 14:43:31 -04:00
}
if ! strings . Contains ( out , "Uids and gids must be in range" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected error about uids range, got %s" , out )
2014-05-17 14:43:31 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUserByIDNegative ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "-u" , "-1" , "busybox" , "id" )
2014-05-17 14:43:31 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "No error, but must be." , out )
2014-05-17 14:43:31 -04:00
}
if ! strings . Contains ( out , "Uids and gids must be in range" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected error about uids range, got %s" , out )
2014-05-17 14:43:31 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUserByIDZero ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "-u" , "0" , "busybox" , "id" )
2014-05-17 14:43:31 -04:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-05-17 14:43:31 -04:00
}
if ! strings . Contains ( out , "uid=0(root) gid=0(root) groups=10(wheel)" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected daemon user got %s" , out )
2014-05-17 14:43:31 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUserNotFound ( c * check . C ) {
2015-07-19 16:47:47 -04:00
_ , _ , err := dockerCmdWithError ( c , "run" , "-u" , "notme" , "busybox" , "id" )
2014-04-18 17:35:16 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "unknown user should cause container to fail" )
2014-04-18 17:35:16 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunTwoConcurrentContainers ( c * check . C ) {
2014-04-18 17:35:16 -04:00
group := sync . WaitGroup { }
group . Add ( 2 )
2015-04-27 13:29:48 -04:00
errChan := make ( chan error , 2 )
2014-04-18 17:35:16 -04:00
for i := 0 ; i < 2 ; i ++ {
go func ( ) {
defer group . Done ( )
2015-07-19 16:47:47 -04:00
_ , _ , err := dockerCmdWithError ( c , "run" , "busybox" , "sleep" , "2" )
2015-04-27 13:29:48 -04:00
errChan <- err
2014-04-18 17:35:16 -04:00
} ( )
}
group . Wait ( )
2015-04-27 13:29:48 -04:00
close ( errChan )
for err := range errChan {
c . Assert ( err , check . IsNil )
}
2014-04-18 17:35:16 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEnvironment ( c * check . C ) {
2014-07-31 14:45:32 -04:00
cmd := exec . Command ( dockerBinary , "run" , "-h" , "testing" , "-e=FALSE=true" , "-e=TRUE" , "-e=TRICKY" , "-e=HOME=" , "busybox" , "env" )
2014-04-18 17:35:16 -04:00
cmd . Env = append ( os . Environ ( ) ,
"TRUE=false" ,
"TRICKY=tri\ncky\n" ,
)
out , _ , err := runCommandWithOutput ( cmd )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-04-18 17:35:16 -04:00
}
2015-01-19 19:32:29 -05:00
actualEnvLxc := strings . Split ( strings . TrimSpace ( out ) , "\n" )
actualEnv := [ ] string { }
for i := range actualEnvLxc {
if actualEnvLxc [ i ] != "container=lxc" {
actualEnv = append ( actualEnv , actualEnvLxc [ i ] )
}
}
2014-04-18 17:35:16 -04:00
sort . Strings ( actualEnv )
goodEnv := [ ] string {
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ,
"HOSTNAME=testing" ,
"FALSE=true" ,
"TRUE=false" ,
"TRICKY=tri" ,
"cky" ,
"" ,
2014-02-22 22:06:37 -05:00
"HOME=/root" ,
2014-04-18 17:35:16 -04:00
}
sort . Strings ( goodEnv )
if len ( goodEnv ) != len ( actualEnv ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Wrong environment: should be %d variables, not: %q\n" , len ( goodEnv ) , strings . Join ( actualEnv , ", " ) )
2014-04-18 17:35:16 -04:00
}
for i := range goodEnv {
if actualEnv [ i ] != goodEnv [ i ] {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Wrong environment variable: should be %s, not %s" , goodEnv [ i ] , actualEnv [ i ] )
2014-04-18 17:35:16 -04:00
}
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEnvironmentErase ( c * check . C ) {
2015-01-16 15:57:08 -05:00
// Test to make sure that when we use -e on env vars that are
// not set in our local env that they're removed (if present) in
// the container
2015-02-20 01:56:02 -05:00
2015-01-16 15:57:08 -05:00
cmd := exec . Command ( dockerBinary , "run" , "-e" , "FOO" , "-e" , "HOSTNAME" , "busybox" , "env" )
2015-03-07 04:03:44 -05:00
cmd . Env = appendBaseEnv ( [ ] string { } )
2015-02-12 14:20:48 -05:00
2015-01-16 15:57:08 -05:00
out , _ , err := runCommandWithOutput ( cmd )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2015-01-16 15:57:08 -05:00
}
2015-01-19 19:32:29 -05:00
actualEnvLxc := strings . Split ( strings . TrimSpace ( out ) , "\n" )
actualEnv := [ ] string { }
for i := range actualEnvLxc {
if actualEnvLxc [ i ] != "container=lxc" {
actualEnv = append ( actualEnv , actualEnvLxc [ i ] )
}
}
2015-01-16 15:57:08 -05:00
sort . Strings ( actualEnv )
goodEnv := [ ] string {
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ,
"HOME=/root" ,
}
sort . Strings ( goodEnv )
if len ( goodEnv ) != len ( actualEnv ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Wrong environment: should be %d variables, not: %q\n" , len ( goodEnv ) , strings . Join ( actualEnv , ", " ) )
2015-01-16 15:57:08 -05:00
}
for i := range goodEnv {
if actualEnv [ i ] != goodEnv [ i ] {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Wrong environment variable: should be %s, not %s" , goodEnv [ i ] , actualEnv [ i ] )
2015-01-16 15:57:08 -05:00
}
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEnvironmentOverride ( c * check . C ) {
2015-01-16 15:57:08 -05:00
// Test to make sure that when we use -e on env vars that are
// already in the env that we're overriding them
2015-02-20 01:56:02 -05:00
2015-01-16 15:57:08 -05:00
cmd := exec . Command ( dockerBinary , "run" , "-e" , "HOSTNAME" , "-e" , "HOME=/root2" , "busybox" , "env" )
2015-03-07 04:03:44 -05:00
cmd . Env = appendBaseEnv ( [ ] string { "HOSTNAME=bar" } )
2015-02-12 14:20:48 -05:00
2015-01-16 15:57:08 -05:00
out , _ , err := runCommandWithOutput ( cmd )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2015-01-16 15:57:08 -05:00
}
2015-01-19 19:32:29 -05:00
actualEnvLxc := strings . Split ( strings . TrimSpace ( out ) , "\n" )
actualEnv := [ ] string { }
for i := range actualEnvLxc {
if actualEnvLxc [ i ] != "container=lxc" {
actualEnv = append ( actualEnv , actualEnvLxc [ i ] )
}
}
2015-01-16 15:57:08 -05:00
sort . Strings ( actualEnv )
goodEnv := [ ] string {
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ,
"HOME=/root2" ,
"HOSTNAME=bar" ,
}
sort . Strings ( goodEnv )
if len ( goodEnv ) != len ( actualEnv ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Wrong environment: should be %d variables, not: %q\n" , len ( goodEnv ) , strings . Join ( actualEnv , ", " ) )
2015-01-16 15:57:08 -05:00
}
for i := range goodEnv {
if actualEnv [ i ] != goodEnv [ i ] {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Wrong environment variable: should be %s, not %s" , goodEnv [ i ] , actualEnv [ i ] )
2015-01-16 15:57:08 -05:00
}
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunContainerNetwork ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "busybox" , "ping" , "-c" , "1" , "127.0.0.1" )
2014-04-18 17:35:16 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunNetHostNotAllowedWithLinks ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "linked" , "busybox" , "true" )
_ , _ , err := dockerCmdWithError ( c , "run" , "--net=host" , "--link" , "linked:linked" , "busybox" , "true" )
2014-07-16 17:09:30 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected error" )
2014-07-16 17:09:30 -04:00
}
}
2014-09-24 11:00:01 -04:00
// #7851 hostname outside container shows FQDN, inside only shortname
// For testing purposes it is not required to set host's hostname directly
// and use "--net=host" (as the original issue submitter did), as the same
// codepath is executed with "docker run -h <hostname>". Both were manually
// tested, but this testcase takes the simpler path of using "run -h .."
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunFullHostnameSet ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-h" , "foo.bar.baz" , "busybox" , "hostname" )
2014-09-24 11:00:01 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "foo.bar.baz" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected hostname 'foo.bar.baz', received %s" , actual )
2014-09-24 11:00:01 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunPrivilegedCanMknod ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--privileged" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-04-18 17:35:16 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-04-18 17:35:16 -04:00
}
}
2015-05-13 08:24:54 -04:00
func ( s * DockerSuite ) TestRunUnprivilegedCanMknod ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-04-18 17:35:16 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-04-18 17:35:16 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapDropInvalid ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--cap-drop=CHPASS" , "busybox" , "ls" )
2014-07-10 19:38:11 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-07-10 19:38:11 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapDropCannotMknod ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--cap-drop=MKNOD" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-07-10 17:51:15 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-07-10 17:51:15 -04:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-10 17:51:15 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapDropCannotMknodLowerCase ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--cap-drop=mknod" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-07-16 14:47:55 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-07-16 14:47:55 -04:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-16 14:47:55 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapDropALLCannotMknod ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--cap-drop=ALL" , "--cap-add=SETGID" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-07-10 18:31:01 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-07-10 18:31:01 -04:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-10 18:31:01 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapDropALLAddMknodCanMknod ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--cap-drop=ALL" , "--cap-add=MKNOD" , "--cap-add=SETGID" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-07-10 19:02:39 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-07-10 19:02:39 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapAddInvalid ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--cap-add=CHPASS" , "busybox" , "ls" )
2014-07-10 19:38:11 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-07-10 19:38:11 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapAddCanDownInterface ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--cap-add=NET_ADMIN" , "busybox" , "sh" , "-c" , "ip link set eth0 down && echo ok" )
2014-07-10 17:51:15 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-07-10 17:51:15 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapAddALLCanDownInterface ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--cap-add=ALL" , "busybox" , "sh" , "-c" , "ip link set eth0 down && echo ok" )
2014-07-10 18:31:01 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-07-10 18:31:01 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCapAddALLDropNetAdminCanDownInterface ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--cap-add=ALL" , "--cap-drop=NET_ADMIN" , "busybox" , "sh" , "-c" , "ip link set eth0 down && echo ok" )
2014-07-10 19:02:39 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-07-10 19:02:39 -04:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-10 19:02:39 -04:00
}
}
2015-06-17 14:39:59 -04:00
func ( s * DockerSuite ) TestRunGroupAdd ( c * check . C ) {
2015-07-24 19:10:59 -04:00
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--group-add=audio" , "--group-add=dbus" , "--group-add=777" , "busybox" , "sh" , "-c" , "id" )
2015-06-17 14:39:59 -04:00
groupsList := "uid=0(root) gid=0(root) groups=10(wheel),29(audio),81(dbus),777"
if actual := strings . Trim ( out , "\r\n" ) ; actual != groupsList {
c . Fatalf ( "expected output %s received %s" , groupsList , actual )
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunPrivilegedCanMount ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--privileged" , "busybox" , "sh" , "-c" , "mount -t tmpfs none /tmp && echo ok" )
2014-04-18 17:35:16 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-04-18 17:35:16 -04:00
}
}
2015-05-13 08:24:54 -04:00
func ( s * DockerSuite ) TestRunUnprivilegedCannotMount ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "busybox" , "sh" , "-c" , "mount -t tmpfs none /tmp && echo ok" )
2014-04-18 17:35:16 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-04-18 17:35:16 -04:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-04-18 17:35:16 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunSysNotWritableInNonPrivilegedContainers ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code , err := dockerCmdWithError ( c , "run" , "busybox" , "touch" , "/sys/kernel/profiling" ) ; err == nil || code == 0 {
2015-04-18 12:46:47 -04:00
c . Fatal ( "sys should not be writable in a non privileged container" )
2014-04-17 23:20:17 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunSysWritableInPrivilegedContainers ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code , err := dockerCmdWithError ( c , "run" , "--privileged" , "busybox" , "touch" , "/sys/kernel/profiling" ) ; err != nil || code != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "sys should be writable in privileged container" )
2014-04-17 23:20:17 -04:00
}
2014-04-30 21:00:42 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunProcNotWritableInNonPrivilegedContainers ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code , err := dockerCmdWithError ( c , "run" , "busybox" , "touch" , "/proc/sysrq-trigger" ) ; err == nil || code == 0 {
2015-04-18 12:46:47 -04:00
c . Fatal ( "proc should not be writable in a non privileged container" )
2014-04-30 21:00:42 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunProcWritableInPrivilegedContainers ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code := dockerCmd ( c , "run" , "--privileged" , "busybox" , "touch" , "/proc/sysrq-trigger" ) ; code != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "proc should be writable in privileged container" )
2014-04-30 21:00:42 -04:00
}
2015-04-08 04:58:59 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithCpuset ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code := dockerCmd ( c , "run" , "--cpuset" , "0" , "busybox" , "true" ) ; code != 0 {
c . Fatalf ( "container should run successfully with cpuset of 0" )
2014-05-12 20:44:57 -04:00
}
}
2014-02-17 18:14:30 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithCpusetCpus ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code := dockerCmd ( c , "run" , "--cpuset-cpus" , "0" , "busybox" , "true" ) ; code != 0 {
c . Fatalf ( "container should run successfully with cpuset-cpus of 0" )
move resources from Config to HostConfig
Cgroup resources are host dependent, they should be in hostConfig.
For backward compatibility, we just copy it to hostConfig, and leave it in
Config for now, so there is no regressions, but the right way to use this
throught json is to put it in HostConfig, like:
{
"Hostname": "",
...
"HostConfig": {
"CpuShares": 512,
"Memory": 314572800,
...
}
}
As we will add CpusetMems, CpusetCpus is definitely a better name, but some
users are already using Cpuset in their http APIs, we also make it compatible.
The main idea is keep using Cpuset in Config Struct, and make it has the same
value as CpusetCpus, but not always, some scenarios:
- Users use --cpuset in docker command, it can setup cpuset.cpus and can
get Cpuset field from docker inspect or other http API which will get
config info.
- Users use --cpuset-cpus in docker command, ditto.
- Users use Cpuset field in their http APIs, ditto.
- Users use CpusetCpus field in their http APIs, they won't get Cpuset field
in Config info, because by then, they should already know what happens
to Cpuset.
Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
2015-03-10 21:31:18 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithCpusetMems ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code := dockerCmd ( c , "run" , "--cpuset-mems" , "0" , "busybox" , "true" ) ; code != 0 {
c . Fatalf ( "container should run successfully with cpuset-mems of 0" )
2015-04-14 21:33:46 -04:00
}
}
2015-05-06 23:55:58 -04:00
func ( s * DockerSuite ) TestRunWithBlkioWeight ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , code := dockerCmd ( c , "run" , "--blkio-weight" , "300" , "busybox" , "true" ) ; code != 0 {
c . Fatalf ( "container should run successfully with blkio-weight of 300" )
2015-05-06 23:55:58 -04:00
}
}
func ( s * DockerSuite ) TestRunWithBlkioInvalidWeight ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if _ , _ , err := dockerCmdWithError ( c , "run" , "--blkio-weight" , "5" , "busybox" , "true" ) ; err == nil {
2015-05-06 23:55:58 -04:00
c . Fatalf ( "run with invalid blkio-weight should failed" )
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunDeviceNumbers ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "busybox" , "sh" , "-c" , "ls -l /dev/null" )
2014-02-17 18:14:30 -05:00
deviceLineFields := strings . Fields ( out )
deviceLineFields [ 6 ] = ""
deviceLineFields [ 7 ] = ""
deviceLineFields [ 8 ] = ""
expected := [ ] string { "crw-rw-rw-" , "1" , "root" , "root" , "1," , "3" , "" , "" , "" , "/dev/null" }
if ! ( reflect . DeepEqual ( deviceLineFields , expected ) ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output\ncrw-rw-rw- 1 root root 1, 3 May 24 13:29 /dev/null\n received\n %s\n" , out )
2014-02-17 18:14:30 -05:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunThatCharacterDevicesActLikeCharacterDevices ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "busybox" , "sh" , "-c" , "dd if=/dev/zero of=/zero bs=1k count=5 2> /dev/null ; du -h /zero" )
2014-02-17 18:14:30 -05:00
if actual := strings . Trim ( out , "\r\n" ) ; actual [ 0 ] == '0' {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected a new file called /zero to be create that is greater than 0 bytes long, but du says: %s" , actual )
2014-02-17 18:14:30 -05:00
}
}
2014-06-02 21:23:47 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUnprivilegedWithChroot ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "busybox" , "chroot" , "/" , "true" )
2014-06-02 21:23:47 -04:00
}
2014-06-12 15:11:51 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAddingOptionalDevices ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--device" , "/dev/zero:/dev/nulo" , "busybox" , "sh" , "-c" , "ls /dev/nulo" )
2014-05-31 00:00:47 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "/dev/nulo" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output /dev/nulo, received %s" , actual )
2014-05-31 00:00:47 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunModeHostname ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2014-06-12 15:11:51 -04:00
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-h=testhostname" , "busybox" , "cat" , "/etc/hostname" )
2014-06-12 15:11:51 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "testhostname" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected 'testhostname', but says: %q" , actual )
2014-06-12 15:11:51 -04:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "--net=host" , "busybox" , "cat" , "/etc/hostname" )
2014-06-12 15:11:51 -04:00
hostname , err := os . Hostname ( )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-06-12 15:11:51 -04:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual != hostname {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected %q, but says: %q" , hostname , actual )
2014-06-12 15:11:51 -04:00
}
2014-06-24 12:53:53 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunRootWorkdir ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--workdir" , "/" , "busybox" , "pwd" )
2015-04-18 12:46:47 -04:00
if out != "/\n" {
c . Fatalf ( "pwd returned %q (expected /\\n)" , s )
2014-06-24 12:53:53 -04:00
}
}
2014-06-26 13:50:18 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAllowBindMountingRoot ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , "/:/host" , "busybox" , "ls" , "/host" )
2014-06-26 13:50:18 -04:00
}
2014-06-27 12:51:24 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunDisallowBindMountingRootToRoot ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "-v" , "/:/" , "busybox" , "ls" , "/host" )
2014-06-27 12:51:24 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( out , err )
2014-06-27 12:51:24 -04:00
}
}
2014-06-26 07:03:23 -04:00
2015-01-09 12:06:48 -05:00
// Verify that a container gets default DNS when only localhost resolvers exist
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunDnsDefaultOptions ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-01-09 12:06:48 -05:00
// preserve original resolv.conf for restoring after test
2014-10-07 20:58:39 -04:00
origResolvConf , err := ioutil . ReadFile ( "/etc/resolv.conf" )
if os . IsNotExist ( err ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "/etc/resolv.conf does not exist" )
2014-10-07 20:58:39 -04:00
}
2015-01-09 12:06:48 -05:00
// defer restored original conf
2014-10-07 20:58:39 -04:00
defer func ( ) {
if err := ioutil . WriteFile ( "/etc/resolv.conf" , origResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-10-07 20:58:39 -04:00
}
} ( )
2015-01-09 12:06:48 -05:00
// test 3 cases: standard IPv4 localhost, commented out localhost, and IPv6 localhost
// 2 are removed from the file at container start, and the 3rd (commented out) one is ignored by
// GetNameservers(), leading to a replacement of nameservers with the default set
tmpResolvConf := [ ] byte ( "nameserver 127.0.0.1\n#nameserver 127.0.2.1\nnameserver ::1" )
if err := ioutil . WriteFile ( "/etc/resolv.conf" , tmpResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-01-09 12:06:48 -05:00
}
2015-07-19 16:47:47 -04:00
actual , _ := dockerCmd ( c , "run" , "busybox" , "cat" , "/etc/resolv.conf" )
2015-01-09 12:06:48 -05:00
// check that the actual defaults are appended to the commented out
// localhost resolver (which should be preserved)
// NOTE: if we ever change the defaults from google dns, this will break
expected := "#nameserver 127.0.2.1\n\nnameserver 8.8.8.8\nnameserver 8.8.4.4"
2014-10-07 20:58:39 -04:00
if actual != expected {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected resolv.conf be: %q, but was: %q" , expected , actual )
2014-06-26 07:03:23 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunDnsOptions ( c * check . C ) {
2015-07-20 14:20:50 -04:00
out , stderr , _ := dockerCmdWithStdoutStderr ( c , "run" , "--dns=127.0.0.1" , "--dns-search=mydomain" , "busybox" , "cat" , "/etc/resolv.conf" )
2014-06-26 07:03:23 -04:00
2015-03-10 10:22:29 -04:00
// The client will get a warning on stderr when setting DNS to a localhost address; verify this:
if ! strings . Contains ( stderr , "Localhost DNS setting" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Expected warning on stderr about localhost resolver, but got %q" , stderr )
2015-03-10 10:22:29 -04:00
}
2014-06-26 07:03:23 -04:00
actual := strings . Replace ( strings . Trim ( out , "\r\n" ) , "\n" , " " , - 1 )
if actual != "nameserver 127.0.0.1 search mydomain" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected 'nameserver 127.0.0.1 search mydomain', but says: %q" , actual )
2014-06-26 07:03:23 -04:00
}
2015-07-20 14:20:50 -04:00
out , stderr , _ = dockerCmdWithStdoutStderr ( c , "run" , "--dns=127.0.0.1" , "--dns-search=." , "busybox" , "cat" , "/etc/resolv.conf" )
2014-06-26 07:03:23 -04:00
actual = strings . Replace ( strings . Trim ( strings . Trim ( out , "\r\n" ) , " " ) , "\n" , " " , - 1 )
if actual != "nameserver 127.0.0.1" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected 'nameserver 127.0.0.1', but says: %q" , actual )
2014-06-26 07:03:23 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunDnsOptionsBasedOnHostResolvConf ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2014-10-07 18:35:32 -04:00
origResolvConf , err := ioutil . ReadFile ( "/etc/resolv.conf" )
2014-06-26 07:03:23 -04:00
if os . IsNotExist ( err ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "/etc/resolv.conf does not exist" )
2014-06-26 07:03:23 -04:00
}
2014-10-07 18:35:32 -04:00
hostNamservers := resolvconf . GetNameservers ( origResolvConf )
hostSearch := resolvconf . GetSearchDomains ( origResolvConf )
2014-06-26 07:03:23 -04:00
2015-02-18 23:06:23 -05:00
var out string
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "--dns=127.0.0.1" , "busybox" , "cat" , "/etc/resolv.conf" )
2014-06-26 07:03:23 -04:00
if actualNameservers := resolvconf . GetNameservers ( [ ] byte ( out ) ) ; string ( actualNameservers [ 0 ] ) != "127.0.0.1" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected '127.0.0.1', but says: %q" , string ( actualNameservers [ 0 ] ) )
2014-06-26 07:03:23 -04:00
}
actualSearch := resolvconf . GetSearchDomains ( [ ] byte ( out ) )
if len ( actualSearch ) != len ( hostSearch ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected %q search domain(s), but it has: %q" , len ( hostSearch ) , len ( actualSearch ) )
2014-06-26 07:03:23 -04:00
}
for i := range actualSearch {
if actualSearch [ i ] != hostSearch [ i ] {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected %q domain, but says: %q" , actualSearch [ i ] , hostSearch [ i ] )
2014-06-26 07:03:23 -04:00
}
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "--dns-search=mydomain" , "busybox" , "cat" , "/etc/resolv.conf" )
2014-06-26 07:03:23 -04:00
actualNameservers := resolvconf . GetNameservers ( [ ] byte ( out ) )
if len ( actualNameservers ) != len ( hostNamservers ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected %q nameserver(s), but it has: %q" , len ( hostNamservers ) , len ( actualNameservers ) )
2014-06-26 07:03:23 -04:00
}
for i := range actualNameservers {
if actualNameservers [ i ] != hostNamservers [ i ] {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected %q nameserver, but says: %q" , actualNameservers [ i ] , hostNamservers [ i ] )
2014-06-26 07:03:23 -04:00
}
}
if actualSearch = resolvconf . GetSearchDomains ( [ ] byte ( out ) ) ; string ( actualSearch [ 0 ] ) != "mydomain" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected 'mydomain', but says: %q" , string ( actualSearch [ 0 ] ) )
2014-10-07 18:35:32 -04:00
}
// test with file
tmpResolvConf := [ ] byte ( "search example.com\nnameserver 12.34.56.78\nnameserver 127.0.0.1" )
if err := ioutil . WriteFile ( "/etc/resolv.conf" , tmpResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-10-07 18:35:32 -04:00
}
// put the old resolvconf back
defer func ( ) {
if err := ioutil . WriteFile ( "/etc/resolv.conf" , origResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-10-07 18:35:32 -04:00
}
} ( )
resolvConf , err := ioutil . ReadFile ( "/etc/resolv.conf" )
if os . IsNotExist ( err ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "/etc/resolv.conf does not exist" )
2014-10-07 18:35:32 -04:00
}
hostNamservers = resolvconf . GetNameservers ( resolvConf )
hostSearch = resolvconf . GetSearchDomains ( resolvConf )
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "busybox" , "cat" , "/etc/resolv.conf" )
2014-10-07 18:35:32 -04:00
if actualNameservers = resolvconf . GetNameservers ( [ ] byte ( out ) ) ; string ( actualNameservers [ 0 ] ) != "12.34.56.78" || len ( actualNameservers ) != 1 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected '12.34.56.78', but has: %v" , actualNameservers )
2014-10-07 18:35:32 -04:00
}
actualSearch = resolvconf . GetSearchDomains ( [ ] byte ( out ) )
if len ( actualSearch ) != len ( hostSearch ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected %q search domain(s), but it has: %q" , len ( hostSearch ) , len ( actualSearch ) )
2014-10-07 18:35:32 -04:00
}
for i := range actualSearch {
if actualSearch [ i ] != hostSearch [ i ] {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected %q domain, but says: %q" , actualSearch [ i ] , hostSearch [ i ] )
2014-10-07 18:35:32 -04:00
}
2014-06-26 07:03:23 -04:00
}
}
2014-07-16 13:47:12 -04:00
2015-05-20 02:06:44 -04:00
// Test to see if a non-root user can resolve a DNS name and reach out to it. Also
// check if the container resolv.conf file has atleast 0644 perm.
func ( s * DockerSuite ) TestRunNonRootUserResolvName ( c * check . C ) {
2015-07-24 20:44:37 -04:00
testRequires ( c , SameHostDaemon , Network )
2015-05-20 02:06:44 -04:00
2015-07-24 20:44:37 -04:00
dockerCmd ( c , "run" , "--name=testperm" , "--user=default" , "busybox" , "ping" , "-c" , "1" , "apt.dockerproject.org" )
2015-05-20 02:06:44 -04:00
cID , err := getIDByName ( "testperm" )
if err != nil {
c . Fatal ( err )
}
fmode := ( os . FileMode ) ( 0644 )
finfo , err := os . Stat ( containerStorageFile ( cID , "resolv.conf" ) )
if err != nil {
c . Fatal ( err )
}
if ( finfo . Mode ( ) & fmode ) != fmode {
c . Fatalf ( "Expected container resolv.conf mode to be atleast %s, instead got %s" , fmode . String ( ) , finfo . Mode ( ) . String ( ) )
}
}
2015-05-06 18:39:29 -04:00
// Test if container resolv.conf gets updated the next time it restarts
// if host /etc/resolv.conf has changed. This only applies if the container
// uses the host's /etc/resolv.conf and does not have any dns options provided.
func ( s * DockerSuite ) TestRunResolvconfUpdate ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2014-12-10 00:55:09 -05:00
tmpResolvConf := [ ] byte ( "search pommesfrites.fr\nnameserver 12.34.56.78" )
tmpLocalhostResolvConf := [ ] byte ( "nameserver 127.0.0.1" )
//take a copy of resolv.conf for restoring after test completes
resolvConfSystem , err := ioutil . ReadFile ( "/etc/resolv.conf" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
2015-02-11 15:01:30 -05:00
// This test case is meant to test monitoring resolv.conf when it is
2015-04-18 12:46:47 -04:00
// a regular file not a bind mounc. So we unmount resolv.conf and replace
2015-02-11 15:01:30 -05:00
// it with a file containing the original settings.
cmd := exec . Command ( "umount" , "/etc/resolv.conf" )
if _ , err = runCommand ( cmd ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-02-11 15:01:30 -05:00
}
2014-12-10 00:55:09 -05:00
//cleanup
defer func ( ) {
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
} ( )
2015-05-06 18:39:29 -04:00
//1. test that a restarting container gets an updated resolv.conf
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name='first'" , "busybox" , "true" )
2014-12-10 00:55:09 -05:00
containerID1 , err := getIDByName ( "first" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
// replace resolv.conf with our temporary copy
bytesResolvConf := [ ] byte ( tmpResolvConf )
if err := ioutil . WriteFile ( "/etc/resolv.conf" , bytesResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
2015-05-06 18:39:29 -04:00
// start the container again to pickup changes
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "start" , "first" )
2015-05-06 18:39:29 -04:00
2014-12-10 00:55:09 -05:00
// check for update in container
containerResolv , err := readContainerFile ( containerID1 , "resolv.conf" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
if ! bytes . Equal ( containerResolv , bytesResolvConf ) {
2015-05-06 18:39:29 -04:00
c . Fatalf ( "Restarted container does not have updated resolv.conf; expected %q, got %q" , tmpResolvConf , string ( containerResolv ) )
2014-12-10 00:55:09 -05:00
}
2015-06-24 13:23:00 -04:00
/ * //make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-07-19 16:47:47 -04:00
c . Fatal ( err )
} * /
2015-05-06 18:39:29 -04:00
//2. test that a restarting container does not receive resolv.conf updates
2014-12-10 00:55:09 -05:00
// if it modified the container copy of the starting point resolv.conf
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name='second'" , "busybox" , "sh" , "-c" , "echo 'search mylittlepony.com' >>/etc/resolv.conf" )
2014-12-10 00:55:09 -05:00
containerID2 , err := getIDByName ( "second" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
//make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
2015-05-06 18:39:29 -04:00
// start the container again
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "start" , "second" )
2015-05-06 18:39:29 -04:00
// check for update in container
containerResolv , err = readContainerFile ( containerID2 , "resolv.conf" )
2014-12-10 00:55:09 -05:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
2015-05-06 18:39:29 -04:00
if bytes . Equal ( containerResolv , resolvConfSystem ) {
c . Fatalf ( "Restarting a container after container updated resolv.conf should not pick up host changes; expected %q, got %q" , string ( containerResolv ) , string ( resolvConfSystem ) )
2014-12-10 00:55:09 -05:00
}
//3. test that a running container's resolv.conf is not modified while running
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-12-10 00:55:09 -05:00
runningContainerID := strings . TrimSpace ( out )
// replace resolv.conf
if err := ioutil . WriteFile ( "/etc/resolv.conf" , bytesResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
2015-05-06 18:39:29 -04:00
// check for update in container
containerResolv , err = readContainerFile ( runningContainerID , "resolv.conf" )
2014-12-10 00:55:09 -05:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
2015-05-06 18:39:29 -04:00
if bytes . Equal ( containerResolv , bytesResolvConf ) {
c . Fatalf ( "Running container should not have updated resolv.conf; expected %q, got %q" , string ( resolvConfSystem ) , string ( containerResolv ) )
2014-12-10 00:55:09 -05:00
}
//4. test that a running container's resolv.conf is updated upon restart
// (the above container is still running..)
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "restart" , runningContainerID )
2014-12-10 00:55:09 -05:00
// check for update in container
containerResolv , err = readContainerFile ( runningContainerID , "resolv.conf" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
if ! bytes . Equal ( containerResolv , bytesResolvConf ) {
2015-05-06 18:39:29 -04:00
c . Fatalf ( "Restarted container should have updated resolv.conf; expected %q, got %q" , string ( bytesResolvConf ) , string ( containerResolv ) )
2014-12-10 00:55:09 -05:00
}
//5. test that additions of a localhost resolver are cleaned from
// host resolv.conf before updating container's resolv.conf copies
// replace resolv.conf with a localhost-only nameserver copy
bytesResolvConf = [ ] byte ( tmpLocalhostResolvConf )
if err = ioutil . WriteFile ( "/etc/resolv.conf" , bytesResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
2015-05-06 18:39:29 -04:00
// start the container again to pickup changes
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "start" , "first" )
2015-05-06 18:39:29 -04:00
2014-12-10 00:55:09 -05:00
// our first exited container ID should have been updated, but with default DNS
// after the cleanup of resolv.conf found only a localhost nameserver:
containerResolv , err = readContainerFile ( containerID1 , "resolv.conf" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-10 00:55:09 -05:00
}
expected := "\nnameserver 8.8.8.8\nnameserver 8.8.4.4"
if ! bytes . Equal ( containerResolv , [ ] byte ( expected ) ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q" , expected , string ( containerResolv ) )
2014-12-10 00:55:09 -05:00
}
2015-02-11 15:01:30 -05:00
//6. Test that replacing (as opposed to modifying) resolv.conf triggers an update
// of containers' resolv.conf.
// Restore the original resolv.conf
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-02-11 15:01:30 -05:00
}
// Run the container so it picks up the old settings
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name='third'" , "busybox" , "true" )
2015-02-11 15:01:30 -05:00
containerID3 , err := getIDByName ( "third" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-02-11 15:01:30 -05:00
}
// Create a modified resolv.conf.aside and override resolv.conf with it
bytesResolvConf = [ ] byte ( tmpResolvConf )
if err := ioutil . WriteFile ( "/etc/resolv.conf.aside" , bytesResolvConf , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-02-11 15:01:30 -05:00
}
err = os . Rename ( "/etc/resolv.conf.aside" , "/etc/resolv.conf" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-02-11 15:01:30 -05:00
}
2015-05-06 18:39:29 -04:00
// start the container again to pickup changes
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "start" , "third" )
2015-05-06 18:39:29 -04:00
2015-02-11 15:01:30 -05:00
// check for update in container
containerResolv , err = readContainerFile ( containerID3 , "resolv.conf" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-02-11 15:01:30 -05:00
}
if ! bytes . Equal ( containerResolv , bytesResolvConf ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Stopped container does not have updated resolv.conf; expected\n%q\n got\n%q" , tmpResolvConf , string ( containerResolv ) )
2015-02-11 15:01:30 -05:00
}
2014-12-10 00:55:09 -05:00
//cleanup, restore original resolv.conf happens in defer func()
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAddHost ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--add-host=extra:86.75.30.9" , "busybox" , "grep" , "extra" , "/etc/hosts" )
2014-09-13 00:35:59 -04:00
actual := strings . Trim ( out , "\r\n" )
if actual != "86.75.30.9\textra" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected '86.75.30.9\textra', but says: %q" , actual )
2014-09-13 00:35:59 -04:00
}
}
2014-07-16 13:47:12 -04:00
// Regression test for #6983
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAttachStdErrOnlyTTYMode ( c * check . C ) {
2015-07-19 16:47:47 -04:00
_ , exitCode := dockerCmd ( c , "run" , "-t" , "-a" , "stderr" , "busybox" , "true" )
if exitCode != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container should have exited with error code 0" )
2014-07-16 13:47:12 -04:00
}
}
// Regression test for #6983
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAttachStdOutOnlyTTYMode ( c * check . C ) {
2015-07-19 16:47:47 -04:00
_ , exitCode := dockerCmd ( c , "run" , "-t" , "-a" , "stdout" , "busybox" , "true" )
if exitCode != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container should have exited with error code 0" )
2014-07-16 13:47:12 -04:00
}
}
// Regression test for #6983
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAttachStdOutAndErrTTYMode ( c * check . C ) {
2015-07-19 16:47:47 -04:00
_ , exitCode := dockerCmd ( c , "run" , "-t" , "-a" , "stdout" , "-a" , "stderr" , "busybox" , "true" )
if exitCode != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container should have exited with error code 0" )
2014-07-16 13:47:12 -04:00
}
}
2014-07-17 02:15:23 -04:00
2015-01-28 16:03:21 -05:00
// Test for #10388 - this will run the same test as TestRunAttachStdOutAndErrTTYMode
// but using --attach instead of -a to make sure we read the flag correctly
2015-05-13 05:49:19 -04:00
func ( s * DockerSuite ) TestRunAttachWithDetach ( c * check . C ) {
2015-01-28 16:03:21 -05:00
cmd := exec . Command ( dockerBinary , "run" , "-d" , "--attach" , "stdout" , "busybox" , "true" )
_ , stderr , _ , err := runCommandWithStdoutStderr ( cmd )
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container should have exited with error code different than 0" )
2015-01-28 16:03:21 -05:00
} else if ! strings . Contains ( stderr , "Conflicting options: -a and -d" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Should have been returned an error with conflicting options -a and -d" )
2015-01-28 16:03:21 -05:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunState ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-07-17 02:15:23 -04:00
id := strings . TrimSpace ( out )
state , err := inspectField ( id , "State.Running" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-07-17 02:15:23 -04:00
if state != "true" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container state is 'not running'" )
2014-07-17 02:15:23 -04:00
}
pid1 , err := inspectField ( id , "State.Pid" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-07-17 02:15:23 -04:00
if pid1 == "0" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container state Pid 0" )
2014-07-17 02:15:23 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "stop" , id )
2014-07-17 02:15:23 -04:00
state , err = inspectField ( id , "State.Running" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-07-17 02:15:23 -04:00
if state != "false" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container state is 'running'" )
2014-07-17 02:15:23 -04:00
}
pid2 , err := inspectField ( id , "State.Pid" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-07-17 02:15:23 -04:00
if pid2 == pid1 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container state Pid %s, but expected %s" , pid2 , pid1 )
2014-07-17 02:15:23 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "start" , id )
2014-07-17 02:15:23 -04:00
state , err = inspectField ( id , "State.Running" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-07-17 02:15:23 -04:00
if state != "true" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container state is 'not running'" )
2014-07-17 02:15:23 -04:00
}
pid3 , err := inspectField ( id , "State.Pid" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-07-17 02:15:23 -04:00
if pid3 == pid1 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container state Pid %s, but expected %s" , pid2 , pid1 )
2014-07-17 02:15:23 -04:00
}
}
2014-07-16 15:40:04 -04:00
// Test for #1737
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCopyVolumeUidGid ( c * check . C ) {
2014-07-16 15:40:04 -04:00
name := "testrunvolumesuidgid"
_ , err := buildImage ( name ,
` FROM busybox
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir - p / hello && touch / hello / test && chown dockerio . dockerio / hello ` ,
true )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-07-16 15:40:04 -04:00
}
// Test that the uid and gid is copied from the image to the volume
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--rm" , "-v" , "/hello" , name , "sh" , "-c" , "ls -l / | grep hello | awk '{print $3\":\"$4}'" )
2014-07-16 15:40:04 -04:00
out = strings . TrimSpace ( out )
if out != "dockerio:dockerio" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Wrong /hello ownership: %s, expected dockerio:dockerio" , out )
2014-07-16 15:40:04 -04:00
}
}
2014-07-17 13:36:45 -04:00
// Test for #1582
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCopyVolumeContent ( c * check . C ) {
2014-07-17 13:36:45 -04:00
name := "testruncopyvolumecontent"
_ , err := buildImage ( name ,
` FROM busybox
RUN mkdir - p / hello / local && echo hello > / hello / local / world ` ,
true )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-07-17 13:36:45 -04:00
}
// Test that the content is copied from the image to the volume
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--rm" , "-v" , "/hello" , name , "find" , "/hello" )
2014-07-17 13:36:45 -04:00
if ! ( strings . Contains ( out , "/hello/local/world" ) && strings . Contains ( out , "/hello/local" ) ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container failed to transfer content to volume" )
2014-07-17 13:36:45 -04:00
}
}
2014-07-10 01:46:11 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCleanupCmdOnEntrypoint ( c * check . C ) {
2014-07-10 01:46:11 -04:00
name := "testrunmdcleanuponentrypoint"
if _ , err := buildImage ( name ,
` FROM busybox
ENTRYPOINT [ "echo" ]
2015-07-19 16:47:47 -04:00
CMD [ "testingpoint" ] ` ,
2014-07-10 01:46:11 -04:00
true ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-07-10 01:46:11 -04:00
}
2015-07-19 16:47:47 -04:00
out , exit := dockerCmd ( c , "run" , "--entrypoint" , "whoami" , name )
2014-07-10 01:46:11 -04:00
if exit != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected exit code 0 received %d, out: %q" , exit , out )
2014-07-10 01:46:11 -04:00
}
out = strings . TrimSpace ( out )
if out != "root" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Expected output root, got %q" , out )
2014-07-10 01:46:11 -04:00
}
}
2014-08-12 03:48:36 -04:00
// TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWorkdirExistsAndIsFile ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , exit , err := dockerCmdWithError ( c , "run" , "-w" , "/bin/cat" , "busybox" )
2014-08-12 03:48:36 -04:00
if ! ( err != nil && exit == 1 && strings . Contains ( out , "Cannot mkdir: /bin/cat is not a directory" ) ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Docker must complains about making dir, but we got out: %s, exit: %d, err: %s" , out , exit , err )
2014-08-12 03:48:36 -04:00
}
}
2014-08-12 05:36:49 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunExitOnStdinClose ( c * check . C ) {
2014-08-12 05:36:49 -04:00
name := "testrunexitonstdinclose"
runCmd := exec . Command ( dockerBinary , "run" , "--name" , name , "-i" , "busybox" , "/bin/cat" )
stdin , err := runCmd . StdinPipe ( )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-08-12 05:36:49 -04:00
}
stdout , err := runCmd . StdoutPipe ( )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-08-12 05:36:49 -04:00
}
if err := runCmd . Start ( ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-08-12 05:36:49 -04:00
}
if _ , err := stdin . Write ( [ ] byte ( "hello\n" ) ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-08-12 05:36:49 -04:00
}
r := bufio . NewReader ( stdout )
line , err := r . ReadString ( '\n' )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-08-12 05:36:49 -04:00
}
line = strings . TrimSpace ( line )
if line != "hello" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Output should be 'hello', got '%q'" , line )
2014-08-12 05:36:49 -04:00
}
if err := stdin . Close ( ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-08-12 05:36:49 -04:00
}
2015-04-27 13:29:48 -04:00
finish := make ( chan error )
2014-08-12 05:36:49 -04:00
go func ( ) {
2015-04-27 13:29:48 -04:00
finish <- runCmd . Wait ( )
2014-08-12 05:36:49 -04:00
close ( finish )
} ( )
select {
2015-04-27 13:29:48 -04:00
case err := <- finish :
c . Assert ( err , check . IsNil )
2014-08-12 05:36:49 -04:00
case <- time . After ( 1 * time . Second ) :
2015-04-18 12:46:47 -04:00
c . Fatal ( "docker run failed to exit on stdin close" )
2014-08-12 05:36:49 -04:00
}
state , err := inspectField ( name , "State.Running" )
2015-04-27 13:29:48 -04:00
c . Assert ( err , check . IsNil )
2014-08-12 05:36:49 -04:00
if state != "false" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container must be stopped after stdin closing" )
2014-08-12 05:36:49 -04:00
}
}
2014-07-22 14:16:15 -04:00
// Test for #2267
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWriteHostsFileAndNotCommit ( c * check . C ) {
2014-07-22 14:16:15 -04:00
name := "writehosts"
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--name" , name , "busybox" , "sh" , "-c" , "echo test2267 >> /etc/hosts && cat /etc/hosts" )
2014-07-22 14:16:15 -04:00
if ! strings . Contains ( out , "test2267" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "/etc/hosts should contain 'test2267'" )
2014-07-22 14:16:15 -04:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "diff" , name )
2015-04-18 12:46:47 -04:00
if len ( strings . Trim ( out , "\r\n" ) ) != 0 && ! eqToBaseDiff ( out , c ) {
c . Fatal ( "diff should be empty" )
2014-07-22 14:16:15 -04:00
}
}
2015-04-18 12:46:47 -04:00
func eqToBaseDiff ( out string , c * check . C ) bool {
2015-07-19 16:47:47 -04:00
out1 , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "echo" , "hello" )
2015-04-06 09:21:18 -04:00
cID := strings . TrimSpace ( out1 )
2015-07-19 16:47:47 -04:00
baseDiff , _ := dockerCmd ( c , "diff" , cID )
2015-03-25 21:40:23 -04:00
baseArr := strings . Split ( baseDiff , "\n" )
sort . Strings ( baseArr )
outArr := strings . Split ( out , "\n" )
sort . Strings ( outArr )
return sliceEq ( baseArr , outArr )
2015-01-19 19:32:29 -05:00
}
func sliceEq ( a , b [ ] string ) bool {
if len ( a ) != len ( b ) {
return false
}
for i := range a {
if a [ i ] != b [ i ] {
return false
}
}
return true
}
2014-07-22 14:16:15 -04:00
// Test for #2267
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWriteHostnameFileAndNotCommit ( c * check . C ) {
2014-07-22 14:16:15 -04:00
name := "writehostname"
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--name" , name , "busybox" , "sh" , "-c" , "echo test2267 >> /etc/hostname && cat /etc/hostname" )
2014-07-22 14:16:15 -04:00
if ! strings . Contains ( out , "test2267" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "/etc/hostname should contain 'test2267'" )
2014-07-22 14:16:15 -04:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "diff" , name )
2015-04-18 12:46:47 -04:00
if len ( strings . Trim ( out , "\r\n" ) ) != 0 && ! eqToBaseDiff ( out , c ) {
c . Fatal ( "diff should be empty" )
2014-07-22 14:16:15 -04:00
}
}
// Test for #2267
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWriteResolvFileAndNotCommit ( c * check . C ) {
2014-07-22 14:16:15 -04:00
name := "writeresolv"
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--name" , name , "busybox" , "sh" , "-c" , "echo test2267 >> /etc/resolv.conf && cat /etc/resolv.conf" )
2014-07-22 14:16:15 -04:00
if ! strings . Contains ( out , "test2267" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "/etc/resolv.conf should contain 'test2267'" )
2014-07-22 14:16:15 -04:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "diff" , name )
2015-04-18 12:46:47 -04:00
if len ( strings . Trim ( out , "\r\n" ) ) != 0 && ! eqToBaseDiff ( out , c ) {
c . Fatal ( "diff should be empty" )
2014-07-22 14:16:15 -04:00
}
}
2014-08-24 06:09:30 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithBadDevice ( c * check . C ) {
2014-08-24 06:09:30 -04:00
name := "baddevice"
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--name" , name , "--device" , "/etc" , "busybox" , "true" )
2014-08-24 06:09:30 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Run should fail with bad device" )
2014-08-24 06:09:30 -04:00
}
2015-05-09 14:33:06 -04:00
expected := ` "/etc": not a device node `
2014-08-24 06:09:30 -04:00
if ! strings . Contains ( out , expected ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Output should contain %q, actual out: %q" , expected , out )
2014-08-24 06:09:30 -04:00
}
}
2014-08-27 20:25:10 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunEntrypoint ( c * check . C ) {
2014-08-27 20:25:10 -04:00
name := "entrypoint"
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--name" , name , "--entrypoint" , "/bin/echo" , "busybox" , "-n" , "foobar" )
2014-08-27 20:25:10 -04:00
expected := "foobar"
if out != expected {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Output should be %q, actual out: %q" , expected , out )
2014-08-27 20:25:10 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunBindMounts ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2014-11-17 11:05:49 -05:00
2014-08-27 20:25:10 -04:00
tmpDir , err := ioutil . TempDir ( "" , "docker-test-container" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-08-27 20:25:10 -04:00
}
defer os . RemoveAll ( tmpDir )
2015-04-18 12:46:47 -04:00
writeFile ( path . Join ( tmpDir , "touch-me" ) , "" , c )
2014-08-27 20:25:10 -04:00
// Test reading from a read-only bind mount
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:/tmp:ro" , tmpDir ) , "busybox" , "ls" , "/tmp" )
2014-08-27 20:25:10 -04:00
if ! strings . Contains ( out , "touch-me" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container failed to read from bind mount" )
2014-08-27 20:25:10 -04:00
}
// test writing to bind mount
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:/tmp:rw" , tmpDir ) , "busybox" , "touch" , "/tmp/holla" )
2015-04-18 12:46:47 -04:00
readFile ( path . Join ( tmpDir , "holla" ) , c ) // Will fail if the file doesn't exist
2014-08-27 20:25:10 -04:00
// test mounting to an illegal destination directory
2015-07-19 16:47:47 -04:00
_ , _ , err = dockerCmdWithError ( c , "run" , "-v" , fmt . Sprintf ( "%s:." , tmpDir ) , "busybox" , "ls" , "." )
2014-08-27 20:25:10 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container bind mounted illegal directory" )
2014-08-27 20:25:10 -04:00
}
// test mount a file
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s/holla:/tmp/holla:rw" , tmpDir ) , "busybox" , "sh" , "-c" , "echo -n 'yotta' > /tmp/holla" )
2015-04-18 12:46:47 -04:00
content := readFile ( path . Join ( tmpDir , "holla" ) , c ) // Will fail if the file doesn't exist
2014-08-27 20:25:10 -04:00
expected := "yotta"
if content != expected {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Output should be %q, actual out: %q" , expected , content )
2014-08-27 20:25:10 -04:00
}
}
2014-07-14 19:19:37 -04:00
2014-09-01 11:55:39 -04:00
// Ensure that CIDFile gets deleted if it's empty
// Perform this test by making `docker run` fail
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCidFileCleanupIfEmpty ( c * check . C ) {
2014-09-01 11:55:39 -04:00
tmpDir , err := ioutil . TempDir ( "" , "TestRunCidFile" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-01 11:55:39 -04:00
}
defer os . RemoveAll ( tmpDir )
tmpCidFile := path . Join ( tmpDir , "cid" )
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--cidfile" , tmpCidFile , "emptyfs" )
2014-09-01 11:55:39 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Run without command must fail. out=%s" , out )
2015-03-06 01:01:49 -05:00
} else if ! strings . Contains ( out , "No command specified" ) {
2015-04-27 16:33:30 -04:00
c . Fatalf ( "Run without command failed with wrong output. out=%s\nerr=%v" , out , err )
2014-09-01 11:55:39 -04:00
}
if _ , err := os . Stat ( tmpCidFile ) ; err == nil {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "empty CIDFile %q should've been deleted" , tmpCidFile )
2014-09-01 11:55:39 -04:00
}
}
2014-09-01 12:15:20 -04:00
// #2098 - Docker cidFiles only contain short version of the containerId
2015-04-18 12:46:47 -04:00
//sudo docker run --cidfile /tmp/docker_tesc.cid ubuntu echo "test"
2014-09-01 12:15:20 -04:00
// TestRunCidFile tests that run --cidfile returns the longid
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCidFileCheckIDLength ( c * check . C ) {
2014-09-01 12:15:20 -04:00
tmpDir , err := ioutil . TempDir ( "" , "TestRunCidFile" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-01 12:15:20 -04:00
}
tmpCidFile := path . Join ( tmpDir , "cid" )
defer os . RemoveAll ( tmpDir )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "--cidfile" , tmpCidFile , "busybox" , "true" )
2014-09-01 12:15:20 -04:00
id := strings . TrimSpace ( out )
buffer , err := ioutil . ReadFile ( tmpCidFile )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-01 12:15:20 -04:00
}
cid := string ( buffer )
if len ( cid ) != 64 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "--cidfile should be a long id, not %q" , id )
2014-09-01 12:15:20 -04:00
}
if cid != id {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "cid must be equal to %s, got %s" , id , cid )
2014-09-01 12:15:20 -04:00
}
}
2014-09-04 01:50:58 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunSetMacAddress ( c * check . C ) {
2014-10-03 17:02:17 -04:00
mac := "12:34:56:78:9a:bc"
2015-02-18 01:18:28 -05:00
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-i" , "--rm" , fmt . Sprintf ( "--mac-address=%s" , mac ) , "busybox" , "/bin/sh" , "-c" , "ip link show eth0 | tail -1 | awk '{print $2}'" )
2014-10-03 17:02:17 -04:00
actualMac := strings . TrimSpace ( out )
if actualMac != mac {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Set MAC address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q" , actualMac , mac )
2014-10-03 17:02:17 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunInspectMacAddress ( c * check . C ) {
2014-10-03 17:02:17 -04:00
mac := "12:34:56:78:9a:bc"
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "--mac-address=" + mac , "busybox" , "top" )
2014-10-03 17:02:17 -04:00
id := strings . TrimSpace ( out )
inspectedMac , err := inspectField ( id , "NetworkSettings.MacAddress" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-10-03 17:02:17 -04:00
if inspectedMac != mac {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "docker inspect outputs wrong MAC address: %q, should be: %q" , inspectedMac , mac )
2014-10-03 17:02:17 -04:00
}
}
2015-02-27 10:27:12 -05:00
// test docker run use a invalid mac address
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunWithInvalidMacAddress ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--mac-address" , "92:d0:c6:0a:29" , "busybox" )
2015-02-27 10:27:12 -05:00
//use a invalid mac address should with a error out
if err == nil || ! strings . Contains ( out , "is not a valid mac address" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "run with an invalid --mac-address should with error out" )
2015-02-27 10:27:12 -05:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunDeallocatePortOnMissingIptablesRule ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "-p" , "23:23" , "busybox" , "top" )
2014-09-09 08:47:25 -04:00
id := strings . TrimSpace ( out )
ip , err := inspectField ( id , "NetworkSettings.IPAddress" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-11-14 20:36:38 -05:00
iptCmd := exec . Command ( "iptables" , "-D" , "DOCKER" , "-d" , fmt . Sprintf ( "%s/32" , ip ) ,
2014-09-09 08:47:25 -04:00
"!" , "-i" , "docker0" , "-o" , "docker0" , "-p" , "tcp" , "-m" , "tcp" , "--dport" , "23" , "-j" , "ACCEPT" )
out , _ , err = runCommandWithOutput ( iptCmd )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err , out )
2014-09-09 08:47:25 -04:00
}
if err := deleteContainer ( id ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-09 08:47:25 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "-p" , "23:23" , "busybox" , "top" )
2014-09-09 08:47:25 -04:00
}
2014-09-05 21:59:31 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunPortInUse ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2014-09-05 21:59:31 -04:00
port := "1234"
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "-p" , port + ":80" , "busybox" , "top" )
2014-10-08 08:41:26 -04:00
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "-d" , "-p" , port + ":80" , "busybox" , "top" )
2014-11-10 19:19:16 -05:00
if err == nil {
c . Fatalf ( "Binding on used port must fail" )
2014-10-08 08:41:26 -04:00
}
2014-11-10 19:19:16 -05:00
if ! strings . Contains ( out , "port is already allocated" ) {
c . Fatalf ( "Out must be about \"port is already allocated\", got %s" , out )
2014-10-08 08:41:26 -04:00
}
}
2015-04-08 01:31:47 -04:00
// https://github.com/docker/docker/issues/12148
func ( s * DockerSuite ) TestRunAllocatePortInReservedRange ( c * check . C ) {
// allocate a dynamic port to get the most recent
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "-P" , "-p" , "80" , "busybox" , "top" )
2015-04-08 01:31:47 -04:00
id := strings . TrimSpace ( out )
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "port" , id , "80" )
2015-04-08 01:31:47 -04:00
strPort := strings . Split ( strings . TrimSpace ( out ) , ":" ) [ 1 ]
port , err := strconv . ParseInt ( strPort , 10 , 64 )
if err != nil {
c . Fatalf ( "invalid port, got: %s, error: %s" , strPort , err )
}
// allocate a static port and a dynamic port together, with static port
// takes the next recent port in dynamic port range.
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "-P" , "-p" , "80" , "-p" , fmt . Sprintf ( "%d:8080" , port + 1 ) , "busybox" , "top" )
2015-04-08 01:31:47 -04:00
}
2014-09-15 20:51:06 -04:00
// Regression test for #7792
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunMountOrdering ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2014-09-15 20:51:06 -04:00
tmpDir , err := ioutil . TempDir ( "" , "docker_nested_mount_test" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-15 20:51:06 -04:00
}
defer os . RemoveAll ( tmpDir )
tmpDir2 , err := ioutil . TempDir ( "" , "docker_nested_mount_test2" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-15 20:51:06 -04:00
}
defer os . RemoveAll ( tmpDir2 )
2015-04-18 12:46:47 -04:00
// Create a temporary tmpfs mounc.
2014-09-15 20:51:06 -04:00
fooDir := filepath . Join ( tmpDir , "foo" )
if err := os . MkdirAll ( filepath . Join ( tmpDir , "foo" ) , 0755 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "failed to mkdir at %s - %s" , fooDir , err )
2014-09-15 20:51:06 -04:00
}
if err := ioutil . WriteFile ( fmt . Sprintf ( "%s/touch-me" , fooDir ) , [ ] byte { } , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-15 20:51:06 -04:00
}
if err := ioutil . WriteFile ( fmt . Sprintf ( "%s/touch-me" , tmpDir ) , [ ] byte { } , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-15 20:51:06 -04:00
}
if err := ioutil . WriteFile ( fmt . Sprintf ( "%s/touch-me" , tmpDir2 ) , [ ] byte { } , 0644 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-15 20:51:06 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" ,
2015-05-19 16:05:25 -04:00
"-v" , fmt . Sprintf ( "%s:/tmp" , tmpDir ) ,
"-v" , fmt . Sprintf ( "%s:/tmp/foo" , fooDir ) ,
"-v" , fmt . Sprintf ( "%s:/tmp/tmp2" , tmpDir2 ) ,
"-v" , fmt . Sprintf ( "%s:/tmp/tmp2/foo" , fooDir ) ,
"busybox:latest" , "sh" , "-c" ,
"ls /tmp/touch-me && ls /tmp/foo/touch-me && ls /tmp/tmp2/touch-me && ls /tmp/tmp2/foo/touch-me" )
2014-09-15 20:51:06 -04:00
}
2014-09-10 12:43:16 -04:00
2014-09-26 14:28:21 -04:00
// Regression test for https://github.com/docker/docker/issues/8259
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunReuseBindVolumeThatIsSymlink ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2014-09-26 14:28:21 -04:00
tmpDir , err := ioutil . TempDir ( os . TempDir ( ) , "testlink" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-26 14:28:21 -04:00
}
defer os . RemoveAll ( tmpDir )
linkPath := os . TempDir ( ) + "/testlink2"
if err := os . Symlink ( tmpDir , linkPath ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-09-26 14:28:21 -04:00
}
defer os . RemoveAll ( linkPath )
// Create first container
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:/tmp/test" , linkPath ) , "busybox" , "ls" , "-lh" , "/tmp/test" )
2014-09-26 14:28:21 -04:00
// Create second container with same symlinked path
// This will fail if the referenced issue is hit with a "Volume exists" error
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:/tmp/test" , linkPath ) , "busybox" , "ls" , "-lh" , "/tmp/test" )
2014-09-26 14:28:21 -04:00
}
2014-10-06 13:30:42 -04:00
2015-03-05 09:41:56 -05:00
//GH#10604: Test an "/etc" volume doesn't overlay special bind mounts in container
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunCreateVolumeEtc ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--dns=127.0.0.1" , "-v" , "/etc" , "busybox" , "cat" , "/etc/resolv.conf" )
2015-02-11 21:39:07 -05:00
if ! strings . Contains ( out , "nameserver 127.0.0.1" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "/etc volume mount hides /etc/resolv.conf" )
2015-02-11 21:39:07 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "-h=test123" , "-v" , "/etc" , "busybox" , "cat" , "/etc/hostname" )
2015-02-11 21:39:07 -05:00
if ! strings . Contains ( out , "test123" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "/etc volume mount hides /etc/hostname" )
2015-02-11 21:39:07 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "--add-host=test:192.168.0.1" , "-v" , "/etc" , "busybox" , "cat" , "/etc/hosts" )
2015-02-11 21:39:07 -05:00
out = strings . Replace ( out , "\n" , " " , - 1 )
2015-03-05 09:41:56 -05:00
if ! strings . Contains ( out , "192.168.0.1\ttest" ) || ! strings . Contains ( out , "127.0.0.1\tlocalhost" ) {
2015-04-18 12:46:47 -04:00
c . Fatal ( "/etc volume mount hides /etc/hosts" )
2015-02-11 21:39:07 -05:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestVolumesNoCopyData ( c * check . C ) {
2014-10-06 13:30:42 -04:00
if _ , err := buildImage ( "dataimage" ,
` FROM busybox
2015-07-19 16:47:47 -04:00
RUN mkdir - p / foo
RUN touch / foo / bar ` ,
2014-10-06 13:30:42 -04:00
true ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-10-06 13:30:42 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--name" , "test" , "-v" , "/foo" , "busybox" )
2014-10-06 13:30:42 -04:00
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "run" , "--volumes-from" , "test" , "dataimage" , "ls" , "-lh" , "/foo/bar" ) ; err == nil || ! strings . Contains ( out , "No such file or directory" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Data was copied on volumes-from but shouldn't be:\n%q" , out )
2014-10-06 13:30:42 -04:00
}
2015-02-20 03:58:44 -05:00
tmpDir := randomUnixTmpDirPath ( "docker_test_bind_mount_copy_data" )
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "run" , "-v" , tmpDir + ":/foo" , "dataimage" , "ls" , "-lh" , "/foo/bar" ) ; err == nil || ! strings . Contains ( out , "No such file or directory" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Data was copied on bind-mount but shouldn't be:\n%q" , out )
2014-10-06 13:30:42 -04:00
}
}
2014-10-08 15:01:25 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunNoOutputFromPullInStdout ( c * check . C ) {
2014-10-17 14:06:05 -04:00
// just run with unknown image
cmd := exec . Command ( dockerBinary , "run" , "asdfsg" )
stdout := bytes . NewBuffer ( nil )
cmd . Stdout = stdout
if err := cmd . Run ( ) ; err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Run with unknown image should fail" )
2014-10-17 14:06:05 -04:00
}
if stdout . Len ( ) != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Stdout contains output from pull: %s" , stdout )
2014-10-17 14:06:05 -04:00
}
}
2014-10-20 15:27:26 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunVolumesCleanPaths ( c * check . C ) {
2014-10-20 15:27:26 -04:00
if _ , err := buildImage ( "run_volumes_clean_paths" ,
` FROM busybox
2015-07-19 16:47:47 -04:00
VOLUME / foo / ` ,
2014-10-20 15:27:26 -04:00
true ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-10-20 15:27:26 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , "/foo" , "-v" , "/bar/" , "--name" , "dark_helmet" , "run_volumes_clean_paths" )
2014-10-20 15:27:26 -04:00
2015-06-03 15:21:38 -04:00
out , err := inspectMountSourceField ( "dark_helmet" , "/foo/" )
2015-07-22 08:59:24 -04:00
if err != errMountNotFound {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Found unexpected volume entry for '/foo/' in volumes\n%q" , out )
2014-10-20 15:27:26 -04:00
}
2015-06-03 15:21:38 -04:00
out , err = inspectMountSourceField ( "dark_helmet" , "/foo" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2015-05-19 16:05:25 -04:00
if ! strings . Contains ( out , volumesConfigPath ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Volume was not defined for /foo\n%q" , out )
2014-10-20 15:27:26 -04:00
}
2015-06-03 15:21:38 -04:00
out , err = inspectMountSourceField ( "dark_helmet" , "/bar/" )
2015-07-22 08:59:24 -04:00
if err != errMountNotFound {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Found unexpected volume entry for '/bar/' in volumes\n%q" , out )
2014-10-20 15:27:26 -04:00
}
2015-06-03 15:21:38 -04:00
out , err = inspectMountSourceField ( "dark_helmet" , "/bar" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2015-05-19 16:05:25 -04:00
if ! strings . Contains ( out , volumesConfigPath ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Volume was not defined for /bar\n%q" , out )
2014-10-20 15:27:26 -04:00
}
}
2014-10-03 13:38:44 -04:00
// Regression test for #3631
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunSlowStdoutConsumer ( c * check . C ) {
cont := exec . Command ( dockerBinary , "run" , "--rm" , "busybox" , "/bin/sh" , "-c" , "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | catv" )
2014-10-03 13:38:44 -04:00
2015-04-18 12:46:47 -04:00
stdout , err := cont . StdoutPipe ( )
2014-10-03 13:38:44 -04:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-10-03 13:38:44 -04:00
}
2015-04-18 12:46:47 -04:00
if err := cont . Start ( ) ; err != nil {
c . Fatal ( err )
2014-10-03 13:38:44 -04:00
}
2014-10-30 15:10:38 -04:00
n , err := consumeWithSpeed ( stdout , 10000 , 5 * time . Millisecond , nil )
2014-10-03 13:38:44 -04:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-10-03 13:38:44 -04:00
}
expected := 2 * 1024 * 2000
if n != expected {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Expected %d, got %d" , expected , n )
2014-10-03 13:38:44 -04:00
}
}
2014-09-16 21:08:30 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAllowPortRangeThroughExpose ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "--expose" , "3000-3003" , "-P" , "busybox" , "top" )
2014-09-16 21:08:30 -04:00
id := strings . TrimSpace ( out )
portstr , err := inspectFieldJSON ( id , "NetworkSettings.Ports" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-09-16 21:08:30 -04:00
var ports nat . PortMap
2015-03-25 23:18:42 -04:00
if err = unmarshalJSON ( [ ] byte ( portstr ) , & ports ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-03-25 23:18:42 -04:00
}
2014-09-16 21:08:30 -04:00
for port , binding := range ports {
portnum , _ := strconv . Atoi ( strings . Split ( string ( port ) , "/" ) [ 0 ] )
if portnum < 3000 || portnum > 3003 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Port %d is out of range " , portnum )
2014-09-16 21:08:30 -04:00
}
if binding == nil || len ( binding ) != 1 || len ( binding [ 0 ] . HostPort ) == 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Port is not mapped for the port %d" , port )
2014-09-16 21:08:30 -04:00
}
}
}
2014-11-05 21:23:42 -05:00
2015-02-19 18:18:13 -05:00
// test docker run expose a invalid port
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunExposePort ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--expose" , "80000" , "busybox" )
2015-02-19 18:18:13 -05:00
//expose a invalid port should with a error out
if err == nil || ! strings . Contains ( out , "Invalid range format for --expose" ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "run --expose a invalid port should with error out" )
2015-02-19 18:18:13 -05:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunUnknownCommand ( c * check . C ) {
testRequires ( c , NativeExecDriver )
2015-07-20 14:20:50 -04:00
out , _ , _ := dockerCmdWithStdoutStderr ( c , "create" , "busybox" , "/bin/nada" )
2014-11-05 21:23:42 -05:00
2015-07-20 14:20:50 -04:00
cID := strings . TrimSpace ( out )
_ , _ , err := dockerCmdWithError ( c , "start" , cID )
c . Assert ( err , check . NotNil )
2014-11-05 21:23:42 -05:00
2015-05-17 22:06:13 -04:00
rc , err := inspectField ( cID , "State.ExitCode" )
c . Assert ( err , check . IsNil )
2015-01-19 19:32:29 -05:00
if rc == "0" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "ExitCode(%v) cannot be 0" , rc )
2014-11-05 21:23:42 -05:00
}
}
2014-11-10 16:14:17 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunModeIpcHost ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2014-11-10 16:14:17 -05:00
hostIpc , err := os . Readlink ( "/proc/1/ns/ipc" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-11-10 16:14:17 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--ipc=host" , "busybox" , "readlink" , "/proc/self/ns/ipc" )
out = strings . Trim ( out , "\n" )
if hostIpc != out {
c . Fatalf ( "IPC different with --ipc=host %s != %s\n" , hostIpc , out )
2014-11-10 16:14:17 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/ipc" )
out = strings . Trim ( out , "\n" )
if hostIpc == out {
c . Fatalf ( "IPC should be different without --ipc=host %s == %s\n" , hostIpc , out )
2014-11-10 16:14:17 -05:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunModeIpcContainer ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-11-10 16:14:17 -05:00
id := strings . TrimSpace ( out )
state , err := inspectField ( id , "State.Running" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-11-10 16:14:17 -05:00
if state != "true" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Container state is 'not running'" )
2014-11-10 16:14:17 -05:00
}
pid1 , err := inspectField ( id , "State.Pid" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-11-10 16:14:17 -05:00
parentContainerIpc , err := os . Readlink ( fmt . Sprintf ( "/proc/%s/ns/ipc" , pid1 ) )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-11-10 16:14:17 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , fmt . Sprintf ( "--ipc=container:%s" , id ) , "busybox" , "readlink" , "/proc/self/ns/ipc" )
out = strings . Trim ( out , "\n" )
if parentContainerIpc != out {
c . Fatalf ( "IPC different with --ipc=container:%s %s != %s\n" , id , parentContainerIpc , out )
2014-11-10 16:14:17 -05:00
}
}
2014-11-18 18:10:07 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunModeIpcContainerNotExists ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "-d" , "--ipc" , "container:abcd1234" , "busybox" , "top" )
2015-03-27 21:07:20 -04:00
if ! strings . Contains ( out , "abcd1234" ) || err == nil {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "run IPC from a non exists container should with correct error out" )
2015-03-27 21:07:20 -04:00
}
}
2015-05-22 19:15:14 -04:00
func ( s * DockerSuite ) TestRunModeIpcContainerNotRunning ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "create" , "busybox" )
2015-05-22 19:15:14 -04:00
2015-07-19 16:47:47 -04:00
id := strings . TrimSpace ( out )
out , _ , err := dockerCmdWithError ( c , "run" , fmt . Sprintf ( "--ipc=container:%s" , id ) , "busybox" )
2015-05-22 19:15:14 -04:00
if err == nil {
c . Fatalf ( "Run container with ipc mode container should fail with non running container: %s\n%s" , out , err )
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerNetworkMode ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-11-18 18:10:07 -05:00
id := strings . TrimSpace ( out )
if err := waitRun ( id ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-11-18 18:10:07 -05:00
}
pid1 , err := inspectField ( id , "State.Pid" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2014-11-18 18:10:07 -05:00
parentContainerNet , err := os . Readlink ( fmt . Sprintf ( "/proc/%s/ns/net" , pid1 ) )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-11-18 18:10:07 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , fmt . Sprintf ( "--net=container:%s" , id ) , "busybox" , "readlink" , "/proc/self/ns/net" )
out = strings . Trim ( out , "\n" )
if parentContainerNet != out {
c . Fatalf ( "NET different with --net=container:%s %s != %s\n" , id , parentContainerNet , out )
2014-11-18 18:10:07 -05:00
}
}
2014-11-20 10:29:04 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunModePidHost ( c * check . C ) {
testRequires ( c , NativeExecDriver , SameHostDaemon )
2015-02-20 01:56:02 -05:00
2015-01-13 19:39:08 -05:00
hostPid , err := os . Readlink ( "/proc/1/ns/pid" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-01-13 19:39:08 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--pid=host" , "busybox" , "readlink" , "/proc/self/ns/pid" )
out = strings . Trim ( out , "\n" )
if hostPid != out {
c . Fatalf ( "PID different with --pid=host %s != %s\n" , hostPid , out )
2015-01-13 19:39:08 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/pid" )
out = strings . Trim ( out , "\n" )
if hostPid == out {
c . Fatalf ( "PID should be different without --pid=host %s == %s\n" , hostPid , out )
2015-01-13 19:39:08 -05:00
}
}
2015-05-05 18:32:36 -04:00
func ( s * DockerSuite ) TestRunModeUTSHost ( c * check . C ) {
testRequires ( c , NativeExecDriver , SameHostDaemon )
hostUTS , err := os . Readlink ( "/proc/1/ns/uts" )
if err != nil {
c . Fatal ( err )
}
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--uts=host" , "busybox" , "readlink" , "/proc/self/ns/uts" )
out = strings . Trim ( out , "\n" )
if hostUTS != out {
c . Fatalf ( "UTS different with --uts=host %s != %s\n" , hostUTS , out )
2015-05-05 18:32:36 -04:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/uts" )
out = strings . Trim ( out , "\n" )
if hostUTS == out {
c . Fatalf ( "UTS should be different without --uts=host %s == %s\n" , hostUTS , out )
2015-05-05 18:32:36 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunTLSverify ( c * check . C ) {
2015-07-19 16:47:47 -04:00
if out , code , err := dockerCmdWithError ( c , "ps" ) ; err != nil || code != 0 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Should have worked: %v:\n%v" , err , out )
2014-11-20 10:29:04 -05:00
}
// Regardless of whether we specify true or false we need to
// test to make sure tls is turned on if --tlsverify is specified at all
2015-07-19 16:47:47 -04:00
out , code , err := dockerCmdWithError ( c , "--tlsverify=false" , "ps" )
if err == nil || code == 0 || ! strings . Contains ( out , "trying to connect" ) {
c . Fatalf ( "Should have failed: \net:%v\nout:%v\nerr:%v" , code , out , err )
2014-11-20 10:29:04 -05:00
}
2015-07-19 16:47:47 -04:00
out , code , err = dockerCmdWithError ( c , "--tlsverify=true" , "ps" )
if err == nil || code == 0 || ! strings . Contains ( out , "cert" ) {
c . Fatalf ( "Should have failed: \net:%v\nout:%v\nerr:%v" , code , out , err )
2014-11-20 10:29:04 -05:00
}
}
2014-12-01 19:24:43 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunPortFromDockerRangeInUse ( c * check . C ) {
2014-12-01 19:24:43 -05:00
// first find allocator current position
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "-p" , ":80" , "busybox" , "top" )
2014-12-01 19:24:43 -05:00
id := strings . TrimSpace ( out )
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "port" , id )
2015-02-17 05:15:51 -05:00
2015-07-19 16:47:47 -04:00
out = strings . TrimSpace ( out )
2015-02-17 05:15:51 -05:00
if out == "" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "docker port command output is empty" )
2015-02-17 05:15:51 -05:00
}
2014-12-01 19:24:43 -05:00
out = strings . Split ( out , ":" ) [ 1 ]
lastPort , err := strconv . Atoi ( out )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-01 19:24:43 -05:00
}
port := lastPort + 1
l , err := net . Listen ( "tcp" , ":" + strconv . Itoa ( port ) )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-01 19:24:43 -05:00
}
defer l . Close ( )
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "-d" , "-p" , ":80" , "busybox" , "top" )
2014-12-01 19:24:43 -05:00
id = strings . TrimSpace ( out )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "port" , id )
2014-12-01 19:24:43 -05:00
}
2014-12-05 19:50:56 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunTtyWithPipe ( c * check . C ) {
2015-04-27 13:29:48 -04:00
errChan := make ( chan error )
2014-12-05 19:50:56 -05:00
go func ( ) {
2015-04-27 13:29:48 -04:00
defer close ( errChan )
2014-12-05 19:50:56 -05:00
cmd := exec . Command ( dockerBinary , "run" , "-ti" , "busybox" , "true" )
if _ , err := cmd . StdinPipe ( ) ; err != nil {
2015-04-27 13:29:48 -04:00
errChan <- err
return
2014-12-05 19:50:56 -05:00
}
expected := "cannot enable tty mode"
if out , _ , err := runCommandWithOutput ( cmd ) ; err == nil {
2015-04-27 13:29:48 -04:00
errChan <- fmt . Errorf ( "run should have failed" )
return
2014-12-05 19:50:56 -05:00
} else if ! strings . Contains ( out , expected ) {
2015-04-27 13:29:48 -04:00
errChan <- fmt . Errorf ( "run failed with error %q: expected %q" , out , expected )
return
2014-12-05 19:50:56 -05:00
}
} ( )
select {
2015-04-27 13:29:48 -04:00
case err := <- errChan :
c . Assert ( err , check . IsNil )
2014-12-05 19:50:56 -05:00
case <- time . After ( 3 * time . Second ) :
2015-04-18 12:46:47 -04:00
c . Fatal ( "container is running but should have failed" )
2014-12-05 19:50:56 -05:00
}
}
2014-12-22 17:54:55 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunNonLocalMacAddress ( c * check . C ) {
2014-12-22 17:54:55 -05:00
addr := "00:16:3E:08:00:50"
2015-07-19 16:47:47 -04:00
if out , _ := dockerCmd ( c , "run" , "--mac-address" , addr , "busybox" , "ifconfig" ) ; ! strings . Contains ( out , addr ) {
c . Fatalf ( "Output should have contained %q: %s" , addr , out )
2014-12-22 17:54:55 -05:00
}
}
2014-12-24 23:40:41 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunNetHost ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-25 23:16:44 -05:00
2014-12-29 15:56:07 -05:00
hostNet , err := os . Readlink ( "/proc/1/ns/net" )
2014-12-24 23:40:41 -05:00
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2014-12-24 23:40:41 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--net=host" , "busybox" , "readlink" , "/proc/self/ns/net" )
out = strings . Trim ( out , "\n" )
if hostNet != out {
c . Fatalf ( "Net namespace different with --net=host %s != %s\n" , hostNet , out )
2014-12-29 15:56:07 -05:00
}
2015-07-19 16:47:47 -04:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/net" )
out = strings . Trim ( out , "\n" )
if hostNet == out {
c . Fatalf ( "Net namespace should be different without --net=host %s == %s\n" , hostNet , out )
2014-12-29 15:56:07 -05:00
}
2014-12-24 23:40:41 -05:00
}
2014-11-03 13:15:55 -05:00
2015-06-24 13:23:00 -04:00
func ( s * DockerSuite ) TestRunNetHostTwiceSameName ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--rm" , "--name=thost" , "--net=host" , "busybox" , "true" )
dockerCmd ( c , "run" , "--rm" , "--name=thost" , "--net=host" , "busybox" , "true" )
2015-06-24 13:23:00 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunNetContainerWhichHost ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-04-07 18:20:39 -04:00
hostNet , err := os . Readlink ( "/proc/1/ns/net" )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-04-07 18:20:39 -04:00
}
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "--net=host" , "--name=test" , "busybox" , "top" )
2015-04-07 18:20:39 -04:00
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--net=container:test" , "busybox" , "readlink" , "/proc/self/ns/net" )
2015-04-07 18:20:39 -04:00
out = strings . Trim ( out , "\n" )
if hostNet != out {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container should have host network namespace" )
2015-04-07 18:20:39 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunAllowPortRangeThroughPublish ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "--expose" , "3000-3003" , "-p" , "3000-3003" , "busybox" , "top" )
2014-11-03 13:15:55 -05:00
id := strings . TrimSpace ( out )
portstr , err := inspectFieldJSON ( id , "NetworkSettings.Ports" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2015-07-19 16:47:47 -04:00
2014-11-03 13:15:55 -05:00
var ports nat . PortMap
err = unmarshalJSON ( [ ] byte ( portstr ) , & ports )
for port , binding := range ports {
portnum , _ := strconv . Atoi ( strings . Split ( string ( port ) , "/" ) [ 0 ] )
if portnum < 3000 || portnum > 3003 {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Port %d is out of range " , portnum )
2014-11-03 13:15:55 -05:00
}
if binding == nil || len ( binding ) != 1 || len ( binding [ 0 ] . HostPort ) == 0 {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Port is not mapped for the port " + port , out )
2014-11-03 13:15:55 -05:00
}
}
}
2015-01-09 18:42:55 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunSetDefaultRestartPolicy ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , "test" , "busybox" , "top" )
2015-05-17 22:06:13 -04:00
out , err := inspectField ( "test" , "HostConfig.RestartPolicy.Name" )
c . Assert ( err , check . IsNil )
2015-03-09 22:09:12 -04:00
if out != "no" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Set default restart policy failed" )
2015-03-09 22:09:12 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunRestartMaxRetries ( c * check . C ) {
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "--restart=on-failure:3" , "busybox" , "false" )
2015-01-13 18:19:12 -05:00
id := strings . TrimSpace ( string ( out ) )
2015-04-16 15:48:04 -04:00
if err := waitInspect ( id , "{{ .State.Restarting }} {{ .State.Running }}" , "false false" , 10 ) ; err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( err )
2015-01-13 18:19:12 -05:00
}
2015-07-19 16:47:47 -04:00
2015-01-13 18:19:12 -05:00
count , err := inspectField ( id , "RestartCount" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2015-01-13 18:19:12 -05:00
if count != "3" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container was restarted %s times, expected %d" , count , 3 )
2015-01-13 18:19:12 -05:00
}
2015-07-19 16:47:47 -04:00
2015-03-17 01:19:59 -04:00
MaximumRetryCount , err := inspectField ( id , "HostConfig.RestartPolicy.MaximumRetryCount" )
2015-05-17 22:06:13 -04:00
c . Assert ( err , check . IsNil )
2015-03-17 01:19:59 -04:00
if MaximumRetryCount != "3" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "Container Maximum Retry Count is %s, expected %s" , MaximumRetryCount , "3" )
2015-03-17 01:19:59 -04:00
}
2015-01-13 18:19:12 -05:00
}
2015-01-13 16:52:51 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunContainerWithWritableRootfs ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "--rm" , "busybox" , "touch" , "/file" )
2015-01-13 16:52:51 -05:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunContainerWithReadonlyRootfs ( c * check . C ) {
testRequires ( c , NativeExecDriver )
2015-02-25 23:16:44 -05:00
2015-06-02 12:16:43 -04:00
for _ , f := range [ ] string { "/file" , "/etc/hosts" , "/etc/resolv.conf" , "/etc/hostname" , "/proc/uptime" , "/sys/kernel" , "/dev/.dont.touch.me" } {
2015-05-02 11:29:00 -04:00
testReadOnlyFile ( f , c )
}
}
2015-06-02 12:16:43 -04:00
func ( s * DockerSuite ) TestPermissionsPtsReadonlyRootfs ( c * check . C ) {
testRequires ( c , NativeExecDriver )
// Ensure we have not broken writing /dev/pts
out , status := dockerCmd ( c , "run" , "--read-only" , "--rm" , "busybox" , "mount" )
if status != 0 {
c . Fatal ( "Could not obtain mounts when checking /dev/pts mntpnt." )
}
expected := "type devpts (rw,"
if ! strings . Contains ( string ( out ) , expected ) {
c . Fatalf ( "expected output to contain %s but contains %s" , expected , out )
}
}
2015-05-02 11:29:00 -04:00
func testReadOnlyFile ( filename string , c * check . C ) {
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--read-only" , "--rm" , "busybox" , "touch" , filename )
2015-01-13 16:52:51 -05:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "expected container to error on run with read only error" )
2015-01-13 16:52:51 -05:00
}
expected := "Read-only file system"
if ! strings . Contains ( string ( out ) , expected ) {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected output from failure to contain %s but contains %s" , expected , out )
2015-01-13 16:52:51 -05:00
}
2015-06-02 12:16:43 -04:00
2015-07-19 16:47:47 -04:00
out , _ , err = dockerCmdWithError ( c , "run" , "--read-only" , "--privileged" , "--rm" , "busybox" , "touch" , filename )
2015-06-02 12:16:43 -04:00
if err == nil {
c . Fatal ( "expected container to error on run with read only error" )
}
expected = "Read-only file system"
if ! strings . Contains ( string ( out ) , expected ) {
c . Fatalf ( "expected output from failure to contain %s but contains %s" , expected , out )
2015-01-13 16:52:51 -05:00
}
}
2014-12-18 09:57:36 -05:00
2015-05-02 11:29:00 -04:00
func ( s * DockerSuite ) TestRunContainerWithReadonlyEtcHostsAndLinkedContainer ( c * check . C ) {
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , "test-etc-hosts-ro-linked" , "busybox" , "top" )
2015-05-02 11:29:00 -04:00
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--read-only" , "--link" , "test-etc-hosts-ro-linked:testlinked" , "busybox" , "cat" , "/etc/hosts" )
2015-05-02 11:29:00 -04:00
if ! strings . Contains ( string ( out ) , "testlinked" ) {
c . Fatal ( "Expected /etc/hosts to be updated even if --read-only enabled" )
}
}
func ( s * DockerSuite ) TestRunContainerWithReadonlyRootfsWithDnsFlag ( c * check . C ) {
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--read-only" , "--dns" , "1.1.1.1" , "busybox" , "/bin/cat" , "/etc/resolv.conf" )
2015-05-02 11:29:00 -04:00
if ! strings . Contains ( string ( out ) , "1.1.1.1" ) {
c . Fatal ( "Expected /etc/resolv.conf to be updated even if --read-only enabled and --dns flag used" )
}
}
func ( s * DockerSuite ) TestRunContainerWithReadonlyRootfsWithAddHostFlag ( c * check . C ) {
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--read-only" , "--add-host" , "testreadonly:127.0.0.1" , "busybox" , "/bin/cat" , "/etc/hosts" )
2015-05-02 11:29:00 -04:00
if ! strings . Contains ( string ( out ) , "testreadonly" ) {
c . Fatal ( "Expected /etc/hosts to be updated even if --read-only enabled and --add-host flag used" )
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunVolumesFromRestartAfterRemoved ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , "voltest" , "-v" , "/foo" , "busybox" )
dockerCmd ( c , "run" , "-d" , "--name" , "restarter" , "--volumes-from" , "voltest" , "busybox" , "top" )
2014-12-18 09:57:36 -05:00
// Remove the main volume container and restart the consuming container
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "rm" , "-f" , "voltest" )
2014-12-18 09:57:36 -05:00
// This should not fail since the volumes-from were already applied
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "restart" , "restarter" )
2014-12-18 09:57:36 -05:00
}
2015-03-22 14:09:12 -04:00
// run container with --rm should remove container if exit code != 0
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunContainerWithRmFlagExitCodeNotEqualToZero ( c * check . C ) {
2015-04-08 19:20:42 -04:00
name := "flowers"
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--name" , name , "--rm" , "busybox" , "ls" , "/notexists" )
2015-03-22 14:09:12 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected docker run to fail" , out , err )
2015-03-22 14:09:12 -04:00
}
out , err = getAllContainers ( )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( out , err )
2015-03-22 14:09:12 -04:00
}
if out != "" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected not to have containers" , out )
2015-03-22 14:09:12 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunContainerWithRmFlagCannotStartContainer ( c * check . C ) {
2015-04-08 19:20:42 -04:00
name := "sparkles"
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "--name" , name , "--rm" , "busybox" , "commandNotFound" )
2015-03-22 14:09:12 -04:00
if err == nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected docker run to fail" , out , err )
2015-03-22 14:09:12 -04:00
}
out , err = getAllContainers ( )
if err != nil {
2015-04-18 12:46:47 -04:00
c . Fatal ( out , err )
2015-03-22 14:09:12 -04:00
}
if out != "" {
2015-04-18 12:46:47 -04:00
c . Fatal ( "Expected not to have containers" , out )
2015-03-22 14:09:12 -04:00
}
}
2015-04-10 14:04:30 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestRunPidHostWithChildIsKillable ( c * check . C ) {
2015-04-10 14:04:30 -04:00
name := "ibuildthecloud"
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "--pid=host" , "--name" , name , "busybox" , "sh" , "-c" , "sleep 30; echo hi" )
2015-04-10 14:04:30 -04:00
time . Sleep ( 1 * time . Second )
errchan := make ( chan error )
go func ( ) {
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "kill" , name ) ; err != nil {
2015-04-10 14:04:30 -04:00
errchan <- fmt . Errorf ( "%v:\n%s" , err , out )
}
close ( errchan )
} ( )
select {
case err := <- errchan :
2015-04-27 13:29:48 -04:00
c . Assert ( err , check . IsNil )
2015-04-10 14:04:30 -04:00
case <- time . After ( 5 * time . Second ) :
2015-04-18 12:46:47 -04:00
c . Fatal ( "Kill container timed out" )
2015-04-10 14:04:30 -04:00
}
}
2015-04-20 14:58:24 -04:00
2015-05-07 18:02:08 -04:00
func ( s * DockerSuite ) TestRunWithTooSmallMemoryLimit ( c * check . C ) {
2015-04-20 14:58:24 -04:00
// this memory limit is 1 byte less than the min, which is 4MB
// https://github.com/docker/docker/blob/v1.5.0/daemon/create.go#L22
2015-07-19 16:47:47 -04:00
out , _ , err := dockerCmdWithError ( c , "run" , "-m" , "4194303" , "busybox" )
2015-04-20 14:58:24 -04:00
if err == nil || ! strings . Contains ( out , "Minimum memory limit allowed is 4MB" ) {
2015-05-07 18:02:08 -04:00
c . Fatalf ( "expected run to fail when using too low a memory limit: %q" , out )
2015-04-20 14:58:24 -04:00
}
}
2015-05-07 18:02:08 -04:00
func ( s * DockerSuite ) TestRunWriteToProcAsound ( c * check . C ) {
2015-07-19 16:47:47 -04:00
_ , code , err := dockerCmdWithError ( c , "run" , "busybox" , "sh" , "-c" , "echo 111 >> /proc/asound/version" )
2015-04-20 14:58:24 -04:00
if err == nil || code == 0 {
2015-05-07 18:02:08 -04:00
c . Fatal ( "standard container should not be able to write to /proc/asound" )
2015-04-20 14:58:24 -04:00
}
}
2015-04-20 16:54:49 -04:00
2015-05-07 18:02:08 -04:00
func ( s * DockerSuite ) TestRunReadProcTimer ( c * check . C ) {
2015-05-07 20:39:39 -04:00
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
out , code , err := dockerCmdWithError ( c , "run" , "busybox" , "cat" , "/proc/timer_stats" )
2015-04-29 14:20:31 -04:00
if err != nil || code != 0 {
2015-05-07 18:02:08 -04:00
c . Fatal ( err )
2015-04-29 14:20:31 -04:00
}
if strings . Trim ( out , "\n " ) != "" {
2015-05-07 18:02:08 -04:00
c . Fatalf ( "expected to receive no output from /proc/timer_stats but received %q" , out )
2015-04-20 16:54:49 -04:00
}
}
2015-05-07 18:02:08 -04:00
func ( s * DockerSuite ) TestRunReadProcLatency ( c * check . C ) {
2015-05-07 20:39:39 -04:00
testRequires ( c , NativeExecDriver )
2015-04-29 14:20:31 -04:00
// some kernels don't have this configured so skip the test if this file is not found
// on the host running the tests.
if _ , err := os . Stat ( "/proc/latency_stats" ) ; err != nil {
2015-05-07 18:02:08 -04:00
c . Skip ( "kernel doesnt have latency_stats configured" )
2015-04-29 14:20:31 -04:00
return
}
2015-07-19 16:47:47 -04:00
out , code , err := dockerCmdWithError ( c , "run" , "busybox" , "cat" , "/proc/latency_stats" )
2015-04-29 14:20:31 -04:00
if err != nil || code != 0 {
2015-05-07 18:02:08 -04:00
c . Fatal ( err )
2015-04-29 14:20:31 -04:00
}
if strings . Trim ( out , "\n " ) != "" {
2015-05-07 18:02:08 -04:00
c . Fatalf ( "expected to receive no output from /proc/latency_stats but received %q" , out )
2015-04-20 16:54:49 -04:00
}
}
2015-04-21 20:31:05 -04:00
2015-05-07 18:02:08 -04:00
func ( s * DockerSuite ) TestMountIntoProc ( c * check . C ) {
2015-05-07 20:39:39 -04:00
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
_ , code , err := dockerCmdWithError ( c , "run" , "-v" , "/proc//sys" , "busybox" , "true" )
2015-04-21 20:31:05 -04:00
if err == nil || code == 0 {
2015-05-07 18:02:08 -04:00
c . Fatal ( "container should not be able to mount into /proc" )
2015-04-21 20:31:05 -04:00
}
}
2015-05-07 18:02:08 -04:00
func ( s * DockerSuite ) TestMountIntoSys ( c * check . C ) {
2015-05-07 20:39:39 -04:00
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-v" , "/sys/fs/cgroup" , "busybox" , "true" )
2015-04-21 20:31:05 -04:00
}
2015-05-20 12:35:24 -04:00
2015-05-04 16:20:01 -04:00
func ( s * DockerSuite ) TestRunUnshareProc ( c * check . C ) {
2015-05-26 13:31:21 -04:00
testRequires ( c , Apparmor , NativeExecDriver )
2015-05-04 16:20:01 -04:00
name := "acidburn"
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "run" , "--name" , name , "jess/unshare" , "unshare" , "-p" , "-m" , "-f" , "-r" , "--mount-proc=/proc" , "mount" ) ; err == nil || ! strings . Contains ( out , "Permission denied" ) {
2015-05-04 16:20:01 -04:00
c . Fatalf ( "unshare should have failed with permission denied, got: %s, %v" , out , err )
}
name = "cereal"
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "run" , "--name" , name , "jess/unshare" , "unshare" , "-p" , "-m" , "-f" , "-r" , "mount" , "-t" , "proc" , "none" , "/proc" ) ; err == nil || ! strings . Contains ( out , "Permission denied" ) {
2015-05-04 16:20:01 -04:00
c . Fatalf ( "unshare should have failed with permission denied, got: %s, %v" , out , err )
}
2015-05-28 14:55:22 -04:00
/* Ensure still fails if running privileged with the default policy */
name = "crashoverride"
2015-07-19 16:47:47 -04:00
if out , _ , err := dockerCmdWithError ( c , "run" , "--privileged" , "--security-opt" , "apparmor:docker-default" , "--name" , name , "jess/unshare" , "unshare" , "-p" , "-m" , "-f" , "-r" , "mount" , "-t" , "proc" , "none" , "/proc" ) ; err == nil || ! strings . Contains ( out , "Permission denied" ) {
2015-05-04 16:20:01 -04:00
c . Fatalf ( "unshare should have failed with permission denied, got: %s, %v" , out , err )
}
}
2015-05-17 14:57:17 -04:00
func ( s * DockerSuite ) TestRunPublishPort ( c * check . C ) {
2015-07-19 16:47:47 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , "test" , "--expose" , "8080" , "busybox" , "top" )
out , _ := dockerCmd ( c , "port" , "test" )
2015-05-17 14:57:17 -04:00
out = strings . Trim ( out , "\r\n" )
if out != "" {
c . Fatalf ( "run without --publish-all should not publish port, out should be nil, but got: %s" , out )
}
}
2015-05-29 11:29:56 -04:00
// Issue #10184.
func ( s * DockerSuite ) TestDevicePermissions ( c * check . C ) {
2015-06-01 22:27:54 -04:00
testRequires ( c , NativeExecDriver )
2015-05-29 11:29:56 -04:00
const permissions = "crw-rw-rw-"
out , status := dockerCmd ( c , "run" , "--device" , "/dev/fuse:/dev/fuse:mrw" , "busybox:latest" , "ls" , "-l" , "/dev/fuse" )
if status != 0 {
c . Fatalf ( "expected status 0, got %d" , status )
}
if ! strings . HasPrefix ( out , permissions ) {
c . Fatalf ( "output should begin with %q, got %q" , permissions , out )
}
}
2015-05-27 03:31:06 -04:00
2015-07-03 11:25:52 -04:00
func ( s * DockerSuite ) TestRunCapAddCHOWN ( c * check . C ) {
2015-07-22 12:28:53 -04:00
testRequires ( c , NativeExecDriver )
2015-07-19 16:47:47 -04:00
out , _ := dockerCmd ( c , "run" , "--cap-drop=ALL" , "--cap-add=CHOWN" , "busybox" , "sh" , "-c" , "adduser -D -H newuser && chown newuser /home && echo ok" )
2015-07-03 11:25:52 -04:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
c . Fatalf ( "expected output ok received %s" , actual )
}
}
2015-07-09 10:40:39 -04:00
// https://github.com/docker/docker/pull/14498
func ( s * DockerSuite ) TestVolumeFromMixedRWOptions ( c * check . C ) {
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , "/test" , "busybox" , "true" )
dockerCmd ( c , "run" , "--volumes-from" , "parent:ro" , "--name" , "test-volumes-1" , "busybox" , "true" )
dockerCmd ( c , "run" , "--volumes-from" , "parent:rw" , "--name" , "test-volumes-2" , "busybox" , "true" )
2015-06-03 15:21:38 -04:00
mRO , err := inspectMountPoint ( "test-volumes-1" , "/test" )
2015-07-09 10:40:39 -04:00
c . Assert ( err , check . IsNil )
2015-06-03 15:21:38 -04:00
if mRO . RW {
2015-07-09 10:40:39 -04:00
c . Fatalf ( "Expected RO volume was RW" )
}
2015-06-03 15:21:38 -04:00
mRW , err := inspectMountPoint ( "test-volumes-2" , "/test" )
2015-07-09 10:40:39 -04:00
c . Assert ( err , check . IsNil )
2015-06-03 15:21:38 -04:00
if ! mRW . RW {
2015-07-09 10:40:39 -04:00
c . Fatalf ( "Expected RW volume was RO" )
}
}
2015-05-11 23:00:05 -04:00
func ( s * DockerSuite ) TestRunWriteFilteredProc ( c * check . C ) {
2015-07-24 19:10:59 -04:00
testRequires ( c , Apparmor , NativeExecDriver )
2015-05-11 23:00:05 -04:00
testWritePaths := [ ] string {
/ * modprobe and core_pattern should both be denied by generic
* policy of denials for / proc / sys / kernel . These files have been
* picked to be checked as they are particularly sensitive to writes * /
"/proc/sys/kernel/modprobe" ,
"/proc/sys/kernel/core_pattern" ,
"/proc/sysrq-trigger" ,
}
for i , filePath := range testWritePaths {
name := fmt . Sprintf ( "writeprocsieve-%d" , i )
shellCmd := fmt . Sprintf ( "exec 3>%s" , filePath )
runCmd := exec . Command ( dockerBinary , "run" , "--privileged" , "--security-opt" , "apparmor:docker-default" , "--name" , name , "busybox" , "sh" , "-c" , shellCmd )
if out , exitCode , err := runCommandWithOutput ( runCmd ) ; err == nil || exitCode == 0 {
c . Fatalf ( "Open FD for write should have failed with permission denied, got: %s, %v" , out , err )
}
}
}
2015-07-13 20:54:00 -04:00
func ( s * DockerSuite ) TestRunNetworkFilesBindMount ( c * check . C ) {
testRequires ( c , SameHostDaemon )
name := "test-nwfiles-mount"
f , err := ioutil . TempFile ( "" , name )
c . Assert ( err , check . IsNil )
filename := f . Name ( )
defer os . Remove ( filename )
expected := "test123"
err = ioutil . WriteFile ( filename , [ ] byte ( expected ) , 0644 )
c . Assert ( err , check . IsNil )
var actual string
actual , _ = dockerCmd ( c , "run" , "-v" , filename + ":/etc/resolv.conf" , "busybox" , "cat" , "/etc/resolv.conf" )
if actual != expected {
c . Fatalf ( "expected resolv.conf be: %q, but was: %q" , expected , actual )
}
}
2015-07-22 12:14:48 -04:00
func ( s * DockerTrustSuite ) TestTrustedRun ( c * check . C ) {
2015-07-23 08:12:36 -04:00
repoName := s . setupTrustedImage ( c , "trusted-run" )
2015-07-22 12:14:48 -04:00
// Try run
runCmd := exec . Command ( dockerBinary , "run" , repoName )
s . trustedCmd ( runCmd )
2015-07-23 08:12:36 -04:00
out , _ , err := runCommandWithOutput ( runCmd )
2015-07-22 12:14:48 -04:00
if err != nil {
c . Fatalf ( "Error running trusted run: %s\n%s\n" , err , out )
}
if ! strings . Contains ( string ( out ) , "Tagging" ) {
c . Fatalf ( "Missing expected output on trusted push:\n%s" , out )
}
dockerCmd ( c , "rmi" , repoName )
// Try untrusted run to ensure we pushed the tag to the registry
2015-07-24 04:59:42 -04:00
runCmd = exec . Command ( dockerBinary , "run" , "--disable-content-trust=true" , repoName )
2015-07-22 12:14:48 -04:00
s . trustedCmd ( runCmd )
out , _ , err = runCommandWithOutput ( runCmd )
if err != nil {
c . Fatalf ( "Error running trusted run: %s\n%s" , err , out )
}
if ! strings . Contains ( string ( out ) , "Status: Downloaded" ) {
2015-07-24 04:59:42 -04:00
c . Fatalf ( "Missing expected output on trusted run with --disable-content-trust:\n%s" , out )
2015-07-22 12:14:48 -04:00
}
}
func ( s * DockerTrustSuite ) TestUntrustedRun ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockercli/trusted:latest" , privateRegistryURL )
// tag the image and upload it to the private registry
dockerCmd ( c , "tag" , "busybox" , repoName )
dockerCmd ( c , "push" , repoName )
dockerCmd ( c , "rmi" , repoName )
// Try trusted run on untrusted tag
runCmd := exec . Command ( dockerBinary , "run" , repoName )
s . trustedCmd ( runCmd )
out , _ , err := runCommandWithOutput ( runCmd )
if err == nil {
c . Fatalf ( "Error expected when running trusted run with:\n%s" , out )
}
if ! strings . Contains ( string ( out ) , "no trust data available" ) {
c . Fatalf ( "Missing expected output on trusted run:\n%s" , out )
}
}
func ( s * DockerTrustSuite ) TestRunWhenCertExpired ( c * check . C ) {
2015-07-23 08:12:36 -04:00
repoName := s . setupTrustedImage ( c , "trusted-run-expired" )
2015-07-22 12:14:48 -04:00
// Certificates have 10 years of expiration
elevenYearsFromNow := time . Now ( ) . Add ( time . Hour * 24 * 365 * 11 )
runAtDifferentDate ( elevenYearsFromNow , func ( ) {
// Try run
runCmd := exec . Command ( dockerBinary , "run" , repoName )
s . trustedCmd ( runCmd )
2015-07-23 08:12:36 -04:00
out , _ , err := runCommandWithOutput ( runCmd )
2015-07-22 12:14:48 -04:00
if err == nil {
c . Fatalf ( "Error running trusted run in the distant future: %s\n%s" , err , out )
}
if ! strings . Contains ( string ( out ) , "could not validate the path to a trusted root" ) {
c . Fatalf ( "Missing expected output on trusted run in the distant future:\n%s" , out )
}
} )
runAtDifferentDate ( elevenYearsFromNow , func ( ) {
// Try run
2015-07-24 04:59:42 -04:00
runCmd := exec . Command ( dockerBinary , "run" , "--disable-content-trust" , repoName )
2015-07-22 12:14:48 -04:00
s . trustedCmd ( runCmd )
2015-07-23 08:12:36 -04:00
out , _ , err := runCommandWithOutput ( runCmd )
2015-07-22 12:14:48 -04:00
if err != nil {
c . Fatalf ( "Error running untrusted run in the distant future: %s\n%s" , err , out )
}
if ! strings . Contains ( string ( out ) , "Status: Downloaded" ) {
c . Fatalf ( "Missing expected output on untrusted run in the distant future:\n%s" , out )
}
} )
}
2015-07-22 19:10:25 -04:00
func ( s * DockerTrustSuite ) TestTrustedRunFromBadTrustServer ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockerclievilrun/trusted:latest" , privateRegistryURL )
evilLocalConfigDir , err := ioutil . TempDir ( "" , "evil-local-config-dir" )
if err != nil {
c . Fatalf ( "Failed to create local temp dir" )
}
// tag the image and upload it to the private registry
dockerCmd ( c , "tag" , "busybox" , repoName )
pushCmd := exec . Command ( dockerBinary , "push" , repoName )
s . trustedCmd ( pushCmd )
out , _ , err := runCommandWithOutput ( pushCmd )
if err != nil {
c . Fatalf ( "Error running trusted push: %s\n%s" , err , out )
}
if ! strings . Contains ( string ( out ) , "Signing and pushing trust metadata" ) {
c . Fatalf ( "Missing expected output on trusted push:\n%s" , out )
}
dockerCmd ( c , "rmi" , repoName )
// Try run
runCmd := exec . Command ( dockerBinary , "run" , repoName )
s . trustedCmd ( runCmd )
out , _ , err = runCommandWithOutput ( runCmd )
if err != nil {
c . Fatalf ( "Error running trusted run: %s\n%s" , err , out )
}
if ! strings . Contains ( string ( out ) , "Tagging" ) {
c . Fatalf ( "Missing expected output on trusted push:\n%s" , out )
}
dockerCmd ( c , "rmi" , repoName )
// Kill the notary server, start a new "evil" one.
s . not . Close ( )
s . not , err = newTestNotary ( c )
if err != nil {
c . Fatalf ( "Restarting notary server failed." )
}
// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
// tag an image and upload it to the private registry
dockerCmd ( c , "--config" , evilLocalConfigDir , "tag" , "busybox" , repoName )
// Push up to the new server
pushCmd = exec . Command ( dockerBinary , "--config" , evilLocalConfigDir , "push" , repoName )
s . trustedCmd ( pushCmd )
out , _ , err = runCommandWithOutput ( pushCmd )
if err != nil {
c . Fatalf ( "Error running trusted push: %s\n%s" , err , out )
}
if ! strings . Contains ( string ( out ) , "Signing and pushing trust metadata" ) {
c . Fatalf ( "Missing expected output on trusted push:\n%s" , out )
}
// Now, try running with the original client from this new trust server. This should fail.
runCmd = exec . Command ( dockerBinary , "run" , repoName )
s . trustedCmd ( runCmd )
out , _ , err = runCommandWithOutput ( runCmd )
if err == nil {
c . Fatalf ( "Expected to fail on this run due to different remote data: %s\n%s" , err , out )
}
2015-07-22 21:46:59 -04:00
if ! strings . Contains ( string ( out ) , "failed to validate data with current trusted certificates" ) {
2015-07-22 19:10:25 -04:00
c . Fatalf ( "Missing expected output on trusted push:\n%s" , out )
}
}