2014-10-14 17:32:25 -04:00
package main
import (
2015-05-01 18:01:10 -04:00
"archive/tar"
2014-10-14 17:32:25 -04:00
"bytes"
"encoding/json"
2015-07-24 17:12:55 -04:00
"fmt"
2014-10-14 17:32:25 -04:00
"io"
2015-04-14 04:00:46 -04:00
"net/http"
2015-04-29 13:48:30 -04:00
"net/http/httputil"
2015-07-24 17:12:55 -04:00
"net/url"
2015-05-03 08:54:55 -04:00
"os"
2015-11-26 07:14:09 -05:00
"regexp"
2015-06-12 12:49:53 -04:00
"strconv"
2014-12-12 11:01:05 -05:00
"strings"
2015-01-19 19:10:26 -05:00
"time"
2015-04-11 17:49:14 -04:00
"github.com/docker/docker/api/types"
2015-09-09 09:36:44 -04:00
"github.com/docker/docker/pkg/integration"
2015-11-18 19:37:42 -05:00
"github.com/docker/docker/pkg/integration/checker"
2015-04-11 17:49:14 -04:00
"github.com/docker/docker/pkg/stringid"
2015-04-25 04:53:38 -04:00
"github.com/docker/docker/runconfig"
2015-04-18 12:46:47 -04:00
"github.com/go-check/check"
2014-10-14 17:32:25 -04:00
)
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiGetAll ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2014-10-14 17:32:25 -04:00
startCount , err := getContainerCount ( )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil , check . Commentf ( "Cannot query container count" ) )
2014-10-14 17:32:25 -04:00
2014-10-21 18:48:32 -04:00
name := "getall"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name" , name , "busybox" , "true" )
2014-10-14 17:32:25 -04:00
2015-04-20 17:03:56 -04:00
status , body , err := sockRequest ( "GET" , "/containers/json?all=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2014-10-14 17:32:25 -04:00
2014-10-21 18:48:32 -04:00
var inspectJSON [ ] struct {
Names [ ] string
}
2015-11-18 19:37:42 -05:00
err = json . Unmarshal ( body , & inspectJSON )
c . Assert ( err , checker . IsNil , check . Commentf ( "unable to unmarshal response body" ) )
2014-10-14 17:32:25 -04:00
2015-11-18 19:37:42 -05:00
c . Assert ( inspectJSON , checker . HasLen , startCount + 1 )
2014-10-21 18:48:32 -04:00
2015-11-18 19:37:42 -05:00
actual := inspectJSON [ 0 ] . Names [ 0 ]
c . Assert ( actual , checker . Equals , "/" + name )
2014-10-14 17:32:25 -04:00
}
2015-06-03 12:23:14 -04:00
// regression test for empty json field being omitted #13691
func ( s * DockerSuite ) TestContainerApiGetJSONNoFieldsOmitted ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "busybox" , "true" )
2015-06-03 12:23:14 -04:00
status , body , err := sockRequest ( "GET" , "/containers/json?all=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-06-03 12:23:14 -04:00
// empty Labels field triggered this bug, make sense to check for everything
// cause even Ports for instance can trigger this bug
// better safe than sorry..
fields := [ ] string {
"Id" ,
"Names" ,
"Image" ,
"Command" ,
"Created" ,
"Ports" ,
"Labels" ,
"Status" ,
}
// decoding into types.Container do not work since it eventually unmarshal
// and empty field to an empty go map, so we just check for a string
for _ , f := range fields {
if ! strings . Contains ( string ( body ) , f ) {
c . Fatalf ( "Field %s is missing and it shouldn't" , f )
}
}
}
2015-06-12 12:49:53 -04:00
type containerPs struct {
Names [ ] string
Ports [ ] map [ string ] interface { }
}
// regression test for non-empty fields from #13901
func ( s * DockerSuite ) TestContainerPsOmitFields ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-06-12 12:49:53 -04:00
name := "pstest"
port := 80
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , name , "--expose" , strconv . Itoa ( port ) , "busybox" , "top" )
2015-06-12 12:49:53 -04:00
status , body , err := sockRequest ( "GET" , "/containers/json?all=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-06-12 12:49:53 -04:00
var resp [ ] containerPs
err = json . Unmarshal ( body , & resp )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-06-12 12:49:53 -04:00
var foundContainer * containerPs
for _ , container := range resp {
for _ , testName := range container . Names {
if "/" + name == testName {
foundContainer = & container
break
}
}
}
2015-11-18 19:37:42 -05:00
c . Assert ( foundContainer . Ports , checker . HasLen , 1 )
c . Assert ( foundContainer . Ports [ 0 ] [ "PrivatePort" ] , checker . Equals , float64 ( port ) )
2015-06-12 12:49:53 -04:00
_ , ok := foundContainer . Ports [ 0 ] [ "PublicPort" ]
2015-11-18 19:37:42 -05:00
c . Assert ( ok , checker . Not ( checker . Equals ) , true )
2015-06-12 12:49:53 -04:00
_ , ok = foundContainer . Ports [ 0 ] [ "IP" ]
2015-11-18 19:37:42 -05:00
c . Assert ( ok , checker . Not ( checker . Equals ) , true )
2015-06-12 12:49:53 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiGetExport ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2014-10-21 18:48:32 -04:00
name := "exportcontainer"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name" , name , "busybox" , "touch" , "/test" )
2014-10-14 17:32:25 -04:00
2015-04-20 17:03:56 -04:00
status , body , err := sockRequest ( "GET" , "/containers/" + name + "/export" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2014-10-14 17:32:25 -04:00
found := false
for tarReader := tar . NewReader ( bytes . NewReader ( body ) ) ; ; {
h , err := tarReader . Next ( )
2015-11-18 19:37:42 -05:00
if err != nil && err == io . EOF {
break
2014-10-14 17:32:25 -04:00
}
if h . Name == "test" {
found = true
break
}
}
2015-11-18 19:37:42 -05:00
c . Assert ( found , checker . True , check . Commentf ( "The created test file has not been found in the exported image" ) )
2014-10-14 17:32:25 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiGetChanges ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2014-10-21 18:48:32 -04:00
name := "changescontainer"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name" , name , "busybox" , "rm" , "/etc/passwd" )
2014-10-14 17:32:25 -04:00
2015-04-20 17:03:56 -04:00
status , body , err := sockRequest ( "GET" , "/containers/" + name + "/changes" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2014-10-14 17:32:25 -04:00
changes := [ ] struct {
Kind int
Path string
} { }
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & changes ) , checker . IsNil , check . Commentf ( "unable to unmarshal response body" ) )
2014-10-14 17:32:25 -04:00
// Check the changelog for removal of /etc/passwd
success := false
for _ , elem := range changes {
if elem . Path == "/etc/passwd" && elem . Kind == 2 {
success = true
}
}
2015-11-18 19:37:42 -05:00
c . Assert ( success , checker . True , check . Commentf ( "/etc/passwd has been removed but is not present in the diff" ) )
2014-10-14 17:32:25 -04:00
}
2014-12-12 11:01:05 -05:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiStartVolumeBinds ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2014-12-12 11:01:05 -05:00
name := "testing"
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Volumes" : map [ string ] struct { } { "/tmp" : { } } ,
}
2015-04-20 17:03:56 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/create?name=" + name , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2014-12-12 11:01:05 -05:00
2015-09-24 13:53:47 -04:00
bindPath := randomTmpDirPath ( "test" , daemonPlatform )
2014-12-12 11:01:05 -05:00
config = map [ string ] interface { } {
"Binds" : [ ] string { bindPath + ":/tmp" } ,
}
2015-04-20 17:03:56 -04:00
status , _ , err = sockRequest ( "POST" , "/containers/" + name + "/start" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2014-12-12 11:01:05 -05:00
2015-06-03 15:21:38 -04:00
pth , err := inspectMountSourceField ( name , "/tmp" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( pth , checker . Equals , bindPath , check . Commentf ( "expected volume host path to be %s, got %s" , bindPath , pth ) )
2014-12-12 11:01:05 -05:00
}
2015-02-09 11:17:41 -05:00
// Test for GH#10618
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiStartDupVolumeBinds ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-02-09 11:17:41 -05:00
name := "testdups"
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Volumes" : map [ string ] struct { } { "/tmp" : { } } ,
}
2015-04-20 17:03:56 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/create?name=" + name , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-02-09 11:17:41 -05:00
2015-09-24 13:53:47 -04:00
bindPath1 := randomTmpDirPath ( "test1" , daemonPlatform )
bindPath2 := randomTmpDirPath ( "test2" , daemonPlatform )
2015-02-09 11:17:41 -05:00
config = map [ string ] interface { } {
"Binds" : [ ] string { bindPath1 + ":/tmp" , bindPath2 + ":/tmp" } ,
}
2015-04-20 17:03:56 -04:00
status , body , err := sockRequest ( "POST" , "/containers/" + name + "/start" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusInternalServerError )
2015-12-01 13:39:34 -05:00
c . Assert ( string ( body ) , checker . Contains , "Duplicate mount point" , check . Commentf ( "Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v" , string ( body ) , err ) )
2015-02-09 11:17:41 -05:00
}
2015-04-20 17:03:56 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiStartVolumesFrom ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2014-12-12 11:01:05 -05:00
volName := "voltst"
volPath := "/tmp"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , volName , "-v" , volPath , "busybox" )
2014-12-12 11:01:05 -05:00
2015-06-03 15:21:38 -04:00
name := "TestContainerApiStartVolumesFrom"
2014-12-12 11:01:05 -05:00
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Volumes" : map [ string ] struct { } { volPath : { } } ,
}
2015-04-20 17:03:56 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/create?name=" + name , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2014-12-12 11:01:05 -05:00
config = map [ string ] interface { } {
"VolumesFrom" : [ ] string { volName } ,
}
2015-04-20 17:03:56 -04:00
status , _ , err = sockRequest ( "POST" , "/containers/" + name + "/start" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2014-12-12 11:01:05 -05:00
2015-06-03 15:21:38 -04:00
pth , err := inspectMountSourceField ( name , volPath )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-06-03 15:21:38 -04:00
pth2 , err := inspectMountSourceField ( volName , volPath )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( pth , checker . Equals , pth2 , check . Commentf ( "expected volume host path to be %s, got %s" , pth , pth2 ) )
2014-12-12 11:01:05 -05:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestGetContainerStats ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-01-21 15:14:28 -05:00
var (
2015-07-14 02:35:36 -04:00
name = "statscontainer"
2015-01-21 15:14:28 -05:00
)
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , name , "busybox" , "top" )
2015-01-21 15:14:28 -05:00
type b struct {
2015-04-27 13:29:48 -04:00
status int
body [ ] byte
err error
2015-01-21 15:14:28 -05:00
}
bc := make ( chan b , 1 )
2015-01-19 19:10:26 -05:00
go func ( ) {
2015-04-20 17:03:56 -04:00
status , body , err := sockRequest ( "GET" , "/containers/" + name + "/stats" , nil )
2015-04-27 13:29:48 -04:00
bc <- b { status , body , err }
2015-01-19 19:10:26 -05:00
} ( )
2015-01-21 15:14:28 -05:00
// allow some time to stream the stats from the container
time . Sleep ( 4 * time . Second )
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "rm" , "-f" , name )
2015-01-19 19:10:26 -05:00
2015-01-21 15:14:28 -05:00
// collect the results from the stats stream or timeout and fail
// if the stream was not disconnected.
select {
case <- time . After ( 2 * time . Second ) :
2015-04-18 12:46:47 -04:00
c . Fatal ( "stream was not closed after container was removed" )
2015-01-21 15:14:28 -05:00
case sr := <- bc :
2015-11-18 19:37:42 -05:00
c . Assert ( sr . err , checker . IsNil )
c . Assert ( sr . status , checker . Equals , http . StatusOK )
2015-01-21 15:14:28 -05:00
dec := json . NewDecoder ( bytes . NewBuffer ( sr . body ) )
2015-02-24 13:47:47 -05:00
var s * types . Stats
2015-01-21 15:14:28 -05:00
// decode only one object from the stream
2015-11-18 19:37:42 -05:00
c . Assert ( dec . Decode ( & s ) , checker . IsNil )
2015-01-19 19:10:26 -05:00
}
}
2015-01-21 14:08:19 -05:00
2015-05-23 10:09:39 -04:00
func ( s * DockerSuite ) TestGetContainerStatsRmRunning ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-05-26 22:22:03 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
id := strings . TrimSpace ( out )
2015-09-09 09:36:44 -04:00
buf := & integration . ChannelBuffer { make ( chan [ ] byte , 1 ) }
2015-05-26 22:22:03 -04:00
defer buf . Close ( )
chErr := make ( chan error )
go func ( ) {
_ , body , err := sockRequestRaw ( "GET" , "/containers/" + id + "/stats?stream=1" , nil , "application/json" )
if err != nil {
chErr <- err
}
defer body . Close ( )
_ , err = io . Copy ( buf , body )
chErr <- err
} ( )
defer func ( ) {
2015-11-18 19:37:42 -05:00
c . Assert ( <- chErr , checker . IsNil )
2015-05-26 22:22:03 -04:00
} ( )
b := make ( [ ] byte , 32 )
// make sure we've got some stats
_ , err := buf . ReadTimeout ( b , 2 * time . Second )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-05-26 22:22:03 -04:00
// Now remove without `-f` and make sure we are still pulling stats
2015-07-27 14:13:25 -04:00
_ , _ , err = dockerCmdWithError ( "rm" , id )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . Not ( checker . IsNil ) , check . Commentf ( "rm should have failed but didn't" ) )
2015-05-26 22:22:03 -04:00
_ , err = buf . ReadTimeout ( b , 2 * time . Second )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-05-26 22:22:03 -04:00
dockerCmd ( c , "rm" , "-f" , id )
_ , err = buf . ReadTimeout ( b , 2 * time . Second )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . Not ( checker . IsNil ) )
2015-05-26 22:22:03 -04:00
}
2015-05-23 10:09:39 -04:00
// regression test for gh13421
// previous test was just checking one stat entry so it didn't fail (stats with
// stream false always return one stat)
func ( s * DockerSuite ) TestGetContainerStatsStream ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-05-23 10:09:39 -04:00
name := "statscontainer"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , name , "busybox" , "top" )
2015-05-23 10:09:39 -04:00
type b struct {
status int
body [ ] byte
err error
}
bc := make ( chan b , 1 )
go func ( ) {
status , body , err := sockRequest ( "GET" , "/containers/" + name + "/stats" , nil )
bc <- b { status , body , err }
} ( )
// allow some time to stream the stats from the container
time . Sleep ( 4 * time . Second )
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "rm" , "-f" , name )
2015-05-23 10:09:39 -04:00
// collect the results from the stats stream or timeout and fail
// if the stream was not disconnected.
select {
case <- time . After ( 2 * time . Second ) :
c . Fatal ( "stream was not closed after container was removed" )
case sr := <- bc :
2015-11-18 19:37:42 -05:00
c . Assert ( sr . err , checker . IsNil )
c . Assert ( sr . status , checker . Equals , http . StatusOK )
2015-05-23 10:09:39 -04:00
s := string ( sr . body )
// count occurrences of "read" of types.Stats
if l := strings . Count ( s , "read" ) ; l < 2 {
c . Fatalf ( "Expected more than one stat streamed, got %d" , l )
}
}
}
func ( s * DockerSuite ) TestGetContainerStatsNoStream ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-05-23 10:09:39 -04:00
name := "statscontainer"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-d" , "--name" , name , "busybox" , "top" )
2015-05-23 10:09:39 -04:00
type b struct {
status int
body [ ] byte
err error
}
bc := make ( chan b , 1 )
go func ( ) {
status , body , err := sockRequest ( "GET" , "/containers/" + name + "/stats?stream=0" , nil )
bc <- b { status , body , err }
} ( )
// allow some time to stream the stats from the container
time . Sleep ( 4 * time . Second )
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "rm" , "-f" , name )
2015-05-23 10:09:39 -04:00
// collect the results from the stats stream or timeout and fail
// if the stream was not disconnected.
select {
case <- time . After ( 2 * time . Second ) :
c . Fatal ( "stream was not closed after container was removed" )
case sr := <- bc :
2015-11-18 19:37:42 -05:00
c . Assert ( sr . err , checker . IsNil )
c . Assert ( sr . status , checker . Equals , http . StatusOK )
2015-05-23 10:09:39 -04:00
s := string ( sr . body )
// count occurrences of "read" of types.Stats
2015-11-18 19:37:42 -05:00
c . Assert ( strings . Count ( s , "read" ) , checker . Equals , 1 , check . Commentf ( "Expected only one stat streamed, got %d" , strings . Count ( s , "read" ) ) )
2015-05-23 10:09:39 -04:00
}
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestGetStoppedContainerStats ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-27 13:29:48 -04:00
// TODO: this test does nothing because we are c.Assert'ing in goroutine
2015-03-16 07:55:34 -04:00
var (
2015-07-14 02:35:36 -04:00
name = "statscontainer"
2015-03-16 07:55:34 -04:00
)
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "create" , "--name" , name , "busybox" , "top" )
2015-03-16 07:55:34 -04:00
go func ( ) {
// We'll never get return for GET stats from sockRequest as of now,
// just send request and see if panic or error would happen on daemon side.
2015-04-20 17:03:56 -04:00
status , _ , err := sockRequest ( "GET" , "/containers/" + name + "/stats" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-03-16 07:55:34 -04:00
} ( )
// allow some time to send request and let daemon deal with it
time . Sleep ( 1 * time . Second )
}
2015-01-26 17:31:30 -05:00
// #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestPostContainerBindNormalVolume ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "create" , "-v" , "/foo" , "--name=one" , "busybox" )
2015-01-26 17:31:30 -05:00
2015-06-03 15:21:38 -04:00
fooDir , err := inspectMountSourceField ( "one" , "/foo" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-01-26 17:31:30 -05:00
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "create" , "-v" , "/foo" , "--name=two" , "busybox" )
2015-01-26 17:31:30 -05:00
bindSpec := map [ string ] [ ] string { "Binds" : { fooDir + ":/foo" } }
2015-04-20 17:03:56 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/two/start" , bindSpec )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-01-26 17:31:30 -05:00
2015-06-03 15:21:38 -04:00
fooDir2 , err := inspectMountSourceField ( "two" , "/foo" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( fooDir2 , checker . Equals , fooDir , check . Commentf ( "expected volume path to be %s, got: %s" , fooDir , fooDir2 ) )
2015-01-26 17:31:30 -05:00
}
2015-04-09 21:14:01 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiPause ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-09 21:14:01 -04:00
defer unpauseAllContainers ( )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "sleep" , "30" )
2015-04-09 21:14:01 -04:00
ContainerID := strings . TrimSpace ( out )
2015-04-20 17:03:56 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/" + ContainerID + "/pause" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-04-09 21:14:01 -04:00
pausedContainers , err := getSliceOfPausedContainers ( )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error thrown while checking if containers were paused" ) )
2015-04-09 21:14:01 -04:00
if len ( pausedContainers ) != 1 || stringid . TruncateID ( ContainerID ) != pausedContainers [ 0 ] {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "there should be one paused container and not %d" , len ( pausedContainers ) )
2015-04-09 21:14:01 -04:00
}
2015-04-20 17:03:56 -04:00
status , _ , err = sockRequest ( "POST" , "/containers/" + ContainerID + "/unpause" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-04-09 21:14:01 -04:00
pausedContainers , err = getSliceOfPausedContainers ( )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error thrown while checking if containers were paused" ) )
c . Assert ( pausedContainers , checker . IsNil , check . Commentf ( "There should be no paused container." ) )
2015-04-09 21:14:01 -04:00
}
2015-04-14 17:14:29 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiTop ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "/bin/sh" , "-c" , "top" )
2015-04-18 12:46:47 -04:00
id := strings . TrimSpace ( string ( out ) )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2015-04-14 17:14:29 -04:00
type topResp struct {
Titles [ ] string
Processes [ ] [ ] string
}
var top topResp
2015-04-20 17:03:56 -04:00
status , b , err := sockRequest ( "GET" , "/containers/" + id + "/top?ps_args=aux" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
c . Assert ( json . Unmarshal ( b , & top ) , checker . IsNil )
c . Assert ( top . Titles , checker . HasLen , 11 , check . Commentf ( "expected 11 titles, found %d: %v" , len ( top . Titles ) , top . Titles ) )
2015-04-14 17:14:29 -04:00
if top . Titles [ 0 ] != "USER" || top . Titles [ 10 ] != "COMMAND" {
2015-04-18 12:46:47 -04:00
c . Fatalf ( "expected `USER` at `Titles[0]` and `COMMAND` at Titles[10]: %v" , top . Titles )
2015-04-14 17:14:29 -04:00
}
2015-11-18 19:37:42 -05:00
c . Assert ( top . Processes , checker . HasLen , 2 , check . Commentf ( "expected 2 processes, found %d: %v" , len ( top . Processes ) , top . Processes ) )
c . Assert ( top . Processes [ 0 ] [ 10 ] , checker . Equals , "/bin/sh -c top" )
c . Assert ( top . Processes [ 1 ] [ 10 ] , checker . Equals , "top" )
2015-04-14 17:14:29 -04:00
}
2015-04-14 20:48:03 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiCommit ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-25 08:46:47 -04:00
cName := "testapicommit"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name=" + cName , "busybox" , "/bin/sh" , "-c" , "touch /test" )
2015-04-14 20:48:03 -04:00
2015-11-18 17:20:54 -05:00
name := "testcontainerapicommit"
2015-04-25 08:46:47 -04:00
status , b , err := sockRequest ( "POST" , "/commit?repo=" + name + "&testtag=tag&container=" + cName , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-04-14 20:48:03 -04:00
type resp struct {
2015-07-22 08:59:24 -04:00
ID string
2015-04-14 20:48:03 -04:00
}
var img resp
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( b , & img ) , checker . IsNil )
2015-04-14 20:48:03 -04:00
2015-07-22 08:59:24 -04:00
cmd , err := inspectField ( img . ID , "Config.Cmd" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( cmd , checker . Equals , "{[/bin/sh -c touch /test]}" , check . Commentf ( "got wrong Cmd from commit: %q" , cmd ) )
2015-04-14 20:48:03 -04:00
// sanity check, make sure the image is what we think it is
2015-07-22 08:59:24 -04:00
dockerCmd ( c , "run" , img . ID , "ls" , "/test" )
2015-05-30 05:31:51 -04:00
}
func ( s * DockerSuite ) TestContainerApiCommitWithLabelInConfig ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-05-30 05:31:51 -04:00
cName := "testapicommitwithconfig"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name=" + cName , "busybox" , "/bin/sh" , "-c" , "touch /test" )
2015-05-30 05:31:51 -04:00
config := map [ string ] interface { } {
"Labels" : map [ string ] string { "key1" : "value1" , "key2" : "value2" } ,
}
2015-11-18 17:20:54 -05:00
name := "testcontainerapicommitwithconfig"
2015-05-30 05:31:51 -04:00
status , b , err := sockRequest ( "POST" , "/commit?repo=" + name + "&container=" + cName , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-05-30 05:31:51 -04:00
type resp struct {
2015-07-22 08:59:24 -04:00
ID string
2015-05-30 05:31:51 -04:00
}
var img resp
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( b , & img ) , checker . IsNil )
2015-05-30 05:31:51 -04:00
2015-07-22 08:59:24 -04:00
label1 , err := inspectFieldMap ( img . ID , "Config.Labels" , "key1" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( label1 , checker . Equals , "value1" )
2015-05-30 05:31:51 -04:00
2015-07-22 08:59:24 -04:00
label2 , err := inspectFieldMap ( img . ID , "Config.Labels" , "key2" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( label2 , checker . Equals , "value2" )
2015-05-30 05:31:51 -04:00
2015-07-22 08:59:24 -04:00
cmd , err := inspectField ( img . ID , "Config.Cmd" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( cmd , checker . Equals , "{[/bin/sh -c touch /test]}" , check . Commentf ( "got wrong Cmd from commit: %q" , cmd ) )
2015-05-30 05:31:51 -04:00
// sanity check, make sure the image is what we think it is
2015-07-22 08:59:24 -04:00
dockerCmd ( c , "run" , img . ID , "ls" , "/test" )
2015-04-14 20:48:03 -04:00
}
2015-04-14 21:04:43 -04:00
2015-07-15 23:45:48 -04:00
func ( s * DockerSuite ) TestContainerApiBadPort ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-15 23:45:48 -04:00
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Cmd" : [ ] string { "/bin/sh" , "-c" , "echo test" } ,
"PortBindings" : map [ string ] interface { } {
"8080/tcp" : [ ] map [ string ] interface { } {
{
2015-07-21 09:43:32 -04:00
"HostIP" : "" ,
2015-07-15 23:45:48 -04:00
"HostPort" : "aa80" ,
} ,
} ,
} ,
}
jsonData := bytes . NewBuffer ( nil )
json . NewEncoder ( jsonData ) . Encode ( config )
status , b , err := sockRequest ( "POST" , "/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusInternalServerError )
c . Assert ( strings . TrimSpace ( string ( b ) ) , checker . Equals , ` Invalid port specification: "aa80" ` , check . Commentf ( "Incorrect error msg: %s" , string ( b ) ) )
2015-07-15 23:45:48 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiCreate ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-14 21:04:43 -04:00
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Cmd" : [ ] string { "/bin/sh" , "-c" , "touch /test && ls /test" } ,
}
2015-04-20 17:03:56 -04:00
status , b , err := sockRequest ( "POST" , "/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-04-20 17:03:56 -04:00
2015-04-14 21:04:43 -04:00
type createResp struct {
2015-07-22 08:59:24 -04:00
ID string
2015-04-14 21:04:43 -04:00
}
var container createResp
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( b , & container ) , checker . IsNil )
2015-04-14 21:04:43 -04:00
2015-07-22 08:59:24 -04:00
out , _ := dockerCmd ( c , "start" , "-a" , container . ID )
2015-11-18 19:37:42 -05:00
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "/test" )
2015-04-14 21:04:43 -04:00
}
2015-04-14 21:55:04 -04:00
2015-06-06 12:41:42 -04:00
func ( s * DockerSuite ) TestContainerApiCreateEmptyConfig ( c * check . C ) {
config := map [ string ] interface { } { }
status , b , err := sockRequest ( "POST" , "/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusInternalServerError )
2015-06-06 12:41:42 -04:00
expected := "Config cannot be empty in order to create a container\n"
2015-11-18 19:37:42 -05:00
c . Assert ( string ( b ) , checker . Equals , expected )
2015-06-06 12:41:42 -04:00
}
2015-04-22 07:03:57 -04:00
func ( s * DockerSuite ) TestContainerApiCreateWithHostName ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-25 04:53:38 -04:00
hostName := "test-host"
2015-04-22 07:03:57 -04:00
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Hostname" : hostName ,
}
2015-04-25 04:53:38 -04:00
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-04-25 04:53:38 -04:00
var container types . ContainerCreateResponse
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & container ) , checker . IsNil )
2015-04-25 04:53:38 -04:00
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-04-25 04:53:38 -04:00
var containerJSON types . ContainerJSON
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & containerJSON ) , checker . IsNil )
c . Assert ( containerJSON . Config . Hostname , checker . Equals , hostName , check . Commentf ( "Mismatched Hostname" ) )
2015-04-25 04:53:38 -04:00
}
func ( s * DockerSuite ) TestContainerApiCreateWithDomainName ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-25 04:53:38 -04:00
domainName := "test-domain"
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Domainname" : domainName ,
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-04-25 04:53:38 -04:00
var container types . ContainerCreateResponse
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & container ) , checker . IsNil )
2015-04-25 04:53:38 -04:00
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-04-25 04:53:38 -04:00
var containerJSON types . ContainerJSON
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & containerJSON ) , checker . IsNil )
c . Assert ( containerJSON . Config . Domainname , checker . Equals , domainName , check . Commentf ( "Mismatched Domainname" ) )
2015-04-25 04:53:38 -04:00
}
2015-04-22 07:03:57 -04:00
2015-04-25 04:53:38 -04:00
func ( s * DockerSuite ) TestContainerApiCreateNetworkMode ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-25 04:53:38 -04:00
UtilCreateNetworkMode ( c , "host" )
UtilCreateNetworkMode ( c , "bridge" )
UtilCreateNetworkMode ( c , "container:web1" )
}
2015-04-22 07:03:57 -04:00
2015-04-25 04:53:38 -04:00
func UtilCreateNetworkMode ( c * check . C , networkMode string ) {
config := map [ string ] interface { } {
"Image" : "busybox" ,
"HostConfig" : map [ string ] interface { } { "NetworkMode" : networkMode } ,
2015-04-22 07:03:57 -04:00
}
2015-04-25 04:53:38 -04:00
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-04-25 04:53:38 -04:00
var container types . ContainerCreateResponse
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & container ) , checker . IsNil )
2015-04-22 07:03:57 -04:00
2015-04-25 04:53:38 -04:00
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-04-25 04:53:38 -04:00
var containerJSON types . ContainerJSON
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & containerJSON ) , checker . IsNil )
c . Assert ( containerJSON . HostConfig . NetworkMode , checker . Equals , runconfig . NetworkMode ( networkMode ) , check . Commentf ( "Mismatched NetworkMode" ) )
2015-04-22 07:03:57 -04:00
}
2015-05-15 17:00:54 -04:00
func ( s * DockerSuite ) TestContainerApiCreateWithCpuSharesCpuset ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-05-15 17:00:54 -04:00
config := map [ string ] interface { } {
"Image" : "busybox" ,
"CpuShares" : 512 ,
2015-11-15 17:00:39 -05:00
"CpusetCpus" : "0" ,
2015-05-15 17:00:54 -04:00
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-05-15 17:00:54 -04:00
var container types . ContainerCreateResponse
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & container ) , checker . IsNil )
2015-05-15 17:00:54 -04:00
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-05-15 17:00:54 -04:00
2015-07-22 08:59:24 -04:00
var containerJSON types . ContainerJSON
2015-05-15 17:00:54 -04:00
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & containerJSON ) , checker . IsNil )
2015-05-15 17:00:54 -04:00
2015-07-23 05:40:54 -04:00
out , err := inspectField ( containerJSON . ID , "HostConfig.CpuShares" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( out , checker . Equals , "512" )
2015-05-15 17:00:54 -04:00
2015-07-23 05:40:54 -04:00
outCpuset , errCpuset := inspectField ( containerJSON . ID , "HostConfig.CpusetCpus" )
2015-11-18 19:37:42 -05:00
c . Assert ( errCpuset , checker . IsNil , check . Commentf ( "Output: %s" , outCpuset ) )
c . Assert ( outCpuset , checker . Equals , "0" )
2015-05-15 17:00:54 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiVerifyHeader ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-14 21:55:04 -04:00
config := map [ string ] interface { } {
"Image" : "busybox" ,
}
2015-04-27 12:33:08 -04:00
create := func ( ct string ) ( * http . Response , io . ReadCloser , error ) {
2015-04-14 21:55:04 -04:00
jsonData := bytes . NewBuffer ( nil )
2015-11-18 19:37:42 -05:00
c . Assert ( json . NewEncoder ( jsonData ) . Encode ( config ) , checker . IsNil )
2015-04-14 21:55:04 -04:00
return sockRequestRaw ( "POST" , "/containers/create" , jsonData , ct )
}
// Try with no content-type
2015-04-27 12:33:08 -04:00
res , body , err := create ( "" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusInternalServerError )
2015-04-14 21:55:04 -04:00
body . Close ( )
2015-04-20 17:03:56 -04:00
2015-04-14 21:55:04 -04:00
// Try with wrong content-type
2015-04-27 12:33:08 -04:00
res , body , err = create ( "application/xml" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusInternalServerError )
2015-04-14 21:55:04 -04:00
body . Close ( )
// now application/json
2015-04-27 12:33:08 -04:00
res , body , err = create ( "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusCreated )
2015-04-14 21:55:04 -04:00
body . Close ( )
}
2015-04-14 22:07:04 -04:00
2015-06-28 06:16:24 -04:00
//Issue 14230. daemon should return 500 for invalid port syntax
func ( s * DockerSuite ) TestContainerApiInvalidPortSyntax ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-06-28 06:16:24 -04:00
config := ` {
"Image" : "busybox" ,
"HostConfig" : {
"PortBindings" : {
"19039;1230" : [
{ }
]
}
}
} `
res , body , err := sockRequestRaw ( "POST" , "/containers/create" , strings . NewReader ( config ) , "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusInternalServerError )
2015-06-28 06:16:24 -04:00
b , err := readBody ( body )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( string ( b [ : ] ) , checker . Contains , "Invalid port" )
2015-06-28 06:16:24 -04:00
}
2015-04-14 22:07:04 -04:00
// Issue 7941 - test to make sure a "null" in JSON is just ignored.
// W/o this fix a null in JSON would be parsed into a string var as "null"
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestContainerApiPostCreateNull ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-14 22:07:04 -04:00
config := ` {
"Hostname" : "" ,
"Domainname" : "" ,
"Memory" : 0 ,
"MemorySwap" : 0 ,
"CpuShares" : 0 ,
"Cpuset" : null ,
"AttachStdin" : true ,
"AttachStdout" : true ,
"AttachStderr" : true ,
"ExposedPorts" : { } ,
"Tty" : true ,
"OpenStdin" : true ,
"StdinOnce" : true ,
"Env" : [ ] ,
"Cmd" : "ls" ,
"Image" : "busybox" ,
"Volumes" : { } ,
"WorkingDir" : "" ,
"Entrypoint" : null ,
"NetworkDisabled" : false ,
"OnBuild" : null } `
2015-04-27 12:33:08 -04:00
res , body , err := sockRequestRaw ( "POST" , "/containers/create" , strings . NewReader ( config ) , "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusCreated )
2015-04-14 22:07:04 -04:00
b , err := readBody ( body )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-14 22:07:04 -04:00
type createResp struct {
2015-07-22 08:59:24 -04:00
ID string
2015-04-14 22:07:04 -04:00
}
var container createResp
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( b , & container ) , checker . IsNil )
2015-04-14 22:07:04 -04:00
2015-07-22 08:59:24 -04:00
out , err := inspectField ( container . ID , "HostConfig.CpusetCpus" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( out , checker . Equals , "" )
2015-05-12 02:30:16 -04:00
2015-07-22 08:59:24 -04:00
outMemory , errMemory := inspectField ( container . ID , "HostConfig.Memory" )
2015-11-18 19:37:42 -05:00
c . Assert ( outMemory , checker . Equals , "0" )
c . Assert ( errMemory , checker . IsNil )
2015-07-22 08:59:24 -04:00
outMemorySwap , errMemorySwap := inspectField ( container . ID , "HostConfig.MemorySwap" )
2015-11-18 19:37:42 -05:00
c . Assert ( outMemorySwap , checker . Equals , "0" )
c . Assert ( errMemorySwap , checker . IsNil )
2015-04-14 22:07:04 -04:00
}
2015-04-15 18:43:18 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestCreateWithTooLowMemoryLimit ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-15 18:43:18 -04:00
config := ` {
"Image" : "busybox" ,
"Cmd" : "ls" ,
"OpenStdin" : true ,
"CpuShares" : 100 ,
"Memory" : 524287
} `
2015-07-13 08:49:08 -04:00
res , body , err := sockRequestRaw ( "POST" , "/containers/create" , strings . NewReader ( config ) , "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-15 18:43:18 -04:00
b , err2 := readBody ( body )
2015-11-18 19:37:42 -05:00
c . Assert ( err2 , checker . IsNil )
2015-04-15 18:43:18 -04:00
2015-11-18 19:37:42 -05:00
c . Assert ( res . StatusCode , checker . Equals , http . StatusInternalServerError )
c . Assert ( string ( b ) , checker . Contains , "Minimum memory limit allowed is 4MB" )
2015-04-15 18:43:18 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestStartWithTooLowMemoryLimit ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "create" , "busybox" )
2015-04-15 18:43:18 -04:00
containerID := strings . TrimSpace ( out )
config := ` {
"CpuShares" : 100 ,
"Memory" : 524287
} `
2015-07-13 08:49:08 -04:00
res , body , err := sockRequestRaw ( "POST" , "/containers/" + containerID + "/start" , strings . NewReader ( config ) , "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-15 18:43:18 -04:00
b , err2 := readBody ( body )
2015-11-18 19:37:42 -05:00
c . Assert ( err2 , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusInternalServerError )
c . Assert ( string ( b ) , checker . Contains , "Minimum memory limit allowed is 4MB" )
2015-04-15 18:43:18 -04:00
}
2015-04-24 07:57:04 -04:00
func ( s * DockerSuite ) TestContainerApiRename ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "--name" , "TestContainerApiRename" , "-d" , "busybox" , "sh" )
2015-04-24 07:57:04 -04:00
containerID := strings . TrimSpace ( out )
2015-04-26 12:50:25 -04:00
newName := "TestContainerApiRenameNew"
2015-04-24 07:57:04 -04:00
statusCode , _ , err := sockRequest ( "POST" , "/containers/" + containerID + "/rename?name=" + newName , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-24 07:57:04 -04:00
// 204 No Content is expected, not 200
2015-11-18 19:37:42 -05:00
c . Assert ( statusCode , checker . Equals , http . StatusNoContent )
2015-04-24 07:57:04 -04:00
name , err := inspectField ( containerID , "Name" )
2015-11-18 19:37:42 -05:00
c . Assert ( name , checker . Equals , "/" + newName , check . Commentf ( "Failed to rename container" ) )
2015-04-24 07:57:04 -04:00
}
2015-04-29 07:56:45 -04:00
func ( s * DockerSuite ) TestContainerApiKill ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "test-api-kill"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-di" , "--name" , name , "busybox" , "top" )
2015-04-29 07:56:45 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/" + name + "/kill" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-04-29 07:56:45 -04:00
state , err := inspectField ( name , "State.Running" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( state , checker . Equals , "false" , check . Commentf ( "got wrong State from container %s: %q" , name , state ) )
2015-04-29 07:56:45 -04:00
}
func ( s * DockerSuite ) TestContainerApiRestart ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "test-api-restart"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-di" , "--name" , name , "busybox" , "top" )
2015-04-29 07:56:45 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/" + name + "/restart?t=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
c . Assert ( waitInspect ( name , "{{ .State.Restarting }} {{ .State.Running }}" , "false true" , 5 * time . Second ) , checker . IsNil )
2015-04-29 07:56:45 -04:00
}
2015-05-06 19:49:16 -04:00
func ( s * DockerSuite ) TestContainerApiRestartNotimeoutParam ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-05-06 19:49:16 -04:00
name := "test-api-restart-no-timeout-param"
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-di" , "--name" , name , "busybox" , "top" )
2015-05-06 19:49:16 -04:00
id := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2015-05-06 19:49:16 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/" + name + "/restart" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
c . Assert ( waitInspect ( name , "{{ .State.Restarting }} {{ .State.Running }}" , "false true" , 5 * time . Second ) , checker . IsNil )
2015-05-06 19:49:16 -04:00
}
2015-04-29 07:56:45 -04:00
func ( s * DockerSuite ) TestContainerApiStart ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "testing-start"
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Cmd" : [ ] string { "/bin/sh" , "-c" , "/bin/top" } ,
"OpenStdin" : true ,
}
status , _ , err := sockRequest ( "POST" , "/containers/create?name=" + name , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-04-29 07:56:45 -04:00
conf := make ( map [ string ] interface { } )
status , _ , err = sockRequest ( "POST" , "/containers/" + name + "/start" , conf )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-04-29 07:56:45 -04:00
// second call to start should give 304
status , _ , err = sockRequest ( "POST" , "/containers/" + name + "/start" , conf )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNotModified )
2015-04-29 07:56:45 -04:00
}
func ( s * DockerSuite ) TestContainerApiStop ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "test-api-stop"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "-di" , "--name" , name , "busybox" , "top" )
2015-04-29 07:56:45 -04:00
status , _ , err := sockRequest ( "POST" , "/containers/" + name + "/stop?t=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
c . Assert ( waitInspect ( name , "{{ .State.Running }}" , "false" , 5 * time . Second ) , checker . IsNil )
2015-04-29 07:56:45 -04:00
// second call to start should give 304
status , _ , err = sockRequest ( "POST" , "/containers/" + name + "/stop?t=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNotModified )
2015-04-29 07:56:45 -04:00
}
func ( s * DockerSuite ) TestContainerApiWait ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "test-api-wait"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name" , name , "busybox" , "sleep" , "5" )
2015-04-29 07:56:45 -04:00
status , body , err := sockRequest ( "POST" , "/containers/" + name + "/wait" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
c . Assert ( waitInspect ( name , "{{ .State.Running }}" , "false" , 5 * time . Second ) , checker . IsNil )
2015-04-29 07:56:45 -04:00
var waitres types . ContainerWaitResponse
2015-11-18 19:37:42 -05:00
c . Assert ( json . Unmarshal ( body , & waitres ) , checker . IsNil )
c . Assert ( waitres . StatusCode , checker . Equals , 0 )
2015-04-29 07:56:45 -04:00
}
func ( s * DockerSuite ) TestContainerApiCopy ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "test-container-api-copy"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name" , name , "busybox" , "touch" , "/test.txt" )
2015-04-29 07:56:45 -04:00
postData := types . CopyConfig {
Resource : "/test.txt" ,
}
status , body , err := sockRequest ( "POST" , "/containers/" + name + "/copy" , postData )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
2015-04-29 07:56:45 -04:00
found := false
for tarReader := tar . NewReader ( bytes . NewReader ( body ) ) ; ; {
h , err := tarReader . Next ( )
if err != nil {
if err == io . EOF {
break
}
c . Fatal ( err )
}
if h . Name == "test.txt" {
found = true
break
}
}
2015-11-18 19:37:42 -05:00
c . Assert ( found , checker . True )
2015-04-29 07:56:45 -04:00
}
func ( s * DockerSuite ) TestContainerApiCopyResourcePathEmpty ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "test-container-api-copy-resource-empty"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name" , name , "busybox" , "touch" , "/test.txt" )
2015-04-29 07:56:45 -04:00
postData := types . CopyConfig {
Resource : "" ,
}
status , body , err := sockRequest ( "POST" , "/containers/" + name + "/copy" , postData )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusInternalServerError )
c . Assert ( string ( body ) , checker . Matches , "Path cannot be empty\n" )
2015-04-29 07:56:45 -04:00
}
func ( s * DockerSuite ) TestContainerApiCopyResourcePathNotFound ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 07:56:45 -04:00
name := "test-container-api-copy-resource-not-found"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "run" , "--name" , name , "busybox" )
2015-04-29 07:56:45 -04:00
postData := types . CopyConfig {
Resource : "/notexist" ,
}
status , body , err := sockRequest ( "POST" , "/containers/" + name + "/copy" , postData )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusInternalServerError )
c . Assert ( string ( body ) , checker . Matches , "Could not find the file /notexist in container " + name + "\n" )
2015-04-29 07:56:45 -04:00
}
func ( s * DockerSuite ) TestContainerApiCopyContainerNotFound ( c * check . C ) {
postData := types . CopyConfig {
Resource : "/something" ,
}
status , _ , err := sockRequest ( "POST" , "/containers/notexists/copy" , postData )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNotFound )
2015-04-29 07:56:45 -04:00
}
2015-05-03 08:54:55 -04:00
func ( s * DockerSuite ) TestContainerApiDelete ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2015-05-03 08:54:55 -04:00
id := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2015-05-03 08:54:55 -04:00
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "stop" , id )
2015-05-03 08:54:55 -04:00
status , _ , err := sockRequest ( "DELETE" , "/containers/" + id , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-05-03 08:54:55 -04:00
}
func ( s * DockerSuite ) TestContainerApiDeleteNotExist ( c * check . C ) {
status , body , err := sockRequest ( "DELETE" , "/containers/doesnotexist" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNotFound )
2015-12-04 02:00:08 -05:00
c . Assert ( string ( body ) , checker . Matches , "No such container: doesnotexist\n" )
2015-05-03 08:54:55 -04:00
}
func ( s * DockerSuite ) TestContainerApiDeleteForce ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2015-05-03 08:54:55 -04:00
id := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2015-05-03 08:54:55 -04:00
status , _ , err := sockRequest ( "DELETE" , "/containers/" + id + "?force=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-05-03 08:54:55 -04:00
}
func ( s * DockerSuite ) TestContainerApiDeleteRemoveLinks ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "--name" , "tlink1" , "busybox" , "top" )
2015-05-03 08:54:55 -04:00
id := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2015-05-03 08:54:55 -04:00
2015-07-14 02:35:36 -04:00
out , _ = dockerCmd ( c , "run" , "--link" , "tlink1:tlink1" , "--name" , "tlink2" , "-d" , "busybox" , "top" )
2015-05-03 08:54:55 -04:00
id2 := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id2 ) , checker . IsNil )
2015-05-03 08:54:55 -04:00
links , err := inspectFieldJSON ( id2 , "HostConfig.Links" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( links , checker . Equals , "[\"/tlink1:/tlink2/tlink1\"]" , check . Commentf ( "expected to have links between containers" ) )
2015-05-03 08:54:55 -04:00
status , _ , err := sockRequest ( "DELETE" , "/containers/tlink2/tlink1?link=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
2015-05-03 08:54:55 -04:00
linksPostRm , err := inspectFieldJSON ( id2 , "HostConfig.Links" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( linksPostRm , checker . Equals , "null" , check . Commentf ( "call to api deleteContainer links should have removed the specified links" ) )
2015-05-03 08:54:55 -04:00
}
func ( s * DockerSuite ) TestContainerApiDeleteConflict ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2015-05-03 08:54:55 -04:00
id := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2015-05-03 08:54:55 -04:00
status , _ , err := sockRequest ( "DELETE" , "/containers/" + id , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusConflict )
2015-05-03 08:54:55 -04:00
}
func ( s * DockerSuite ) TestContainerApiDeleteRemoveVolume ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-05-03 08:54:55 -04:00
testRequires ( c , SameHostDaemon )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "-v" , "/testvolume" , "busybox" , "top" )
2015-05-03 08:54:55 -04:00
id := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( id ) , checker . IsNil )
2015-05-03 08:54:55 -04:00
2015-06-03 15:21:38 -04:00
source , err := inspectMountSourceField ( id , "/testvolume" )
_ , err = os . Stat ( source )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-05-03 08:54:55 -04:00
status , _ , err := sockRequest ( "DELETE" , "/containers/" + id + "?v=1&force=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusNoContent )
_ , err = os . Stat ( source )
c . Assert ( os . IsNotExist ( err ) , checker . True , check . Commentf ( "expected to get ErrNotExist error, got %v" , err ) )
2015-05-03 08:54:55 -04:00
}
2015-04-29 13:48:30 -04:00
// Regression test for https://github.com/docker/docker/issues/6231
func ( s * DockerSuite ) TestContainersApiChunkedEncoding ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 13:48:30 -04:00
out , _ := dockerCmd ( c , "create" , "-v" , "/foo" , "busybox" , "true" )
id := strings . TrimSpace ( out )
conn , err := sockConn ( time . Duration ( 10 * time . Second ) )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-29 13:48:30 -04:00
client := httputil . NewClientConn ( conn , nil )
defer client . Close ( )
bindCfg := strings . NewReader ( ` { "Binds": ["/tmp:/foo"]} ` )
req , err := http . NewRequest ( "POST" , "/containers/" + id + "/start" , bindCfg )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-29 13:48:30 -04:00
req . Header . Set ( "Content-Type" , "application/json" )
// This is a cheat to make the http request do chunked encoding
// Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite
// https://golang.org/src/pkg/net/http/request.go?s=11980:12172
req . ContentLength = - 1
resp , err := client . Do ( req )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error starting container with chunked encoding" ) )
2015-04-29 13:48:30 -04:00
resp . Body . Close ( )
2015-11-18 19:37:42 -05:00
c . Assert ( resp . StatusCode , checker . Equals , 204 )
2015-04-29 13:48:30 -04:00
out , err = inspectFieldJSON ( id , "HostConfig.Binds" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-29 13:48:30 -04:00
var binds [ ] string
2015-11-18 19:37:42 -05:00
c . Assert ( json . NewDecoder ( strings . NewReader ( out ) ) . Decode ( & binds ) , checker . IsNil )
c . Assert ( binds , checker . HasLen , 1 , check . Commentf ( "Got unexpected binds: %v" , binds ) )
2015-04-29 13:48:30 -04:00
expected := "/tmp:/foo"
2015-11-18 19:37:42 -05:00
c . Assert ( binds [ 0 ] , checker . Equals , expected , check . Commentf ( "got incorrect bind spec" ) )
2015-04-29 13:48:30 -04:00
}
2015-04-27 14:55:11 -04:00
func ( s * DockerSuite ) TestPostContainerStop ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2015-04-27 14:55:11 -04:00
containerID := strings . TrimSpace ( out )
2015-11-18 19:37:42 -05:00
c . Assert ( waitRun ( containerID ) , checker . IsNil )
2015-04-27 14:55:11 -04:00
statusCode , _ , err := sockRequest ( "POST" , "/containers/" + containerID + "/stop" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-04-27 14:55:11 -04:00
// 204 No Content is expected, not 200
2015-11-18 19:37:42 -05:00
c . Assert ( statusCode , checker . Equals , http . StatusNoContent )
c . Assert ( waitInspect ( containerID , "{{ .State.Running }}" , "false" , 5 * time . Second ) , checker . IsNil )
2015-04-27 14:55:11 -04:00
}
2015-06-26 01:15:57 -04:00
// #14170
func ( s * DockerSuite ) TestPostContainersCreateWithStringOrSliceEntrypoint ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-06-26 01:15:57 -04:00
config := struct {
Image string
Entrypoint string
Cmd [ ] string
} { "busybox" , "echo" , [ ] string { "hello" , "world" } }
_ , _ , err := sockRequest ( "POST" , "/containers/create?name=echotest" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-06-26 01:15:57 -04:00
out , _ := dockerCmd ( c , "start" , "-a" , "echotest" )
2015-11-18 19:37:42 -05:00
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "hello world" )
2015-06-26 01:15:57 -04:00
config2 := struct {
Image string
Entrypoint [ ] string
Cmd [ ] string
} { "busybox" , [ ] string { "echo" } , [ ] string { "hello" , "world" } }
_ , _ , err = sockRequest ( "POST" , "/containers/create?name=echotest2" , config2 )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-06-26 01:15:57 -04:00
out , _ = dockerCmd ( c , "start" , "-a" , "echotest2" )
2015-11-18 19:37:42 -05:00
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "hello world" )
2015-06-26 01:15:57 -04:00
}
// #14170
func ( s * DockerSuite ) TestPostContainersCreateWithStringOrSliceCmd ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-06-26 01:15:57 -04:00
config := struct {
Image string
Entrypoint string
Cmd string
} { "busybox" , "echo" , "hello world" }
_ , _ , err := sockRequest ( "POST" , "/containers/create?name=echotest" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-06-26 01:15:57 -04:00
out , _ := dockerCmd ( c , "start" , "-a" , "echotest" )
2015-11-18 19:37:42 -05:00
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "hello world" )
2015-06-26 01:15:57 -04:00
config2 := struct {
Image string
Cmd [ ] string
} { "busybox" , [ ] string { "echo" , "hello" , "world" } }
_ , _ , err = sockRequest ( "POST" , "/containers/create?name=echotest2" , config2 )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-06-26 01:15:57 -04:00
out , _ = dockerCmd ( c , "start" , "-a" , "echotest2" )
2015-11-18 19:37:42 -05:00
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "hello world" )
2015-06-26 01:15:57 -04:00
}
2015-07-01 13:59:18 -04:00
// regression #14318
func ( s * DockerSuite ) TestPostContainersCreateWithStringOrSliceCapAddDrop ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-01 13:59:18 -04:00
config := struct {
Image string
CapAdd string
CapDrop string
} { "busybox" , "NET_ADMIN" , "SYS_ADMIN" }
status , _ , err := sockRequest ( "POST" , "/containers/create?name=capaddtest0" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-07-01 13:59:18 -04:00
config2 := struct {
Image string
CapAdd [ ] string
CapDrop [ ] string
} { "busybox" , [ ] string { "NET_ADMIN" , "SYS_ADMIN" } , [ ] string { "SETGID" } }
status , _ , err = sockRequest ( "POST" , "/containers/create?name=capaddtest1" , config2 )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-07-01 13:59:18 -04:00
}
2015-07-21 15:18:56 -04:00
// #14640
func ( s * DockerSuite ) TestPostContainersStartWithoutLinksInHostConfig ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-21 15:18:56 -04:00
name := "test-host-config-links"
dockerCmd ( c , "create" , "--name" , name , "busybox" , "top" )
hc , err := inspectFieldJSON ( name , "HostConfig" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-07-21 15:18:56 -04:00
config := ` { "HostConfig": ` + hc + ` } `
2015-07-23 07:24:14 -04:00
res , b , err := sockRequestRaw ( "POST" , "/containers/" + name + "/start" , strings . NewReader ( config ) , "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusNoContent )
2015-07-23 07:24:14 -04:00
b . Close ( )
2015-07-21 15:18:56 -04:00
}
// #14640
func ( s * DockerSuite ) TestPostContainersStartWithLinksInHostConfig ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-21 15:18:56 -04:00
name := "test-host-config-links"
dockerCmd ( c , "run" , "--name" , "foo" , "-d" , "busybox" , "top" )
dockerCmd ( c , "create" , "--name" , name , "--link" , "foo:bar" , "busybox" , "top" )
hc , err := inspectFieldJSON ( name , "HostConfig" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-07-21 15:18:56 -04:00
config := ` { "HostConfig": ` + hc + ` } `
2015-07-23 07:24:14 -04:00
res , b , err := sockRequestRaw ( "POST" , "/containers/" + name + "/start" , strings . NewReader ( config ) , "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusNoContent )
2015-07-23 07:24:14 -04:00
b . Close ( )
2015-07-21 15:18:56 -04:00
}
// #14640
func ( s * DockerSuite ) TestPostContainersStartWithLinksInHostConfigIdLinked ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-21 15:18:56 -04:00
name := "test-host-config-links"
out , _ := dockerCmd ( c , "run" , "--name" , "link0" , "-d" , "busybox" , "top" )
id := strings . TrimSpace ( out )
dockerCmd ( c , "create" , "--name" , name , "--link" , id , "busybox" , "top" )
hc , err := inspectFieldJSON ( name , "HostConfig" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-07-21 15:18:56 -04:00
config := ` { "HostConfig": ` + hc + ` } `
2015-07-23 07:24:14 -04:00
res , b , err := sockRequestRaw ( "POST" , "/containers/" + name + "/start" , strings . NewReader ( config ) , "application/json" )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusNoContent )
2015-07-23 07:24:14 -04:00
b . Close ( )
2015-07-21 15:18:56 -04:00
}
2015-07-25 07:39:13 -04:00
// #14915
func ( s * DockerSuite ) TestContainersApiCreateNoHostConfig118 ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-25 07:39:13 -04:00
config := struct {
Image string
} { "busybox" }
status , _ , err := sockRequest ( "POST" , "/v1.18/containers/create" , config )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusCreated )
2015-07-25 07:39:13 -04:00
}
2015-07-24 17:12:55 -04:00
// Ensure an error occurs when you have a container read-only rootfs but you
// extract an archive to a symlink in a writable volume which points to a
// directory outside of the volume.
func ( s * DockerSuite ) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs ( c * check . C ) {
2015-09-18 13:41:12 -04:00
// Requires local volume mount bind.
// --read-only + userns has remount issues
testRequires ( c , SameHostDaemon , NotUserNamespace )
2015-07-24 17:12:55 -04:00
testVol := getTestDir ( c , "test-put-container-archive-err-symlink-in-volume-to-read-only-rootfs-" )
defer os . RemoveAll ( testVol )
makeTestContentInDir ( c , testVol )
cID := makeTestContainer ( c , testContainerOptions {
readOnly : true ,
volumes : defaultVolumes ( testVol ) , // Our bind mount is at /vol2
} )
defer deleteContainer ( cID )
// Attempt to extract to a symlink in the volume which points to a
// directory outside the volume. This should cause an error because the
// rootfs is read-only.
query := make ( url . Values , 1 )
query . Set ( "path" , "/vol2/symlinkToAbsDir" )
urlPath := fmt . Sprintf ( "/v1.20/containers/%s/archive?%s" , cID , query . Encode ( ) )
statusCode , body , err := sockRequest ( "PUT" , urlPath , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
2015-07-24 17:12:55 -04:00
if ! isCpCannotCopyReadOnly ( fmt . Errorf ( string ( body ) ) ) {
c . Fatalf ( "expected ErrContainerRootfsReadonly error, but got %d: %s" , statusCode , string ( body ) )
}
}
2015-09-18 12:39:14 -04:00
func ( s * DockerSuite ) TestContainersApiGetContainersJSONEmpty ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
status , body , err := sockRequest ( "GET" , "/containers/json?all=1" , nil )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusOK )
c . Assert ( string ( body ) , checker . Equals , "[]\n" )
2015-09-18 12:39:14 -04:00
}
2015-09-08 14:40:55 -04:00
func ( s * DockerSuite ) TestPostContainersCreateWithWrongCpusetValues ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
c1 := struct {
Image string
CpusetCpus string
} { "busybox" , "1-42,," }
name := "wrong-cpuset-cpus"
status , body , err := sockRequest ( "POST" , "/containers/create?name=" + name , c1 )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusInternalServerError )
2015-09-08 14:40:55 -04:00
expected := "Invalid value 1-42,, for cpuset cpus.\n"
2015-11-18 19:37:42 -05:00
c . Assert ( string ( body ) , checker . Equals , expected )
2015-09-08 14:40:55 -04:00
c2 := struct {
Image string
CpusetMems string
} { "busybox" , "42-3,1--" }
name = "wrong-cpuset-mems"
status , body , err = sockRequest ( "POST" , "/containers/create?name=" + name , c2 )
2015-11-18 19:37:42 -05:00
c . Assert ( err , checker . IsNil )
c . Assert ( status , checker . Equals , http . StatusInternalServerError )
2015-09-08 14:40:55 -04:00
expected = "Invalid value 42-3,1-- for cpuset mems.\n"
2015-11-18 19:37:42 -05:00
c . Assert ( string ( body ) , checker . Equals , expected )
2015-09-08 14:40:55 -04:00
}
2015-11-30 17:44:34 -05:00
func ( s * DockerSuite ) TestStartWithNilDNS ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
out , _ := dockerCmd ( c , "create" , "busybox" )
containerID := strings . TrimSpace ( out )
config := ` { "HostConfig": { "Dns": null}} `
res , b , err := sockRequestRaw ( "POST" , "/containers/" + containerID + "/start" , strings . NewReader ( config ) , "application/json" )
c . Assert ( err , checker . IsNil )
c . Assert ( res . StatusCode , checker . Equals , http . StatusNoContent )
b . Close ( )
dns , err := inspectFieldJSON ( containerID , "HostConfig.Dns" )
c . Assert ( err , checker . IsNil )
c . Assert ( dns , checker . Equals , "[]" )
}
2015-11-26 07:14:09 -05:00
func ( s * DockerSuite ) TestPostContainersCreateShmSizeNegative ( c * check . C ) {
config := map [ string ] interface { } {
"Image" : "busybox" ,
"HostConfig" : map [ string ] interface { } { "ShmSize" : - 1 } ,
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusInternalServerError )
c . Assert ( string ( body ) , checker . Contains , "SHM size must be greater then 0" )
}
func ( s * DockerSuite ) TestPostContainersCreateShmSizeZero ( c * check . C ) {
config := map [ string ] interface { } {
"Image" : "busybox" ,
"HostConfig" : map [ string ] interface { } { "ShmSize" : 0 } ,
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusInternalServerError )
c . Assert ( string ( body ) , checker . Contains , "SHM size must be greater then 0" )
}
func ( s * DockerSuite ) TestPostContainersCreateShmSizeHostConfigOmitted ( c * check . C ) {
2015-12-02 15:43:51 -05:00
var defaultSHMSize int64 = 67108864
2015-11-26 07:14:09 -05:00
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Cmd" : "mount" ,
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusCreated )
var container types . ContainerCreateResponse
c . Assert ( json . Unmarshal ( body , & container ) , check . IsNil )
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusOK )
var containerJSON types . ContainerJSON
c . Assert ( json . Unmarshal ( body , & containerJSON ) , check . IsNil )
2015-12-02 15:43:51 -05:00
c . Assert ( * containerJSON . HostConfig . ShmSize , check . Equals , defaultSHMSize )
2015-11-26 07:14:09 -05:00
out , _ := dockerCmd ( c , "start" , "-i" , containerJSON . ID )
shmRegexp := regexp . MustCompile ( ` shm on /dev/shm type tmpfs(.*)size=65536k ` )
if ! shmRegexp . MatchString ( out ) {
c . Fatalf ( "Expected shm of 64MB in mount command, got %v" , out )
}
}
func ( s * DockerSuite ) TestPostContainersCreateShmSizeOmitted ( c * check . C ) {
config := map [ string ] interface { } {
"Image" : "busybox" ,
"HostConfig" : map [ string ] interface { } { } ,
"Cmd" : "mount" ,
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusCreated )
var container types . ContainerCreateResponse
c . Assert ( json . Unmarshal ( body , & container ) , check . IsNil )
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusOK )
var containerJSON types . ContainerJSON
c . Assert ( json . Unmarshal ( body , & containerJSON ) , check . IsNil )
2015-12-01 11:51:18 -05:00
c . Assert ( * containerJSON . HostConfig . ShmSize , check . Equals , int64 ( 67108864 ) )
2015-11-26 07:14:09 -05:00
out , _ := dockerCmd ( c , "start" , "-i" , containerJSON . ID )
shmRegexp := regexp . MustCompile ( ` shm on /dev/shm type tmpfs(.*)size=65536k ` )
if ! shmRegexp . MatchString ( out ) {
c . Fatalf ( "Expected shm of 64MB in mount command, got %v" , out )
}
}
func ( s * DockerSuite ) TestPostContainersCreateWithShmSize ( c * check . C ) {
config := map [ string ] interface { } {
"Image" : "busybox" ,
"Cmd" : "mount" ,
"HostConfig" : map [ string ] interface { } { "ShmSize" : 1073741824 } ,
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusCreated )
var container types . ContainerCreateResponse
c . Assert ( json . Unmarshal ( body , & container ) , check . IsNil )
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusOK )
var containerJSON types . ContainerJSON
c . Assert ( json . Unmarshal ( body , & containerJSON ) , check . IsNil )
c . Assert ( * containerJSON . HostConfig . ShmSize , check . Equals , int64 ( 1073741824 ) )
out , _ := dockerCmd ( c , "start" , "-i" , containerJSON . ID )
shmRegex := regexp . MustCompile ( ` shm on /dev/shm type tmpfs(.*)size=1048576k ` )
if ! shmRegex . MatchString ( out ) {
c . Fatalf ( "Expected shm of 1GB in mount command, got %v" , out )
}
}
func ( s * DockerSuite ) TestPostContainersCreateMemorySwappinessHostConfigOmitted ( c * check . C ) {
config := map [ string ] interface { } {
"Image" : "busybox" ,
}
status , body , err := sockRequest ( "POST" , "/containers/create" , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusCreated )
var container types . ContainerCreateResponse
c . Assert ( json . Unmarshal ( body , & container ) , check . IsNil )
status , body , err = sockRequest ( "GET" , "/containers/" + container . ID + "/json" , nil )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusOK )
var containerJSON types . ContainerJSON
c . Assert ( json . Unmarshal ( body , & containerJSON ) , check . IsNil )
2015-12-01 21:53:52 -05:00
c . Assert ( * containerJSON . HostConfig . MemorySwappiness , check . Equals , int64 ( - 1 ) )
2015-11-26 07:14:09 -05:00
}
2015-10-13 05:26:27 -04:00
// check validation is done daemon side and not only in cli
func ( s * DockerSuite ) TestPostContainersCreateWithOomScoreAdjInvalidRange ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
config := struct {
Image string
OomScoreAdj int
} { "busybox" , 1001 }
name := "oomscoreadj-over"
status , b , err := sockRequest ( "POST" , "/containers/create?name=" + name , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusInternalServerError )
expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]."
if ! strings . Contains ( string ( b ) , expected ) {
c . Fatalf ( "Expected output to contain %q, got %q" , expected , string ( b ) )
}
config = struct {
Image string
OomScoreAdj int
} { "busybox" , - 1001 }
name = "oomscoreadj-low"
status , b , err = sockRequest ( "POST" , "/containers/create?name=" + name , config )
c . Assert ( err , check . IsNil )
c . Assert ( status , check . Equals , http . StatusInternalServerError )
expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]."
if ! strings . Contains ( string ( b ) , expected ) {
c . Fatalf ( "Expected output to contain %q, got %q" , expected , string ( b ) )
}
}