2014-12-31 01:22:31 +03:00
// +build !test_no_exec
2014-09-19 01:36:34 +04:00
package main
import (
"bufio"
2015-01-15 21:37:30 +03:00
"fmt"
2015-07-10 06:57:03 +03:00
"net/http"
2014-11-06 02:12:24 +03:00
"os"
2014-09-19 01:36:34 +04:00
"os/exec"
2015-01-19 23:11:19 +03:00
"path/filepath"
2015-01-15 21:37:30 +03:00
"reflect"
"sort"
2014-09-19 01:36:34 +04:00
"strings"
2015-01-15 21:37:30 +03:00
"sync"
2014-09-19 01:36:34 +04:00
"time"
2015-04-18 19:46:47 +03:00
2015-09-29 05:09:04 +03:00
"github.com/docker/docker/pkg/integration/checker"
2015-04-18 19:46:47 +03:00
"github.com/go-check/check"
2014-09-19 01:36:34 +04:00
)
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExec ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "testing" , "busybox" , "sh" , "-c" , "echo test > /tmp/file && top" )
2015-02-20 09:56:02 +03:00
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "exec" , "testing" , "cat" , "/tmp/file" )
2014-09-19 01:36:34 +04:00
out = strings . Trim ( out , "\r\n" )
2015-10-22 02:58:19 +03:00
c . Assert ( out , checker . Equals , "test" )
2014-09-19 01:36:34 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecInteractive ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "testing" , "busybox" , "sh" , "-c" , "echo test > /tmp/file && top" )
2014-09-19 01:36:34 +04:00
execCmd := exec . Command ( dockerBinary , "exec" , "-i" , "testing" , "sh" )
stdin , err := execCmd . StdinPipe ( )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2014-09-19 01:36:34 +04:00
stdout , err := execCmd . StdoutPipe ( )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2014-09-19 01:36:34 +04:00
2015-10-22 02:58:19 +03:00
err = execCmd . Start ( )
c . Assert ( err , checker . IsNil )
_ , err = stdin . Write ( [ ] byte ( "cat /tmp/file\n" ) )
c . Assert ( err , checker . IsNil )
2014-09-19 01:36:34 +04:00
r := bufio . NewReader ( stdout )
line , err := r . ReadString ( '\n' )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2014-09-19 01:36:34 +04:00
line = strings . TrimSpace ( line )
2015-10-22 02:58:19 +03:00
c . Assert ( line , checker . Equals , "test" )
err = stdin . Close ( )
c . Assert ( err , checker . IsNil )
2015-04-27 20:29:48 +03:00
errChan := make ( chan error )
2014-09-19 01:36:34 +04:00
go func ( ) {
2015-04-27 20:29:48 +03:00
errChan <- execCmd . Wait ( )
close ( errChan )
2014-09-19 01:36:34 +04:00
} ( )
select {
2015-04-27 20:29:48 +03:00
case err := <- errChan :
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2014-09-19 01:36:34 +04:00
case <- time . After ( 1 * time . Second ) :
2015-04-18 19:46:47 +03:00
c . Fatal ( "docker exec failed to exit on stdin close" )
2014-09-19 01:36:34 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecAfterContainerRestart ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2015-04-06 16:21:18 +03:00
cleanedContainerID := strings . TrimSpace ( out )
2015-10-25 15:35:05 +03:00
c . Assert ( waitRun ( cleanedContainerID ) , check . IsNil )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "restart" , cleanedContainerID )
2015-10-25 15:35:05 +03:00
c . Assert ( waitRun ( cleanedContainerID ) , check . IsNil )
2014-09-19 01:36:34 +04:00
2015-07-20 09:55:40 +03:00
out , _ = dockerCmd ( c , "exec" , cleanedContainerID , "echo" , "hello" )
2014-09-19 01:36:34 +04:00
outStr := strings . TrimSpace ( out )
2015-10-22 02:58:19 +03:00
c . Assert ( outStr , checker . Equals , "hello" )
2014-09-19 01:36:34 +04:00
}
2015-04-26 05:47:42 +03:00
func ( s * DockerDaemonSuite ) TestExecAfterDaemonRestart ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-04-18 19:46:47 +03:00
testRequires ( c , SameHostDaemon )
2015-02-20 09:56:02 +03:00
2015-10-22 02:58:19 +03:00
err := s . d . StartWithBusybox ( )
c . Assert ( err , checker . IsNil )
2014-09-19 01:36:34 +04:00
2015-10-22 02:58:19 +03:00
out , err := s . d . Cmd ( "run" , "-d" , "--name" , "top" , "-p" , "80" , "busybox:latest" , "top" )
c . Assert ( err , checker . IsNil , check . Commentf ( "Could not run top: %s" , out ) )
2014-09-19 01:36:34 +04:00
2015-10-22 02:58:19 +03:00
err = s . d . Restart ( )
c . Assert ( err , checker . IsNil , check . Commentf ( "Could not restart daemon" ) )
2014-09-19 01:36:34 +04:00
2015-10-22 02:58:19 +03:00
out , err = s . d . Cmd ( "start" , "top" )
c . Assert ( err , checker . IsNil , check . Commentf ( "Could not start top after daemon restart: %s" , out ) )
2014-09-19 01:36:34 +04:00
2015-10-22 02:58:19 +03:00
out , err = s . d . Cmd ( "exec" , "top" , "echo" , "hello" )
c . Assert ( err , checker . IsNil , check . Commentf ( "Could not exec on container top: %s" , out ) )
2014-09-19 01:36:34 +04:00
outStr := strings . TrimSpace ( string ( out ) )
2015-10-22 02:58:19 +03:00
c . Assert ( outStr , checker . Equals , "hello" )
2014-09-19 01:36:34 +04:00
}
2014-11-14 20:37:04 +03:00
2015-03-13 12:12:02 +03:00
// Regression test for #9155, #9044
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecEnv ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-e" , "LALA=value1" , "-e" , "LALA=value2" ,
2014-11-14 20:37:04 +03:00
"-d" , "--name" , "testing" , "busybox" , "top" )
2015-10-24 16:22:23 +03:00
c . Assert ( waitRun ( "testing" ) , check . IsNil )
2014-11-14 20:37:04 +03:00
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "exec" , "testing" , "env" )
2015-10-22 02:58:19 +03:00
c . Assert ( out , checker . Not ( checker . Contains ) , "LALA=value1" )
c . Assert ( out , checker . Contains , "LALA=value2" )
c . Assert ( out , checker . Contains , "HOME=/root" )
2014-11-14 20:37:04 +03:00
}
2014-11-18 02:50:09 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecExitStatus ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "top" , "busybox" , "top" )
2014-11-18 02:50:09 +03:00
// Test normal (non-detached) case first
cmd := exec . Command ( dockerBinary , "exec" , "top" , "sh" , "-c" , "exit 23" )
ec , _ := runCommand ( cmd )
2015-10-22 02:58:19 +03:00
c . Assert ( ec , checker . Equals , 23 )
2014-11-18 02:50:09 +03:00
}
2014-11-27 19:08:39 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecPausedContainer ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2014-11-27 19:08:39 +03:00
defer unpauseAllContainers ( )
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "run" , "-d" , "--name" , "testing" , "busybox" , "top" )
2015-04-06 16:21:18 +03:00
ContainerID := strings . TrimSpace ( out )
2014-11-27 19:08:39 +03:00
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "pause" , "testing" )
2015-07-27 21:13:25 +03:00
out , _ , err := dockerCmdWithError ( "exec" , "-i" , "-t" , ContainerID , "echo" , "hello" )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . NotNil , check . Commentf ( "container should fail to exec new conmmand if it is paused" ) )
2014-11-27 19:08:39 +03:00
expected := ContainerID + " is paused, unpause the container before exec"
2015-10-22 02:58:19 +03:00
c . Assert ( out , checker . Contains , expected , check . Commentf ( "container should not exec new command if it is paused" ) )
2014-11-27 19:08:39 +03:00
}
2014-12-04 04:27:39 +03:00
// regression test for #9476
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecTtyCloseStdin ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "-it" , "--name" , "exec_tty_stdin" , "busybox" )
2014-12-04 04:27:39 +03:00
2015-07-20 09:55:40 +03:00
cmd := exec . Command ( dockerBinary , "exec" , "-i" , "exec_tty_stdin" , "cat" )
2014-12-04 04:27:39 +03:00
stdinRw , err := cmd . StdinPipe ( )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2014-12-04 04:27:39 +03:00
stdinRw . Write ( [ ] byte ( "test" ) )
stdinRw . Close ( )
2015-10-22 02:58:19 +03:00
out , _ , err := runCommandWithOutput ( cmd )
c . Assert ( err , checker . IsNil , check . Commentf ( out ) )
2014-12-04 04:27:39 +03:00
2015-10-22 02:58:19 +03:00
out , _ = dockerCmd ( c , "top" , "exec_tty_stdin" )
2014-12-04 04:27:39 +03:00
outArr := strings . Split ( out , "\n" )
2015-10-22 02:58:19 +03:00
c . Assert ( len ( outArr ) , checker . LessOrEqualThan , 3 , check . Commentf ( "exec process left running" ) )
c . Assert ( out , checker . Not ( checker . Contains ) , "nsenter-exec" )
2014-12-04 04:27:39 +03:00
}
2014-12-06 03:50:56 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecTtyWithoutStdin ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "run" , "-d" , "-ti" , "busybox" )
2014-12-06 03:50:56 +03:00
id := strings . TrimSpace ( out )
2015-10-22 02:58:19 +03:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2014-12-06 03:50:56 +03:00
2015-04-27 20:29:48 +03:00
errChan := make ( chan error )
2014-12-06 03:50:56 +03:00
go func ( ) {
2015-04-27 20:29:48 +03:00
defer close ( errChan )
2014-12-06 03:50:56 +03:00
cmd := exec . Command ( dockerBinary , "exec" , "-ti" , id , "true" )
if _ , err := cmd . StdinPipe ( ) ; err != nil {
2015-04-27 20:29:48 +03:00
errChan <- err
return
2014-12-06 03:50:56 +03:00
}
expected := "cannot enable tty mode"
if out , _ , err := runCommandWithOutput ( cmd ) ; err == nil {
2015-04-27 20:29:48 +03:00
errChan <- fmt . Errorf ( "exec should have failed" )
return
2014-12-06 03:50:56 +03:00
} else if ! strings . Contains ( out , expected ) {
2015-04-27 20:29:48 +03:00
errChan <- fmt . Errorf ( "exec failed with error %q: expected %q" , out , expected )
return
2014-12-06 03:50:56 +03:00
}
} ( )
select {
2015-04-27 20:29:48 +03:00
case err := <- errChan :
c . Assert ( err , check . IsNil )
2014-12-06 03:50:56 +03:00
case <- time . After ( 3 * time . Second ) :
2015-04-18 19:46:47 +03:00
c . Fatal ( "exec is running but should have failed" )
2014-12-06 03:50:56 +03:00
}
}
2014-12-23 22:16:23 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecParseError ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "top" , "busybox" , "top" )
2014-12-23 22:16:23 +03:00
// Test normal (non-detached) case first
cmd := exec . Command ( dockerBinary , "exec" , "top" )
2015-10-22 02:58:19 +03:00
_ , stderr , _ , err := runCommandWithStdoutStderr ( cmd )
c . Assert ( err , checker . NotNil )
c . Assert ( stderr , checker . Contains , "See '" + dockerBinary + " exec --help'" )
2014-12-23 22:16:23 +03:00
}
2014-12-27 04:19:23 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecStopNotHanging ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "testing" , "busybox" , "top" )
2014-12-27 04:19:23 +03:00
2015-10-22 02:58:19 +03:00
err := exec . Command ( dockerBinary , "exec" , "testing" , "top" ) . Start ( )
c . Assert ( err , checker . IsNil )
2014-12-27 04:19:23 +03:00
2015-04-27 20:29:48 +03:00
type dstop struct {
out [ ] byte
err error
}
ch := make ( chan dstop )
2014-12-27 04:19:23 +03:00
go func ( ) {
2015-04-27 20:29:48 +03:00
out , err := exec . Command ( dockerBinary , "stop" , "testing" ) . CombinedOutput ( )
ch <- dstop { out , err }
close ( ch )
2014-12-27 04:19:23 +03:00
} ( )
select {
case <- time . After ( 3 * time . Second ) :
2015-04-18 19:46:47 +03:00
c . Fatal ( "Container stop timed out" )
2015-04-27 20:29:48 +03:00
case s := <- ch :
c . Assert ( s . err , check . IsNil )
2014-12-27 04:19:23 +03:00
}
}
2015-01-15 21:37:30 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecCgroup ( c * check . C ) {
2015-09-18 20:41:12 +03:00
testRequires ( c , NotUserNamespace )
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "testing" , "busybox" , "top" )
2015-01-15 21:37:30 +03:00
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "exec" , "testing" , "cat" , "/proc/1/cgroup" )
containerCgroups := sort . StringSlice ( strings . Split ( out , "\n" ) )
2015-01-15 21:37:30 +03:00
var wg sync . WaitGroup
2015-04-18 19:46:47 +03:00
var mu sync . Mutex
2015-01-15 21:37:30 +03:00
execCgroups := [ ] sort . StringSlice { }
2015-04-27 20:29:48 +03:00
errChan := make ( chan error )
2015-01-15 21:37:30 +03:00
// exec a few times concurrently to get consistent failure
for i := 0 ; i < 5 ; i ++ {
wg . Add ( 1 )
go func ( ) {
2015-07-27 21:13:25 +03:00
out , _ , err := dockerCmdWithError ( "exec" , "testing" , "cat" , "/proc/self/cgroup" )
2015-01-15 21:37:30 +03:00
if err != nil {
2015-04-27 20:29:48 +03:00
errChan <- err
return
2015-01-15 21:37:30 +03:00
}
2015-07-20 09:55:40 +03:00
cg := sort . StringSlice ( strings . Split ( out , "\n" ) )
2015-01-15 21:37:30 +03:00
2015-04-18 19:46:47 +03:00
mu . Lock ( )
2015-01-15 21:37:30 +03:00
execCgroups = append ( execCgroups , cg )
2015-04-18 19:46:47 +03:00
mu . Unlock ( )
2015-01-15 21:37:30 +03:00
wg . Done ( )
} ( )
}
wg . Wait ( )
2015-04-27 20:29:48 +03:00
close ( errChan )
for err := range errChan {
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-04-27 20:29:48 +03:00
}
2015-01-15 21:37:30 +03:00
for _ , cg := range execCgroups {
if ! reflect . DeepEqual ( cg , containerCgroups ) {
fmt . Println ( "exec cgroups:" )
for _ , name := range cg {
fmt . Printf ( " %s\n" , name )
}
fmt . Println ( "container cgroups:" )
for _ , name := range containerCgroups {
fmt . Printf ( " %s\n" , name )
}
2015-04-18 19:46:47 +03:00
c . Fatal ( "cgroups mismatched" )
2015-01-15 21:37:30 +03:00
}
}
}
2014-12-31 01:05:00 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestInspectExecID ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-12-31 01:05:00 +03:00
id := strings . TrimSuffix ( out , "\n" )
2015-07-20 09:55:40 +03:00
out , err := inspectField ( id , "ExecIDs" )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil , check . Commentf ( "failed to inspect container: %s" , out ) )
c . Assert ( out , checker . Equals , "[]" , check . Commentf ( "ExecIDs should be empty, got: %s" , out ) )
2014-12-31 01:05:00 +03:00
2015-08-04 14:08:30 +03:00
// Start an exec, have it block waiting so we can do some checking
cmd := exec . Command ( dockerBinary , "exec" , id , "sh" , "-c" ,
"while ! test -e /tmp/execid1; do sleep 1; done" )
2015-07-10 06:57:03 +03:00
2015-10-22 02:58:19 +03:00
err = cmd . Start ( )
c . Assert ( err , checker . IsNil , check . Commentf ( "failed to start the exec cmd" ) )
2015-07-10 06:57:03 +03:00
// Give the exec 10 chances/seconds to start then give up and stop the test
tries := 10
for i := 0 ; i < tries ; i ++ {
2015-07-18 03:30:24 +03:00
// Since its still running we should see exec as part of the container
out , err = inspectField ( id , "ExecIDs" )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil , check . Commentf ( "failed to inspect container: %s" , out ) )
2015-07-18 03:30:24 +03:00
2015-07-10 06:57:03 +03:00
out = strings . TrimSuffix ( out , "\n" )
if out != "[]" && out != "<no value>" {
break
}
2015-10-22 02:58:19 +03:00
c . Assert ( i + 1 , checker . Not ( checker . Equals ) , tries , check . Commentf ( "ExecIDs should be empty, got: %s" , out ) )
2015-07-10 06:57:03 +03:00
time . Sleep ( 1 * time . Second )
}
// Save execID for later
execID , err := inspectFilter ( id , "index .ExecIDs 0" )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil , check . Commentf ( "failed to get the exec id" ) )
2014-12-31 01:05:00 +03:00
2015-08-04 14:08:30 +03:00
// End the exec by creating the missing file
err = exec . Command ( dockerBinary , "exec" , id ,
"sh" , "-c" , "touch /tmp/execid1" ) . Run ( )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil , check . Commentf ( "failed to run the 2nd exec cmd" ) )
2015-08-04 14:08:30 +03:00
// Wait for 1st exec to complete
2015-07-10 06:57:03 +03:00
cmd . Wait ( )
// All execs for the container should be gone now
2014-12-31 01:05:00 +03:00
out , err = inspectField ( id , "ExecIDs" )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil , check . Commentf ( "failed to inspect container: %s" , out ) )
2014-12-31 01:05:00 +03:00
out = strings . TrimSuffix ( out , "\n" )
2015-10-22 02:58:19 +03:00
c . Assert ( out == "[]" || out == "<no value>" , checker . True )
2015-07-10 06:57:03 +03:00
// But we should still be able to query the execID
sc , body , err := sockRequest ( "GET" , "/exec/" + execID + "/json" , nil )
2015-10-22 02:58:19 +03:00
c . Assert ( sc , checker . Equals , http . StatusOK , check . Commentf ( "received status != 200 OK: %d\n%s" , sc , body ) )
2015-07-10 05:39:57 +03:00
// Now delete the container and then an 'inspect' on the exec should
// result in a 404 (not 'container not running')
out , ec := dockerCmd ( c , "rm" , "-f" , id )
2015-10-22 02:58:19 +03:00
c . Assert ( ec , checker . Equals , 0 , check . Commentf ( "error removing container: %s" , out ) )
2015-07-10 05:39:57 +03:00
sc , body , err = sockRequest ( "GET" , "/exec/" + execID + "/json" , nil )
2015-10-22 02:58:19 +03:00
c . Assert ( sc , checker . Equals , http . StatusNotFound , check . Commentf ( "received status != 404: %d\n%s" , sc , body ) )
2014-12-31 01:05:00 +03:00
}
2015-01-19 23:11:19 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestLinksPingLinkedContainersOnRename ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-01-19 23:11:19 +03:00
var out string
2015-04-18 19:46:47 +03:00
out , _ = dockerCmd ( c , "run" , "-d" , "--name" , "container1" , "busybox" , "top" )
2015-04-06 16:21:18 +03:00
idA := strings . TrimSpace ( out )
2015-10-22 02:58:19 +03:00
c . Assert ( idA , checker . Not ( checker . Equals ) , "" , check . Commentf ( "%s, id should not be nil" , out ) )
2015-04-18 19:46:47 +03:00
out , _ = dockerCmd ( c , "run" , "-d" , "--link" , "container1:alias1" , "--name" , "container2" , "busybox" , "top" )
2015-04-06 16:21:18 +03:00
idB := strings . TrimSpace ( out )
2015-10-22 02:58:19 +03:00
c . Assert ( idB , checker . Not ( checker . Equals ) , "" , check . Commentf ( "%s, id should not be nil" , out ) )
2015-01-19 23:11:19 +03:00
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "exec" , "container2" , "ping" , "-c" , "1" , "alias1" , "-W" , "1" )
2015-04-18 19:46:47 +03:00
dockerCmd ( c , "rename" , "container1" , "container_new" )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "exec" , "container2" , "ping" , "-c" , "1" , "alias1" , "-W" , "1" )
2015-01-19 23:11:19 +03:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestRunExecDir ( c * check . C ) {
2015-09-24 02:04:51 +03:00
testRequires ( c , SameHostDaemon , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2015-01-19 23:11:19 +03:00
id := strings . TrimSpace ( out )
execDir := filepath . Join ( execDriverPath , id )
stateFile := filepath . Join ( execDir , "state.json" )
{
fi , err := os . Stat ( execDir )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-01-19 23:11:19 +03:00
if ! fi . IsDir ( ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%q must be a directory" , execDir )
2015-01-19 23:11:19 +03:00
}
fi , err = os . Stat ( stateFile )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-01-19 23:11:19 +03:00
}
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "stop" , id )
2015-01-19 23:11:19 +03:00
{
2015-03-05 20:55:14 +03:00
_ , err := os . Stat ( execDir )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . NotNil )
c . Assert ( err , checker . NotNil , check . Commentf ( "Exec directory %q exists for removed container!" , execDir ) )
2015-01-19 23:11:19 +03:00
if ! os . IsNotExist ( err ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error should be about non-existing, got %s" , err )
2015-01-19 23:11:19 +03:00
}
}
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "start" , id )
2015-01-19 23:11:19 +03:00
{
fi , err := os . Stat ( execDir )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-01-19 23:11:19 +03:00
if ! fi . IsDir ( ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%q must be a directory" , execDir )
2015-01-19 23:11:19 +03:00
}
fi , err = os . Stat ( stateFile )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-01-19 23:11:19 +03:00
}
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "rm" , "-f" , id )
2015-01-19 23:11:19 +03:00
{
_ , err := os . Stat ( execDir )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . NotNil , check . Commentf ( "Exec directory %q exists for removed container!" , execDir ) )
2015-01-19 23:11:19 +03:00
if ! os . IsNotExist ( err ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error should be about non-existing, got %s" , err )
2015-01-19 23:11:19 +03:00
}
}
}
2015-01-27 04:17:08 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestRunMutableNetworkFiles ( c * check . C ) {
2015-09-24 02:04:51 +03:00
testRequires ( c , SameHostDaemon , DaemonIsLinux )
2015-01-27 04:17:08 +03:00
for _ , fn := range [ ] string { "resolv.conf" , "hosts" } {
deleteAllContainers ( )
content , err := runCommandAndReadContainerFile ( fn , exec . Command ( dockerBinary , "run" , "-d" , "--name" , "c1" , "busybox" , "sh" , "-c" , fmt . Sprintf ( "echo success >/etc/%s && top" , fn ) ) )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-01-27 04:17:08 +03:00
2015-10-22 02:58:19 +03:00
c . Assert ( strings . TrimSpace ( string ( content ) ) , checker . Equals , "success" , check . Commentf ( "Content was not what was modified in the container" , string ( content ) ) )
2015-01-27 04:17:08 +03:00
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "run" , "-d" , "--name" , "c2" , "busybox" , "top" )
2015-01-27 04:17:08 +03:00
contID := strings . TrimSpace ( out )
netFilePath := containerStorageFile ( contID , fn )
f , err := os . OpenFile ( netFilePath , os . O_WRONLY | os . O_SYNC | os . O_APPEND , 0644 )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-01-27 04:17:08 +03:00
if _ , err := f . Seek ( 0 , 0 ) ; err != nil {
f . Close ( )
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-27 04:17:08 +03:00
}
if err := f . Truncate ( 0 ) ; err != nil {
f . Close ( )
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-27 04:17:08 +03:00
}
if _ , err := f . Write ( [ ] byte ( "success2\n" ) ) ; err != nil {
f . Close ( )
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-27 04:17:08 +03:00
}
f . Close ( )
2015-07-20 09:55:40 +03:00
res , _ := dockerCmd ( c , "exec" , contID , "cat" , "/etc/" + fn )
2015-10-22 02:58:19 +03:00
c . Assert ( res , checker . Equals , "success2\n" )
2015-01-27 04:17:08 +03:00
}
}
2015-04-11 06:04:24 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestExecWithUser ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-07-20 09:55:40 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "parent" , "busybox" , "top" )
2015-04-11 06:04:24 +03:00
2015-07-20 09:55:40 +03:00
out , _ := dockerCmd ( c , "exec" , "-u" , "1" , "parent" , "id" )
2015-10-22 02:58:19 +03:00
c . Assert ( out , checker . Contains , "uid=1(daemon) gid=1(daemon)" )
2015-04-11 06:04:24 +03:00
2015-07-20 09:55:40 +03:00
out , _ = dockerCmd ( c , "exec" , "-u" , "root" , "parent" , "id" )
2015-10-22 02:58:19 +03:00
c . Assert ( out , checker . Contains , "uid=0(root) gid=0(root)" , check . Commentf ( "exec with user by id expected daemon user got %s" , out ) )
2015-04-11 06:04:24 +03:00
}
2015-06-27 01:06:37 +03:00
2015-06-19 09:01:50 +03:00
func ( s * DockerSuite ) TestExecWithPrivileged ( c * check . C ) {
2015-09-18 20:41:12 +03:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-06-22 06:06:07 +03:00
// Start main loop which attempts mknod repeatedly
dockerCmd ( c , "run" , "-d" , "--name" , "parent" , "--cap-drop=ALL" , "busybox" , "sh" , "-c" , ` while (true); do if [ -e /exec_priv ]; then cat /exec_priv && mknod /tmp/sda b 8 0 && echo "Success"; else echo "Privileged exec has not run yet"; fi; usleep 10000; done ` )
2015-06-19 09:01:50 +03:00
2015-06-22 06:06:07 +03:00
// Check exec mknod doesn't work
cmd := exec . Command ( dockerBinary , "exec" , "parent" , "sh" , "-c" , "mknod /tmp/sdb b 8 16" )
2015-06-19 09:01:50 +03:00
out , _ , err := runCommandWithOutput ( cmd )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . NotNil , check . Commentf ( "exec mknod in --cap-drop=ALL container without --privileged should fail" ) )
c . Assert ( out , checker . Contains , "Operation not permitted" , check . Commentf ( "exec mknod in --cap-drop=ALL container without --privileged should fail" ) )
2015-06-19 09:01:50 +03:00
2015-06-22 06:06:07 +03:00
// Check exec mknod does work with --privileged
cmd = exec . Command ( dockerBinary , "exec" , "--privileged" , "parent" , "sh" , "-c" , ` echo "Running exec --privileged" > /exec_priv && mknod /tmp/sdb b 8 16 && usleep 50000 && echo "Finished exec --privileged" > /exec_priv && echo ok ` )
2015-06-19 09:01:50 +03:00
out , _ , err = runCommandWithOutput ( cmd )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-06-19 09:01:50 +03:00
2015-10-22 02:58:19 +03:00
actual := strings . TrimSpace ( out )
c . Assert ( actual , checker . Equals , "ok" , check . Commentf ( "exec mknod in --cap-drop=ALL container with --privileged failed, output: %q" , out ) )
2015-06-19 09:01:50 +03:00
2015-06-22 06:06:07 +03:00
// Check subsequent unprivileged exec cannot mknod
cmd = exec . Command ( dockerBinary , "exec" , "parent" , "sh" , "-c" , "mknod /tmp/sdc b 8 32" )
out , _ , err = runCommandWithOutput ( cmd )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . NotNil , check . Commentf ( "repeating exec mknod in --cap-drop=ALL container after --privileged without --privileged should fail" ) )
c . Assert ( out , checker . Contains , "Operation not permitted" , check . Commentf ( "repeating exec mknod in --cap-drop=ALL container after --privileged without --privileged should fail" ) )
2015-06-22 06:06:07 +03:00
// Confirm at no point was mknod allowed
logCmd := exec . Command ( dockerBinary , "logs" , "parent" )
2015-10-22 02:58:19 +03:00
out , _ , err = runCommandWithOutput ( logCmd )
c . Assert ( err , checker . IsNil )
c . Assert ( out , checker . Not ( checker . Contains ) , "Success" )
2015-06-22 06:06:07 +03:00
2015-06-19 09:01:50 +03:00
}
2015-06-27 01:06:37 +03:00
func ( s * DockerSuite ) TestExecWithImageUser ( c * check . C ) {
2015-08-28 20:36:42 +03:00
testRequires ( c , DaemonIsLinux )
2015-06-27 01:06:37 +03:00
name := "testbuilduser"
_ , err := buildImage ( name ,
` FROM busybox
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
USER dockerio ` ,
true )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . IsNil )
2015-06-27 01:06:37 +03:00
dockerCmd ( c , "run" , "-d" , "--name" , "dockerioexec" , name , "top" )
out , _ := dockerCmd ( c , "exec" , "dockerioexec" , "whoami" )
2015-10-22 02:58:19 +03:00
c . Assert ( out , checker . Contains , "dockerio" , check . Commentf ( "exec with user by id expected dockerio user got %s" , out ) )
2015-06-27 01:06:37 +03:00
}
2015-07-30 20:26:45 +03:00
func ( s * DockerSuite ) TestExecOnReadonlyContainer ( c * check . C ) {
2015-09-18 20:41:12 +03:00
// --read-only + userns has remount issues
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-30 20:26:45 +03:00
dockerCmd ( c , "run" , "-d" , "--read-only" , "--name" , "parent" , "busybox" , "top" )
2015-10-22 02:58:19 +03:00
dockerCmd ( c , "exec" , "parent" , "true" )
2015-07-30 20:26:45 +03:00
}
2015-08-21 15:39:26 +03:00
// #15750
func ( s * DockerSuite ) TestExecStartFails ( c * check . C ) {
2015-10-08 23:58:27 +03:00
testRequires ( c , DaemonIsLinux )
2015-08-21 15:39:26 +03:00
name := "exec-15750"
dockerCmd ( c , "run" , "-d" , "--name" , name , "busybox" , "top" )
2015-10-22 02:58:19 +03:00
c . Assert ( waitRun ( name ) , checker . IsNil )
2015-08-21 15:39:26 +03:00
2015-09-29 05:09:04 +03:00
out , _ , err := dockerCmdWithError ( "exec" , name , "no-such-cmd" )
2015-10-22 02:58:19 +03:00
c . Assert ( err , checker . NotNil , check . Commentf ( out ) )
2015-09-29 05:09:04 +03:00
c . Assert ( out , checker . Contains , "executable file not found" )
2015-08-21 15:39:26 +03:00
}