Initial commit

This commit is contained in:
Ria Bhatia
2017-12-04 13:32:57 -06:00
committed by Erik St. Martin
commit 0075e5b0f3
9056 changed files with 2523100 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
*.log
*.bak

View File

@@ -0,0 +1,29 @@
Extra Test Case for hyper cli
=============================
# auth test
> filename: `cli_ex_auth_test.go`
## test case 1: different clock between hyper client and apirouter server
```
1) difftime < 5min : valid request
2) difftime >= 5min : invalid request, should return `Unauthorized, illegal timestamp`
```
# config test
```
//TODO
```
# fip test
```
//TODO
```
# snapshot test
```
//TODO
```

408
vendor/github.com/hyperhq/hypercli/integration-cli/README.md generated vendored Executable file
View File

@@ -0,0 +1,408 @@
Integration test for hyper cli
==================================
Functional test for hyper cli.
> use apirouter service on packet(dev env) or zenlayer(online env) as backend.
<!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
- [Project status](#project-status)
- [cli test case](#cli-test-case)
- [api test case](#api-test-case)
- [extra](#extra)
- [skip](#skip)
- [Test case name](#test-case-name)
- [Command list](#command-list)
- [hyper only](#hyper-only)
- [both](#both)
- [docker only](#docker-only)
- [Run test case](#run-test-case)
- [Clone hypercli repo](#clone-hypercli-repo)
- [Run test in docker container for dev](#run-test-in-docker-container-for-dev)
- [build docker image for dev](#build-docker-image-for-dev)
- [make hyper cli](#make-hyper-cli)
- [enter container](#enter-container)
- [run test in container](#run-test-in-container)
- [Run test on localhost for dev](#run-test-on-localhost-for-dev)
- [prepare](#prepare)
- [run test case](#run-test-case)
- [Run test in docker container for qa](#run-test-in-docker-container-for-qa)
- [build docker image for qa](#build-docker-image-for-qa)
- [run test in docker container](#run-test-in-docker-container)
- [run test via util.sh](#run-test-via-utilsh)
- [run test via docker cli](#run-test-via-docker-cli)
- [run test via hyper cli](#run-test-via-hyper-cli)
<!-- /TOC -->
# Project status
## cli test case
- [ ] cli_attach_test
- [ ] cli_attach_unix_test
- [x] cli_config_test
- [x] cli_create_test
- [x] cli_commit_test
- [x] cli_exec_test
- [x] cli_exec_unix_test
- [x] cli_fip_test
- [x] cli_help_test
- [x] cli_history_test
- [x] cli_images_test
- [x] cli_info_test
- [x] cli_inspect_experimental_test
- [x] cli_inspect_test
- [x] cli_kill_test
- [x] cli_links_test
- [ ] cli_links_unix_test
- [x] cli_load_basic_test
- [x] cli_load_large_test
- [x] cli_load_legacy_test
- [x] cli_load_local_test
- [x] cli_login_test
- [x] cli_logs_test
- [x] cli_port_test
- [x] cli_ps_test
- [x] cli_pull_test
- [x] cli_push_test
- [x] cli_region_test
- [x] cli_rename_test
- [x] cli_restart_test
- [x] cli_rm_test
- [x] cli_rmi_test
- [x] cli_run_test
- [x] cli_run_unix_test
- [x] cli_search_test
- [x] cli_share_volume_test
- [x] cli_snapshot_test
- [x] cli_start_test
- [ ] cli_stats_test
- [x] cli_version_test
- [x] cli_volume_test
## api test case
- [ ] api_attach_test
- [ ] api_containers_test
- [x] api_create_test
- [x] api_exec_test
- [x] api_exec_resize_test
- [x] api_images_test
- [x] api_info_test
- [x] api_inspect_test
- [x] api_logs_test
- [x] api_stats_test
- [x] api_snapshots_test
- [x] api_version_test
- [x] api_volumes_test
## extra
[Extra Test Case](EXTRA_TEST.md)
## skip
> not support build, tag
- [ ] cli_authz_unix_test
- [ ] cli_build_test
- [ ] cli_build_unix_test
- [ ] cli_by_digest_test
- [ ] cli_cp_from_container_test
- [ ] cli_cp_test
- [ ] cli_cp_to_container_test
- [ ] cli_cp_utils
- [ ] cli_daemon_test
- [ ] cli_diff_test
- [ ] cli_events_test
- [ ] cli_events_unix_test
- [ ] cli_experimental_test
- [ ] cli_export_import_test
- [ ] cli_external_graphdriver_unix_test
- [ ] cli_import_test
- [ ] cli_nat_test
- [ ] cli_netmode_test
- [ ] cli_network_unix_test
- [ ] cli_oom_killed_test
- [ ] cli_pause_test
- [ ] cli_proxy_test
- [ ] cli_pull_local_test
- [ ] cli_pull_trusted_test
- [ ] cli_save_load_test
- [ ] cli_save_load_unix_test
- [ ] cli_sni_test
- [ ] cli_start_volume_driver_unix_test
- [ ] cli_tag_test
- [ ] cli_top_test
- [ ] cli_update_unix_test
- [ ] cli_v2_only_test
- [ ] cli_volume_driver_compat_unix_test
- [ ] cli_wait_test
# Test case name
- TestCliConfig
- TestCliCreate
- TestCliCommit
- TestCliExec
- TestCliFip
- TestCliHelp
- TestCliHistory
- TestCliInfo
- TestCliInspect
- TestCliKill
- TestCliLinks
- TestCliLoadFromUrl
- TestCliLoadFromLocal
- TestCliLogin
- TestCliLogs
- TestCliPort
- TestCliPs
- TestCliPull
- TestCliPush
- TestCliRename
- TestCliRestart
- TestCliRmi
- TestCliRm
- TestCliRun
- TestCliSearch
- TestCliSnapshot
- TestCliStart
- TestCliVersion
- TestCliVolume
# Command list
## hyper only
```
config fip snapshot
```
## both
```
attach create exec history images
info inspect kill login logout
logs port ps pull rename
restart rm rmi run search
start stats stop version volume
```
## docker only
> not support for hyper currently
```
build commit cp diff events
export import load network pause
push save tag top unpause
update wait
```
# Run test case
## Clone hypercli repo
```
$ git clone https://github.com/hyperhq/hypercli.git
```
## Run test in docker container for dev
### build docker image for dev
> build docker image in host OS
> Use `CentOS` as test env
> Image name is `hyperhq/hypercli-auto-test:dev`
```
// run in dir hypercli/integration-cli on host os
$ ./util.sh build-dev
```
### make hyper cli
> build hyper cli binary from source code
```
// run in dir hypercli/integration-cli on host os
$ ./util.sh make
```
### enter container
> update `ACCESS_KEY` and `SECRET_KEY` in `integration-cli/util.conf`
```
// run in dir hypercli/integration-cli on host os
$ ./util.sh enter
```
### run test in container
```
$ ./util.sh test all
```
## Run test on localhost for dev
### prepare
```
// ensure hyperhq and docker dir
mkdir -p $GOPATH/src/github.com/{hyperhq,docker}
// clone and build hypercli
cd $GOPATH/src/github.com/hyperhq
git clone git@github.com:hyperhq/hypercli.git
cd hypercli
./build.sh
// copy hyper binary to /usr/bin/hyper
sudo cp hyper/hyper /usr/bin/hyper
// create link
cd $GOPATH/src/github.com/docker
ln -s ../hyperhq/hypercli docker
// generate util.conf
$ cd $GOPATH/src/github.com/hyperhq/hypercli
$ git checkout integration-test
$ cd integration-cli
$ ./util.sh
// config util.conf
$ vi util.conf
ACCESS_KEY="<hyper access key>"
SECRET_KEY="<hyper secret key>"
```
### run test case
```
// run all test cases
$ ./util.sh test all
// run test case with timeout
$ ./util.sh test all -timout 20m
// run specified test case
$ ./util.sh test -check.f ^TestCliLoadFromLocalTar$
// run test cases start with specified prefix
$ ./util.sh test -check.f TestCliLoadFromLocalTar
// combined use
$ ./util.sh test -check.f 'TestCliLoadFromLocalTarEmpty|TestCliLoadFromLocalPullAndLoad' -timeout 20m
```
## Run test in docker container for qa
### build docker image for qa
> build docker image in host OS
> Use `CentOS` as test env
> Image name is `hyperhq/hypercli-auto-test:qa`
```
// run in dir hypercli/integration-cli on host os
$ ./util.sh build-qa
```
### run test in docker container
> run all test case for qa
#### run test via util.sh
```
$ cd integration-cli
//test master branch
$ ./util.sh qa
//test integration-test branch
$ ./util.sh qa integration-test
//test PR
$ ./util.sh qa "#222"
```
#### run test via docker cli
Required parameters:
`APIROUTER`: apirouter entrypoint
`REGION`: could be us-west-1(zl2), eu-central-1(eu1), RegionOne(packet)
`ACCESS_KEY`,`SECRET_KEY`: Hyper credential for test
`BRANCH`: hyper cli branch name or PR number
```
//test `master` branch of hypercli with `eu-west-1` apirouter
$ docker run -it --rm \
-e ACCESS_KEY=${ACCESS_KEY} \
-e SECRET_KEY=${SECRET_KEY} \
-e DOCKER_HOST=tcp://us-west-1.hyper.sh:443 \
-e REGION=us-west-1 \
-e BRANCH=master \
hyperhq/hypercli-auto-test:qa go test -check.f TestCli -timeout 180m
//test `specified PR`
$ docker run -it --rm \
-e DOCKER_HOST=${APIROUTER} \
-e REGION=${REGION} \
-e ACCESS_KEY=${ACCESS_KEY} \
-e SECRET_KEY=${SECRET_KEY} \
-e BRANCH="#221" \
hyperhq/hypercli-auto-test:qa go test -check.f TestCli -timeout 180m
//test `specified case name`
$ docker run -it --rm \
-e DOCKER_HOST=${APIROUTER} \
-e REGION=${REGION} \
-e ACCESS_KEY="${ACCESS_KEY}" \
-e SECRET_KEY="${SECRET_KEY}" \
-e BRANCH=${BRANCH} \
hyperhq/hypercli-auto-test:qa go test -check.f 'TestCliInfo|TestCliFip' -timeout 180m
//test with `packet` apirouter
$ docker run -it --rm \
-e ACCESS_KEY=${ACCESS_KEY} \
-e SECRET_KEY=${SECRET_KEY} \
-e BRANCH=${BRANCH} \
-e DOCKER_HOST=tcp://147.75.x.x:6443 \
-e REGION=RegionOne \
hyperhq/hypercli-auto-test:qa go test -check.f TestCli -timeout 180m
//test with http proxy
$ docker run -it --rm \
-e DOCKER_HOST=${APIROUTER} \
-e REGION=${REGION} \
-e ACCESS_KEY=${ACCESS_KEY} \
-e SECRET_KEY=${SECRET_KEY} \
-e BRANCH=${BRANCH} \
-e http_proxy=${http_proxy} \
-e https_proxy=${https_proxy} \
hyperhq/hypercli-auto-test:qa go test -check.f TestCliInfo
//test basic test case only
$ docker run -it --rm \
-e DOCKER_HOST=${APIROUTER} \
-e REGION=${REGION} \
-e ACCESS_KEY=${ACCESS_KEY} \
-e SECRET_KEY=${SECRET_KEY} \
-e BRANCH=${BRANCH} \
hyperhq/hypercli-auto-test:qa go test -check.f "TestCli.*Basic" -timeout 180m
```
#### run test via hyper cli
Just replace `docker` with `hyper` in command line.

View File

@@ -0,0 +1,187 @@
package main
import (
"os"
"fmt"
"testing"
"github.com/docker/docker/pkg/reexec"
"github.com/go-check/check"
)
func Test(t *testing.T) {
reexec.Init() // This is required for external graphdriver tests
if !isLocalDaemon {
fmt.Printf("INFO: Testing against a remote daemon(%v)\n",os.Getenv("DOCKER_HOST"))
} else {
fmt.Println("INFO: Testing against a local daemon")
}
check.TestingT(t)
}
func init() {
check.Suite(&DockerSuite{})
}
type DockerSuite struct {
}
//status only support : created, restarting, running, exited (https://github.com/getdvm/hyper-api-router/blob/master/pkg/apiserver/router/local/container.go#L204)
func (s *DockerSuite) TearDownTest(c *check.C) {
//unpauseAllContainers()
deleteAllContainers()
deleteAllImages()
deleteAllSnapshots()
deleteAllVolumes()
deleteAllFips()
//deleteAllNetworks()
}
func init() {
check.Suite(&DockerRegistrySuite{
ds: &DockerSuite{},
})
fmt.Printf("INFO: clear resources(containers, images, snapshots, volumes, fips)\n")
deleteAllContainers()
deleteAllImages()
deleteAllSnapshots()
deleteAllVolumes()
deleteAllFips()
fmt.Println("INFO: finish init")
}
type DockerRegistrySuite struct {
ds *DockerSuite
reg *testRegistryV2
//d *Daemon
}
func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux, RegistryHosting)
s.reg = setupRegistry(c, false, false)
//s.d = NewDaemon(c)
}
func (s *DockerRegistrySuite) TearDownTest(c *check.C) {
if s.reg != nil {
s.reg.Close()
}
//if s.d != nil {
// s.d.Stop()
//}
s.ds.TearDownTest(c)
}
func init() {
check.Suite(&DockerSchema1RegistrySuite{
ds: &DockerSuite{},
})
}
type DockerSchema1RegistrySuite struct {
ds *DockerSuite
reg *testRegistryV2
//d *Daemon
}
func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux, RegistryHosting)
s.reg = setupRegistry(c, true, false)
//s.d = NewDaemon(c)
}
func (s *DockerSchema1RegistrySuite) TearDownTest(c *check.C) {
if s.reg != nil {
s.reg.Close()
}
//if s.d != nil {
// s.d.Stop()
//}
s.ds.TearDownTest(c)
}
func init() {
check.Suite(&DockerRegistryAuthSuite{
ds: &DockerSuite{},
})
}
type DockerRegistryAuthSuite struct {
ds *DockerSuite
reg *testRegistryV2
//d *Daemon
}
func (s *DockerRegistryAuthSuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux, RegistryHosting)
s.reg = setupRegistry(c, false, true)
//s.d = NewDaemon(c)
}
func (s *DockerRegistryAuthSuite) TearDownTest(c *check.C) {
if s.reg != nil {
//out, err := s.d.Cmd("logout", privateRegistryURL)
//c.Assert(err, check.IsNil, check.Commentf(out))
s.reg.Close()
}
//if s.d != nil {
// s.d.Stop()
//}
s.ds.TearDownTest(c)
}
func init() {
check.Suite(&DockerDaemonSuite{
ds: &DockerSuite{},
})
}
type DockerDaemonSuite struct {
ds *DockerSuite
//d *Daemon
}
func (s *DockerDaemonSuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux)
//s.d = NewDaemon(c)
}
func (s *DockerDaemonSuite) TearDownTest(c *check.C) {
testRequires(c, DaemonIsLinux)
//if s.d != nil {
// s.d.Stop()
//}
s.ds.TearDownTest(c)
}
func init() {
check.Suite(&DockerTrustSuite{
ds: &DockerSuite{},
})
}
type DockerTrustSuite struct {
ds *DockerSuite
reg *testRegistryV2
not *testNotary
}
func (s *DockerTrustSuite) SetUpTest(c *check.C) {
testRequires(c, RegistryHosting, NotaryHosting)
s.reg = setupRegistry(c, false, false)
s.not = setupNotary(c)
}
func (s *DockerTrustSuite) TearDownTest(c *check.C) {
if s.reg != nil {
s.reg.Close()
}
if s.not != nil {
s.not.Close()
}
s.ds.TearDownTest(c)
}

View File

@@ -0,0 +1,93 @@
package main
import (
"os"
"os/exec"
"runtime"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func init() {
// FIXME. Temporarily turning this off for Windows as GH16039 was breaking
// Windows to Linux CI @icecrime
if runtime.GOOS != "windows" {
check.Suite(newDockerHubPullSuite())
}
}
// DockerHubPullSuite provides a isolated daemon that doesn't have all the
// images that are baked into our 'global' test environment daemon (e.g.,
// busybox, httpserver, ...).
//
// We use it for push/pull tests where we want to start fresh, and measure the
// relative impact of each individual operation. As part of this suite, all
// images are removed after each test.
type DockerHubPullSuite struct {
d *Daemon
ds *DockerSuite
}
// newDockerHubPullSuite returns a new instance of a DockerHubPullSuite.
func newDockerHubPullSuite() *DockerHubPullSuite {
return &DockerHubPullSuite{
ds: &DockerSuite{},
}
}
// SetUpSuite starts the suite daemon.
func (s *DockerHubPullSuite) SetUpSuite(c *check.C) {
/*
testRequires(c, DaemonIsLinux)
err := s.d.Start()
c.Assert(err, checker.IsNil, check.Commentf("starting push/pull test daemon: %v", err))
*/
}
// TearDownSuite stops the suite daemon.
func (s *DockerHubPullSuite) TearDownSuite(c *check.C) {
if s.d != nil {
err := s.d.Stop()
c.Assert(err, checker.IsNil, check.Commentf("stopping push/pull test daemon: %v", err))
}
}
// SetUpTest declares that all tests of this suite require network.
func (s *DockerHubPullSuite) SetUpTest(c *check.C) {
testRequires(c, Network)
}
// TearDownTest removes all images from the suite daemon.
func (s *DockerHubPullSuite) TearDownTest(c *check.C) {
out := s.Cmd(c, "images", "-aq")
images := strings.Split(out, "\n")
images = append([]string{"-f"}, images...)
s.d.Cmd("rmi", images...)
s.ds.TearDownTest(c)
}
// Cmd executes a command against the suite daemon and returns the combined
// output. The function fails the test when the command returns an error.
func (s *DockerHubPullSuite) Cmd(c *check.C, name string, arg ...string) string {
out, err := s.CmdWithError(name, arg...)
c.Assert(err, checker.IsNil, check.Commentf("%q failed with errors: %s, %v", strings.Join(arg, " "), out, err))
return out
}
// CmdWithError executes a command against the suite daemon and returns the
// combined output as well as any error.
func (s *DockerHubPullSuite) CmdWithError(name string, arg ...string) (string, error) {
c := s.MakeCmd(name, arg...)
b, err := c.CombinedOutput()
return string(b), err
}
// MakeCmd returns a exec.Cmd command to run against the suite daemon.
func (s *DockerHubPullSuite) MakeCmd(name string, arg ...string) *exec.Cmd {
//args := []string{"--region", s.d.sock(), name}
args := []string{"--region", os.Getenv("DOCKER_HOST"), name}
args = append(args, arg...)
return exec.Command(dockerBinary, args...)
}

View File

@@ -0,0 +1,131 @@
package main
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"github.com/docker/docker/pkg/reexec"
)
var (
// the docker binary to use
dockerBinary = "hyper"
//debugEndpoint = "/version"
debugEndpoint = ""
// the private registry image to use for tests involving the registry
registryImageName = "registry"
//image for testing port related test case
singlePortImage = "hyperhq/test-port-single"
multiPortImage = "hyperhq/test-port-list"
rangePortImage = "hyperhq/test-port-range"
mixPortocalPortImage = "hyperhq/test-port-mix"
// the private registry to use for tests
privateRegistryURL = "127.0.0.1:5000"
// TODO Windows CI. These are incorrect and need fixing into
// platform specific pieces.
runtimePath = "/var/run/docker"
execDriverPath = runtimePath + "/execdriver/native"
workingDirectory string
// isLocalDaemon is true if the daemon under test is on the same
// host as the CLI.
isLocalDaemon bool
// daemonPlatform is held globally so that tests can make intelligent
// decisions on how to configure themselves according to the platform
// of the daemon. This is initialized in docker_utils by sending
// a version call to the daemon and examining the response header.
daemonPlatform string
// windowsDaemonKV is used on Windows to distinguish between different
// versions. This is necessary to enable certain tests based on whether
// the platform supports it. For example, Windows Server 2016 TP3 does
// not support volumes, but TP4 does.
windowsDaemonKV int
// daemonDefaultImage is the name of the default image to use when running
// tests. This is platform dependent.
daemonDefaultImage string
// For a local daemon on Linux, these values will be used for testing
// user namespace support as the standard graph path(s) will be
// appended with the root remapped uid.gid prefix
dockerBasePath string
volumesConfigPath string
containerStoragePath string
)
const (
// WindowsBaseImage is the name of the base image for Windows testing
WindowsBaseImage = "windowsservercore"
// DefaultImage is the name of the base image for the majority of tests that
// are run across suites
DefaultImage = "busybox"
)
func init() {
reexec.Init()
if dockerBin := os.Getenv("DOCKER_BINARY"); dockerBin != "" {
dockerBinary = dockerBin
}
var err error
dockerBinary, err = exec.LookPath(dockerBinary)
if err != nil {
fmt.Printf("ERROR: couldn't resolve full path to the Docker binary (%v)", err)
os.Exit(1)
}
if registryImage := os.Getenv("REGISTRY_IMAGE"); registryImage != "" {
registryImageName = registryImage
}
if registry := os.Getenv("REGISTRY_URL"); registry != "" {
privateRegistryURL = registry
}
workingDirectory, _ = os.Getwd()
// Deterministically working out the environment in which CI is running
// to evaluate whether the daemon is local or remote is not possible through
// a build tag.
//
// For example Windows to Linux CI under Jenkins tests the 64-bit
// Windows binary build with the daemon build tag, but calls a remote
// Linux daemon.
//
// We can't just say if Windows then assume the daemon is local as at
// some point, we will be testing the Windows CLI against a Windows daemon.
//
// Similarly, it will be perfectly valid to also run CLI tests from
// a Linux CLI (built with the daemon tag) against a Windows daemon.
if len(os.Getenv("DOCKER_REMOTE_DAEMON")) > 0 {
isLocalDaemon = false
} else {
isLocalDaemon = true
}
// TODO Windows CI. This are incorrect and need fixing into
// platform specific pieces.
// This is only used for a tests with local daemon true (Linux-only today)
// default is "/var/lib/docker", but we'll try and ask the
// /info endpoint for the specific root dir
dockerBasePath = "/var/lib/docker"
type Info struct {
DockerRootDir string
}
var i Info
status, b, err := sockRequest("GET", "/info", nil)
if err == nil && status == 200 {
if err = json.Unmarshal(b, &i); err == nil {
dockerBasePath = i.DockerRootDir
}
}
volumesConfigPath = dockerBasePath + "/volumes"
containerStoragePath = dockerBasePath + "/containers"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"os/exec"
"regexp"
"strconv"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
var (
reTimestamp = `\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{9}(:?(:?(:?-|\+)\d{2}:\d{2})|Z)`
reEventType = `(?P<eventType>\w+)`
reAction = `(?P<action>\w+)`
reID = `(?P<id>[^\s]+)`
reAttributes = `(\s\((?P<attributes>[^\)]+)\))?`
reString = fmt.Sprintf(`\A%s\s%s\s%s\s%s%s\z`, reTimestamp, reEventType, reAction, reID, reAttributes)
// eventCliRegexp is a regular expression that matches all possible event outputs in the cli
eventCliRegexp = regexp.MustCompile(reString)
)
// eventMatcher is a function that tries to match an event input.
// It returns true if the event matches and a map with
// a set of key/value to identify the match.
type eventMatcher func(text string) (map[string]string, bool)
// eventMatchProcessor is a function to handle an event match.
// It receives a map of key/value with the information extracted in a match.
type eventMatchProcessor func(matches map[string]string)
// eventObserver runs an events commands and observes its output.
type eventObserver struct {
buffer *bytes.Buffer
command *exec.Cmd
scanner *bufio.Scanner
startTime string
disconnectionError error
}
// newEventObserver creates the observer and initializes the command
// without running it. Users must call `eventObserver.Start` to start the command.
func newEventObserver(c *check.C, args ...string) (*eventObserver, error) {
since := daemonTime(c).Unix()
return newEventObserverWithBacklog(c, since, args...)
}
// newEventObserverWithBacklog creates a new observer changing the start time of the backlog to return.
func newEventObserverWithBacklog(c *check.C, since int64, args ...string) (*eventObserver, error) {
startTime := strconv.FormatInt(since, 10)
cmdArgs := []string{"events", "--since", startTime}
if len(args) > 0 {
cmdArgs = append(cmdArgs, args...)
}
eventsCmd := exec.Command(dockerBinary, cmdArgs...)
stdout, err := eventsCmd.StdoutPipe()
if err != nil {
return nil, err
}
return &eventObserver{
buffer: new(bytes.Buffer),
command: eventsCmd,
scanner: bufio.NewScanner(stdout),
startTime: startTime,
}, nil
}
// Start starts the events command.
func (e *eventObserver) Start() error {
return e.command.Start()
}
// Stop stops the events command.
func (e *eventObserver) Stop() {
e.command.Process.Kill()
e.command.Process.Release()
}
// Match tries to match the events output with a given matcher.
func (e *eventObserver) Match(match eventMatcher, process eventMatchProcessor) {
for e.scanner.Scan() {
text := e.scanner.Text()
e.buffer.WriteString(text)
e.buffer.WriteString("\n")
if matches, ok := match(text); ok {
process(matches)
}
}
err := e.scanner.Err()
if err == nil {
err = io.EOF
}
logrus.Debug("EventObserver scanner loop finished: %v", err)
e.disconnectionError = err
}
func (e *eventObserver) CheckEventError(c *check.C, id, event string, match eventMatcher) {
var foundEvent bool
scannerOut := e.buffer.String()
if e.disconnectionError != nil {
until := strconv.FormatInt(daemonTime(c).Unix(), 10)
out, _ := dockerCmd(c, "events", "--since", e.startTime, "--until", until)
events := strings.Split(strings.TrimSpace(out), "\n")
for _, e := range events {
if _, ok := match(e); ok {
foundEvent = true
break
}
}
scannerOut = out
}
if !foundEvent {
c.Fatalf("failed to observe event `%s` for %s. Disconnection error: %v\nout:\n%v", event, id, e.disconnectionError, scannerOut)
}
}
// matchEventLine matches a text with the event regular expression.
// It returns the matches and true if the regular expression matches with the given id and event type.
// It returns an empty map and false if there is no match.
func matchEventLine(id, eventType string, actions map[string]chan bool) eventMatcher {
return func(text string) (map[string]string, bool) {
matches := parseEventText(text)
if len(matches) == 0 {
return matches, false
}
if matchIDAndEventType(matches, id, eventType) {
if _, ok := actions[matches["action"]]; ok {
return matches, true
}
}
return matches, false
}
}
// processEventMatch closes an action channel when an event line matches the expected action.
func processEventMatch(actions map[string]chan bool) eventMatchProcessor {
return func(matches map[string]string) {
if ch, ok := actions[matches["action"]]; ok {
close(ch)
}
}
}
// parseEventText parses a line of events coming from the cli and returns
// the matchers in a map.
func parseEventText(text string) map[string]string {
matches := eventCliRegexp.FindAllStringSubmatch(text, -1)
md := map[string]string{}
if len(matches) == 0 {
return md
}
names := eventCliRegexp.SubexpNames()
for i, n := range matches[0] {
md[names[i]] = n
}
return md
}
// parseEventAction parses an event text and returns the action.
// It fails if the text is not in the event format.
func parseEventAction(c *check.C, text string) string {
matches := parseEventText(text)
return matches["action"]
}
// eventActionsByIDAndType returns the actions for a given id and type.
// It fails if the text is not in the event format.
func eventActionsByIDAndType(c *check.C, events []string, id, eventType string) []string {
var filtered []string
for _, event := range events {
matches := parseEventText(event)
c.Assert(matches, checker.Not(checker.IsNil))
if matchIDAndEventType(matches, id, eventType) {
filtered = append(filtered, matches["action"])
}
}
return filtered
}
// matchIDAndEventType returns true if an event matches a given id and type.
// It also resolves names in the event attributes if the id doesn't match.
func matchIDAndEventType(matches map[string]string, id, eventType string) bool {
return matchEventID(matches, id) && matches["eventType"] == eventType
}
func matchEventID(matches map[string]string, id string) bool {
matchID := matches["id"] == id || strings.HasPrefix(matches["id"], id)
if !matchID && matches["attributes"] != "" {
// try matching a name in the attributes
attributes := map[string]string{}
for _, a := range strings.Split(matches["attributes"], ", ") {
kv := strings.Split(a, "=")
attributes[kv[0]] = kv[1]
}
matchID = attributes["name"] == id
}
return matchID
}
func parseEvents(c *check.C, out, match string) {
events := strings.Split(strings.TrimSpace(out), "\n")
for _, event := range events {
matches := parseEventText(event)
matched, err := regexp.MatchString(match, matches["action"])
c.Assert(err, checker.IsNil)
c.Assert(matched, checker.True, check.Commentf("Matcher: %s did not match %s", match, matches["action"]))
}
}
func parseEventsWithID(c *check.C, out, match, id string) {
events := strings.Split(strings.TrimSpace(out), "\n")
for _, event := range events {
matches := parseEventText(event)
c.Assert(matchEventID(matches, id), checker.True)
matched, err := regexp.MatchString(match, matches["action"])
c.Assert(err, checker.IsNil)
c.Assert(matched, checker.True, check.Commentf("Matcher: %s did not match %s", match, matches["action"]))
}
}

View File

@@ -0,0 +1,151 @@
package main
import (
"fmt"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"os"
"time"
)
//Prerequisite: update image balance to 2 in tenant collection of hypernetes in mongodb
//db.tenant.update({tenantid:"<tenant_id>"},{$set:{"resourceinfo.balance.images":2}})
func (s *DockerSuite) TestCliLoadUrlBasicFromPublicURLWithQuota(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
deleteAllImages()
helloworldURL := "http://image-tarball.s3.amazonaws.com/test/public/helloworld.tar"
multiImgURL := "http://image-tarball.s3.amazonaws.com/test/public/busybox_alpine.tar"
ubuntuURL := "http://image-tarball.s3.amazonaws.com/test/public/ubuntu.tar.gz"
//exceedQuotaMsg := "Exceeded quota, please either delete images, or email support@hyper.sh to request increased quota"
exceedQuotaMsg := "you do not have enough quota"
///// [init] /////
// balance 3, images 0
out, _ := dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 0")
///// [step 1] load new hello-world image /////
// balance 3 -> 2, image: 0 -> 1
output, exitCode, err := dockerCmdWithError("load", "-i", helloworldURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
checkImage(c, true, "hello-world")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 1")
///// [step 2] load hello-world image again /////
// balance 2 -> 2, image 1 -> 1
output, exitCode, err = dockerCmdWithError("load", "-i", helloworldURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
checkImage(c, true, "hello-world")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 1")
///// [step 3] load multiple image(busybox+alpine) /////
// balance 2 -> 2, image 1 -> 1
output, exitCode, err = dockerCmdWithError("load", "-i", multiImgURL)
c.Assert(output, checker.Contains, exceedQuotaMsg)
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
checkImage(c, false, "busybox")
checkImage(c, false, "alpine")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 1")
///// [step 4] load new ubuntu image /////
// balance 2 -> 1, image 1 -> 2
output, exitCode, err = dockerCmdWithError("load", "-i", ubuntuURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
checkImage(c, true, "ubuntu")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 2")
///// [step 5] remove hello-world image /////
// balance 1 -> 2, image 2 -> 1
images, _ := dockerCmd(c, "rmi", "-f", "hello-world")
c.Assert(images, checker.Contains, "Untagged: hello-world:latest")
checkImage(c, false, "hello-world")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 1")
///// [step 6] remove busybox and ubuntu image /////
// balance 2 -> 3, image 1 -> 0
images, _ = dockerCmd(c, "rmi", "-f", "ubuntu:latest")
c.Assert(images, checker.Contains, "Untagged: ubuntu:latest")
checkImage(c, false, "ubuntu")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 0")
///// [step 7] load multiple image(busybox+alpine) again /////
// balance 3 -> 0, image 0 -> 3
output, exitCode, err = dockerCmdWithError("load", "-i", multiImgURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
checkImage(c, true, "busybox")
checkImage(c, true, "alpine")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 3")
}
func (s *DockerSuite) TestCliLoadUrlBasicFromAWSS3PreSignedURL(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
deleteAllImages()
s3Region := "us-west-1"
s3Bucket := "image-tarball"
s3Key := "test/private/cirros.tar"
preSignedUrl, err_ := generateS3PreSignedURL(s3Region, s3Bucket, s3Key)
c.Assert(err_, checker.IsNil)
time.Sleep(1 * time.Second)
output, err := dockerCmd(c, "load", "-i", preSignedUrl)
if err != 0 {
fmt.Printf("preSignedUrl:[%v]\n", preSignedUrl)
fmt.Printf("output:\n%v\n", output)
}
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.Equals, 0)
checkImage(c, true, "cirros")
}
func (s *DockerSuite) TestCliLoadUrlBasicFromBasicAuthURL(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
urlWithAuth := os.Getenv("URL_WITH_BASIC_AUTH")
c.Assert(urlWithAuth, checker.NotNil)
dockerCmd(c, "load", "-i", urlWithAuth)
images, _ := dockerCmd(c, "images", "ubuntu")
c.Assert(images, checker.Contains, "ubuntu")
}

View File

@@ -0,0 +1,26 @@
package main
import (
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"strings"
)
func (s *DockerSuite) TestCliLoadFromUrlLargeImageArchiveFile(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
imageName := "consol/centos-xfce-vnc";
imageUrl := "http://image-tarball.s3.amazonaws.com/test/public/consol_centos-xfce-vnc.tar"; //1.53GB
output, exitCode, err := dockerCmdWithError("load", "-i", imageUrl)
c.Assert(output, checker.Contains, "Starting to download and load the image archive, please wait...\n")
c.Assert(output, checker.Contains, "has been loaded.\n")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
images, _ := dockerCmd(c, "images")
c.Assert(images, checker.Contains, imageName)
c.Assert(len(strings.Split(images, "\n")), checker.Equals, 3)
}

View File

@@ -0,0 +1,165 @@
package main
import (
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"strings"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"os"
//"fmt"
)
func (s *DockerSuite) TestCliLoadFromUrlLegacyImageArchiveFileWithQuota(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
imageName := "ubuntu";
legacyImageUrl := "http://image-tarball.s3.amazonaws.com/test/public/old/ubuntu_1.8.tar.gz"
imageUrl := "http://image-tarball.s3.amazonaws.com/test/public/ubuntu.tar.gz"
/////////////////////////////////////////////////////////////////////
checkImageQuota(c, 2)
//load legacy image(saved by docker 1.8)
output, exitCode, err := dockerCmdWithError("load", "-i", legacyImageUrl)
c.Assert(output, checker.Contains, "Starting to download and load the image archive, please wait...\n")
c.Assert(output, checker.Contains, "has been loaded.\n")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
output, _ = dockerCmd(c, "images")
c.Assert(output, checker.Contains, imageName)
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 3)
/////////////////////////////////////////////////////////////////////
checkImageQuota(c, 1)
//load new format image(saved by docker 1.10)
output, exitCode, err = dockerCmdWithError("load", "-i", imageUrl)
c.Assert(output, checker.Contains, "Start to download and load the image archive, please wait...\n")
c.Assert(output, checker.Contains, "has been loaded.\n")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
output, _ = dockerCmd(c, "images")
c.Assert(output, checker.Contains, imageName)
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 3)
/////////////////////////////////////////////////////////////////////
checkImageQuota(c, 1)
//delete single layer
output, _ = dockerCmd(c, "images", "-q", imageName)
imageId := strings.Split(output, "\n")[0]
c.Assert(imageId, checker.Not(checker.Equals), "")
output, _ = dockerCmd(c, "rmi", "--no-prune", imageId)
c.Assert(output, checker.Contains, "Untagged:")
c.Assert(output, checker.Contains, "Deleted:")
checkImageQuota(c, 1)
output, _ = dockerCmd(c, "images")
c.Assert(output, checker.Contains, "<none>")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 3)
imageId = strings.Split(output, "\n")[0]
output, _ = dockerCmd(c, "images", "-a")
c.Assert(output, checker.Contains, "<none>")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 6)
/////////////////////////////////////////////////////////////////////
checkImageQuota(c, 1)
//delete all rest layer
output, _ = dockerCmd(c, "images", "-q")
imageId = strings.Split(output, "\n")[0]
c.Assert(imageId, checker.Not(checker.Equals), "")
output, _ = dockerCmd(c, "rmi", imageId)
c.Assert(output, checker.Contains, "Deleted:")
checkImageQuota(c, 2)
output, _ = dockerCmd(c, "images")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 2)
output, _ = dockerCmd(c, "images", "-a")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 2)
}
//func (s *DockerSuite) TestCliLoadFromUrlLegacyCheckImageQuota(c *check.C) {
// printTestCaseName(); defer printTestDuration(time.Now())
// testRequires(c, DaemonIsLinux)
// checkImageQuota(c, 2)
//}
func checkImageQuota(c *check.C, expected int) {
//collection struct: credential
type Credential struct {
TenantId string `bson:"tenantId"`
}
//collection struct: tenant
type Total struct {
Images int `bson:"images"`
}
type Balance struct {
Images int `bson:"images"`
}
type Resourceinfo struct {
Total Total `bson:"total"`
Balance Balance `bson:"balance"`
}
type Tenant struct {
Resourceinfo Resourceinfo `bson:"resourceinfo"`
}
///////////////////////////////////////////
//init connection to mongodb
session, err := mgo.Dial(os.Getenv("MONGODB_URL"))
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
db := session.DB("hypernetes")
///////////////////////////////////////////
// query tenantId by accessKey
collection := db.C("credentials")
resultCred := Credential{}
//countNum, _ := collection.Find(condition).Count()
//fmt.Println("\ncount:\n", countNum)
collection.Find(bson.M{"accessKey": os.Getenv("ACCESS_KEY")}).Select(bson.M{"tenantId": 1}).One(&resultCred)
c.Assert(resultCred.TenantId, checker.NotNil)
tenantId := resultCred.TenantId
///////////////////////////////////////////
// query image quota by tenant
collection = db.C("tenant")
resultTenant := Tenant{}
//countNum, _ := collection.Find(condition).Count()
//fmt.Println("\ncount:\n", countNum)
collection.Find(bson.M{"tenantid": tenantId}).Select(bson.M{"resourceinfo": 1}).One(&resultTenant)
//fmt.Printf("total images: %v\n", resultTenant.Resourceinfo.Total.Images)
//fmt.Printf("balance images: %v\n", resultTenant.Resourceinfo.Balance.Images)
totalImages := resultTenant.Resourceinfo.Total.Images
balanceImages := resultTenant.Resourceinfo.Balance.Images
c.Assert(totalImages, checker.GreaterThan, 0)
c.Assert(balanceImages, checker.LessOrEqualThan, totalImages)
c.Assert(balanceImages, checker.Equals, expected)
}

View File

@@ -0,0 +1,66 @@
package main
import (
"fmt"
"os"
"os/exec"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliLoadFromLocalDocker(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
testImage := "hello-world:latest"
//local docker pull image
pullCmd := exec.Command("docker", "--region", os.Getenv("LOCAL_DOCKER_HOST"), "pull", testImage)
output, exitCode, err := runCommandWithOutput(pullCmd)
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//load image from local docker to hyper
output, exitCode, err = dockerCmdWithError("load", "-l", testImage)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//check image
images, _ := dockerCmd(c, "images", "hello-world")
c.Assert(images, checker.Contains, "hello-world")
}
func (s *DockerSuite) TestCliLoadFromLocalTarSize600MB(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/jenkins.tar"
imagePath := fmt.Sprintf("%s/jenkins.tar", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
c.Assert(pathExist(imagePath), checker.Equals, true)
//ensure jenkins:latest not exist
dockerCmdWithError("rmi", "jenkins:latest")
images, _ := dockerCmd(c, "images", "jenkins:latest")
c.Assert(images, checker.Not(checker.Contains), "jenkins")
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//check image
images, _ = dockerCmd(c, "images", "jenkins:latest")
c.Assert(images, checker.Contains, "jenkins")
}

View File

@@ -0,0 +1,84 @@
package main
import (
//"encoding/json"
"fmt"
//"io"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/jsonlog"
"github.com/go-check/check"
)
//TODO: get exited container log
// Regression test for #8832
func (s *DockerSuite) TestCliLogsFollowSlowStdoutConsumer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", `usleep 600000;yes X | head -c 200000`)
time.Sleep(10 * time.Second)
id := strings.TrimSpace(out)
stopSlowRead := make(chan bool)
go func() {
exec.Command(dockerBinary, "stop", id).Run()
time.Sleep(10 * time.Second)
stopSlowRead <- true
}()
logCmd := exec.Command(dockerBinary, "logs", "-f", id)
stdout, err := logCmd.StdoutPipe()
c.Assert(err, checker.IsNil)
c.Assert(logCmd.Start(), checker.IsNil)
// First read slowly
bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
c.Assert(err, checker.IsNil)
// After the container has finished we can continue reading fast
bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil)
c.Assert(err, checker.IsNil)
actual := bytes1 + bytes2
expected := 200000
c.Assert(actual, checker.Equals, expected)
}
//TODO: get exited container log
func (s *DockerSuite) TestCliLogsFollowStopped(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
time.Sleep(5 * time.Second)
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
time.Sleep(5 * time.Second)
logsCmd := exec.Command(dockerBinary, "logs", "-f", id)
c.Assert(logsCmd.Start(), checker.IsNil)
errChan := make(chan error)
go func() {
errChan <- logsCmd.Wait()
close(errChan)
}()
select {
case err := <-errChan:
c.Assert(err, checker.IsNil)
case <-time.After(10 * time.Second):
c.Fatal("Following logs is hanged")
}
}

View File

@@ -0,0 +1,38 @@
package main
import (
"fmt"
"os"
"strings"
"time"
"github.com/go-check/check"
"github.com/hyperhq/hypercli/pkg/integration/checker"
)
func (s *DockerSuite) TestCliPush(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
var (
out string
err error
newImage = fmt.Sprintf("%v/busybox:latest", os.Getenv("DOCKERHUB_USERNAME"))
)
pullImageIfNotExist("busybox")
out, _ = dockerCmd(c, "run", "-d", "busybox", "bash", "-c", "touch", "test")
cleanedContainerID := strings.TrimSpace(out)
_, _, err = dockerCmdWithError("commit", cleanedContainerID, newImage)
c.Assert(err, checker.IsNil)
//login dockerhub
out, _ = dockerCmd(c, "login", "-e", os.Getenv("DOCKERHUB_EMAIL"), "-u", os.Getenv("DOCKERHUB_USERNAME"), "-p", os.Getenv("DOCKERHUB_PASSWD"))
c.Assert(out, checker.Contains, "Login Succeeded")
//push to dockerhub
out, _, err = dockerCmdWithError("push", newImage)
c.Assert(out, checker.Contains, "digest:")
c.Assert(err, checker.IsNil)
}

View File

@@ -0,0 +1,84 @@
package main
import (
"time"
"os"
"os/exec"
"github.com/go-check/check"
"github.com/docker/docker/pkg/integration/checker"
)
func (s *DockerSuite) TestCliRegionBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
var (
defaultRegion = os.Getenv("REGION")
anotherRegion = ""
err error
)
switch defaultRegion {
case "":
defaultRegion = "us-west-1"
anotherRegion = "eu-central-1"
case "us-west-1":
anotherRegion = "eu-central-1"
case "eu-central-1":
anotherRegion = "us-west-1"
}
////////////////////////////////////////////
//pull image with default region
cmd := exec.Command(dockerBinary, "pull", "busybox")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
c.Assert(out, checker.Contains, "Status: Downloaded newer image for busybox:latest")
cmd = exec.Command(dockerBinary, "run", "busybox", "echo", "test123")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
c.Assert(out, checker.Not(checker.Contains), "Unable to find image 'busybox:latest' in the current region")
c.Assert(out, checker.Contains, "test123")
////////////////////////////////////////////
//image not exist in another region
cmd = exec.Command(dockerBinary, "--region", anotherRegion, "images", "busybox")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
c.Assert(out, checker.Not(checker.Contains), "busybox")
////////////////////////////////////////////
//pull image with specified region
cmd = exec.Command(dockerBinary, "--region", anotherRegion, "pull", "ubuntu")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
c.Assert(out, checker.Contains, "Status: Downloaded newer image for ubuntu:latest")
cmd = exec.Command(dockerBinary, "--region", anotherRegion, "run", "ubuntu", "echo", "test123")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
c.Assert(out, checker.Not(checker.Contains), "Unable to find image 'ubuntu:latest' in the current region")
c.Assert(out, checker.Contains, "test123")
}
func (s *DockerSuite) TestCliRegionWithFullEntrypoint(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
cmd := exec.Command(dockerBinary, "--region", os.Getenv("DOCKER_HOST"), "pull", "busybox")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
c.Assert(out, checker.Contains, "Status: Downloaded newer image for busybox:latest")
}

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID0TCCAzqgAwIBAgIJAP2r7GqEJwSnMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMG
A1UEChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTERMA8GA1UEAxMI
Y2hhbmdlbWUxETAPBgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWls
QGhvc3QuZG9tYWluMB4XDTEzMTIwMzE2NTYzMFoXDTIzMTIwMTE2NTYzMFowgaIx
CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2Nv
MRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMREwDwYD
VQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEW
EG1haWxAaG9zdC5kb21haW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALAn
0xDw+5y7ZptQacq66pUhRu82JP2WU6IDgo5QUtNU6/CX5PwQATe/OnYTZQFbksxp
AU9boG0FCkgxfsgPYXEuZxVEGKI2fxfKHOZZI8mrkWmj6eWU/0cvCjGVc9rTITP5
sNQvg+hORyVDdNp2IdsbMJayiB3AQYMFx3vSDOMTAgMBAAGjggELMIIBBzAdBgNV
HQ4EFgQUZu7DFz09q0QBa2+ymRm9qgK1NPswgdcGA1UdIwSBzzCBzIAUZu7DFz09
q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJD
QTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24x
ETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMI
Y2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQD9q+xq
hCcEpzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAF8fJKKM+/oOdnNi
zEd0M1+PmZOyqvjYQn/2ZR8UHH6Imgc/OPQKZXf0bVE1Txc/DaUNn9Isd1SuCuaE
ic3vAIYYU7PmgeNN6vwec48V96T7jr+GAi6AVMhQEc2hHCfVtx11Xx+x6aHDZzJt
Zxtf5lL6KSO9Y+EFwM+rju6hm5hW
-----END CERTIFICATE-----

View File

@@ -0,0 +1,73 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain
Validity
Not Before: Dec 4 14:17:54 2013 GMT
Not After : Dec 2 14:17:54 2023 GMT
Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=client/name=changeme/emailAddress=mail@host.domain
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:ca:c9:05:d0:09:4e:3e:a4:fc:d5:14:f4:a5:e8:
34:d3:6b:51:e3:f3:62:ea:a1:f0:e8:ed:c4:2a:bc:
f0:4f:ca:07:df:e3:88:fa:f4:21:99:35:0e:3d:ea:
b0:86:e7:c4:d2:8a:83:2b:42:b8:ec:a3:99:62:70:
81:46:cc:fc:a5:1d:d2:63:e8:eb:07:25:9a:e2:25:
6d:11:56:f2:1a:51:a1:b6:3e:1c:57:32:e9:7b:2c:
aa:1b:cc:97:2d:89:2d:b1:c9:5e:35:28:4d:7c:fa:
65:31:3e:f7:70:dd:6e:0b:3c:58:af:a8:2e:24:c0:
7e:4e:78:7d:0a:9e:8f:42:43
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
Easy-RSA Generated Certificate
X509v3 Subject Key Identifier:
DE:42:EF:2D:98:A3:6C:A8:AA:E0:8C:71:2C:9D:64:23:A9:E2:7E:81
X509v3 Authority Key Identifier:
keyid:66:EE:C3:17:3D:3D:AB:44:01:6B:6F:B2:99:19:BD:AA:02:B5:34:FB
DirName:/C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain
serial:FD:AB:EC:6A:84:27:04:A7
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Key Usage:
Digital Signature
Signature Algorithm: sha1WithRSAEncryption
1c:44:26:ea:e1:66:25:cb:e4:8e:57:1c:f6:b9:17:22:62:40:
12:90:8f:3b:b2:61:7a:54:94:8f:b1:20:0b:bf:a3:51:e3:fa:
1c:a1:be:92:3a:d0:76:44:c0:57:83:ab:6a:e4:1a:45:49:a4:
af:39:0d:60:32:fc:3a:be:d7:fb:5d:99:7a:1f:87:e7:d5:ab:
84:a2:5e:90:d8:bf:fa:89:6d:32:26:02:5e:31:35:68:7f:31:
f5:6b:51:46:bc:af:70:ed:5a:09:7d:ec:b2:48:4f:fe:c5:2f:
56:04:ad:f6:c1:d2:2a:e4:6a:c4:87:fe:08:35:c5:38:cb:5e:
4a:c4
-----BEGIN CERTIFICATE-----
MIIEFTCCA36gAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx
CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xFTATBgNVBAoTDEZv
cnQtRnVuc3RvbjERMA8GA1UECxMIY2hhbmdlbWUxETAPBgNVBAMTCGNoYW5nZW1l
MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRv
bWFpbjAeFw0xMzEyMDQxNDE3NTRaFw0yMzEyMDIxNDE3NTRaMIGgMQswCQYDVQQG
EwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMGA1UE
ChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTEPMA0GA1UEAxMGY2xp
ZW50MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0
LmRvbWFpbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyskF0AlOPqT81RT0
peg002tR4/Ni6qHw6O3EKrzwT8oH3+OI+vQhmTUOPeqwhufE0oqDK0K47KOZYnCB
Rsz8pR3SY+jrByWa4iVtEVbyGlGhtj4cVzLpeyyqG8yXLYktscleNShNfPplMT73
cN1uCzxYr6guJMB+Tnh9Cp6PQkMCAwEAAaOCAVkwggFVMAkGA1UdEwQCMAAwLQYJ
YIZIAYb4QgENBCAWHkVhc3ktUlNBIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV
HQ4EFgQU3kLvLZijbKiq4IxxLJ1kI6nifoEwgdcGA1UdIwSBzzCBzIAUZu7DFz09
q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJD
QTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24x
ETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMI
Y2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQD9q+xq
hCcEpzATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCB4AwDQYJKoZIhvcN
AQEFBQADgYEAHEQm6uFmJcvkjlcc9rkXImJAEpCPO7JhelSUj7EgC7+jUeP6HKG+
kjrQdkTAV4OrauQaRUmkrzkNYDL8Or7X+12Zeh+H59WrhKJekNi/+oltMiYCXjE1
aH8x9WtRRryvcO1aCX3sskhP/sUvVgSt9sHSKuRqxIf+CDXFOMteSsQ=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMrJBdAJTj6k/NUU
9KXoNNNrUePzYuqh8OjtxCq88E/KB9/jiPr0IZk1Dj3qsIbnxNKKgytCuOyjmWJw
gUbM/KUd0mPo6wclmuIlbRFW8hpRobY+HFcy6XssqhvMly2JLbHJXjUoTXz6ZTE+
93Ddbgs8WK+oLiTAfk54fQqej0JDAgMBAAECgYBOFEzKp2qbMEexe9ofL2N3rDDh
xkrl8OijpzkLA6i78BxMFn4dsnZlWUpciMrjhsYAExkiRRSS+QMMJimAq1jzQqc3
FAQV2XGYwkd0cUn7iZGvfNnEPysjsfyYQM+m+sT0ATj4BZjVShC6kkSjTdm1leLN
OSvcHdcu3Xxg9ufF0QJBAPYdnNt5sIndt2WECePuRVi+uF4mlxTobFY0fjn26yhC
4RsnhhD3Vldygo9gvnkwrAZYaALGSPBewes2InxvjA8CQQDS7erKiNXpwoqz5XiU
SVEsIIVTdWzBjGbIqMOu/hUwM5FK4j6JTBks0aTGMyh0YV9L1EzM0X79J29JahCe
iQKNAkBKNMOGqTpBV0hko1sYDk96YobUXG5RL4L6uvkUIQ7mJMQam+AgXXL7Ctuy
v0iu4a38e8tgisiTMP7nHHtpaXihAkAOiN54/lzfMsykANgCP9scE1GcoqbP34Dl
qttxH4kOPT9xzY1JoLjLYdbc4YGUI3GRpBt2sajygNkmUey7P+2xAkBBsVCZFvTw
qHvOpPS2kX5ml5xoc/QAHK9N7kR+X7XFYx82RTVSqJEK4lPb+aEWn+CjiIewO4Q5
ksDFuNxAzbhl
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,73 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, ST=CA, L=SanFrancisco, O=Evil Inc, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain
Validity
Not Before: Feb 24 17:54:59 2014 GMT
Not After : Feb 22 17:54:59 2024 GMT
Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=client/name=changeme/emailAddress=mail@host.domain
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:e8:e2:2c:b8:d4:db:89:50:4f:47:1e:68:db:f7:
e4:cc:47:41:63:75:03:37:50:7a:a8:4d:27:36:d5:
15:01:08:b6:cf:56:f7:56:6d:3d:f9:e2:8d:1a:5d:
bf:a0:24:5e:07:55:8e:d0:dc:f1:fa:19:87:1d:d6:
b6:58:82:2e:ba:69:6d:e9:d9:c8:16:0d:1d:59:7f:
f4:8e:58:10:01:3d:21:14:16:3c:ec:cd:8c:b7:0e:
e6:7b:77:b4:f9:90:a5:17:01:bb:84:c6:b2:12:87:
70:eb:9f:6d:4f:d0:68:8b:96:c0:e7:0b:51:b4:9d:
1d:7b:6c:7b:be:89:6b:88:8b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
Easy-RSA Generated Certificate
X509v3 Subject Key Identifier:
9E:F8:49:D0:A2:76:30:5C:AB:2B:8A:B5:8D:C6:45:1F:A7:F8:CF:85
X509v3 Authority Key Identifier:
keyid:DC:A5:F1:76:DB:4E:CD:8E:EF:B1:23:56:1D:92:80:99:74:3B:EA:6F
DirName:/C=US/ST=CA/L=SanFrancisco/O=Evil Inc/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain
serial:E7:21:1E:18:41:1B:96:83
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Key Usage:
Digital Signature
Signature Algorithm: sha1WithRSAEncryption
48:76:c0:18:fa:0a:ee:4e:1a:ec:02:9d:d4:83:ca:94:54:a1:
3f:51:2f:3e:4b:95:c3:42:9b:71:a0:4b:d9:af:47:23:b9:1c:
fb:85:ba:76:e2:09:cb:65:bb:d2:7d:44:3d:4b:67:ba:80:83:
be:a8:ed:c4:b9:ea:1a:1b:c7:59:3b:d9:5c:0d:46:d8:c9:92:
cb:10:c5:f2:1a:38:a4:aa:07:2c:e3:84:16:79:c7:95:09:e3:
01:d2:15:a2:77:0b:8b:bf:94:04:e9:7f:c0:cd:e6:2e:64:cd:
1e:a3:32:ec:11:cc:62:ce:c7:4e:cd:ad:48:5c:b1:b8:e9:76:
b3:f9
-----BEGIN CERTIFICATE-----
MIIEDTCCA3agAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx
CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xETAPBgNVBAoTCEV2
aWwgSW5jMREwDwYDVQQLEwhjaGFuZ2VtZTERMA8GA1UEAxMIY2hhbmdlbWUxETAP
BgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9tYWlu
MB4XDTE0MDIyNDE3NTQ1OVoXDTI0MDIyMjE3NTQ1OVowgaAxCzAJBgNVBAYTAlVT
MQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxG
b3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMQ8wDQYDVQQDEwZjbGllbnQx
ETAPBgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9t
YWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo4iy41NuJUE9HHmjb9+TM
R0FjdQM3UHqoTSc21RUBCLbPVvdWbT354o0aXb+gJF4HVY7Q3PH6GYcd1rZYgi66
aW3p2cgWDR1Zf/SOWBABPSEUFjzszYy3DuZ7d7T5kKUXAbuExrISh3Drn21P0GiL
lsDnC1G0nR17bHu+iWuIiwIDAQABo4IBVTCCAVEwCQYDVR0TBAIwADAtBglghkgB
hvhCAQ0EIBYeRWFzeS1SU0EgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW
BBSe+EnQonYwXKsrirWNxkUfp/jPhTCB0wYDVR0jBIHLMIHIgBTcpfF2207Nju+x
I1YdkoCZdDvqb6GBpKSBoTCBnjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRUw
EwYDVQQHEwxTYW5GcmFuY2lzY28xETAPBgNVBAoTCEV2aWwgSW5jMREwDwYDVQQL
EwhjaGFuZ2VtZTERMA8GA1UEAxMIY2hhbmdlbWUxETAPBgNVBCkTCGNoYW5nZW1l
MR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9tYWluggkA5yEeGEEbloMwEwYD
VR0lBAwwCgYIKwYBBQUHAwIwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBBQUAA4GB
AEh2wBj6Cu5OGuwCndSDypRUoT9RLz5LlcNCm3GgS9mvRyO5HPuFunbiCctlu9J9
RD1LZ7qAg76o7cS56hobx1k72VwNRtjJkssQxfIaOKSqByzjhBZ5x5UJ4wHSFaJ3
C4u/lATpf8DN5i5kzR6jMuwRzGLOx07NrUhcsbjpdrP5
-----END CERTIFICATE-----

View File

@@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOjiLLjU24lQT0ce
aNv35MxHQWN1AzdQeqhNJzbVFQEIts9W91ZtPfnijRpdv6AkXgdVjtDc8foZhx3W
tliCLrppbenZyBYNHVl/9I5YEAE9IRQWPOzNjLcO5nt3tPmQpRcBu4TGshKHcOuf
bU/QaIuWwOcLUbSdHXtse76Ja4iLAgMBAAECgYADs+TmI2xCKKa6CL++D5jxrohZ
nnionnz0xBVFh+nHlG3jqgxQsXf0yydXLfpn/2wHTdLxezHVuiYt0UYg7iD0CglW
+IjcgMebzyjLeYqYOE5llPlMvhp2HoEMYJNb+7bRrZ1WCITbu+Su0w1cgA7Cs+Ej
VlfvGzN+qqnDThRUYQJBAPY0sMWZJKly8QhUmUvmcXdPczzSOf6Mm7gc5LR6wzxd
vW7syuqk50qjqVqFpN81vCV7GoDxRUWbTM9ftf7JGFkCQQDyJc/1RMygE2o+enU1
6UBxJyclXITEYtDn8aoEpLNc7RakP1WoPUKjZOnjkcoKcIkFNkSPeCfQujrb5f3F
MkuDAkByAI/hzzmkpK5rFxEsjfX4Mve/L/DepyjrpaVY1IdWimlO1aJX6CeY7hNa
8QsYt/74s/nfvtg+lNyKIV1aLq9xAkB+WSSNgfyTeg3x08vc+Xxajmdqoz/TiQwg
OoTQL3A3iK5LvZBgXLasszcnOycFE3srcQmNItEDpGiZ3QPxJTEpAkEA45EE9NMJ
SA7EGWSFlbz4f4u4oBeiDiJRJbGGfAyVxZlpCWUjPpg9+swsWoFEOjnGYaChAMk5
nrOdMf15T6QF7Q==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,76 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4 (0x4)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain
Validity
Not Before: Dec 4 15:01:20 2013 GMT
Not After : Dec 2 15:01:20 2023 GMT
Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=*/name=changeme/emailAddress=mail@host.domain
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:c1:ff:7d:30:6f:64:4a:b1:92:b1:71:d1:c1:74:
e2:1d:db:2d:11:24:e1:00:d4:00:ae:6f:c8:9e:ae:
67:b3:4a:bd:f7:e6:9e:57:6d:19:4c:3c:23:94:2d:
3d:d6:63:84:d8:fa:76:2b:38:12:c1:ed:20:9d:32:
e0:e8:c2:bf:9a:77:70:04:3f:7f:ca:8c:2c:82:d6:
3d:25:5c:02:1a:4f:64:93:03:dd:9c:42:97:5e:09:
49:af:f0:c2:e1:30:08:0e:21:46:95:d1:13:59:c0:
c8:76:be:94:0d:8b:43:67:21:33:b2:08:60:9d:76:
a8:05:32:1e:f9:95:09:14:75
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
Easy-RSA Generated Server Certificate
X509v3 Subject Key Identifier:
14:02:FD:FD:DD:13:38:E0:71:EA:D1:BE:C0:0E:89:1A:2D:B6:19:06
X509v3 Authority Key Identifier:
keyid:66:EE:C3:17:3D:3D:AB:44:01:6B:6F:B2:99:19:BD:AA:02:B5:34:FB
DirName:/C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain
serial:FD:AB:EC:6A:84:27:04:A7
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Key Usage:
Digital Signature, Key Encipherment
Signature Algorithm: sha1WithRSAEncryption
40:0f:10:39:c4:b7:0f:0d:2f:bf:d2:16:cc:8e:d3:9a:fb:8b:
ce:4b:7b:0d:48:77:ce:f1:fe:d5:8f:ea:b1:71:ed:49:1d:9f:
23:3a:16:d4:70:7c:c5:29:bf:e4:90:34:d0:f0:00:24:f4:e4:
df:2c:c3:83:01:66:61:c9:a8:ab:29:e7:98:6d:27:89:4a:76:
c9:2e:19:8e:fe:6e:d5:f8:99:11:0e:97:67:4b:34:e3:1e:e3:
9f:35:00:a5:32:f9:b5:2c:f2:e0:c5:2e:cc:81:bd:18:dd:5c:
12:c8:6b:fa:0c:17:74:30:55:f6:6e:20:9a:6c:1e:09:b4:0c:
15:42
-----BEGIN CERTIFICATE-----
MIIEKjCCA5OgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx
CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xFTATBgNVBAoTDEZv
cnQtRnVuc3RvbjERMA8GA1UECxMIY2hhbmdlbWUxETAPBgNVBAMTCGNoYW5nZW1l
MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRv
bWFpbjAeFw0xMzEyMDQxNTAxMjBaFw0yMzEyMDIxNTAxMjBaMIGbMQswCQYDVQQG
EwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMGA1UE
ChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTEKMAgGA1UEAxQBKjER
MA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21h
aW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMH/fTBvZEqxkrFx0cF04h3b
LREk4QDUAK5vyJ6uZ7NKvffmnldtGUw8I5QtPdZjhNj6dis4EsHtIJ0y4OjCv5p3
cAQ/f8qMLILWPSVcAhpPZJMD3ZxCl14JSa/wwuEwCA4hRpXRE1nAyHa+lA2LQ2ch
M7IIYJ12qAUyHvmVCRR1AgMBAAGjggFzMIIBbzAJBgNVHRMEAjAAMBEGCWCGSAGG
+EIBAQQEAwIGQDA0BglghkgBhvhCAQ0EJxYlRWFzeS1SU0EgR2VuZXJhdGVkIFNl
cnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUFAL9/d0TOOBx6tG+wA6JGi22GQYw
gdcGA1UdIwSBzzCBzIAUZu7DFz09q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJ
BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUw
EwYDVQQKEwxGb3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQD
EwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1h
aWxAaG9zdC5kb21haW6CCQD9q+xqhCcEpzATBgNVHSUEDDAKBggrBgEFBQcDATAL
BgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADgYEAQA8QOcS3Dw0vv9IWzI7TmvuL
zkt7DUh3zvH+1Y/qsXHtSR2fIzoW1HB8xSm/5JA00PAAJPTk3yzDgwFmYcmoqynn
mG0niUp2yS4Zjv5u1fiZEQ6XZ0s04x7jnzUApTL5tSzy4MUuzIG9GN1cEshr+gwX
dDBV9m4gmmweCbQMFUI=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMH/fTBvZEqxkrFx
0cF04h3bLREk4QDUAK5vyJ6uZ7NKvffmnldtGUw8I5QtPdZjhNj6dis4EsHtIJ0y
4OjCv5p3cAQ/f8qMLILWPSVcAhpPZJMD3ZxCl14JSa/wwuEwCA4hRpXRE1nAyHa+
lA2LQ2chM7IIYJ12qAUyHvmVCRR1AgMBAAECgYAmwckb9RUfSwyYgLm8IYLPHiuJ
wkllZfVg5Bo7gXJcQnFjZmJ56uTj8xvUjZlODIHM63TSO5ibv6kFXtXKCqZGd2M+
wGbhZ0f+2GvKcwMmJERnIQjuoNaYSQLT0tM0VB9Iz0rJlZC+tzPZ+5pPqEumRdsS
IzWNXfF42AhcbwAQYQJBAPVXtMYIJc9EZsz86ZcQiMPWUpCX5vnRmtwL8kKyR8D5
4KfYeiowyFffSRMMcclwNHq7TgSXN+nIXM9WyzyzwikCQQDKbNA28AgZp9aT54HP
WnbeE2pmt+uk/zl/BtxJSoK6H+69Jec+lf7EgL7HgOWYRSNot4uQWu8IhsHLTiUq
+0FtAkEAqwlRxRy4/x24bP+D+QRV0/D97j93joFJbE4Hved7jlSlAV4xDGilwlyv
HNB4Iu5OJ6Gcaibhm+FKkmD3noHSwQJBAIpu3fokLzX0bS+bDFBU6qO3HXX/47xj
+tsfQvkwZrSI8AkU6c8IX0HdVhsz0FBRQAT2ORDQz1XCarfxykNZrwUCQQCGCBIc
BBCWzhHlswlGidWJg3HqqO6hPPClEr3B5G87oCsdeYwiO23XT6rUnoJXfJHp6oCW
5nCwDu5ZTP+khltg
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,76 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, ST=CA, L=SanFrancisco, O=Evil Inc, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain
Validity
Not Before: Feb 28 18:49:31 2014 GMT
Not After : Feb 26 18:49:31 2024 GMT
Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=localhost/name=changeme/emailAddress=mail@host.domain
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:d1:08:58:24:60:a1:69:65:4b:76:46:8f:88:75:
7c:49:3a:d8:03:cc:5b:58:c5:d1:bb:e5:f9:54:b9:
75:65:df:7e:bb:fb:54:d4:b2:e9:6f:58:a2:a4:84:
43:94:77:24:81:38:36:36:f0:66:65:26:e5:5b:2a:
14:1c:a9:ae:57:7f:75:00:23:14:4b:61:58:e4:82:
aa:15:97:94:bd:50:35:0d:5d:18:18:ed:10:6a:bb:
d3:64:5a:eb:36:98:5b:58:a7:fe:67:48:c1:6c:3f:
51:2f:02:65:96:54:77:9b:34:f9:a7:d2:63:54:6a:
9e:02:5c:be:65:98:a4:b4:b5
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
Easy-RSA Generated Server Certificate
X509v3 Subject Key Identifier:
1F:E0:57:CA:CB:76:C9:C4:86:B9:EA:69:17:C0:F3:51:CE:95:40:EC
X509v3 Authority Key Identifier:
keyid:DC:A5:F1:76:DB:4E:CD:8E:EF:B1:23:56:1D:92:80:99:74:3B:EA:6F
DirName:/C=US/ST=CA/L=SanFrancisco/O=Evil Inc/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain
serial:E7:21:1E:18:41:1B:96:83
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Key Usage:
Digital Signature, Key Encipherment
Signature Algorithm: sha1WithRSAEncryption
04:93:0e:28:01:94:18:f0:8c:7c:d3:0c:ad:e9:b7:46:b1:30:
65:ed:68:7c:8c:91:cd:1a:86:66:87:4a:4f:c0:97:bc:f7:85:
4b:38:79:31:b2:65:88:b1:76:16:9e:80:93:38:f4:b9:eb:65:
00:6d:bb:89:e0:a1:bf:95:5e:80:13:8e:01:73:d3:f1:08:73:
85:a5:33:75:0b:42:8a:a3:07:09:35:ef:d7:c6:58:eb:60:a3:
06:89:a0:53:99:e2:aa:41:90:e0:1a:d2:12:4b:48:7d:c3:9c:
ad:bd:0e:5e:5f:f7:09:0c:5d:7c:86:24:dd:92:d5:b3:14:06:
c7:9f
-----BEGIN CERTIFICATE-----
MIIEKjCCA5OgAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx
CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xETAPBgNVBAoTCEV2
aWwgSW5jMREwDwYDVQQLEwhjaGFuZ2VtZTERMA8GA1UEAxMIY2hhbmdlbWUxETAP
BgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3QuZG9tYWlu
MB4XDTE0MDIyODE4NDkzMVoXDTI0MDIyNjE4NDkzMVowgaMxCzAJBgNVBAYTAlVT
MQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxG
b3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMRIwEAYDVQQDEwlsb2NhbGhv
c3QxETAPBgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWlsQGhvc3Qu
ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRCFgkYKFpZUt2Ro+I
dXxJOtgDzFtYxdG75flUuXVl3367+1TUsulvWKKkhEOUdySBODY28GZlJuVbKhQc
qa5Xf3UAIxRLYVjkgqoVl5S9UDUNXRgY7RBqu9NkWus2mFtYp/5nSMFsP1EvAmWW
VHebNPmn0mNUap4CXL5lmKS0tQIDAQABo4IBbzCCAWswCQYDVR0TBAIwADARBglg
hkgBhvhCAQEEBAMCBkAwNAYJYIZIAYb4QgENBCcWJUVhc3ktUlNBIEdlbmVyYXRl
ZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFB/gV8rLdsnEhrnqaRfA81HO
lUDsMIHTBgNVHSMEgcswgciAFNyl8XbbTs2O77EjVh2SgJl0O+pvoYGkpIGhMIGe
MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNj
bzERMA8GA1UEChMIRXZpbCBJbmMxETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQD
EwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1h
aWxAaG9zdC5kb21haW6CCQDnIR4YQRuWgzATBgNVHSUEDDAKBggrBgEFBQcDATAL
BgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADgYEABJMOKAGUGPCMfNMMrem3RrEw
Ze1ofIyRzRqGZodKT8CXvPeFSzh5MbJliLF2Fp6Akzj0uetlAG27ieChv5VegBOO
AXPT8QhzhaUzdQtCiqMHCTXv18ZY62CjBomgU5niqkGQ4BrSEktIfcOcrb0OXl/3
CQxdfIYk3ZLVsxQGx58=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANEIWCRgoWllS3ZG
j4h1fEk62APMW1jF0bvl+VS5dWXffrv7VNSy6W9YoqSEQ5R3JIE4NjbwZmUm5Vsq
FByprld/dQAjFEthWOSCqhWXlL1QNQ1dGBjtEGq702Ra6zaYW1in/mdIwWw/US8C
ZZZUd5s0+afSY1RqngJcvmWYpLS1AgMBAAECgYAJXh9dGfuB1qlIFqduDR3RxlJR
8UGSu+LHUeoXkuwg8aAjWoMVuSLe+5DmYIsKx0AajmNXmPRtyg1zRXJ7SltmubJ8
6qQVDsRk6biMdkpkl6a9Gk2av40psD9/VPGxagEoop7IKYhf3AeKPvPiwVB2qFrl
1aYMZm0aMR55pgRajQJBAOk8IsJDf0beooDZXVdv/oe4hcbM9fxO8Cn3qzoGImqD
37LL+PCzDP7AEV3fk43SsZDeSk+LDX+h0o9nPyhzHasCQQDlb3aDgcQY9NaGLUWO
moOCB3148eBVcAwCocu+OSkf7sbQdvXxgThBOrZl11wwRIMQqh99c2yeUwj+tELl
3VcfAkBZTiNpCvtDIaBLge9RuZpWUXs3wec2cutWxnSTxSGMc25GQf/R+l0xdk2w
ChmvpktDUzpU9sN2aXn8WuY+EMX9AkEApbLpUbKPUELLB958RLA819TW/lkZXjrs
wZ3eSoR3ufM1rOqtVvyvBxUDE+wETWu9iHSFB5Ir2PA5J9JCGkbPmwJAFI1ndfBj
iuyU93nFX0p+JE2wVHKx4dMzKCearNKiJh/lGDtUq3REGgamTNUnG8RAITUbxFs+
Z1hrIq8xYl2LOQ==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,67 @@
-----BEGIN CERTIFICATE-----
MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy
MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh
bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh
bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0
Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6
ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51
UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n
c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY
MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz
30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG
BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv
bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB
AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E
T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p
mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/
e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps
P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY
dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc
2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG
V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4
HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX
j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII
0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap
lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf
+AZxAeKCINT+b72x
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD
VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw
AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6
2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr
ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt
4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq
m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/
vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT
8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE
IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO
KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO
GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/
s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g
JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD
AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9
MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy
bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6
Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ
zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj
Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY
Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5
B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx
PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR
pu/xO28QOG8=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFRTCCBC2gAwIBAgIQX0DtZBXbug12/JeCtiTo4DANBgkqhkiG9w0BAQsFADCB
kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV
BAMTLUNPTU9ETyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
QTAeFw0xNjA0MTQwMDAwMDBaFw0xOTA2MDUyMzU5NTlaMFcxITAfBgNVBAsTGERv
bWFpbiBDb250cm9sIFZhbGlkYXRlZDEdMBsGA1UECxMUUG9zaXRpdmVTU0wgV2ls
ZGNhcmQxEzARBgNVBAMMCiouaHlwZXIuc2gwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDMDLFaF6txvucuY6n5xtSHv/HD6RD3NurIW+ePvTRCk7vkRxYI
WebAqucRZZgu7DxFqhdcm9SfDSojq22j6hPlQUbfJOE4Ctk/unA5y1/Qx0el5FBG
rTRGX4C7P8CGH/Hu7lL98SRDy0dkwFDbDG/AsfsoCLntRfsWjarEEd0gYz1A7hCk
lI9huFw2aWZEaEWpjt3dS/ZR/9mSp4FmeWyInrz+yxybLv7QHiliu4AQMH/tXYCo
ihMUbgSgRaxK606LlHJNSAEBzW9pgkYYBb6kuiH/TIhBIoe9/HnM6bkPkRQlDo5V
uFR8TixEV6sxRGbduLk9bw+fsII1+lzCkapDAgMBAAGjggHRMIIBzTAfBgNVHSME
GDAWgBSQr2o6lFoL2JDqElZz30O0Oija5zAdBgNVHQ4EFgQUF38ELjZwkqAL6++g
x0NfHF1B+IwwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
FAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1UdIARIMEYwOgYLKwYBBAGyMQECAgcw
KzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwCAYG
Z4EMAQIBMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly9jcmwuY29tb2RvY2EuY29t
L0NPTU9ET1JTQURvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcmwwgYUG
CCsGAQUFBwEBBHkwdzBPBggrBgEFBQcwAoZDaHR0cDovL2NydC5jb21vZG9jYS5j
b20vQ09NT0RPUlNBRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAk
BggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMB8GA1UdEQQYMBaC
CiouaHlwZXIuc2iCCGh5cGVyLnNoMA0GCSqGSIb3DQEBCwUAA4IBAQB0cZe/yOu0
l1LXNBGx3M0h323etKVzzUgwHfef9dgfBoHzwZzVXw9JgcN4Hr7BsNVgEvEcfFru
jmCBEn5lvIyx5ZUZ6QOptgVzMdIPwzirEcPV918e/0Hkw83m68CRU573foSxXHIU
ntFbKsi6o6tJBUE6utqcJaPbymrQL7EQ2xTTlv2eqa3h5D7zMVD1kQGSI7drrCng
CP+qhsZJpMqe5pd1vgsKVDAKc/V5sqjbZ2q/IdLGQsNG4TYfLGdegVTcGZnirH3n
WYX6mEz484P7bHlyAsh4NG5bkzKw7w7h7vUdU6HfdKVYTzqQ6IwmSiJ3rZtKb5Hy
C5S+R5whvVXz
-----END CERTIFICATE-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAzAyxWhercb7nLmOp+cbUh7/xw+kQ9zbqyFvnj700QpO75EcW
CFnmwKrnEWWYLuw8RaoXXJvUnw0qI6tto+oT5UFG3yThOArZP7pwOctf0MdHpeRQ
Rq00Rl+Auz/Ahh/x7u5S/fEkQ8tHZMBQ2wxvwLH7KAi57UX7Fo2qxBHdIGM9QO4Q
pJSPYbhcNmlmRGhFqY7d3Uv2Uf/ZkqeBZnlsiJ68/sscmy7+0B4pYruAEDB/7V2A
qIoTFG4EoEWsSutOi5RyTUgBAc1vaYJGGAW+pLoh/0yIQSKHvfx5zOm5D5EUJQ6O
VbhUfE4sRFerMURm3bi5PW8Pn7CCNfpcwpGqQwIDAQABAoIBAC8Z3vaE8DZZctPq
fZoCo5ySWiR28EugiaGmVVWAv0d/Aqg3IIbc+b8PtDb31KFANsl98daWwgXU7B0/
vRdROTZ6Uvm/cZ2WI3/qcW1l3MA8v/UzNrSZ1q9H7FdM6AwN47LboJytxUlA60H+
gquNu14nt2oOWZzDwqn6GakY1opa9IPv3DJ2chz4Ab3C+j646UC3y7luU9vD4RnY
IOGH3Sp+OFMrNdonbyBeb34HN1/FhZ8IBVcqZAQzxqhWYzEZItbvADt8EsuqBrwZ
cpOUZPm5GkkRnqauuOrq/5NPzWykheYgN42pwzDDT02m0WkE7Qssk6u8gINHIKk3
BkBEzQECgYEA6mlMoWW+rbO+Qe77PL/MHydEQBcRyB1gSlOvXH4ou1FYkPeAN3zl
ApiPesevYL83kIBD44MCu9gGJbpRAq+9E0/+gVqwVZo5MOJhOZ87mjBp0nkHwmNm
ymfRzdsMWPNJuyFwRHU7oUcXo9a88ceurroRcy4BJOmKNKBYOh5bFHECgYEA3teO
eraZsj1Odw0ApCRNfwTHOXA6OfKy1hZVx5qYdvakNksxSo+leqnblERKtgJeyKGI
AicFuuXnE+WZfks7+SrEhn+VZbB3XjzwVcL+hjqs12hItCBiQu1RWPyR9RYnWv/+
t5GsvqwZsj5jpCksSuMvnnT1w7nyQE/Il3wW8/MCgYB0WVmozoiLTSkFLupS59wY
JnRQ32J7EmGl4s2qug/bke/E3KQuZnaBCFpHFfAttBuPRKrttSxZMksy1Ly6+aF+
gXkQmYPmqUrzwZmCcU+zI46S4nIAgTgXBNr1M2F4kSEqmdlQkWPMlC3eq4pS88r3
fPGGWvJEcQqhPmksR77rcQKBgGCEGijaJ62EUhTMI+fz9UC7cBJXolBw5rZFDDgc
pEZ6QttlK98wYirDoOARyA4W7riVBdRw1FGDu9bpTdbefQZJWL8sSSe3C6xcVne+
sgCvLydI+pxRnl2AbghNtGXjh34pfEhDpv8aiTKjRQLX9mAlD/3giIWSZvMl2yqJ
S2OzAoGAGSLhfgwpJNADpsbQGpnqUJOnWzPswi2lrBKXrglVTkEaZ/DXQn244xLT
nTuuiScRq5hSgqKuE2vSHjJtKrm/MdMWYM7vuw5yk+wYVHGn/Z0bkcgc1sLaDGHD
QUbC7ZlYs1gmlI5Mk/3/s4mLRAlRtman+Oquc5e5154vwiyxvYU=
-----END RSA PRIVATE KEY-----

Binary file not shown.

View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCTCCAfOgAwIBAgIQTOoFF+ypXwgdXnXHuCTvYDALBgkqhkiG9w0BAQswJjER
MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE1MDcxNzE5
NDg1M1oXDTE4MDcwMTE5NDg1M1owJzERMA8GA1UEChMIUXVpY2tUTFMxEjAQBgNV
BAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDO
qvTBAi0ApXLfe90ApJkdkRGwF838Qzt1UFSxomu5fHRV6l3FjX5XCVHiFQ4w3ROh
dMOu9NahfGLJv9VvWU2MV3YoY9Y7lIXpKwnK1v064wuls4nPh13BUWKQKofcY/e2
qaSPd6/qmSRc/kJUvOI9jZMSX6ZRPu9K4PCqm2CivlbLq9UYuo1AbRGfuqHRvTxg
mQG7WQCzGSvSjuSg5qX3TEh0HckTczJG9ODULNRWNE7ld0W4sfv4VF8R7Uc/G7LO
8QwLCZ9TIl3gYMPCrhUL3Q6z9Jnn1SQS4mhDnPi6ugRYO1X8k3jjdxV9C2sXwUvN
OZI1rLEWl9TJNA7ZXtMCAwEAAaM2MDQwDgYDVR0PAQH/BAQDAgCgMAwGA1UdEwEB
/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MAsGCSqGSIb3DQEBCwOCAQEAH6iq
kM2+UMukGDLEQKHHiauioWJlHDlLXv76bJiNfjSz94B/2XOQMb9PT04//tnGUyPK
K8Dx7RoxSodU6T5VRiz/A36mLOvt2t3bcL/1nHf9sAOHcexGtnCbQbW91V7RKfIL
sjiLNFDkQ9VfVNY+ynQptZoyH1sy07+dplfkIiPzRs5WuVAnEGsX3r6BrhgUITzi
g1B4kpmGZIohP4m6ZEBY5xuo/NQ0+GhjAENQMU38GpuoMyFS0i0dGcbx8weqnI/B
Er/qa0+GE/rBnWY8TiRow8dzpneSFQnUZpJ4EwD9IoOIDHo7k2Nbz2P50HMiCXZf
4RqzctVssRlrRVnO5w==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAwM6q9MECLQClct973QCkmR2REbAXzfxDO3VQVLGia7l8dFXq
XcWNflcJUeIVDjDdE6F0w6701qF8Ysm/1W9ZTYxXdihj1juUhekrCcrW/TrjC6Wz
ic+HXcFRYpAqh9xj97appI93r+qZJFz+QlS84j2NkxJfplE+70rg8KqbYKK+Vsur
1Ri6jUBtEZ+6odG9PGCZAbtZALMZK9KO5KDmpfdMSHQdyRNzMkb04NQs1FY0TuV3
Rbix+/hUXxHtRz8bss7xDAsJn1MiXeBgw8KuFQvdDrP0mefVJBLiaEOc+Lq6BFg7
VfyTeON3FX0LaxfBS805kjWssRaX1Mk0Dtle0wIDAQABAoIBAHbuhNHZROhRn70O
Ui9vOBki/dt1ThnH5AkHQngb4t6kWjrAzILvW2p1cdBKr0ZDqftz+rzCbVD/5+Rg
Iq8bsnB9g23lWEBMHD/GJsAxmRA3hNooamk11IBmwTcVSsbnkdq5mEdkICYphjHC
Ey0DbEf6RBxWlx3WvAWLoNmTw6iFaOCH8IyLavPpe7kLbZc219oNUw2qjCnCXCZE
/NuViADHJBPN8r7g1gmyclJmTumdUK6oHgXEMMPe43vhReGcgcReK9QZjnTcIXPM
4oJOraw+BtoZXVvvIPnC+5ntoLFOzjIzM0kaveReZbdgffqF4zy2vRfCHhWssanc
7a0xR4ECgYEA3Xuvcqy5Xw+v/jVCO0VZj++Z7apA78dY4tWsPx5/0DUTTziTlXkC
ADduEbwX6HgZ/iLvA9j4C3Z4mO8qByby/6UoBU8NEe+PQt6fT7S+dKSP4uy5ZxVM
i5opkEyrJsMbve9Jrlj4bk5CICsydrZ+SBFHnpNGjbduGQick5LORWECgYEA3trt
gepteDGiUYmnnBgjbYtcD11RvpKC8Z/QwGnzN5vk4eBu8r7DkMcLN+SiHjAovlJo
r5j3EbF8sla1zBf/yySdQZFqUGcwtw7MaAKCLdhQl5WsViNMIx6p2OJapu0dzbv2
KTXrnoRCafcH92k0dUX1ahE9eyc8KX6VhbWwXLMCgYATGCCuEDoC+gVAMzM8jOQF
xrBMjwr+IP+GvskUv/pg5tJ9V/FRR5dmkWDJ4p9lCUWkZTqZ6FCqHFKVTLkg2LjG
VWS34HLOAwskxrCRXJG22KEW/TWWr31j46yFpjZzJwrzOvftMfpo+BI3V8IH/f+x
EtxLzYKdoRy6x8VH67YgwQKBgHor2vjV45142FuK83AHa6SqOZXSuvWWrGJ6Ep7p
doSN2jRaLXi2S9AaznOdy6JxFGUCGJHrcccpXgsGrjNtFLXxJKTFa1sYtwQkALsk
ZOltJQF09D1krGC0driHntrUMvqOiKye+sS0DRS6cIuaCUAhUiELwoC5SaoV0zKy
IDUxAoGAOK8Xq+3/sqe79vTpw25RXl+nkAmOAeKjqf3Kh6jbnBhr81rmefyKXB9a
uj0b980tzUnliwA5cCOsyxfN2vASvMnJxFE721QZI04arlcPFHcFqCtmNnUYTcLp
0hgn/yLZptcoxpy+eTBu3eNsxz1Bu/Tx/198+2Wr3MbtGpLNIcA=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,118 @@
package main
import (
"encoding/json"
"net/http"
"net/url"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiImagesFilter(c *check.C) {
name := "utest:tag1"
name2 := "utest/docker:tag2"
name3 := "utest:5000/docker:tag3"
for _, n := range []string{name, name2, name3} {
dockerCmd(c, "tag", "busybox", n)
}
type image types.Image
getImages := func(filter string) []image {
v := url.Values{}
v.Set("filter", filter)
status, b, err := sockRequest("GET", "/images/json?"+v.Encode(), nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var images []image
err = json.Unmarshal(b, &images)
c.Assert(err, checker.IsNil)
return images
}
//incorrect number of matches returned
images := getImages("utest*/*")
c.Assert(images[0].RepoTags, checker.HasLen, 2)
images = getImages("utest")
c.Assert(images[0].RepoTags, checker.HasLen, 1)
images = getImages("utest*")
c.Assert(images[0].RepoTags, checker.HasLen, 1)
images = getImages("*5000*/*")
c.Assert(images[0].RepoTags, checker.HasLen, 1)
}
func (s *DockerSuite) TestApiImagesSaveAndLoad(c *check.C) {
// TODO Windows to Windows CI: Investigate further why this test fails.
testRequires(c, Network)
testRequires(c, DaemonIsLinux)
out, err := buildImage("saveandload", "FROM busybox\nENV FOO bar", false)
c.Assert(err, checker.IsNil)
id := strings.TrimSpace(out)
res, body, err := sockRequestRaw("GET", "/images/"+id+"/get", nil, "")
c.Assert(err, checker.IsNil)
defer body.Close()
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
dockerCmd(c, "rmi", id)
res, loadBody, err := sockRequestRaw("POST", "/images/load", body, "application/x-tar")
c.Assert(err, checker.IsNil)
defer loadBody.Close()
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
inspectOut := inspectField(c, id, "Id")
c.Assert(strings.TrimSpace(string(inspectOut)), checker.Equals, id, check.Commentf("load did not work properly"))
}
func (s *DockerSuite) TestApiImagesDelete(c *check.C) {
if daemonPlatform != "windows" {
testRequires(c, Network)
}
name := "test-api-images-delete"
out, err := buildImage(name, "FROM busybox\nENV FOO bar", false)
c.Assert(err, checker.IsNil)
id := strings.TrimSpace(out)
dockerCmd(c, "tag", name, "test:tag1")
status, _, err := sockRequest("DELETE", "/images/"+id, nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusConflict)
status, _, err = sockRequest("DELETE", "/images/test:noexist", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNotFound) //Status Codes:404 no such image
status, _, err = sockRequest("DELETE", "/images/test:tag1", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
}
func (s *DockerSuite) TestApiImagesHistory(c *check.C) {
if daemonPlatform != "windows" {
testRequires(c, Network)
}
name := "test-api-images-history"
out, err := buildImage(name, "FROM busybox\nENV FOO bar", false)
c.Assert(err, checker.IsNil)
id := strings.TrimSpace(out)
status, body, err := sockRequest("GET", "/images/"+id+"/history", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var historydata []types.ImageHistory
err = json.Unmarshal(body, &historydata)
c.Assert(err, checker.IsNil, check.Commentf("Error on unmarshal"))
c.Assert(historydata, checker.Not(checker.HasLen), 0)
c.Assert(historydata[0].Tags[0], checker.Equals, "test-api-images-history:latest")
}

View File

@@ -0,0 +1,39 @@
package main
import (
"net/http"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiVolumeInit(c *check.C) {
source := "https://raw.githubusercontent.com/hyperhq/hypercli/master/README.md"
volName := "hyperclitestvol"
dockerCmd(c, "volume", "create", "--name="+volName)
options := types.VolumesInitializeRequest{
Reload: false,
Volume: make([]types.VolumeInitDesc, 0),
}
options.Volume = append(options.Volume, types.VolumeInitDesc{Name: volName, Source: source})
status, b, err := sockRequest("POST", "/volumes/initialize", options)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK, check.Commentf(string(b)))
dockerCmd(c, "volume", "rm", volName)
}
func (s *DockerSuite) TestApiVolumeReload(c *check.C) {
source := "https://raw.githubusercontent.com/hyperhq/hypercli/master/README.md"
volName := "hyperclitestvol"
dockerCmd(c, "volume", "create", "--name="+volName)
dockerCmd(c, "volume", "init", source+":"+volName)
options := types.VolumesInitializeRequest{
Reload: true,
Volume: make([]types.VolumeInitDesc, 0),
}
options.Volume = append(options.Volume, types.VolumeInitDesc{Name: volName, Source: source})
status, b, err := sockRequest("POST", "/volumes/initialize", options)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK, check.Commentf(string(b)))
dockerCmd(c, "volume", "rm", volName)
}

View File

@@ -0,0 +1,290 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
)
func (s *DockerSuite) TestImagesEnsureImageIsListed(c *check.C) {
testRequires(c, DaemonIsLinux)
imagesOut, _ := dockerCmd(c, "images")
c.Assert(imagesOut, checker.Contains, "busybox")
}
func (s *DockerSuite) TestImagesEnsureImageWithTagIsListed(c *check.C) {
testRequires(c, DaemonIsLinux)
name := "imagewithtag"
dockerCmd(c, "tag", "busybox", name+":v1")
dockerCmd(c, "tag", "busybox", name+":v1v1")
dockerCmd(c, "tag", "busybox", name+":v2")
imagesOut, _ := dockerCmd(c, "images", name+":v1")
c.Assert(imagesOut, checker.Contains, name)
c.Assert(imagesOut, checker.Contains, "v1")
c.Assert(imagesOut, checker.Not(checker.Contains), "v2")
c.Assert(imagesOut, checker.Not(checker.Contains), "v1v1")
imagesOut, _ = dockerCmd(c, "images", name)
c.Assert(imagesOut, checker.Contains, name)
c.Assert(imagesOut, checker.Contains, "v1")
c.Assert(imagesOut, checker.Contains, "v1v1")
c.Assert(imagesOut, checker.Contains, "v2")
}
func (s *DockerSuite) TestImagesEnsureImageWithBadTagIsNotListed(c *check.C) {
imagesOut, _ := dockerCmd(c, "images", "busybox:nonexistent")
c.Assert(imagesOut, checker.Not(checker.Contains), "busybox")
}
func (s *DockerSuite) TestImagesOrderedByCreationDate(c *check.C) {
testRequires(c, DaemonIsLinux)
id1, err := buildImage("order:test_a",
`FROM scratch
MAINTAINER dockerio1`, true)
c.Assert(err, checker.IsNil)
time.Sleep(1 * time.Second)
id2, err := buildImage("order:test_c",
`FROM scratch
MAINTAINER dockerio2`, true)
c.Assert(err, checker.IsNil)
time.Sleep(1 * time.Second)
id3, err := buildImage("order:test_b",
`FROM scratch
MAINTAINER dockerio3`, true)
c.Assert(err, checker.IsNil)
out, _ := dockerCmd(c, "images", "-q", "--no-trunc")
imgs := strings.Split(out, "\n")
c.Assert(imgs[0], checker.Equals, id3, check.Commentf("First image must be %s, got %s", id3, imgs[0]))
c.Assert(imgs[1], checker.Equals, id2, check.Commentf("First image must be %s, got %s", id2, imgs[1]))
c.Assert(imgs[2], checker.Equals, id1, check.Commentf("First image must be %s, got %s", id1, imgs[2]))
}
func (s *DockerSuite) TestImagesErrorWithInvalidFilterNameTest(c *check.C) {
out, _, err := dockerCmdWithError("images", "-f", "FOO=123")
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "Invalid filter")
}
func (s *DockerSuite) TestImagesFilterLabelMatch(c *check.C) {
testRequires(c, DaemonIsLinux)
imageName1 := "images_filter_test1"
imageName2 := "images_filter_test2"
imageName3 := "images_filter_test3"
image1ID, err := buildImage(imageName1,
`FROM scratch
LABEL match me`, true)
c.Assert(err, check.IsNil)
image2ID, err := buildImage(imageName2,
`FROM scratch
LABEL match="me too"`, true)
c.Assert(err, check.IsNil)
image3ID, err := buildImage(imageName3,
`FROM scratch
LABEL nomatch me`, true)
c.Assert(err, check.IsNil)
out, _ := dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=match")
out = strings.TrimSpace(out)
c.Assert(out, check.Matches, fmt.Sprintf("[\\s\\w:]*%s[\\s\\w:]*", image1ID))
c.Assert(out, check.Matches, fmt.Sprintf("[\\s\\w:]*%s[\\s\\w:]*", image2ID))
c.Assert(out, check.Not(check.Matches), fmt.Sprintf("[\\s\\w:]*%s[\\s\\w:]*", image3ID))
out, _ = dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=match=me too")
out = strings.TrimSpace(out)
c.Assert(out, check.Equals, image2ID)
}
// Regression : #15659
func (s *DockerSuite) TestImagesFilterLabelWithCommit(c *check.C) {
// Create a container
dockerCmd(c, "run", "--name", "bar", "busybox", "/bin/sh")
// Commit with labels "using changes"
out, _ := dockerCmd(c, "commit", "-c", "LABEL foo.version=1.0.0-1", "-c", "LABEL foo.name=bar", "-c", "LABEL foo.author=starlord", "bar", "bar:1.0.0-1")
imageID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=foo.version=1.0.0-1")
out = strings.TrimSpace(out)
c.Assert(out, check.Equals, imageID)
}
func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) {
testRequires(c, DaemonIsLinux)
imageName := "images_filter_test"
buildImage(imageName,
`FROM scratch
RUN touch /test/foo
RUN touch /test/bar
RUN touch /test/baz`, true)
filters := []string{
"dangling=true",
"Dangling=true",
" dangling=true",
"dangling=true ",
"dangling = true",
}
imageListings := make([][]string, 5, 5)
for idx, filter := range filters {
out, _ := dockerCmd(c, "images", "-q", "-f", filter)
listing := strings.Split(out, "\n")
sort.Strings(listing)
imageListings[idx] = listing
}
for idx, listing := range imageListings {
if idx < 4 && !reflect.DeepEqual(listing, imageListings[idx+1]) {
for idx, errListing := range imageListings {
fmt.Printf("out %d", idx)
for _, image := range errListing {
fmt.Print(image)
}
fmt.Print("")
}
c.Fatalf("All output must be the same")
}
}
}
func (s *DockerSuite) TestImagesEnsureDanglingImageOnlyListedOnce(c *check.C) {
testRequires(c, DaemonIsLinux)
// create container 1
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
containerID1 := strings.TrimSpace(out)
// tag as foobox
out, _ = dockerCmd(c, "commit", containerID1, "foobox")
imageID := stringid.TruncateID(strings.TrimSpace(out))
// overwrite the tag, making the previous image dangling
dockerCmd(c, "tag", "-f", "busybox", "foobox")
out, _ = dockerCmd(c, "images", "-q", "-f", "dangling=true")
// Expect one dangling image
c.Assert(strings.Count(out, imageID), checker.Equals, 1)
out, _ = dockerCmd(c, "images", "-q", "-f", "dangling=false")
//dangling=false would not include dangling images
c.Assert(out, checker.Not(checker.Contains), imageID)
out, _ = dockerCmd(c, "images")
//docker images still include dangling images
c.Assert(out, checker.Contains, imageID)
}
func (s *DockerSuite) TestImagesWithIncorrectFilter(c *check.C) {
out, _, err := dockerCmdWithError("images", "-f", "dangling=invalid")
c.Assert(err, check.NotNil)
c.Assert(out, checker.Contains, "Invalid filter")
}
func (s *DockerSuite) TestImagesEnsureOnlyHeadsImagesShown(c *check.C) {
testRequires(c, DaemonIsLinux)
dockerfile := `
FROM scratch
MAINTAINER docker
ENV foo bar`
head, out, err := buildImageWithOut("scratch-image", dockerfile, false)
c.Assert(err, check.IsNil)
// this is just the output of docker build
// we're interested in getting the image id of the MAINTAINER instruction
// and that's located at output, line 5, from 7 to end
split := strings.Split(out, "\n")
intermediate := strings.TrimSpace(split[5][7:])
out, _ = dockerCmd(c, "images")
// images shouldn't show non-heads images
c.Assert(out, checker.Not(checker.Contains), intermediate)
// images should contain final built images
c.Assert(out, checker.Contains, stringid.TruncateID(head))
}
func (s *DockerSuite) TestImagesEnsureImagesFromScratchShown(c *check.C) {
testRequires(c, DaemonIsLinux)
dockerfile := `
FROM scratch
MAINTAINER docker`
id, _, err := buildImageWithOut("scratch-image", dockerfile, false)
c.Assert(err, check.IsNil)
out, _ := dockerCmd(c, "images")
// images should contain images built from scratch
c.Assert(out, checker.Contains, stringid.TruncateID(id))
}
// #18181
func (s *DockerSuite) TestImagesFilterNameWithPort(c *check.C) {
tag := "a.b.c.d:5000/hello"
dockerCmd(c, "tag", "busybox", tag)
out, _ := dockerCmd(c, "images", tag)
c.Assert(out, checker.Contains, tag)
out, _ = dockerCmd(c, "images", tag+":latest")
c.Assert(out, checker.Contains, tag)
out, _ = dockerCmd(c, "images", tag+":no-such-tag")
c.Assert(out, checker.Not(checker.Contains), tag)
}
func (s *DockerSuite) TestImagesFormat(c *check.C) {
// testRequires(c, DaemonIsLinux)
tag := "myimage"
dockerCmd(c, "tag", "busybox", tag+":v1")
dockerCmd(c, "tag", "busybox", tag+":v2")
out, _ := dockerCmd(c, "images", "--format", "{{.Repository}}", tag)
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
expected := []string{"myimage", "myimage"}
var names []string
for _, l := range lines {
names = append(names, l)
}
c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
}
// ImagesDefaultFormatAndQuiet
func (s *DockerSuite) TestImagesFormatDefaultFormat(c *check.C) {
testRequires(c, DaemonIsLinux)
// create container 1
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
containerID1 := strings.TrimSpace(out)
// tag as foobox
out, _ = dockerCmd(c, "commit", containerID1, "myimage")
imageID := stringid.TruncateID(strings.TrimSpace(out))
config := `{
"imagesFormat": "{{ .ID }} default"
}`
d, err := ioutil.TempDir("", "integration-cli-")
c.Assert(err, checker.IsNil)
defer os.RemoveAll(d)
err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "--config", d, "images", "-q", "myimage")
c.Assert(out, checker.Equals, imageID+"\n", check.Commentf("Expected to print only the image id, got %v\n", out))
}

View File

@@ -0,0 +1,69 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// Image volume mounted at directory "/data1"
func (s *DockerSuite) TestVerifyNoautoVolumeBaseImage(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "hyperhq/noauto_volume_test")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "df", "/data1")
c.Assert(err, checker.Equals, 0)
c.Assert(strings.Contains(string(out), "data1"), checker.True, check.Commentf("got df results: %s", string(out)))
dockerCmd(c, "rm", "-fv", "voltest")
}
// No volume mounted at directory "/data1"
func (s *DockerSuite) TestNoautoVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
_, err := dockerCmd(c, "run", "-d", "--noauto-volume", "--name=voltest", "hyperhq/noauto_volume_test")
c.Assert(err, checker.Equals, 0)
_, exitCode, _ := dockerCmdWithError("exec", "voltest", "ls", "/data1")
c.Assert(exitCode, checker.GreaterThan, 0)
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestImplicitOverwriteNoautoVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
_, err := dockerCmd(c, "run", "-d", "--noauto-volume", "--name=voltest", "-v", "/data1", "hyperhq/noauto_volume_test")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "df", "/data1")
c.Assert(err, checker.Equals, 0)
c.Assert(strings.Contains(string(out), "data1"), checker.True, check.Commentf("got df results: %s", string(out)))
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestNamedOverwriteNoautoVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "run", "-d", "--noauto-volume", "--name=voltest", "-v", volName+":/data1", "hyperhq/noauto_volume_test")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "df", "/data1")
c.Assert(err, checker.Equals, 0)
c.Assert(strings.Contains(string(out), "data1"), checker.True, check.Commentf("got df results: %s", string(out)))
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestNoautoAndNormalVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "run", "-d", "--noauto-volume", "--name=voltest", "-v", volName+":/vol/data", "hyperhq/noauto_volume_test")
c.Assert(err, checker.Equals, 0)
_, exitCode, _ := dockerCmdWithError("exec", "voltest", "ls", "/data1")
c.Assert(exitCode, checker.GreaterThan, 0)
out, err := dockerCmd(c, "exec", "voltest", "df", "/vol/data")
c.Assert(err, checker.Equals, 0)
c.Assert(strings.Contains(string(out), "data"), checker.True, check.Commentf("got df /vol/data results: %s", string(out)))
dockerCmd(c, "rm", "-fv", "voltest")
}

View File

@@ -0,0 +1,178 @@
package main
import (
"io/ioutil"
"os/exec"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestRunGitVolumeBinding(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
source := "git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "cat", "/data/README")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "util-linux")
dockerCmd(c, "rm", "-fv", "voltest")
source = "git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git:stable/v2.13.0"
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err = dockerCmd(c, "exec", "voltest", "cat", "/data/configure.ac")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "2.13.0")
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestRunHttpGitVolumeBinding(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
source := "http://git.kernel.org/pub/scm/utils/util-linux/util-linux.git"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "cat", "/data/README")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "util-linux")
dockerCmd(c, "rm", "-fv", "voltest")
source = "http://git.kernel.org/pub/scm/utils/util-linux/util-linux.git:stable/v2.13.0"
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err = dockerCmd(c, "exec", "voltest", "cat", "/data/configure.ac")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "2.13.0")
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestRunHttpsGitVolumeBinding(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
source := "https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "cat", "/data/README")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "util-linux")
dockerCmd(c, "rm", "-fv", "voltest")
source = "http://git.kernel.org/pub/scm/utils/util-linux/util-linux.git:stable/v2.13.0"
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err = dockerCmd(c, "exec", "voltest", "cat", "/data/README")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "util-linux")
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestRunHttpFileVolumeBinding(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
source := "https://raw.githubusercontent.com/hyperhq/hypercli/master/README.md"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "stat", "/data")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "regular file")
dockerCmd(c, "rm", "-fv", "voltest")
source = "https://raw.githubusercontent.com/hyperhq/hypercli/master/README.md"
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err = dockerCmd(c, "exec", "voltest", "stat", "/data")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "regular file")
dockerCmd(c, "rm", "-fv", "voltest")
source = "https://raw.githubusercontent.com/nosuchuser/nosuchrepo/masterbeta/README.md"
_, _, cmdErr := dockerCmdWithError("run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(cmdErr, checker.NotNil)
}
func (s *DockerSuite) TestRunLocalFileVolumeBinding(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
source := "/tmp/hyper_integration_test_local_file_volume_file"
ioutil.WriteFile(source, []byte("foo"), 0644)
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/volume/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "cat", "/volume/data")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Equals, "foo")
dockerCmd(c, "rm", "-fv", "voltest")
// Dir destination as a file
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", source+":/volume/data/", "busybox")
c.Assert(err, checker.Equals, 0)
out, err = dockerCmd(c, "exec", "voltest", "cat", "/volume/data")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Equals, "foo")
dockerCmd(c, "rm", "-fv", "voltest")
exec.Command("rm", "-f", source).CombinedOutput()
// NonexistingVolumeBinding
dir := "/tmp/nosuchfile"
_, _, realErr := dockerCmdWithError("run", "-d", "--name=voltest", "-v", dir+":/data", "busybox")
c.Assert(realErr, checker.NotNil)
}
func (s *DockerSuite) TestRunLocalDirVolumeBinding(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
dir := "/tmp/hyper_integration_test_local_dir_volume_dir"
file := "datafile"
exec.Command("mkdir", "-p", dir).CombinedOutput()
ioutil.WriteFile(dir+"/"+file, []byte("foo"), 0644)
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", dir+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "cat", "/data/"+file)
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Equals, "foo")
dockerCmd(c, "rm", "-fv", "voltest")
exec.Command("rm", "-r", dir).CombinedOutput()
// Deep dir binding
dir = "/tmp/hyper_integration_test_local_dir_volume_dir"
middle_dir := "/dir1/dir2/dir3/dir4/dir5"
file = "datafile"
exec.Command("mkdir", "-p", dir+"/"+middle_dir).CombinedOutput()
ioutil.WriteFile(dir+"/"+middle_dir+"/"+file, []byte("foo"), 0644)
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", dir+":/data", "busybox")
c.Assert(err, checker.Equals, 0)
out, err = dockerCmd(c, "exec", "voltest", "cat", "/data/"+middle_dir+"/"+file)
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Equals, "foo")
dockerCmd(c, "rm", "-fv", "voltest")
exec.Command("rm", "-r", dir).CombinedOutput()
}
func (s *DockerSuite) TestRunExceptionVolumeBinding(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// NonexistingVolumeBinding
source := "/tmp/nosuchfile"
_, _, err := dockerCmdWithError("run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.NotNil)
source = "http://nosuchdomain"
_, _, err = dockerCmdWithError("run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.NotNil)
source = "git://nosuchdomain.git"
_, _, err = dockerCmdWithError("run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.NotNil)
source = "git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git:nosuchbranch"
_, _, err = dockerCmdWithError("run", "-d", "--name=voltest", "-v", source+":/data", "busybox")
c.Assert(err, checker.NotNil)
}

View File

@@ -0,0 +1,28 @@
package main
import (
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestMultiMountImplicitVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", volName+":/data1", "-v", volName+":/vol/data", "busybox")
c.Assert(err, checker.Equals, 0)
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestMultiMountNamedVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "volume", "create", "--name", volName)
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", volName+":/data1", "-v", volName+":/vol/data", "busybox")
c.Assert(err, checker.Equals, 0)
dockerCmd(c, "rm", "-fv", "voltest")
}

View File

@@ -0,0 +1,83 @@
package main
import (
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestPopulateImplicitVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", volName+":/etc", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "ls", "/etc")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "passwd")
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestPopulateNamedVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "volume", "create", "--name", volName)
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", volName+":/etc", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "ls", "/etc")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "passwd")
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestPopulateMultiMountImplicitVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "-v", volName+":/lib/modules/", "-v", volName+":/tmp", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "ls", "/lib/modules")
c.Assert(err, checker.Equals, 0)
c.Assert(string(out), checker.HasLen, 0)
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestPopulateMultiMountNamedVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "volume", "create", "--name", volName)
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "run", "-d", "--name=voltest", "-v", volName+":/lib/modules/", "-v", volName+":/tmp", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "ls", "/lib/modules")
c.Assert(err, checker.Equals, 0)
c.Assert(string(out), checker.HasLen, 0)
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestPopulateImageVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "--size=l1", "neo4j")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "ls", "/data")
c.Assert(err, checker.Equals, 0)
c.Assert(string(out), checker.Contains, "databases")
dockerCmd(c, "rm", "-fv", "voltest")
}
func (s *DockerSuite) TestPopulateNamedImageVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
volName := "testvolume"
_, err := dockerCmd(c, "run", "-d", "--name=voltest", "--size=l1", "-v", volName+":/data", "neo4j")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "voltest", "ls", "/data")
c.Assert(err, checker.Equals, 0)
c.Assert(string(out), checker.Contains, "databases")
dockerCmd(c, "rm", "-fv", "voltest")
}

View File

@@ -0,0 +1,49 @@
package main
import (
"net/http"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiCreateWithNotExistImage(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
name := "test"
config := map[string]interface{}{
"Image": "test456:v1",
"Volumes": map[string]struct{}{"/tmp": {}},
}
status, resp, err := sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNotFound)
expected := "No such image: test456:v1"
c.Assert(strings.TrimSpace(string(resp)), checker.Contains, expected)
config2 := map[string]interface{}{
"Image": "test456",
"Volumes": map[string]struct{}{"/tmp": {}},
}
status, resp, err = sockRequest("POST", "/containers/create?name="+name, config2)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNotFound)
expected = "No such image: test456:latest"
c.Assert(strings.TrimSpace(string(resp)), checker.Equals, expected)
config3 := map[string]interface{}{
"Image": "sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
}
status, resp, err = sockRequest("POST", "/containers/create?name="+name, config3)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNotFound)
expected = "No such image: sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa"
c.Assert(strings.TrimSpace(string(resp)), checker.Equals, expected)
}

View File

@@ -0,0 +1,130 @@
// +build !test_no_exec
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// Regression test for #9414
func (s *DockerSuite) TestApiExecBasicCreateNoCmd(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
name := "exec-test"
dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "top")
status, body, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": nil})
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusBadRequest)
comment := check.Commentf("Expected message when creating exec command with no Cmd specified")
c.Assert(string(body), checker.Contains, "No exec command specified", comment)
}
func (s *DockerSuite) TestApiExecBasicCreateNoValidContentType(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
name := "exec-test"
dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
jsonData := bytes.NewBuffer(nil)
if err := json.NewEncoder(jsonData).Encode(map[string]interface{}{"Cmd": nil}); err != nil {
c.Fatalf("Can not encode data to json %s", err)
}
res, body, err := sockRequestRaw("POST", fmt.Sprintf("/containers/%s/exec", name), jsonData, "text/plain")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
b, err := readBody(body)
c.Assert(err, checker.IsNil)
comment := check.Commentf("Expected message when creating exec command with invalid Content-Type specified")
c.Assert(string(b), checker.Equals, "The server encountered an internal error or misconfiguration...\n", comment)
}
//TODO: fix #86
/*func (s *DockerSuite) TestApiExecBasicApiStart(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux) // Uses pause/unpause but bits may be salvagable to Windows to Windows CI
dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
id := createExec(c, "test")
startExec(c, id, http.StatusOK)
id = createExec(c, "test")
dockerCmd(c, "stop", "test")
startExec(c, id, http.StatusNotFound)
dockerCmd(c, "start", "test")
startExec(c, id, http.StatusNotFound)
}
func (s *DockerSuite) TestApiExecBasicApiStartMultipleTimesError(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
runSleepingContainer(c, "-d", "--name", "test")
execID := createExec(c, "test")
startExec(c, execID, http.StatusOK)
timeout := time.After(60 * time.Second)
var execJSON struct{ Running bool }
for {
select {
case <-timeout:
c.Fatal("timeout waiting for exec to start")
default:
}
inspectExec(c, execID, &execJSON)
if !execJSON.Running {
break
}
}
startExec(c, execID, http.StatusConflict)
}*/
func createExec(c *check.C, name string) string {
_, b, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": []string{"true"}})
c.Assert(err, checker.IsNil, check.Commentf(string(b)))
createResp := struct {
ID string `json:"Id"`
}{}
c.Assert(json.Unmarshal(b, &createResp), checker.IsNil, check.Commentf(string(b)))
return createResp.ID
}
func startExec(c *check.C, id string, code int) {
resp, body, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/start", id), strings.NewReader(`{"Detach": true}`), "application/json")
c.Assert(err, checker.IsNil)
b, err := readBody(body)
comment := check.Commentf("response body: %s", b)
c.Assert(err, checker.IsNil, comment)
c.Assert(resp.StatusCode, checker.Equals, code, comment)
}
func inspectExec(c *check.C, id string, out interface{}) {
resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/exec/%s/json", id), nil, "")
c.Assert(err, checker.IsNil)
defer body.Close()
c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
err = json.NewDecoder(body).Decode(out)
c.Assert(err, checker.IsNil)
}

View File

@@ -0,0 +1,112 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"sync"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiExecResizeHeightWidthNoInt(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar"
status, _, err := sockRequest("POST", endpoint, nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNotFound)
}
// Part of #14845
func (s *DockerSuite) TestApiExecResizeImmediatelyAfterExecStart(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
name := "exec-resize-test"
dockerCmd(c, "run", "-d", "-i", "-t", "--name", name, "--restart", "always", "busybox", "/bin/sh")
testExecResize := func() error {
data := map[string]interface{}{
"AttachStdin": true,
"Cmd": []string{"/bin/sh"},
}
uri := fmt.Sprintf("/containers/%s/exec", name)
status, body, err := sockRequest("POST", uri, data)
if err != nil {
return err
}
if status != http.StatusCreated {
return fmt.Errorf("POST %s is expected to return %d, got %d", uri, http.StatusCreated, status)
}
out := map[string]string{}
err = json.Unmarshal(body, &out)
if err != nil {
return fmt.Errorf("ExecCreate returned invalid json. Error: %q", err.Error())
}
execID := out["Id"]
if len(execID) < 1 {
return fmt.Errorf("ExecCreate got invalid execID")
}
payload := bytes.NewBufferString(`{"Tty":true}`)
conn, _, err := sockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json")
if err != nil {
return fmt.Errorf("Failed to start the exec: %q", err.Error())
}
defer conn.Close()
_, rc, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), nil, "text/plain")
// It's probably a panic of the daemon if io.ErrUnexpectedEOF is returned.
if err == io.ErrUnexpectedEOF {
return fmt.Errorf("The daemon might have crashed.")
}
if err == nil {
rc.Close()
}
// We only interested in the io.ErrUnexpectedEOF error, so we return nil otherwise.
return nil
}
// The panic happens when daemon.ContainerExecStart is called but the
// container.Exec is not called.
// Because the panic is not 100% reproducible, we send the requests concurrently
// to increase the probability that the problem is triggered.
var (
n = 10
ch = make(chan error, n)
wg sync.WaitGroup
)
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
if err := testExecResize(); err != nil {
ch <- err
}
}()
}
wg.Wait()
select {
case err := <-ch:
c.Fatal(err.Error())
default:
}
}

View File

@@ -0,0 +1,60 @@
package main
import (
"encoding/json"
"net/http"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
//this test case will test all the apis about fip
func (s *DockerSuite) TestApiFip(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
endpoint := "/fips/allocate?count=1"
status, body, err := sockRequest("POST", endpoint, nil)
c.Assert(status, checker.Equals, http.StatusCreated)
c.Assert(err, checker.IsNil)
var IP []string
err = json.Unmarshal(body, &IP)
c.Assert(err, checker.IsNil)
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
containerID := strings.TrimSpace(out)
endpoint = "/fips/associate?ip=" + IP[0] + "&container=" + containerID
status, body, err = sockRequest("POST", endpoint, nil)
c.Assert(status, checker.Equals, http.StatusNoContent)
c.Assert(err, checker.IsNil)
endpoint = "/fips"
status, body, err = sockRequest("GET", endpoint, nil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(string(body), checker.Contains, IP[0], check.Commentf("should get IP %s", IP[0]))
c.Assert(string(body), checker.Contains, containerID, check.Commentf("should get containerID %s", containerID))
endpoint = "/fips/disassociate?container=" + containerID
status, body, err = sockRequest("POST", endpoint, nil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
time.Sleep(5 * time.Second)
endpoint = "/fips/release?ip=" + IP[0]
status, body, err = sockRequest("POST", endpoint, nil)
c.Assert(status, checker.Equals, http.StatusNoContent)
c.Assert(err, checker.IsNil)
//make sure that IP[0] has been released
endpoint = "/fips"
status, body, err = sockRequest("GET", endpoint, nil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(string(body), checker.Not(checker.Contains), IP[0], check.Commentf("should not get IP %s", IP[0]))
}

View File

@@ -0,0 +1,44 @@
package main
import (
"net/http"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"strings"
)
func (s *DockerSuite) TestApiImagesSearchJSONContentType(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, Network)
res, b, err := sockRequestRaw("GET", "/images/search?term=test", nil, "application/json")
c.Assert(err, check.IsNil)
b.Close()
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
c.Assert(res.Header.Get("Content-Type"), checker.Equals, "application/json")
}
func (s *DockerSuite) TestApiImagesLoad(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
postData := map[string]interface{}{
"fromSrc": "http://image-tarball.s3.amazonaws.com/test/public/helloworld.tar.gz",
"quiet": false,
}
//debugEndpoint = "/images/load"
status, resp, err := sockRequest("POST", "/images/load", postData)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
expected := "{\"status\":\"Starting to download and load the image archive, please wait...\"}"
c.Assert(strings.TrimSpace(string(resp)), checker.Contains, expected)
expected = "has been loaded.\"}"
c.Assert(strings.TrimSpace(string(resp)), checker.Contains, expected)
}

View File

@@ -0,0 +1,44 @@
package main
import (
"net/http"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiInfo(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
endpoint := "/info"
status, body, err := sockRequest("GET", endpoint, nil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
// always shown fields
stringsToCheck := []string{
"ID",
"Containers",
"ContainersRunning",
"ContainersPaused",
"ContainersStopped",
"Images",
"ExecutionDriver",
"LoggingDriver",
"OperatingSystem",
"NCPU",
"OSType",
"Architecture",
"MemTotal",
"KernelVersion",
"Driver",
"ServerVersion"}
out := string(body)
for _, linePrefix := range stringsToCheck {
c.Assert(out, checker.Contains, linePrefix)
}
}

View File

@@ -0,0 +1,49 @@
package main
import (
"encoding/json"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiInspectContainerResponse(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
ensureImageExist(c, "busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
cleanedContainerID := strings.TrimSpace(out)
keysBase := []string{"Id", "State", "Created", "Path", "Args", "Config", "Image", "NetworkSettings",
"ResolvConfPath", "HostnamePath", "HostsPath", "LogPath", "Name", "Driver", "MountLabel", "ProcessLabel", "GraphDriver"}
type acase struct {
version string
keys []string
}
var cases []acase
cases = []acase{
{"v1.23", append(keysBase, "Mounts")},
}
for _, cs := range cases {
body := getInspectBodyWithoutVersion(c, cleanedContainerID)
var inspectJSON map[string]interface{}
err := json.Unmarshal(body, &inspectJSON)
c.Assert(err, checker.IsNil, check.Commentf("Unable to unmarshal body for version %s", cs.version))
for _, key := range cs.keys {
_, ok := inspectJSON[key]
c.Check(ok, checker.True, check.Commentf("%s does not exist in response for version %s", key, cs.version))
}
_, ok := inspectJSON["Path"].(bool)
c.Assert(ok, checker.False, check.Commentf("Path of `true` should not be converted to boolean `true` via JSON marshalling"))
}
}

View File

@@ -0,0 +1,60 @@
package main
import (
"bytes"
"fmt"
"net/http"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
//TODO: fix #90
/*func (s *DockerSuite) TestApiLogsNoStdoutNorStderr(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
name := "logs-test"
dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
status, body, err := sockRequest("GET", fmt.Sprintf("/containers/%s/logs", name), nil)
c.Assert(status, checker.Equals, http.StatusBadRequest)
c.Assert(err, checker.IsNil)
expected := "Bad parameters: you must choose at least one stream"
if !bytes.Contains(body, []byte(expected)) {
c.Fatalf("Expected %s, got %s", expected, string(body[:]))
}
}*/
// Regression test for #12704
func (s *DockerSuite) TestApiLogsFollowEmptyOutput(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
name := "logs-test"
t0 := time.Now()
dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "sleep", "10")
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name), bytes.NewBuffer(nil), "")
t1 := time.Now()
c.Assert(err, checker.IsNil)
body.Close()
elapsed := t1.Sub(t0).Seconds()
if elapsed > 40.0 {
c.Fatalf("HTTP response was not immediate (elapsed %.1fs)", elapsed)
}
}
func (s *DockerSuite) TestApiLogsContainerNotFound(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
name := "nonExistentContainer"
resp, _, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name), bytes.NewBuffer(nil), "")
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
}

View File

@@ -0,0 +1,25 @@
package main
import (
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiContainerStartNilHostconfig(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
name := "testing"
config := map[string]interface{}{
"Image": "busybox",
}
_, _, err := sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(err, checker.IsNil)
config = map[string]interface{}{}
_, _, err = sockRequest("POST", "/containers/"+name+"/start", config)
c.Assert(err, checker.IsNil)
}

View File

@@ -0,0 +1,77 @@
package main
import (
"encoding/json"
"net/http"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiSnapshotsCreate(c *check.C) {
dockerCmd(c, "volume", "create", "--name", "test")
status, b, err := sockRequest("POST", "/snapshots/create?name=snap-test&volume=test", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated, check.Commentf(string(b)))
var snap types.Snapshot
err = json.Unmarshal(b, &snap)
c.Assert(err, checker.IsNil)
}
func (s *DockerSuite) TestApiSnapshotsList(c *check.C) {
dockerCmd(c, "volume", "create", "--name", "test")
sockRequest("POST", "/snapshots/create?name=snap-test&volume=test", nil)
status, b, err := sockRequest("GET", "/snapshots", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var snapshots types.SnapshotsListResponse
c.Assert(json.Unmarshal(b, &snapshots), checker.IsNil)
c.Assert(len(snapshots.Snapshots), checker.Equals, 1, check.Commentf("\n%v", snapshots.Snapshots))
}
func (s *DockerSuite) TestApiSnapshotsRemove(c *check.C) {
dockerCmd(c, "volume", "create", "--name", "test")
sockRequest("POST", "/snapshots/create?name=snap-test&volume=test", nil)
status, b, err := sockRequest("GET", "/snapshots", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var snapshots types.SnapshotsListResponse
c.Assert(json.Unmarshal(b, &snapshots), checker.IsNil)
c.Assert(len(snapshots.Snapshots), checker.Equals, 1, check.Commentf("\n%v", snapshots.Snapshots))
snap := snapshots.Snapshots[0]
status, data, err := sockRequest("DELETE", "/snapshots/"+snap.Name, nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent, check.Commentf(string(data)))
}
func (s *DockerSuite) TestApiSnapshotsInspect(c *check.C) {
dockerCmd(c, "volume", "create", "--name", "test")
sockRequest("POST", "/snapshots/create?name=snap-test&volume=test", nil)
status, b, err := sockRequest("GET", "/snapshots", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var snapshots types.SnapshotsListResponse
c.Assert(json.Unmarshal(b, &snapshots), checker.IsNil)
c.Assert(len(snapshots.Snapshots), checker.Equals, 1, check.Commentf("\n%v", snapshots.Snapshots))
var snap types.Snapshot
status, b, err = sockRequest("GET", "/snapshots/snap-test", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf(string(b)))
c.Assert(json.Unmarshal(b, &snap), checker.IsNil)
c.Assert(snap.Name, checker.Equals, "snap-test")
}

View File

@@ -0,0 +1,193 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
"os/exec"
"runtime"
"strconv"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/version"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
var expectedNetworkInterfaceStats = strings.Split("rx_bytes rx_dropped rx_errors rx_packets tx_bytes tx_dropped tx_errors tx_packets", " ")
func (s *DockerSuite) TestApiStatsNoStreamGetCpu(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true;do echo 'Hello'; usleep 100000; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
c.Assert(resp.Header.Get("Content-Type"), checker.Equals, "application/json")
var v *types.Stats
err = json.NewDecoder(body).Decode(&v)
c.Assert(err, checker.IsNil)
body.Close()
var cpuPercent = 0.0
cpuDelta := float64(v.CPUStats.CPUUsage.TotalUsage - v.PreCPUStats.CPUUsage.TotalUsage)
systemDelta := float64(v.CPUStats.SystemUsage - v.PreCPUStats.SystemUsage)
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
c.Assert(cpuPercent, check.Not(checker.Equals), 0.0, check.Commentf("docker stats with no-stream get cpu usage failed: was %v", cpuPercent))
}
func (s *DockerSuite) TestApiStatsNetworkStats(c *check.C) {
testRequires(c, SameHostDaemon)
testRequires(c, DaemonIsLinux)
out, _ := runSleepingContainer(c)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
// Retrieve the container address
contIP := findContainerIP(c, id, "bridge")
numPings := 4
var preRxPackets uint64
var preTxPackets uint64
var postRxPackets uint64
var postTxPackets uint64
// Get the container networking stats before and after pinging the container
nwStatsPre := getNetworkStats(c, id)
for _, v := range nwStatsPre {
preRxPackets += v.RxPackets
preTxPackets += v.TxPackets
}
countParam := "-c"
if runtime.GOOS == "windows" {
countParam = "-n" // Ping count parameter is -n on Windows
}
pingout, err := exec.Command("ping", contIP, countParam, strconv.Itoa(numPings)).Output()
pingouts := string(pingout[:])
c.Assert(err, checker.IsNil)
nwStatsPost := getNetworkStats(c, id)
for _, v := range nwStatsPost {
postRxPackets += v.RxPackets
postTxPackets += v.TxPackets
}
// Verify the stats contain at least the expected number of packets (account for ARP)
expRxPkts := 1 + preRxPackets + uint64(numPings)
expTxPkts := 1 + preTxPackets + uint64(numPings)
c.Assert(postTxPackets, checker.GreaterOrEqualThan, expTxPkts,
check.Commentf("Reported less TxPackets than expected. Expected >= %d. Found %d. %s", expTxPkts, postTxPackets, pingouts))
c.Assert(postRxPackets, checker.GreaterOrEqualThan, expRxPkts,
check.Commentf("Reported less Txbytes than expected. Expected >= %d. Found %d. %s", expRxPkts, postRxPackets, pingouts))
}
func (s *DockerSuite) TestApiStatsNetworkStatsVersioning(c *check.C) {
testRequires(c, SameHostDaemon)
testRequires(c, DaemonIsLinux)
out, _ := runSleepingContainer(c)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
for i := 17; i <= 21; i++ {
apiVersion := fmt.Sprintf("v1.%d", i)
statsJSONBlob := getVersionedStats(c, id, apiVersion)
if version.Version(apiVersion).LessThan("v1.21") {
c.Assert(jsonBlobHasLTv121NetworkStats(statsJSONBlob), checker.Equals, true,
check.Commentf("Stats JSON blob from API %s %#v does not look like a <v1.21 API stats structure", apiVersion, statsJSONBlob))
} else {
c.Assert(jsonBlobHasGTE121NetworkStats(statsJSONBlob), checker.Equals, true,
check.Commentf("Stats JSON blob from API %s %#v does not look like a >=v1.21 API stats structure", apiVersion, statsJSONBlob))
}
}
}
func getNetworkStats(c *check.C, id string) map[string]types.NetworkStats {
var st *types.StatsJSON
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
c.Assert(err, checker.IsNil)
err = json.NewDecoder(body).Decode(&st)
c.Assert(err, checker.IsNil)
body.Close()
return st.Networks
}
// getVersionedStats returns stats result for the
// container with id using an API call with version apiVersion. Since the
// stats result type differs between API versions, we simply return
// map[string]interface{}.
func getVersionedStats(c *check.C, id string, apiVersion string) map[string]interface{} {
stats := make(map[string]interface{})
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/%s/containers/%s/stats?stream=false", apiVersion, id), nil, "")
c.Assert(err, checker.IsNil)
defer body.Close()
err = json.NewDecoder(body).Decode(&stats)
c.Assert(err, checker.IsNil, check.Commentf("failed to decode stat: %s", err))
return stats
}
func jsonBlobHasLTv121NetworkStats(blob map[string]interface{}) bool {
networkStatsIntfc, ok := blob["network"]
if !ok {
return false
}
networkStats, ok := networkStatsIntfc.(map[string]interface{})
if !ok {
return false
}
for _, expectedKey := range expectedNetworkInterfaceStats {
if _, ok := networkStats[expectedKey]; !ok {
return false
}
}
return true
}
func jsonBlobHasGTE121NetworkStats(blob map[string]interface{}) bool {
networksStatsIntfc, ok := blob["networks"]
if !ok {
return false
}
networksStats, ok := networksStatsIntfc.(map[string]interface{})
if !ok {
return false
}
for _, networkInterfaceStatsIntfc := range networksStats {
networkInterfaceStats, ok := networkInterfaceStatsIntfc.(map[string]interface{})
if !ok {
return false
}
for _, expectedKey := range expectedNetworkInterfaceStats {
if _, ok := networkInterfaceStats[expectedKey]; !ok {
return false
}
}
}
return true
}
func (s *DockerSuite) TestApiStatsContainerNotFound(c *check.C) {
testRequires(c, DaemonIsLinux)
status, _, err := sockRequest("GET", "/containers/nonexistent/stats", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNotFound)
status, _, err = sockRequest("GET", "/containers/nonexistent/stats?stream=0", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNotFound)
}

View File

@@ -0,0 +1,43 @@
package main
import (
"encoding/json"
"net/http"
"time"
"fmt"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiGetVersion(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
status, body, err := sockRequest("GET", "/version", nil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
var v types.Version
c.Assert(json.Unmarshal(body, &v), checker.IsNil)
c.Assert(v.Version, checker.Equals, dockerversion.Version, check.Commentf("Version mismatch"))
}
func (s *DockerSuite) TestApiSimpleCreate(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
"Cmd": []string{"/bin/sh"},
}
status, b, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, checker.IsNil)
type createResp struct {
ID string
Warning string
}
//var container createResp
fmt.Println(string(b))
c.Assert(status, checker.Equals, http.StatusCreated)
}

View File

@@ -0,0 +1,88 @@
package main
import (
"encoding/json"
"net/http"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiVolumesList(c *check.C) {
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "busybox")
status, b, err := sockRequest("GET", "/volumes", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var volumes types.VolumesListResponse
c.Assert(json.Unmarshal(b, &volumes), checker.IsNil)
c.Assert(len(volumes.Volumes), checker.Equals, 1, check.Commentf("\n%v", volumes.Volumes))
}
func (s *DockerSuite) TestApiVolumesCreate(c *check.C) {
config := types.VolumeCreateRequest{
Name: "test",
Driver: "hyper",
}
status, b, err := sockRequest("POST", "/volumes/create", config)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated, check.Commentf(string(b)))
var vol types.Volume
err = json.Unmarshal(b, &vol)
c.Assert(err, checker.IsNil)
}
func (s *DockerSuite) TestApiVolumesRemove(c *check.C) {
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "--name=test", "busybox")
status, b, err := sockRequest("GET", "/volumes", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var volumes types.VolumesListResponse
c.Assert(json.Unmarshal(b, &volumes), checker.IsNil)
c.Assert(len(volumes.Volumes), checker.Equals, 1, check.Commentf("\n%v", volumes.Volumes))
v := volumes.Volumes[0]
status, _, err = sockRequest("DELETE", "/volumes/"+v.Name, nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusConflict, check.Commentf("Should not be able to remove a volume that is in use"))
dockerCmd(c, "rm", "-f", "test")
status, data, err := sockRequest("DELETE", "/volumes/"+v.Name, nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent, check.Commentf(string(data)))
}
func (s *DockerSuite) TestApiVolumesInspect(c *check.C) {
config := types.VolumeCreateRequest{
Name: "test",
Driver: "hyper",
}
status, b, err := sockRequest("POST", "/volumes/create", config)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated, check.Commentf(string(b)))
status, b, err = sockRequest("GET", "/volumes", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf(string(b)))
var volumes types.VolumesListResponse
c.Assert(json.Unmarshal(b, &volumes), checker.IsNil)
c.Assert(len(volumes.Volumes), checker.Equals, 1, check.Commentf("\n%v", volumes.Volumes))
var vol types.Volume
status, b, err = sockRequest("GET", "/volumes/"+config.Name, nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf(string(b)))
c.Assert(json.Unmarshal(b, &vol), checker.IsNil)
c.Assert(vol.Name, checker.Equals, config.Name)
}

View File

@@ -0,0 +1,100 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliCommitAfterContainerIsDone(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "commit", cleanedContainerID)
cleanedImageID := strings.TrimSpace(out)
dockerCmd(c, "inspect", cleanedImageID)
}
func (s *DockerSuite) TestCliCommitRunningContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
cleanedContainerID := strings.TrimSpace(out)
out, _, err := dockerCmdWithError("commit", cleanedContainerID)
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Equals, "Error response from daemon: Bad request parameters: only stopped container could be committed\n")
}
func (s *DockerSuite) TestCliCommitNewFileBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name", "commiter", "busybox", "/bin/sh", "-c", "echo koye > /foo")
imageID, _ := dockerCmd(c, "commit", "commiter")
imageID = strings.TrimSpace(imageID)
out, _ := dockerCmd(c, "run", imageID, "cat", "/foo")
actual := strings.TrimSpace(out)
c.Assert(actual, checker.Equals, "koye")
}
func (s *DockerSuite) TestCliCommitChange(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name", "test", "busybox", "true")
imageID, _ := dockerCmd(c, "commit",
"--change", "EXPOSE 8080",
"--change", "ENV DEBUG true",
"--change", "ENV test 1",
"--change", "ENV PATH /foo",
"--change", "LABEL foo bar",
"--change", "CMD [\"/bin/sh\"]",
"--change", "WORKDIR /opt",
"--change", "ENTRYPOINT [\"/bin/sh\"]",
"--change", "USER testuser",
"--change", "VOLUME /var/lib/docker",
"test", "test-commit",
)
imageID = strings.TrimSpace(imageID)
expected := map[string]string{
"Config.ExposedPorts": "map[8080/tcp:{}]",
"Config.Env": "[DEBUG=true test=1 PATH=/foo]",
"Config.Labels": "map[foo:bar]",
"Config.Cmd": "[/bin/sh]",
"Config.WorkingDir": "/opt",
"Config.Entrypoint": "[/bin/sh]",
"Config.User": "testuser",
"Config.Volumes": "map[/var/lib/docker:{}]",
}
for conf, value := range expected {
res := inspectField(c, imageID, conf)
if res != value {
c.Errorf("%s('%s'), expected %s", conf, res, value)
}
}
}

View File

@@ -0,0 +1,89 @@
package main
import (
"path/filepath"
"os"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"github.com/hyperhq/hypercli/cliconfig"
"github.com/hyperhq/hypercli/pkg/homedir"
"os/exec"
)
func (s *DockerSuite) TestCliConfigAndRewrite(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
cmd := exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", "xx", "--secretkey", "xxxx", "tcp://127.0.0.1:6443")
out, _, _, err := runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
configDir := filepath.Join(homedir.Get(), ".hyper")
conf, err := cliconfig.Load(configDir)
c.Assert(err, checker.IsNil)
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6443"].AccessKey, checker.Equals, "xx", check.Commentf("Should get xx, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6443"].AccessKey))
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6443"].SecretKey, checker.Equals, "xxxx", check.Commentf("Should get xxxx, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6443"].SecretKey))
cmd = exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", "yy", "--secretkey", "yyyy", "tcp://127.0.0.1:6443")
out, _, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
conf, err = cliconfig.Load(configDir)
c.Assert(err, checker.IsNil)
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6443"].AccessKey, checker.Equals, "yy", check.Commentf("Should get yy, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6443"].AccessKey))
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6443"].SecretKey, checker.Equals, "yyyy", check.Commentf("Should get yyyy, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6443"].SecretKey))
//patch
cmd = exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", os.Getenv("ACCESS_KEY"), "--secretkey", os.Getenv("SECRET_KEY"), os.Getenv("DOCKER_HOST"))
out, _, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
cmd = exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", os.Getenv("ACCESS_KEY"), "--secretkey", os.Getenv("SECRET_KEY"))
out, _, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
}
func (s *DockerSuite) TestCliConfigMultiHostBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
cmd := exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", "xx", "--secretkey", "xxxx", "tcp://127.0.0.1:6443")
out, _, _, err := runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
configDir := filepath.Join(homedir.Get(), ".hyper")
conf, err := cliconfig.Load(configDir)
c.Assert(err, checker.IsNil)
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6443"].AccessKey, checker.Equals, "xx", check.Commentf("Should get xx, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6443"].AccessKey))
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6443"].SecretKey, checker.Equals, "xxxx", check.Commentf("Should get xxxx, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6443"].SecretKey))
cmd = exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", "yy", "--secretkey", "yyyy", "tcp://127.0.0.1:6444")
out, _, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
conf, err = cliconfig.Load(configDir)
c.Assert(err, checker.IsNil)
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6444"].AccessKey, checker.Equals, "yy", check.Commentf("Should get yy, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6444"].AccessKey))
c.Assert(conf.CloudConfig["tcp://127.0.0.1:6444"].SecretKey, checker.Equals, "yyyy", check.Commentf("Should get yyyy, but get %s\n", conf.CloudConfig["tcp://127.0.0.1:6444"].SecretKey))
//patch
cmd = exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", os.Getenv("ACCESS_KEY"), "--secretkey", os.Getenv("SECRET_KEY"), os.Getenv("DOCKER_HOST"))
out, _, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
cmd = exec.Command(dockerBinary, "config", "--default-region" , os.Getenv("REGION"), "--accesskey", os.Getenv("ACCESS_KEY"), "--secretkey", os.Getenv("SECRET_KEY"))
out, _, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "WARNING: Your login credentials has been saved in "+homedir.Get()+"/.hyper/config.json")
}

View File

@@ -0,0 +1,322 @@
package main
import (
"encoding/json"
"fmt"
"os"
"reflect"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// Make sure we can create a simple container with some args
func (s *DockerSuite) TestCliCreateArgs(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// TODO Windows. This requires further investigation for porting to
// Windows CI. Currently fails.
if daemonPlatform == "windows" {
c.Skip("Fails on Windows CI")
}
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "create", "busybox", "command", "arg1", "arg2", "arg with space")
cleanedContainerID := getIDfromOutput(c, out)
out, _ = dockerCmd(c, "inspect", cleanedContainerID)
containers := []struct {
ID string
Created time.Time
Path string
Args []string
Image string
}{}
err := json.Unmarshal([]byte(out), &containers)
c.Assert(err, check.IsNil, check.Commentf("Error inspecting the container: %s", err))
c.Assert(containers, checker.HasLen, 1)
cont := containers[0]
c.Assert(string(cont.Path), checker.Equals, "command", check.Commentf("Unexpected container path. Expected command, received: %s", cont.Path))
b := false
expected := []string{"arg1", "arg2", "arg with space"}
for i, arg := range expected {
if arg != cont.Args[i] {
b = true
break
}
}
if len(cont.Args) != len(expected) || b {
c.Fatalf("Unexpected args. Expected %v, received: %v", expected, cont.Args)
}
}
// Make sure we can set hostconfig options too
func (s *DockerSuite) TestCliCreateHostConfigBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "create", "busybox", "echo")
cleanedContainerID := getIDfromOutput(c, out)
out, _ = dockerCmd(c, "inspect", cleanedContainerID)
containers := []struct {
HostConfig *struct {
PublishAllPorts bool
}
}{}
err := json.Unmarshal([]byte(out), &containers)
c.Assert(err, check.IsNil, check.Commentf("Error inspecting the container: %s", err))
c.Assert(containers, checker.HasLen, 1)
cont := containers[0]
c.Assert(cont.HostConfig, check.NotNil, check.Commentf("Expected HostConfig, got none"))
c.Assert(cont.HostConfig.PublishAllPorts, check.NotNil, check.Commentf("Expected PublishAllPorts, got false"))
}
// "test123" should be printed by docker create + start
func (s *DockerSuite) TestCliCreateEchoStdoutBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "create", "busybox", "echo", "test123")
cleanedContainerID := getIDfromOutput(c, out)
out, _ = dockerCmd(c, "start", "-ai", cleanedContainerID)
time.Sleep(5 * time.Second)
c.Assert(out, checker.Equals, "test123\n", check.Commentf("container should've printed 'test123', got %q", out))
}
func (s *DockerSuite) TestCliCreateVolumesCreated(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, SameHostDaemon)
prefix := "/"
if daemonPlatform == "windows" {
prefix = `c:\`
}
name := "test_create_volume"
dockerCmd(c, "create", "--name", name, "-v", prefix+"foo", "busybox")
dir, err := inspectMountSourceField(name, prefix+"foo")
c.Assert(err, check.IsNil, check.Commentf("Error getting volume host path: %q", err))
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
c.Fatalf("Volume was not created")
}
if err != nil {
c.Fatalf("Error statting volume host path: %q", err)
}
}
func (s *DockerSuite) TestCliCreateLabels(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
name := "test-create-labels"
expected := map[string]string{"k1": "v1", "k2": "v2", "sh.hyper.fip": "", "sh_hyper_instancetype": "s4"}
dockerCmd(c, "create", "--name", name, "-l", "k1=v1", "--label", "k2=v2", "busybox")
actual := make(map[string]string)
inspectFieldAndMarshall(c, name, "Config.Labels", &actual)
if !reflect.DeepEqual(expected, actual) {
c.Fatalf("Expected %s got %s", expected, actual)
}
}
func (s *DockerSuite) TestCliCreateRM(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// Test to make sure we can 'rm' a new container that is in
// "Created" state, and has ever been run. Test "rm -f" too.
// create a container
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "create", "busybox")
cID := getIDfromOutput(c, out)
dockerCmd(c, "rm", cID)
// Now do it again so we can "rm -f" this time
out, _ = dockerCmd(c, "create", "busybox")
cID = strings.TrimSpace(out)
dockerCmd(c, "rm", "-f", cID)
}
func (s *DockerSuite) TestCliCreateModeIpcContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// Uses Linux specific functionality (--ipc)
testRequires(c, DaemonIsLinux)
testRequires(c, SameHostDaemon, NotUserNamespace)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "create", "busybox")
id := strings.TrimSpace(out)
dockerCmd(c, "create", fmt.Sprintf("--ipc=container:%s", id), "busybox")
}
/*
func (s *DockerTrustSuite) TestCliCreateTrustedCreate(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
repoName := s.setupTrustedImage(c, "trusted-create")
// Try create
createCmd := exec.Command(dockerBinary, "create", repoName)
s.trustedCmd(createCmd)
out, _, err := runCommandWithOutput(createCmd)
c.Assert(err, check.IsNil)
c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out))
dockerCmd(c, "rmi", repoName)
// Try untrusted create to ensure we pushed the tag to the registry
createCmd = exec.Command(dockerBinary, "create", "--disable-content-trust=true", repoName)
s.trustedCmd(createCmd)
out, _, err = runCommandWithOutput(createCmd)
c.Assert(err, check.IsNil)
c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted create with --disable-content-trust:\n%s", out))
}
func (s *DockerTrustSuite) TestCliCreateUntrustedCreate(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
repoName := fmt.Sprintf("%v/dockercliuntrusted/createtest", privateRegistryURL)
withTagName := fmt.Sprintf("%s:latest", repoName)
// tag the image and upload it to the private registry
dockerCmd(c, "tag", "busybox", withTagName)
dockerCmd(c, "push", withTagName)
dockerCmd(c, "rmi", withTagName)
// Try trusted create on untrusted tag
createCmd := exec.Command(dockerBinary, "create", withTagName)
s.trustedCmd(createCmd)
out, _, err := runCommandWithOutput(createCmd)
c.Assert(err, check.Not(check.IsNil))
c.Assert(string(out), checker.Contains, fmt.Sprintf("does not have trust data for %s", repoName), check.Commentf("Missing expected output on trusted create:\n%s", out))
}
func (s *DockerTrustSuite) TestCliCreateTrustedIsolatedCreate(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
repoName := s.setupTrustedImage(c, "trusted-isolated-create")
// Try create
createCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated-create", "create", repoName)
s.trustedCmd(createCmd)
out, _, err := runCommandWithOutput(createCmd)
c.Assert(err, check.IsNil)
c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out))
dockerCmd(c, "rmi", repoName)
}
func (s *DockerTrustSuite) TestCliCreateWhenCertExpired(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
c.Skip("Currently changes system time, causing instability")
repoName := s.setupTrustedImage(c, "trusted-create-expired")
// Certificates have 10 years of expiration
elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11)
runAtDifferentDate(elevenYearsFromNow, func() {
// Try create
createCmd := exec.Command(dockerBinary, "create", repoName)
s.trustedCmd(createCmd)
out, _, err := runCommandWithOutput(createCmd)
c.Assert(err, check.Not(check.IsNil))
c.Assert(string(out), checker.Contains, "could not validate the path to a trusted root", check.Commentf("Missing expected output on trusted create in the distant future:\n%s", out))
})
runAtDifferentDate(elevenYearsFromNow, func() {
// Try create
createCmd := exec.Command(dockerBinary, "create", "--disable-content-trust", repoName)
s.trustedCmd(createCmd)
out, _, err := runCommandWithOutput(createCmd)
c.Assert(err, check.Not(check.IsNil))
c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted create in the distant future:\n%s", out))
})
}
func (s *DockerTrustSuite) TestCliCreateTrustedCreateFromBadTrustServer(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
repoName := fmt.Sprintf("%v/dockerclievilcreate/trusted:latest", privateRegistryURL)
evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
c.Assert(err, check.IsNil)
// tag the image and upload it to the private registry
dockerCmd(c, "tag", "busybox", repoName)
pushCmd := exec.Command(dockerBinary, "push", repoName)
s.trustedCmd(pushCmd)
out, _, err := runCommandWithOutput(pushCmd)
c.Assert(err, check.IsNil)
c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out))
dockerCmd(c, "rmi", repoName)
// Try create
createCmd := exec.Command(dockerBinary, "create", repoName)
s.trustedCmd(createCmd)
out, _, err = runCommandWithOutput(createCmd)
c.Assert(err, check.IsNil)
c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out))
dockerCmd(c, "rmi", repoName)
// Kill the notary server, start a new "evil" one.
s.not.Close()
s.not, err = newTestNotary(c)
c.Assert(err, check.IsNil)
// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
// tag an image and upload it to the private registry
dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
// Push up to the new server
pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName)
s.trustedCmd(pushCmd)
out, _, err = runCommandWithOutput(pushCmd)
c.Assert(err, check.IsNil)
c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out))
// Now, try creating with the original client from this new trust server. This should fail.
createCmd = exec.Command(dockerBinary, "create", repoName)
s.trustedCmd(createCmd)
out, _, err = runCommandWithOutput(createCmd)
c.Assert(err, check.Not(check.IsNil))
c.Assert(string(out), checker.Contains, "valid signatures did not meet threshold", check.Commentf("Missing expected output on trusted push:\n%s", out))
}
*/
func (s *DockerSuite) TestCliCreateWithWorkdir(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// TODO Windows. This requires further investigation for porting to
// Windows CI. Currently fails.
if daemonPlatform == "windows" {
c.Skip("Fails on Windows CI")
}
name := "foo"
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
dir := prefix + slash + "home" + slash + "foo" + slash + "bar"
dockerCmd(c, "create", "--name", name, "-w", dir, "busybox")
}

View File

@@ -0,0 +1,488 @@
// +build !test_no_exec
package main
import (
"fmt"
"net/http"
"os"
"os/exec"
"path/filepath"
"reflect"
"sort"
"strings"
"sync"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliExecBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "--name", "test", "busybox", "sh", "-c", "echo test > /tmp/file && top")
out, _ := dockerCmd(c, "exec", "test", "cat", "/tmp/file")
out = strings.Trim(out, "\r\n")
c.Assert(out, checker.Equals, "test")
}
//TODO:FIX ExecInteractive WAITING TOO LONG
/*func (s *DockerSuite) TestCliExecInteractive(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "-d", "--name", "test", "busybox", "sh", "-c", "echo test > /tmp/file && top")
execCmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", "-i", "test", "sh")
stdin, err := execCmd.StdinPipe()
c.Assert(err, checker.IsNil)
stdout, err := execCmd.StdoutPipe()
c.Assert(err, checker.IsNil)
err = execCmd.Start()
c.Assert(err, checker.IsNil)
_, err = stdin.Write([]byte("cat /tmp/file\n"))
c.Assert(err, checker.IsNil)
r := bufio.NewReader(stdout)
line, err := r.ReadString('\n')
c.Assert(err, checker.IsNil)
line = strings.TrimSpace(line)
c.Assert(line, checker.Equals, "test")
err = stdin.Close()
c.Assert(err, checker.IsNil)
errChan := make(chan error)
go func() {
errChan <- execCmd.Wait()
close(errChan)
}()
select {
case err := <-errChan:
c.Assert(err, checker.IsNil)
case <-time.After(10 * time.Second):
c.Fatal("docker exec failed to exit on stdin close")
}
}*/
func (s *DockerSuite) TestCliExecAfterContainerRestart(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
out, _ := runSleepingContainer(c, "-d")
cleanedContainerID := strings.TrimSpace(out)
c.Assert(waitRun(cleanedContainerID), check.IsNil)
dockerCmd(c, "restart", cleanedContainerID)
c.Assert(waitRun(cleanedContainerID), check.IsNil)
out, _ = dockerCmd(c, "exec", cleanedContainerID, "echo", "hello")
outStr := strings.TrimSpace(out)
c.Assert(outStr, checker.Equals, "hello")
}
//TODO:FIX TestExecEnv WAITING TOO LONG
/*func (s *DockerSuite) TestCliExecEnv(c *check.C) {
// TODO Windows CI: This one is interesting and may just end up being a feature
// difference between Windows and Linux. On Windows, the environment is passed
// into the process that is launched, not into the machine environment. Hence
// a subsequent exec will not have LALA set/
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
runSleepingContainer(c, "-e", "LALA=value1", "-e", "LALA=value2", "-d", "--name", "test")
c.Assert(waitRun("test"), check.IsNil)
out, _ := dockerCmd(c, "exec", "test", "env")
c.Assert(out, checker.Not(checker.Contains), "LALA=value1")
c.Assert(out, checker.Contains, "LALA=value2")
c.Assert(out, checker.Contains, "HOME=/root")
}*/
func (s *DockerSuite) TestCliExecExitStatus(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
runSleepingContainer(c, "-d", "--name", "top")
// Test normal (non-detached) case first
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", "top", "sh", "-c", "exit 23")
ec, _ := runCommand(cmd)
c.Assert(ec, checker.Equals, 23)
}
//TODO:FIX TestExecTTYCloseStdin WAITING TOO LONG SAME AS TestExecInteractive
/*func (s *DockerSuite) TestCliExecTTYCloseStdin(c *check.C) {
// TODO Windows CI: This requires some work to port to Windows.
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "-d", "-it", "--name", "test", "busybox")
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", "-i", "test", "cat")
stdinRw, err := cmd.StdinPipe()
c.Assert(err, checker.IsNil)
stdinRw.Write([]byte("test"))
stdinRw.Close()
out, _, err := runCommandWithOutput(cmd)
c.Assert(err, checker.IsNil, check.Commentf(out))
out, _ = dockerCmd(c, "top", "test")
outArr := strings.Split(out, "\n")
c.Assert(len(outArr), checker.LessOrEqualThan, 3, check.Commentf("exec process left running"))
c.Assert(out, checker.Not(checker.Contains), "nsenter-exec")
}*/
func (s *DockerSuite) TestCliExecTTYWithoutStdin(c *check.C) {
// TODO Windows CI: This requires some work to port to Windows.
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
errChan := make(chan error)
go func() {
defer close(errChan)
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", "-ti", id, "true")
if _, err := cmd.StdinPipe(); err != nil {
errChan <- err
return
}
expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil {
errChan <- fmt.Errorf("exec should have failed")
return
} else if !strings.Contains(out, expected) {
errChan <- fmt.Errorf("exec failed with error %q: expected %q", out, expected)
return
}
}()
select {
case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(30 * time.Second):
c.Fatal("exec is running but should have failed")
}
}
func (s *DockerSuite) TestCliExecParseError(c *check.C) {
// TODO Windows CI: Requires some extra work. Consider copying the
// runSleepingContainer helper to have an exec version.
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "-d", "--name", "top", "busybox", "top")
// Test normal (non-detached) case first
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", "top")
_, stderr, _, err := runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.NotNil)
c.Assert(stderr, checker.Contains, "See '"+dockerBinary+" exec --help'")
}
func (s *DockerSuite) TestCliExecStopNotHanging(c *check.C) {
// TODO Windows CI: Requires some extra work. Consider copying the
// runSleepingContainer helper to have an exec version.
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
err := exec.Command(dockerBinary, "exec", "--region="+os.Getenv("DOCKER_HOST"), "test", "top").Start()
c.Assert(err, checker.IsNil)
type dstop struct {
out []byte
err error
}
ch := make(chan dstop)
go func() {
out, err := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "stop", "test").CombinedOutput()
ch <- dstop{out, err}
close(ch)
}()
select {
case <-time.After(30 * time.Second):
c.Fatal("Container stop timed out")
case s := <-ch:
c.Assert(s.err, check.IsNil)
}
}
func (s *DockerSuite) TestCliExecCgroup(c *check.C) {
// Not applicable on Windows - using Linux specific functionality
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, NotUserNamespace)
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
out, _ := dockerCmd(c, "exec", "test", "cat", "/proc/1/cgroup")
containerCgroups := sort.StringSlice(strings.Split(out, "\n"))
var wg sync.WaitGroup
var mu sync.Mutex
execCgroups := []sort.StringSlice{}
errChan := make(chan error)
// exec a few times concurrently to get consistent failure
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
out, _, err := dockerCmdWithError("exec", "test", "cat", "/proc/self/cgroup")
if err != nil {
errChan <- err
return
}
cg := sort.StringSlice(strings.Split(out, "\n"))
mu.Lock()
execCgroups = append(execCgroups, cg)
mu.Unlock()
wg.Done()
}()
}
wg.Wait()
close(errChan)
for err := range errChan {
c.Assert(err, checker.IsNil)
}
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)
}
c.Fatal("cgroups mismatched")
}
}
}
func (s *DockerSuite) TestCliExecLinksPingLinkedContainersOnRename(c *check.C) {
// Problematic on Windows as Windows does not support links
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
var out string
out, _ = dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
idA := strings.TrimSpace(out)
c.Assert(idA, checker.Not(checker.Equals), "", check.Commentf("%s, id should not be nil", out))
out, _ = dockerCmd(c, "run", "-d", "--link", "container1:alias1", "--name", "container2", "busybox", "top")
idB := strings.TrimSpace(out)
c.Assert(idB, checker.Not(checker.Equals), "", check.Commentf("%s, id should not be nil", out))
dockerCmd(c, "exec", "container2", "ping", "-c", "1", "alias1", "-W", "1")
dockerCmd(c, "rename", "container1", "container-new")
dockerCmd(c, "exec", "container2", "ping", "-c", "1", "alias1", "-W", "1")
}
func (s *DockerSuite) TestCliExecDir(c *check.C) {
// TODO Windows CI. This requires some work to port as it uses execDriverPath
// which is currently (and incorrectly) hard coded as a string assuming
// the daemon is running Linux :(
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, SameHostDaemon, DaemonIsLinux)
out, _ := runSleepingContainer(c, "-d")
id := strings.TrimSpace(out)
execDir := filepath.Join(execDriverPath, id)
stateFile := filepath.Join(execDir, "state.json")
{
fi, err := os.Stat(execDir)
c.Assert(err, checker.IsNil)
if !fi.IsDir() {
c.Fatalf("%q must be a directory", execDir)
}
fi, err = os.Stat(stateFile)
c.Assert(err, checker.IsNil)
}
dockerCmd(c, "stop", id)
{
_, err := os.Stat(execDir)
c.Assert(err, checker.NotNil)
c.Assert(err, checker.NotNil, check.Commentf("Exec directory %q exists for removed container!", execDir))
if !os.IsNotExist(err) {
c.Fatalf("Error should be about non-existing, got %s", err)
}
}
dockerCmd(c, "start", id)
{
fi, err := os.Stat(execDir)
c.Assert(err, checker.IsNil)
if !fi.IsDir() {
c.Fatalf("%q must be a directory", execDir)
}
fi, err = os.Stat(stateFile)
c.Assert(err, checker.IsNil)
}
dockerCmd(c, "rm", "-f", id)
{
_, err := os.Stat(execDir)
c.Assert(err, checker.NotNil, check.Commentf("Exec directory %q exists for removed container!", execDir))
if !os.IsNotExist(err) {
c.Fatalf("Error should be about non-existing, got %s", err)
}
}
}
func (s *DockerSuite) TestCliExecRunMutableNetworkFiles(c *check.C) {
// Not applicable on Windows to Windows CI.
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, SameHostDaemon, DaemonIsLinux)
pullImageIfNotExist("busybox")
for _, fn := range []string{"resolv.conf", "hosts"} {
deleteAllContainers()
content, err := runCommandAndReadContainerFile(fn, exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "run", "-d", "--name", "c1", "busybox", "sh", "-c", fmt.Sprintf("echo success >/etc/%s && top", fn)))
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(string(content)), checker.Equals, "success", check.Commentf("Content was not what was modified in the container", string(content)))
out, _ := dockerCmd(c, "run", "-d", "--name", "c2", "busybox", "top")
contID := strings.TrimSpace(out)
netFilePath := containerStorageFile(contID, fn)
f, err := os.OpenFile(netFilePath, os.O_WRONLY|os.O_SYNC|os.O_APPEND, 0644)
c.Assert(err, checker.IsNil)
if _, err := f.Seek(0, 0); err != nil {
f.Close()
c.Fatal(err)
}
if err := f.Truncate(0); err != nil {
f.Close()
c.Fatal(err)
}
if _, err := f.Write([]byte("success2\n")); err != nil {
f.Close()
c.Fatal(err)
}
f.Close()
res, _ := dockerCmd(c, "exec", contID, "cat", "/etc/"+fn)
c.Assert(res, checker.Equals, "success2\n")
}
}
func (s *DockerSuite) TestCliExecStartFails(c *check.C) {
// TODO Windows CI. This test should be portable. Figure out why it fails
// currently.
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
name := "exec-15750"
runSleepingContainer(c, "-d", "--name", name)
c.Assert(waitRun(name), checker.IsNil)
out, _, err := dockerCmdWithError("exec", name, "no-such-cmd")
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "exec failed: No such file or directory")
}
func (s *DockerSuite) TestCliExecInspectID(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
out, _ := runSleepingContainer(c, "-d")
id := strings.TrimSuffix(out, "\n")
out = inspectField(c, id, "ExecIDs")
c.Assert(out, checker.Equals, "[]", check.Commentf("ExecIDs should be empty, got: %s", out))
// Start an exec, have it block waiting so we can do some checking
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", id, "sh", "-c",
"while ! test -e /execid1; do sleep 1; done")
err := cmd.Start()
c.Assert(err, checker.IsNil, check.Commentf("failed to start the exec cmd"))
// Give the exec 10 chances/seconds to start then give up and stop the test
tries := 10
for i := 0; i < tries; i++ {
// Since its still running we should see exec as part of the container
out = strings.TrimSpace(inspectField(c, id, "ExecIDs"))
if out != "[]" && out != "<no value>" {
break
}
c.Assert(i+1, checker.Not(checker.Equals), tries, check.Commentf("ExecIDs still empty after 10 second"))
time.Sleep(1 * time.Second)
}
// Save execID for later
execID, err := inspectFilter(id, "index .ExecIDs 0")
c.Assert(err, checker.IsNil, check.Commentf("failed to get the exec id"))
// End the exec by creating the missing file
err = exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", id,
"sh", "-c", "touch /execid1").Run()
c.Assert(err, checker.IsNil, check.Commentf("failed to run the 2nd exec cmd"))
// Wait for 1st exec to complete
cmd.Wait()
// Give the exec 10 chances/seconds to stop then give up and stop the test
for i := 0; i < tries; i++ {
// Since its still running we should see exec as part of the container
out = strings.TrimSpace(inspectField(c, id, "ExecIDs"))
if out == "[]" {
break
}
c.Assert(i+1, checker.Not(checker.Equals), tries, check.Commentf("ExecIDs still not empty after 10 second"))
time.Sleep(1 * time.Second)
}
// But we should still be able to query the execID
sc, body, err := sockRequest("GET", "/exec/"+execID+"/json", nil)
c.Assert(sc, checker.Equals, http.StatusOK, check.Commentf("received status != 200 OK: %d\n%s", sc, body))
//TODO: fix receive 500
// 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)
c.Assert(ec, checker.Equals, 0, check.Commentf("error removing container: %s", out))
sc, body, err = sockRequest("GET", "/exec/"+execID+"/json", nil)
c.Assert(sc, checker.Equals, http.StatusNotFound, check.Commentf("received status != 404: %d\n%s", sc, body))*/
}

View File

@@ -0,0 +1,78 @@
// +build !windows,!test_no_exec
package main
import (
"bytes"
"io"
"os"
"os/exec"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"github.com/kr/pty"
)
// regression test for #12546
func (s *DockerSuite) TestCliExecInteractiveStdinClose(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-itd", "busybox", "/bin/cat")
contID := strings.TrimSpace(out)
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", "-i", contID, "echo", "-n", "hello")
p, err := pty.Start(cmd)
c.Assert(err, checker.IsNil)
b := bytes.NewBuffer(nil)
go io.Copy(b, p)
ch := make(chan error)
go func() { ch <- cmd.Wait() }()
select {
case err := <-ch:
c.Assert(err, checker.IsNil)
output := b.String()
c.Assert(strings.TrimSpace(output), checker.Equals, "hello")
case <-time.After(15 * time.Second):
c.Fatal("timed out running docker exec")
}
}
func (s *DockerSuite) TestCliExecTTY(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "-d", "--name=test", "busybox", "sh", "-c", "echo hello > /foo && top")
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "exec", "-it", "test", "sh")
p, err := pty.Start(cmd)
c.Assert(err, checker.IsNil)
defer p.Close()
_, err = p.Write([]byte("cat /foo && sleep 2 && exit\n"))
c.Assert(err, checker.IsNil)
chErr := make(chan error)
go func() {
chErr <- cmd.Wait()
}()
select {
case err := <-chErr:
c.Assert(err, checker.IsNil)
case <-time.After(15 * time.Second):
c.Fatal("timeout waiting for exec to exit")
}
buf := make([]byte, 256)
read, err := p.Read(buf)
c.Assert(err, checker.IsNil)
c.Assert(bytes.Contains(buf, []byte("hello")), checker.Equals, true, check.Commentf(string(buf[:read])))
}

View File

@@ -0,0 +1,135 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliFipAssociateUsedIPBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _ := dockerCmd(c, "fip", "allocate", "-y", "1")
firstIP := strings.TrimSpace(out)
fipList := []string{firstIP}
defer releaseFip(c, fipList)
pullImageIfNotExist("busybox")
out, _ = runSleepingContainer(c, "-d")
firstContainerID := strings.TrimSpace(out)
out, _ = runSleepingContainer(c, "-d")
secondContainerID := strings.TrimSpace(out)
dockerCmd(c, "fip", "attach", firstIP, firstContainerID)
out, _, err := dockerCmdWithError("fip", "attach", firstIP, secondContainerID)
c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
out, _ = dockerCmd(c, "fip", "detach", firstContainerID)
c.Assert(out, checker.Equals, firstIP+"\n")
}
func (s *DockerSuite) TestCliFipAttachConfedContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _ := dockerCmd(c, "fip", "allocate", "-y", "1")
firstIP := strings.TrimSpace(out)
fipList := []string{firstIP}
out, _ = dockerCmd(c, "fip", "allocate", "-y", "1")
secondIP := strings.TrimSpace(out)
fipList = append(fipList, secondIP)
defer releaseFip(c, fipList)
pullImageIfNotExist("busybox")
out, _ = runSleepingContainer(c, "-d")
firstContainerID := strings.TrimSpace(out)
dockerCmd(c, "fip", "attach", firstIP, firstContainerID)
out, _, err := dockerCmdWithError("fip", "attach", secondIP, firstContainerID)
c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
out, _ = dockerCmd(c, "fip", "detach", firstContainerID)
c.Assert(out, checker.Equals, firstIP+"\n")
}
func (s *DockerSuite) TestCliFipDettachUnconfedContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
out, _ := runSleepingContainer(c, "-d")
firstContainerID := strings.TrimSpace(out)
out, _, err := dockerCmdWithError("fip", "detach", firstContainerID)
c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
}
func (s *DockerSuite) TestCliFipReleaseUsedIP(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _ := dockerCmd(c, "fip", "allocate", "-y", "1")
firstIP := strings.TrimSpace(out)
fipList := []string{firstIP}
defer releaseFip(c, fipList)
pullImageIfNotExist("busybox")
out, _ = runSleepingContainer(c, "-d")
firstContainerID := strings.TrimSpace(out)
dockerCmd(c, "fip", "attach", firstIP, firstContainerID)
out, _, err := dockerCmdWithError("fip", "release", firstIP)
c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
out, _ = dockerCmd(c, "fip", "detach", firstContainerID)
c.Assert(out, checker.Equals, firstIP+"\n")
}
func (s *DockerSuite) TestCliFipReleaseInvalidIP(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _, err := dockerCmdWithError("fip", "release", "InvalidIP")
c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
out, _, err = dockerCmdWithError("fip", "release", "0.0.0.0")
c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
}
func (s *DockerSuite) TestCliFipName(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _ := dockerCmd(c, "fip", "allocate", "-y", "1")
firstIP := strings.TrimSpace(out)
fipList := []string{firstIP}
out, _ = dockerCmd(c, "fip", "allocate", "-y", "1")
secondIP := strings.TrimSpace(out)
fipList = append(fipList, secondIP)
defer releaseFip(c, fipList)
pullImageIfNotExist("busybox")
out, _ = runSleepingContainer(c, "-d")
firstContainerID := strings.TrimSpace(out)
// multiple FIPs without name, attach one with container
dockerCmd(c, "fip", "attach", secondIP, firstContainerID)
out, _ = dockerCmd(c, "fip", "detach", firstContainerID)
c.Assert(out, checker.Equals, secondIP+"\n")
// multiple FIPs (one FIP has name), attach one with container
dockerCmd(c, "fip", "name", secondIP, "ip2")
dockerCmd(c, "fip", "attach", secondIP, firstContainerID)
out, _ = dockerCmd(c, "fip", "detach", firstContainerID)
c.Assert(out, checker.Equals, secondIP+"\n")
// multiple FIPs (two FIPs have name), attach one with container
dockerCmd(c, "fip", "name", firstIP, "ip1")
dockerCmd(c, "fip", "attach", secondIP, firstContainerID)
out, _ = dockerCmd(c, "fip", "detach", firstContainerID)
c.Assert(out, checker.Equals, secondIP+"\n")
}

View File

@@ -0,0 +1,305 @@
package main
import (
"os"
"os/exec"
"runtime"
"strings"
"time"
"unicode"
"github.com/docker/docker/pkg/homedir"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliHelpTextVerifyBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
// Make sure main help text fits within 80 chars and that
// on non-windows system we use ~ when possible (to shorten things).
// Test for HOME set to its default value and set to "/" on linux
// Yes on windows setting up an array and looping (right now) isn't
// necessary because we just have one value, but we'll need the
// array/loop on linux so we might as well set it up so that we can
// test any number of home dirs later on and all we need to do is
// modify the array - the rest of the testing infrastructure should work
homes := []string{homedir.Get()}
// Non-Windows machines need to test for this special case of $HOME
if runtime.GOOS != "windows" {
homes = append(homes, "/")
}
homeKey := homedir.Key()
baseEnvs := os.Environ()
// Remove HOME env var from list so we can add a new value later.
for i, env := range baseEnvs {
if strings.HasPrefix(env, homeKey+"=") {
baseEnvs = append(baseEnvs[:i], baseEnvs[i+1:]...)
break
}
}
for _, home := range homes {
// Dup baseEnvs and add our new HOME value
newEnvs := make([]string, len(baseEnvs)+1)
copy(newEnvs, baseEnvs)
newEnvs[len(newEnvs)-1] = homeKey + "=" + home
scanForHome := runtime.GOOS != "windows" && home != "/"
// Check main help text to make sure its not over 80 chars
helpCmd := exec.Command(dockerBinary, "help")
helpCmd.Env = newEnvs
out, _, err := runCommandWithOutput(helpCmd)
c.Assert(err, checker.IsNil, check.Commentf(out))
lines := strings.Split(out, "\n")
for _, line := range lines {
c.Assert(len(line), checker.LessOrEqualThan, 80, check.Commentf("Line is too long:\n%s", line))
// All lines should not end with a space
c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Line should not end with a space"))
if scanForHome && strings.Contains(line, `=`+home) {
c.Fatalf("Line should use '%q' instead of %q:\n%s", homedir.GetShortcutString(), home, line)
}
if runtime.GOOS != "windows" {
i := strings.Index(line, homedir.GetShortcutString())
if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
c.Fatalf("Main help should not have used home shortcut:\n%s", line)
}
}
}
// Make sure each cmd's help text fits within 90 chars and that
// on non-windows system we use ~ when possible (to shorten things).
// Pull the list of commands from the "Commands:" section of docker help
helpCmd = exec.Command(dockerBinary, "help")
helpCmd.Env = newEnvs
out, _, err = runCommandWithOutput(helpCmd)
c.Assert(err, checker.IsNil, check.Commentf(out))
i := strings.Index(out, "Commands:")
c.Assert(i, checker.GreaterOrEqualThan, 0, check.Commentf("Missing 'Commands:' in:\n%s", out))
cmds := []string{}
// Grab all chars starting at "Commands:"
helpOut := strings.Split(out[i:], "\n")
// First line is just "Commands:"
if isLocalDaemon {
// Replace first line with "daemon" command since it's not part of the list of commands.
helpOut[0] = " daemon"
} else {
// Skip first line
helpOut = helpOut[1:]
}
// Create the list of commands we want to test
cmdsToTest := []string{}
for _, cmd := range helpOut {
// Stop on blank line or non-idented line
if cmd == "" || !unicode.IsSpace(rune(cmd[0])) {
break
}
// Grab just the first word of each line
cmd = strings.Split(strings.TrimSpace(cmd), " ")[0]
cmds = append(cmds, cmd) // Saving count for later
cmdsToTest = append(cmdsToTest, cmd)
}
// Add some 'two word' commands - would be nice to automatically
// calculate this list - somehow
cmdsToTest = append(cmdsToTest, "volume create")
cmdsToTest = append(cmdsToTest, "volume inspect")
cmdsToTest = append(cmdsToTest, "volume ls")
cmdsToTest = append(cmdsToTest, "volume rm")
for _, cmd := range cmdsToTest {
var stderr string
args := strings.Split("--region="+os.Getenv("DOCKER_HOST")+" "+cmd+" --help", " ")
// Check the full usage text
helpCmd := exec.Command(dockerBinary, args...)
helpCmd.Env = newEnvs
out, stderr, _, err = runCommandWithStdoutStderr(helpCmd)
c.Assert(len(stderr), checker.Equals, 0, check.Commentf("Error on %q help. non-empty stderr:%q", cmd, stderr))
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have blank line on %q\n", cmd))
c.Assert(out, checker.Contains, "--help", check.Commentf("All commands should mention '--help'. Command '%v' did not.\n", cmd))
c.Assert(err, checker.IsNil, check.Commentf(out))
// Check each line for lots of stuff
lines := strings.Split(out, "\n")
for _, line := range lines {
c.Assert(len(line), checker.LessOrEqualThan, 113, check.Commentf("Help for %q is too long:\n%s", cmd, line))
if scanForHome && strings.Contains(line, `"`+home) {
c.Fatalf("Help for %q should use ~ instead of %q on:\n%s",
cmd, home, line)
}
i := strings.Index(line, "~")
if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
c.Fatalf("Help for %q should not have used ~:\n%s", cmd, line)
}
// If a line starts with 4 spaces then assume someone
// added a multi-line description for an option and we need
// to flag it
c.Assert(line, checker.Not(checker.HasPrefix), " ", check.Commentf("Help for %q should not have a multi-line option", cmd))
// Options should NOT end with a period
if strings.HasPrefix(line, " -") && strings.HasSuffix(line, ".") {
c.Fatalf("Help for %q should not end with a period: %s", cmd, line)
}
// Options should NOT end with a space
c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Help for %q should not end with a space", cmd))
}
// For each command make sure we generate an error
// if we give a bad arg
args = strings.Split(cmd+" --badArg", " ")
out, _, err = dockerCmdWithError(args...)
c.Assert(err, checker.NotNil, check.Commentf(out))
// Be really picky
c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker rm'\n"))
// Now make sure that each command will print a short-usage
// (not a full usage - meaning no opts section) if we
// are missing a required arg or pass in a bad arg
// These commands will never print a short-usage so don't test
noShortUsage := map[string]string{
"images": "",
"login": "",
"logout": "",
"network": "",
"stats": "",
"config": "",
}
if _, ok := noShortUsage[cmd]; !ok {
// For each command run it w/o any args. It will either return
// valid output or print a short-usage
var dCmd *exec.Cmd
var stdout, stderr string
var args []string
// skipNoArgs are ones that we don't want to try w/o
// any args. Either because it'll hang the test or
// lead to incorrect test result (like false negative).
// Whatever the reason, skip trying to run w/o args and
// jump to trying with a bogus arg.
skipNoArgs := map[string]struct{}{
"daemon": {},
"events": {},
"load": {},
}
ec := 0
if _, ok := skipNoArgs[cmd]; !ok {
args = strings.Split("--region="+os.Getenv("DOCKER_HOST")+" "+cmd, " ")
dCmd = exec.Command(dockerBinary, args...)
stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd)
}
// If its ok w/o any args then try again with an arg
if ec == 0 {
args = strings.Split("--region="+os.Getenv("DOCKER_HOST")+" "+cmd+" badArg", " ")
dCmd = exec.Command(dockerBinary, args...)
stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd)
}
if len(stdout) != 0 || len(stderr) == 0 || ec == 0 || err == nil {
c.Fatalf("Bad output from %q\nstdout:%q\nstderr:%q\nec:%d\nerr:%q", args, stdout, stderr, ec, err)
}
// Should have just short usage
c.Assert(stderr, checker.Contains, "\nUsage:\t", check.Commentf("Missing short usage on %q\n", args))
// But shouldn't have full usage
c.Assert(stderr, checker.Not(checker.Contains), "--help=false", check.Commentf("Should not have full usage on %q\n", args))
c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line on %q\n", args))
}
}
// Number of commands for standard release and experimental release
standard := 41
experimental := 1
expected := standard + experimental
if isLocalDaemon {
expected++ // for the daemon command
}
c.Assert(len(cmds), checker.LessOrEqualThan, expected, check.Commentf("Wrong # of cmds, it should be: %d\nThe list:\n%q", expected, cmds))
}
}
func (s *DockerSuite) TestCliHelpExitCodesHelpOutput(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
// Test to make sure the exit code and output (stdout vs stderr) of
// various good and bad cases are what we expect
// docker : stdout=all, stderr=empty, rc=0
out, _, err := dockerCmdWithError()
c.Assert(err, checker.IsNil, check.Commentf(out))
// Be really pick
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'hyper'\n"))
// docker help: stdout=all, stderr=empty, rc=0
out, _, err = dockerCmdWithError("help")
c.Assert(err, checker.IsNil, check.Commentf(out))
// Be really pick
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'hyper help'\n"))
// docker --help: stdout=all, stderr=empty, rc=0
out, _, err = dockerCmdWithError("--help")
c.Assert(err, checker.IsNil, check.Commentf(out))
// Be really pick
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'hyper --help'\n"))
// docker inspect busybox: stdout=all, stderr=empty, rc=0
// Just making sure stderr is empty on valid cmd
pullImageIfNotExist("busybox")
out, _, err = dockerCmdWithError("inspect", "busybox")
c.Assert(err, checker.IsNil, check.Commentf(out))
// Be really pick
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'hyper inspect busyBox'\n"))
// docker rm: stdout=empty, stderr=all, rc!=0
// testing the min arg error msg
cmd := exec.Command(dockerBinary, "rm")
stdout, stderr, _, err := runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.NotNil)
c.Assert(stdout, checker.Equals, "")
// Should not contain full help text but should contain info about
// # of args and Usage line
c.Assert(stderr, checker.Contains, "requires a minimum", check.Commentf("Missing # of args text from 'hyper rm'\n"))
// docker rm NoSuchContainer: stdout=empty, stderr=all, rc=0
// testing to make sure no blank line on error
cmd = exec.Command(dockerBinary, "rm", "NoSuchContainer")
stdout, stderr, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.NotNil)
c.Assert(len(stderr), checker.Not(checker.Equals), 0)
c.Assert(stdout, checker.Equals, "")
// Be really picky
c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'hyper rm'\n"))
// docker BadCmd: stdout=empty, stderr=all, rc=0
cmd = exec.Command(dockerBinary, "BadCmd")
stdout, stderr, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.NotNil)
c.Assert(stdout, checker.Equals, "")
c.Assert(stderr, checker.Equals, "hyper: 'BadCmd' is not a hyper command.\nSee 'hyper --help'.\n", check.Commentf("Unexcepted output for 'hyper badCmd'\n"))
}

View File

@@ -0,0 +1,144 @@
package main
import (
//"fmt"
"regexp"
"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
//TODO: add hyper build
/*// This is a heisen-test. Because the created timestamp of images and the behavior of
// sort is not predictable it doesn't always fail.
func (s *DockerSuite) TestCliHistoryBuild(c *check.C) {
testRequires(c, DaemonIsLinux) // TODO Windows: This test passes on Windows,
// but currently adds a disproportionate amount of time for the value it has.
// Removing it from Windows CI for now, but this will be revisited in the
// TP5 timeframe when perf is better.
name := "testbuildhistory"
_, err := buildImage(name, `FROM busybox
RUN echo "A"
RUN echo "B"
RUN echo "C"
RUN echo "D"
RUN echo "E"
RUN echo "F"
RUN echo "G"
RUN echo "H"
RUN echo "I"
RUN echo "J"
RUN echo "K"
RUN echo "L"
RUN echo "M"
RUN echo "N"
RUN echo "O"
RUN echo "P"
RUN echo "Q"
RUN echo "R"
RUN echo "S"
RUN echo "T"
RUN echo "U"
RUN echo "V"
RUN echo "W"
RUN echo "X"
RUN echo "Y"
RUN echo "Z"`,
true)
c.Assert(err, checker.IsNil)
out, _ := dockerCmd(c, "history", "testbuildhistory")
actualValues := strings.Split(out, "\n")[1:27]
expectedValues := [26]string{"Z", "Y", "X", "W", "V", "U", "T", "S", "R", "Q", "P", "O", "N", "M", "L", "K", "J", "I", "H", "G", "F", "E", "D", "C", "B", "A"}
for i := 0; i < 26; i++ {
echoValue := fmt.Sprintf("echo \"%s\"", expectedValues[i])
actualValue := actualValues[i]
c.Assert(actualValue, checker.Contains, echoValue)
}
}*/
func (s *DockerSuite) TestCliHistoryExistentImageBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
_, _, err := dockerCmdWithError("history", "busybox")
c.Assert(err, check.IsNil, check.Commentf("history on a existent image should not fail."))
}
func (s *DockerSuite) TestCliHistoryNonExistentImage(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
_, _, err := dockerCmdWithError("history", "testHistoryNonExistentImage")
c.Assert(err, checker.NotNil, check.Commentf("history on a non-existent image should fail."))
}
//TODO: add hyper commit
/*func (s *DockerSuite) TestCliHistoryImageWithComment(c *check.C) {
name := "testhistoryimagewithcomment"
// make a image through docker commit <container id> [ -m messages ]
dockerCmd(c, "run", "--name", name, "busybox", "true")
dockerCmd(c, "wait", name)
comment := "This_is_a_comment"
dockerCmd(c, "commit", "-m="+comment, name, name)
// test docker history <image id> to check comment messages
out, _ := dockerCmd(c, "history", name)
outputTabs := strings.Fields(strings.Split(out, "\n")[1])
actualValue := outputTabs[len(outputTabs)-1]
c.Assert(actualValue, checker.Contains, comment)
}*/
func (s *DockerSuite) TestCliHistoryHumanOptionFalse(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "history", "--human=false", "busybox")
lines := strings.Split(out, "\n")
sizeColumnRegex, _ := regexp.Compile("SIZE +")
indices := sizeColumnRegex.FindStringIndex(lines[0])
startIndex := indices[0]
endIndex := indices[1]
for i := 1; i < len(lines)-1; i++ {
if endIndex > len(lines[i]) {
endIndex = len(lines[i])
}
sizeString := lines[i][startIndex:endIndex]
_, err := strconv.Atoi(strings.TrimSpace(sizeString))
c.Assert(err, checker.IsNil, check.Commentf("The size '%s' was not an Integer", sizeString))
}
}
func (s *DockerSuite) TestCliHistoryHumanOptionTrue(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "history", "--human=true", "busybox")
lines := strings.Split(out, "\n")
sizeColumnRegex, _ := regexp.Compile("SIZE +")
humanSizeRegexRaw := "\\d+.*B" // Matches human sizes like 10 MB, 3.2 KB, etc
indices := sizeColumnRegex.FindStringIndex(lines[0])
startIndex := indices[0]
endIndex := indices[1]
for i := 1; i < len(lines)-1; i++ {
if endIndex > len(lines[i]) {
endIndex = len(lines[i])
}
sizeString := lines[i][startIndex:endIndex]
c.Assert(strings.TrimSpace(sizeString), checker.Matches, humanSizeRegexRaw, check.Commentf("The size '%s' was not in human format", sizeString))
}
}

View File

@@ -0,0 +1,187 @@
package main
import (
"fmt"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// ensure docker info succeeds
func (s *DockerSuite) TestCliInfoEnsureSucceedsBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _ := dockerCmd(c, "info")
// always shown fields
stringsToCheck := []string{
"Containers",
" Running",
" Paused",
" Stopped",
"Images",
"Server Version",
"Storage Driver",
"Execution Driver",
"Plugins",
" Volume",
" Network",
" Authorization",
"Kernel Version",
"CPUs",
"Total Memory",
"ID",
"Debug mode (client)",
"Debug mode (server)",
}
//if utils.ExperimentalBuild() {
// stringsToCheck = append(stringsToCheck, "Experimental: true")
//}
for _, linePrefix := range stringsToCheck {
c.Assert(out, checker.Contains, linePrefix, check.Commentf("couldn't find string %v in output", linePrefix))
}
}
//comment: not support discoveryBackend
//// TestInfoDiscoveryBackend verifies that a daemon run with `--cluster-advertise` and
//// `--cluster-store` properly show the backend's endpoint in info output.
//func (s *DockerSuite) TestCliInfoDiscoveryBackend(c *check.C) {
// printTestCaseName(); defer printTestDuration(time.Now())
// testRequires(c, SameHostDaemon, DaemonIsLinux)
//
// d := NewDaemon(c)
// discoveryBackend := "consul://consuladdr:consulport/some/path"
// discoveryAdvertise := "1.1.1.1:2375"
// err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend), fmt.Sprintf("--cluster-advertise=%s", discoveryAdvertise))
// c.Assert(err, checker.IsNil)
// defer d.Stop()
//
// out, err := d.Cmd("info")
// c.Assert(err, checker.IsNil)
// c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: %s\n", discoveryBackend))
// c.Assert(out, checker.Contains, fmt.Sprintf("Cluster advertise: %s\n", discoveryAdvertise))
//}
//comment: not support discoveryBackend
//// TestInfoDiscoveryInvalidAdvertise verifies that a daemon run with
//// an invalid `--cluster-advertise` configuration
//func (s *DockerSuite) TestCliInfoDiscoveryInvalidAdvertise(c *check.C) {
// printTestCaseName(); defer printTestDuration(time.Now())
// testRequires(c, SameHostDaemon, DaemonIsLinux)
//
// d := NewDaemon(c)
// discoveryBackend := "consul://consuladdr:consulport/some/path"
//
// // --cluster-advertise with an invalid string is an error
// err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend), "--cluster-advertise=invalid")
// c.Assert(err, checker.Not(checker.IsNil))
//
// // --cluster-advertise without --cluster-store is also an error
// err = d.Start("--cluster-advertise=1.1.1.1:2375")
// c.Assert(err, checker.Not(checker.IsNil))
//}
//comment: not support discoveryBackend
//// TestInfoDiscoveryAdvertiseInterfaceName verifies that a daemon run with `--cluster-advertise`
//// configured with interface name properly show the advertise ip-address in info output.
//func (s *DockerSuite) TestCliInfoDiscoveryAdvertiseInterfaceName(c *check.C) {
// printTestCaseName(); defer printTestDuration(time.Now())
// testRequires(c, SameHostDaemon, Network, DaemonIsLinux)
//
// d := NewDaemon(c)
// discoveryBackend := "consul://consuladdr:consulport/some/path"
// discoveryAdvertise := "eth0"
//
// err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend), fmt.Sprintf("--cluster-advertise=%s:2375", discoveryAdvertise))
// c.Assert(err, checker.IsNil)
// defer d.Stop()
//
// iface, err := net.InterfaceByName(discoveryAdvertise)
// c.Assert(err, checker.IsNil)
// addrs, err := iface.Addrs()
// c.Assert(err, checker.IsNil)
// c.Assert(len(addrs), checker.GreaterThan, 0)
// ip, _, err := net.ParseCIDR(addrs[0].String())
// c.Assert(err, checker.IsNil)
//
// out, err := d.Cmd("info")
// c.Assert(err, checker.IsNil)
// c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: %s\n", discoveryBackend))
// c.Assert(out, checker.Contains, fmt.Sprintf("Cluster advertise: %s:2375\n", ip.String()))
//}
func (s *DockerSuite) TestCliInfoDisplaysRunningContainersBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "busybox", "top")
out, _ := dockerCmd(c, "info")
c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 1))
c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 0))
c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 0))
}
//comment: not support pause status
//func (s *DockerSuite) TestCliInfoDisplaysPausedContainers(c *check.C) {
// printTestCaseName(); defer printTestDuration(time.Now())
// testRequires(c, DaemonIsLinux)
//
// out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
// cleanedContainerID := strings.TrimSpace(out)
//
// dockerCmd(c, "pause", cleanedContainerID)
//
// out, _ = dockerCmd(c, "info")
// c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
// c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 0))
// c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 1))
// c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 0))
//}
func (s *DockerSuite) TestCliInfoDisplaysStoppedContainers(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
outAry := strings.Split(out, "\n")
c.Assert(len(outAry), checker.GreaterOrEqualThan, 2)
cleanedContainerID := outAry[len(outAry)-2]
dockerCmd(c, "stop", cleanedContainerID)
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 0))
c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 0))
c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 1))
}
// not support daemon
//func (s *DockerSuite) TestCliInfoDebug(c *check.C) {
// printTestCaseName(); defer printTestDuration(time.Now())
// testRequires(c, SameHostDaemon, DaemonIsLinux)
//
// d := NewDaemon(c)
// err := d.Start("--debug")
// c.Assert(err, checker.IsNil)
// defer d.Stop()
//
// out, err := d.Cmd("--debug", "info")
// c.Assert(err, checker.IsNil)
// c.Assert(out, checker.Contains, "Debug mode (client): true\n")
// c.Assert(out, checker.Contains, "Debug mode (server): true\n")
// c.Assert(out, checker.Contains, "File Descriptors")
// c.Assert(out, checker.Contains, "Goroutines")
// c.Assert(out, checker.Contains, "System Time")
// c.Assert(out, checker.Contains, "EventsListeners")
// c.Assert(out, checker.Contains, "Docker Root Dir")
//}

View File

@@ -0,0 +1,35 @@
package main
import (
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliInspectNamedMountPointBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "--name", "test", "-v", "data:/data", "busybox", "cat")
vol := inspectFieldJSON(c, "test", "Mounts")
var mp []types.MountPoint
err := unmarshalJSON([]byte(vol), &mp)
c.Assert(err, checker.IsNil)
c.Assert(mp, checker.HasLen, 1, check.Commentf("Expected 1 mount point"))
m := mp[0]
c.Assert(m.Name, checker.Equals, "data", check.Commentf("Expected name data"))
c.Assert(m.Source, checker.Not(checker.Equals), "", check.Commentf("Expected source to not be empty"))
c.Assert(m.RW, checker.Equals, true)
c.Assert(m.Destination, checker.Equals, "/data", check.Commentf("Expected destination /data"))
}

View File

@@ -0,0 +1,365 @@
package main
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types/container"
"github.com/go-check/check"
)
func checkValidGraphDriver(c *check.C, name string) {
if name != "rbd" && name != "devicemapper" && name != "overlay" && name != "vfs" && name != "zfs" && name != "btrfs" && name != "aufs" {
c.Fatalf("%v is not a valid graph driver name", name)
}
}
func (s *DockerSuite) TestCliInspectImageBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
imageTest := "busybox:1.26.2"
ensureImageExist(c, imageTest)
// It is important that this ID remain stable. If a code change causes
// it to be different, this is equivalent to a cache bust when pulling
// a legacy-format manifest. If the check at the end of this function
// fails, fix the difference in the image serialization instead of
// updating this hash.
// Warning: before test , make sure imageTest and imageTestId are match
imageTestID := "sha256:c30178c5239f2937c21c261b0365efcda25be4921ccb95acd63beeeb78786f27"
id := inspectField(c, imageTest, "Id")
c.Assert(id, checker.Equals, imageTestID)
}
func (s *DockerSuite) TestCliInspectInt64(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "--name", "inspect-test", "busybox", "true")
inspectOut := inspectField(c, "inspect-test", "HostConfig.Memory")
c.Assert(inspectOut, checker.Equals, "0")
}
func (s *DockerSuite) TestCliInspectDefault(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
//Both the container and image are named busybox. docker inspect will fetch the container JSON.
//If the container JSON is not available, it will go for the image JSON.
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "true")
containerID := getIDfromOutput(c, out)
inspectOut := inspectField(c, "busybox", "Id")
c.Assert(strings.TrimSpace(inspectOut), checker.Equals, containerID)
}
func (s *DockerSuite) TestCliInspectStatusBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// defer unpauseAllContainers()
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
out = getIDfromOutput(c, out)
inspectOut := inspectField(c, out, "State.Status")
c.Assert(inspectOut, checker.Equals, "running")
dockerCmd(c, "stop", out)
inspectOut = inspectField(c, out, "State.Status")
c.Assert(inspectOut, checker.Equals, "exited")
}
func (s *DockerSuite) TestCliInspectTypeFlagContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
//Both the container and image are named busybox. docker inspect will fetch container
//JSON State.Running field. If the field is true, it's a container.
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
formatStr := "--format='{{.State.Running}}'"
out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox")
c.Assert(out, checker.Equals, "true\n") // not a container JSON
}
func (s *DockerSuite) TestCliInspectTypeFlagWithNoContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
//Run this test on an image named busybox. docker inspect will try to fetch container
//JSON. Since there is no container named busybox and --type=container, docker inspect will
//not try to get the image JSON. It will throw an error.
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "busybox", "true")
_, _, err := dockerCmdWithError("inspect", "--type=container", "busybox")
// docker inspect should fail, as there is no container named busybox
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliInspectTypeFlagWithImage(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
//Both the container and image are named busybox. docker inspect will fetch image
//JSON as --type=image. if there is no image with name busybox, docker inspect
//will throw an error.
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "true")
out, _ := dockerCmd(c, "inspect", "--type=image", "busybox")
c.Assert(out, checker.Not(checker.Contains), "State") // not an image JSON
}
func (s *DockerSuite) TestCliInspectTypeFlagWithInvalidValue(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
//Both the container and image are named busybox. docker inspect will fail
//as --type=foobar is not a valid value for the flag.
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "true")
out, exitCode, err := dockerCmdWithError("inspect", "--type=foobar", "busybox")
c.Assert(err, checker.NotNil, check.Commentf("%s", exitCode))
c.Assert(exitCode, checker.Equals, 1, check.Commentf("%s", err))
c.Assert(out, checker.Contains, "not a valid value for --type")
}
func (s *DockerSuite) TestCliInspectImageFilterInt(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
imageTest := "busybox"
ensureImageExist(c, imageTest)
out := inspectField(c, imageTest, "Size")
size, err := strconv.Atoi(out)
c.Assert(err, checker.IsNil, check.Commentf("failed to inspect size of the image: %s, %v", out, err))
//now see if the size turns out to be the same
formatStr := fmt.Sprintf("--format='{{eq .Size %d}}'", size)
out, _ = dockerCmd(c, "inspect", formatStr, imageTest)
result, err := strconv.ParseBool(strings.TrimSuffix(out, "\n"))
c.Assert(err, checker.IsNil)
c.Assert(result, checker.Equals, true)
}
func (s *DockerSuite) TestCliInspectContainerFilterIntBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
id := getIDfromOutput(c, out)
out = inspectField(c, id, "State.ExitCode")
exitCode, err := strconv.Atoi(out)
c.Assert(err, checker.IsNil, check.Commentf("failed to inspect exitcode of the container: %s, %v", out, err))
//now get the exit code to verify
formatStr := fmt.Sprintf("--format='{{eq .State.ExitCode %d}}'", exitCode)
out, _ = dockerCmd(c, "inspect", formatStr, id)
result, err := strconv.ParseBool(strings.TrimSuffix(out, "\n"))
c.Assert(err, checker.IsNil)
c.Assert(result, checker.Equals, true)
}
func (s *DockerSuite) TestCliInspectImageGraphDriver(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
imageTest := "busybox"
ensureImageExist(c, imageTest)
name := inspectField(c, imageTest, "GraphDriver.Name")
checkValidGraphDriver(c, name)
if name != "devicemapper" {
c.Skip("requires devicemapper graphdriver")
}
deviceID := inspectField(c, imageTest, "GraphDriver.Data.DeviceId")
_, err := strconv.Atoi(deviceID)
c.Assert(err, checker.IsNil, check.Commentf("failed to inspect DeviceId of the image: %s, %v", deviceID, err))
deviceSize := inspectField(c, imageTest, "GraphDriver.Data.DeviceSize")
_, err = strconv.ParseUint(deviceSize, 10, 64)
c.Assert(err, checker.IsNil, check.Commentf("failed to inspect DeviceSize of the image: %s, %v", deviceSize, err))
}
// #14947
func (s *DockerSuite) TestCliInspectTimesAsRFC3339Nano(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
id := getIDfromOutput(c, out)
startedAt := inspectField(c, id, "State.StartedAt")
finishedAt := inspectField(c, id, "State.FinishedAt")
created := inspectField(c, id, "Created")
_, err := time.Parse(time.RFC3339Nano, startedAt)
c.Assert(err, checker.IsNil)
_, err = time.Parse(time.RFC3339Nano, finishedAt)
c.Assert(err, checker.IsNil)
_, err = time.Parse(time.RFC3339Nano, created)
c.Assert(err, checker.IsNil)
created = inspectField(c, "busybox", "Created")
_, err = time.Parse(time.RFC3339Nano, created)
c.Assert(err, checker.IsNil)
}
// #15633
func (s *DockerSuite) TestCliInspectLogConfigNoType(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "create", "--name=test", "busybox")
var logConfig container.LogConfig
out := inspectFieldJSON(c, "test", "HostConfig.LogConfig")
err := json.NewDecoder(strings.NewReader(out)).Decode(&logConfig)
c.Assert(err, checker.IsNil, check.Commentf("%v", out))
c.Assert(logConfig.Type, checker.Equals, "json-file")
c.Assert(logConfig.Config["max-file"], checker.Equals, "10", check.Commentf("%v", logConfig))
}
func (s *DockerSuite) TestCliInspectNoSizeFlagContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
//Both the container and image are named busybox. docker inspect will fetch container
//JSON SizeRw and SizeRootFs field. If there is no flag --size/-s, there are no size fields.
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
formatStr := "--format='{{.SizeRw}},{{.SizeRootFs}}'"
out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox")
c.Assert(strings.TrimSpace(out), check.Equals, "<nil>,<nil>", check.Commentf("Exepcted not to display size info: %s", out))
}
func (s *DockerSuite) TestCliInspectSizeFlagContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
formatStr := "--format='{{.SizeRw}},{{.SizeRootFs}}'"
out, _ := dockerCmd(c, "inspect", "-s", "--type=container", formatStr, "busybox")
sz := strings.Split(out, ",")
c.Assert(strings.TrimSpace(sz[0]), check.Not(check.Equals), "<nil>")
c.Assert(strings.TrimSpace(sz[1]), check.Not(check.Equals), "<nil>")
}
func (s *DockerSuite) TestCliInspectSizeFlagImage(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
formatStr := "--format='{{.SizeRw}},{{.SizeRootFs}}'"
out, _, err := dockerCmdWithError("inspect", "-s", "--type=image", formatStr, "busybox")
// Template error rather than <no value>
// This is a more correct behavior because images don't have sizes associated.
c.Assert(err, check.Not(check.IsNil))
c.Assert(out, checker.Contains, "Template parsing error")
}
func (s *DockerSuite) TestCliInspectTempateError(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// Template parsing error for both the container and image.
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=container1", "-d", "busybox", "top")
out, _, err := dockerCmdWithError("inspect", "--type=container", "--format='Format container: {{.ThisDoesNotExist}}'", "container1")
c.Assert(err, check.Not(check.IsNil))
c.Assert(out, checker.Contains, "Template parsing error")
out, _, err = dockerCmdWithError("inspect", "--type=image", "--format='Format container: {{.ThisDoesNotExist}}'", "busybox")
c.Assert(err, check.Not(check.IsNil))
c.Assert(out, checker.Contains, "Template parsing error")
}
func (s *DockerSuite) TestCliInspectJSONFields(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
out, _, err := dockerCmdWithError("inspect", "--type=container", "--format='{{.HostConfig.Dns}}'", "busybox")
c.Assert(err, check.IsNil)
c.Assert(out, checker.Equals, "[]\n")
}
func (s *DockerSuite) TestCliInspectByPrefix(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
imageTest := "busybox"
ensureImageExist(c, imageTest)
id := inspectField(c, imageTest, "Id")
c.Assert(id, checker.HasPrefix, "sha256:")
id2 := inspectField(c, id[:12], "Id")
c.Assert(id, checker.Equals, id2)
id3 := inspectField(c, strings.TrimPrefix(id, "sha256:")[:12], "Id")
c.Assert(id, checker.Equals, id3)
}
func (s *DockerSuite) TestCliInspectStopWhenNotFound(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "top")
dockerCmd(c, "run", "--name=not-shown", "-d", "busybox", "top")
out, _, err := dockerCmdWithError("inspect", "--type=container", "--format='{{.Name}}'", "busybox", "missing", "not-shown")
c.Assert(err, checker.Not(check.IsNil))
c.Assert(out, checker.Contains, "busybox")
c.Assert(out, checker.Not(checker.Contains), "not-shown")
c.Assert(out, checker.Contains, "Error: No such container: missing")
}

View File

@@ -0,0 +1,52 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliKillContainerBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
cleanedContainerID := strings.TrimSpace(out)
c.Assert(waitRun(cleanedContainerID), check.IsNil)
dockerCmd(c, "kill", cleanedContainerID)
out, _ = dockerCmd(c, "ps", "-q")
c.Assert(out, checker.Not(checker.Contains), cleanedContainerID, check.Commentf("killed container is still running"))
}
func (s *DockerSuite) TestCliKillofStoppedContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "stop", cleanedContainerID)
_, _, err := dockerCmdWithError("kill", "-s", "30", cleanedContainerID)
c.Assert(err, check.Not(check.IsNil), check.Commentf("Container %s is not running", cleanedContainerID))
}
/*
func (s *DockerSuite) TestCliKillStoppedContainerAPIPre120(c *check.C) {
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "--name", "docker-kill-test-api", "-d", "busybox", "top")
dockerCmd(c, "stop", "docker-kill-test-api")
status, _, err := sockRequest("POST", fmt.Sprintf("/v1.19/containers/%s/kill", "docker-kill-test-api"), nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNoContent)
}
*/

View File

@@ -0,0 +1,245 @@
package main
import (
"fmt"
"regexp"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliLinksPingUnlinkedContainers(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
_, exitCode, err := dockerCmdWithError("run", "--rm", "busybox", "sh", "-c", "ping -c 1 alias1 -W 5 && ping -c 1 alias2 -W 5")
// run ping failed with error
c.Assert(exitCode, checker.Equals, 1, check.Commentf("error: %v", err))
}
// Test for appropriate error when calling --link with an invalid target container
func (s *DockerSuite) TestCliLinksInvalidContainerTarget(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _, err := dockerCmdWithError("run", "--link", "bogus:alias", "busybox", "true")
// an invalid container target should produce an error
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
// an invalid container target should produce an error
c.Assert(out, checker.Contains, "No such container")
}
func (s *DockerSuite) TestCliLinksPingLinkedContainersBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "--name", "container1", "--hostname", "fred", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "container2", "--hostname", "wilma", "busybox", "top")
runArgs := []string{"run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "sh", "-c"}
pingCmd := "ping -c 1 %s -W 5 && ping -c 1 %s -W 5"
// test ping by alias, ping by name, and ping by hostname
// 1. Ping by alias
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
// 2. Ping by container name
/* FIXME https://github.com/hyperhq/hypercli/issues/78
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
*/
// 3. Ping by hostname
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
}
func (s *DockerSuite) TestCliLinksPingLinkedContainersAfterRename(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
idA := strings.TrimSpace(out)
out, _ = dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
idB := strings.TrimSpace(out)
dockerCmd(c, "rename", "container1", "container-new")
dockerCmd(c, "run", "--rm", "--link", "container-new:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 5 && ping -c 1 alias2 -W 5")
dockerCmd(c, "kill", idA)
dockerCmd(c, "kill", idB)
}
func (s *DockerSuite) TestCliLinksInspectLinksStarted(c *check.C) {
/* FIXME https://github.com/hyperhq/hypercli/issues/76
testRequires(c, DaemonIsLinux)
printTestCaseName(); defer printTestDuration(time.Now())
var (
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
result []string
)
dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
err := unmarshalJSON([]byte(links), &result)
c.Assert(err, checker.IsNil)
output := convertSliceOfStringsToMap(result)
c.Assert(output, checker.DeepEquals, expected)
*/
}
func (s *DockerSuite) TestCliLinksInspectLinksStopped(c *check.C) {
/* FIXME https://github.com/hyperhq/hypercli/issues/76
testRequires(c, DaemonIsLinux)
printTestCaseName(); defer printTestDuration(time.Now())
var (
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
result []string
)
dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
err := unmarshalJSON([]byte(links), &result)
c.Assert(err, checker.IsNil)
output := convertSliceOfStringsToMap(result)
c.Assert(output, checker.DeepEquals, expected)
*/
}
func (s *DockerSuite) TestCliLinksNotStartedParentNotFail(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "create", "--name=first", "busybox", "top")
dockerCmd(c, "create", "--name=second", "--link=first:first", "busybox", "top")
dockerCmd(c, "start", "first")
}
func (s *DockerSuite) TestCliLinksHostsFilesInject(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
testRequires(c, SameHostDaemon, ExecSupport)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-itd", "--name", "one", "busybox", "top")
idOne := strings.TrimSpace(out)
out, _ = dockerCmd(c, "run", "-itd", "--name", "two", "--link", "one:onetwo", "busybox", "top")
idTwo := strings.TrimSpace(out)
c.Assert(waitRun(idTwo), checker.IsNil)
contentOne, err := readContainerFileWithExec(idOne, "/etc/hosts")
c.Assert(err, checker.IsNil, check.Commentf("contentOne: %s", string(contentOne)))
contentTwo, err := readContainerFileWithExec(idTwo, "/etc/hosts")
c.Assert(err, checker.IsNil, check.Commentf("contentTwo: %s", string(contentTwo)))
// Host is not present in updated hosts file
c.Assert(string(contentTwo), checker.Contains, "onetwo")
}
func (s *DockerSuite) TestCliLinksUpdateOnRestart(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
testRequires(c, SameHostDaemon, ExecSupport)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "--name", "one", "busybox", "top")
out, _ := dockerCmd(c, "run", "-d", "--name", "two", "--link", "one:onetwo", "--link", "one:one", "busybox", "top")
id := strings.TrimSpace(string(out))
realIP := inspectField(c, "one", "NetworkSettings.Networks.bridge.IPAddress")
content, err := readContainerFileWithExec(id, "/etc/hosts")
c.Assert(err, checker.IsNil)
getIP := func(hosts []byte, hostname string) string {
re := regexp.MustCompile(fmt.Sprintf(`(\S*)\t%s`, regexp.QuoteMeta(hostname)))
matches := re.FindSubmatch(hosts)
c.Assert(matches, checker.NotNil, check.Commentf("Hostname %s have no matches in hosts", hostname))
return string(matches[1])
}
ip := getIP(content, "one")
c.Assert(ip, checker.Equals, realIP)
ip = getIP(content, "onetwo")
c.Assert(ip, checker.Equals, realIP)
dockerCmd(c, "restart", "one")
realIP = inspectField(c, "one", "NetworkSettings.Networks.bridge.IPAddress")
content, err = readContainerFileWithExec(id, "/etc/hosts")
c.Assert(err, checker.IsNil, check.Commentf("content: %s", string(content)))
ip = getIP(content, "one")
c.Assert(ip, checker.Equals, realIP)
ip = getIP(content, "onetwo")
c.Assert(ip, checker.Equals, realIP)
}
func (s *DockerSuite) TestCliLinksEnvs(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "-e", "e1=", "-e", "e2=v2", "-e", "e3=v3=v3", "--name=first", "busybox", "top")
out, _ := dockerCmd(c, "run", "--name=second", "--link=first:first", "busybox", "env")
/* FIXME
c.Assert(out, checker.Contains, "FIRST_ENV_e1=\n")
*/
c.Assert(out, checker.Contains, "FIRST_ENV_e2=v2")
c.Assert(out, checker.Contains, "FIRST_ENV_e3=v3=v3")
}
func (s *DockerSuite) TestCliLinkShortDefinition(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--name", "shortlinkdef", "busybox", "top")
cid := strings.TrimSpace(out)
c.Assert(waitRun(cid), checker.IsNil)
out, _ = dockerCmd(c, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top")
cid2 := strings.TrimSpace(out)
c.Assert(waitRun(cid2), checker.IsNil)
/* FIXME https://github.com/hyperhq/hypercli/issues/76
links := inspectFieldJSON(c, cid2, "HostConfig.Links")
c.Assert(links, checker.Equals, "[\"/shortlinkdef:/link2/shortlinkdef\"]")
*/
}
func (s *DockerSuite) TestCliLinksMultipleWithSameName(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "--name=upstream-a", "busybox", "top")
dockerCmd(c, "run", "-d", "--name=upstream-b", "busybox", "top")
dockerCmd(c, "run", "--link", "upstream-a:upstream", "--link", "upstream-b:upstream", "busybox", "sh", "-c", "ping -c 1 upstream")
}

View File

@@ -0,0 +1,210 @@
package main
import (
"fmt"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"time"
)
/// test invalid url //////////////////////////////////////////////////////////////////////////
func (s *DockerSuite) TestCliLoadFromUrlInvalidUrlProtocal(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
invalidURL := "ftp://image-tarball.s3.amazonaws.com/test/public/helloworld.tar"
output, exitCode, err := dockerCmdWithError("load", "-i", invalidURL)
c.Assert(output, checker.Equals, "Error response from daemon: Bad request parameters: Get "+invalidURL+": unsupported protocol scheme \"ftp\"\n")
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliLoadFromUrlInvalidUrlHost(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
invalidHost := "invalidhost"
invalidURL := "http://" + invalidHost + "/test/public/helloworld.tar"
output, exitCode, err := dockerCmdWithError("load", "-i", invalidURL)
c.Assert(output, checker.Contains, "Error response from daemon: Bad request parameters: Get "+invalidURL+": dial tcp: lookup invalidhost")
c.Assert(output, checker.Contains, "no such host\n")
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliLoadFromUrlInvalidUrlPath(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
output, exitCode, err := dockerCmdWithError("load", "-i", "http://image-tarball.s3.amazonaws.com/test/public/notexist.tar")
c.Assert(output, checker.Equals, "Error response from daemon: Bad request parameters: Got HTTP status code >= 400: 403 Forbidden\n")
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
//test invalid ContentType and ContentLength///////////////////////////////////////////////////////////////////////////
func (s *DockerSuite) TestCliLoadFromUrlInvalidContentType(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
output, exitCode, err := dockerCmdWithError("load", "-i", "http://image-tarball.s3.amazonaws.com/test/public/readme.txt")
c.Assert(output, checker.Equals, "Error response from daemon: Download failed: URL MIME type should be one of: binary/octet-stream, application/octet-stream, application/x-tar, application/x-gzip, application/x-bzip, application/x-xz, but now is text/plain\n")
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliLoadFromUrlInvalidContentLengthTooLarge(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
const MaxLength = 4294967295
output, exitCode, err := dockerCmdWithError("load", "-i", "http://image-tarball.s3.amazonaws.com/test/public/largefile.tar")
c.Assert(output, checker.Contains, fmt.Sprintf("should be greater than zero and less than or equal to %v\n", MaxLength))
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
//test invalid content///////////////////////////////////////////////////////////////////////////
func (s *DockerSuite) TestCliLoadFromUrlInvalidContentLengthZero(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
const MaxLength = 4294967295
output, exitCode, err := dockerCmdWithError("load", "-i", "http://image-tarball.s3.amazonaws.com/test/public/emptyfile.tar")
c.Assert(output, checker.Equals, fmt.Sprintf("Error response from daemon: Bad request parameters: The size of the image archive file is 0, should be greater than zero and less than or equal to %v\n", MaxLength))
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliLoadFromUrlInvalidContentUnrelated(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
output, exitCode, err := dockerCmdWithError("load", "-i", "http://image-tarball.s3.amazonaws.com/test/public/readme.tar")
c.Assert(output, checker.Contains, "invalid argument\n")
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliLoadFromUrlInvalidUntarFail(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
output, exitCode, err := dockerCmdWithError("load", "-i", "http://image-tarball.s3.amazonaws.com/test/public/nottar.tar")
c.Assert(output, checker.Contains, "Untar re-exec error: exit status 1: output: unexpected EOF\n")
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliLoadFromUrlInvalidContentIncomplete(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
deleteAllImages()
url := "http://image-tarball.s3.amazonaws.com/test/public/helloworld-no-repositories.tgz"
output, exitCode, err := dockerCmdWithError("load", "-i", url)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
images, _ := dockerCmd(c, "images", "hello-world")
c.Assert(images, checker.Contains, "hello-world")
deleteAllImages()
//// load this image will be OK, but after delete this image, there is a residual image with <none> tag occur.
//url = "http://image-tarball.s3.amazonaws.com/test/public/helloworld-no-manifest.tgz"
//output, exitCode, err = dockerCmdWithError("load", "-i", url)
//c.Assert(output, check.Not(checker.Contains), "has been loaded.")
//c.Assert(exitCode, checker.Equals, 0)
//c.Assert(err, checker.IsNil)
//
//images, _ = dockerCmd(c, "images", "hello-world")
//c.Assert(images, checker.Contains, "hello-world")
//
//deleteAllImages()
url = "http://image-tarball.s3.amazonaws.com/test/public/helloworld-no-layer.tgz"
output, exitCode, err = dockerCmdWithError("load", "-i", url)
c.Assert(output, checker.Contains, "json: no such file or directory")
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
images, _ = dockerCmd(c, "images", "hello-world")
c.Assert(images, check.Not(checker.Contains), "hello-world")
deleteAllImages()
}
//test normal///////////////////////////////////////////////////////////////////////////
func (s *DockerSuite) TestCliLoadFromUrlValidBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/helloworld.tar"
output, exitCode, err := dockerCmdWithError("load", "-i", publicURL)
c.Assert(output, checker.Contains, "hello-world:latest(sha256:")
c.Assert(output, checker.Contains, "has been loaded.\n")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
images, _ := dockerCmd(c, "images", "hello-world")
c.Assert(images, checker.Contains, "hello-world")
}
func (s *DockerSuite) TestCliLoadFromUrlValidCompressedArchiveBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
extAry := [...]string{"tar.gz", "tgz", "tar.bz2", "tar.xz"}
for _, val := range extAry {
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/helloworld." + val
output, exitCode, err := dockerCmdWithError("load", "-i", publicURL)
c.Assert(output, checker.Contains, "hello-world:latest(sha256:")
c.Assert(output, checker.Contains, "has been loaded.\n")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
time.Sleep(1 * time.Second)
}
}
func (s *DockerSuite) TestCliLoadFromUrlWithQuiet(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/helloworld.tar"
out, _, _ := dockerCmdWithStdoutStderr(c, "load", "-q", "-i", publicURL)
c.Assert(out, check.Equals, "")
images, _ := dockerCmd(c, "images", "hello-world")
c.Assert(images, checker.Contains, "hello-world")
}
func (s *DockerSuite) TestCliLoadFromUrlMultipeImageBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
multiImgURL := "http://image-tarball.s3.amazonaws.com/test/public/busybox_alpine.tar"
dockerCmd(c, "load", "-i", multiImgURL)
images, _ := dockerCmd(c, "images", "busybox")
c.Assert(images, checker.Contains, "busybox")
images, _ = dockerCmd(c, "images", "alpine")
c.Assert(images, checker.Contains, "alpine")
}

View File

@@ -0,0 +1,75 @@
package main
import (
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"strings"
"time"
)
func (s *DockerSuite) TestCliLoadFromUrlLegacyImageArchiveFile(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
imageName := "ubuntu"
legacyImageURL := "http://image-tarball.s3.amazonaws.com/test/public/old/ubuntu_1.8.tar.gz"
imageURL := "http://image-tarball.s3.amazonaws.com/test/public/ubuntu.tar.gz"
//load legacy image(saved by docker 1.8)
output, exitCode, err := dockerCmdWithError("load", "-i", legacyImageURL)
c.Assert(output, checker.Contains, "Starting to download and load the image archive, please wait...\n")
c.Assert(output, checker.Contains, "has been loaded.\n")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
output, _ = dockerCmd(c, "images")
c.Assert(output, checker.Contains, imageName)
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 3)
/////////////////////////////////////////////////////////////////////
//load new format image(saved by docker 1.10)
output, exitCode, err = dockerCmdWithError("load", "-i", imageURL)
c.Assert(output, checker.Contains, "Starting to download and load the image archive, please wait...\n")
c.Assert(output, checker.Contains, "has been loaded.\n")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
output, _ = dockerCmd(c, "images")
c.Assert(output, checker.Contains, imageName)
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 3)
/////////////////////////////////////////////////////////////////////
//delete single layer
output, _ = dockerCmd(c, "images", "-q", imageName)
imageID := strings.Split(output, "\n")[0]
c.Assert(imageID, checker.Not(checker.Equals), "")
output, _ = dockerCmd(c, "rmi", "--no-prune", imageID)
c.Assert(output, checker.Contains, "Untagged:")
c.Assert(output, checker.Contains, "Deleted:")
output, _ = dockerCmd(c, "images")
c.Assert(output, checker.Contains, "<none>")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 3)
imageID = strings.Split(output, "\n")[0]
output, _ = dockerCmd(c, "images", "-a")
c.Assert(output, checker.Contains, "<none>")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 6)
/////////////////////////////////////////////////////////////////////
//delete all rest layer
output, _ = dockerCmd(c, "images", "-q")
imageID = strings.Split(output, "\n")[0]
c.Assert(imageID, checker.Not(checker.Equals), "")
output, _ = dockerCmd(c, "rmi", imageID)
c.Assert(output, checker.Contains, "Deleted:")
output, _ = dockerCmd(c, "images")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 2)
output, _ = dockerCmd(c, "images", "-a")
c.Assert(len(strings.Split(output, "\n")), checker.Equals, 2)
}

View File

@@ -0,0 +1,436 @@
package main
import (
"fmt"
"os"
"os/exec"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
//test normal///////////////////////////////////////////////////////////////////////////
func (s *DockerSuite) TestCliLoadFromLocalTarPipeBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/helloworld.tar"
imagePath := fmt.Sprintf("%s/helloworld.tar", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
_, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(pathExist(imagePath), checker.Equals, true)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
//load via pipe
catCmd := exec.Command("cat", imagePath)
loadCmd := exec.Command(dockerBinary, "--region", os.Getenv("DOCKER_HOST"), "--config", os.Getenv("HYPER_CONFIG"), "load")
catOut, err := catCmd.StdoutPipe()
catCmd.Start()
loadCmd.Stdin = catOut
output, err := loadCmd.Output()
c.Assert(string(output), checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
//check image
images, _ := dockerCmd(c, "images", "hello-world")
c.Assert(images, checker.Contains, "hello-world")
}
func (s *DockerSuite) TestCliLoadFromLocalTar(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/helloworld.tar"
imagePath := fmt.Sprintf("%s/helloworld.tar", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(pathExist(imagePath), checker.Equals, true)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//check image
images, _ := dockerCmd(c, "images", "hello-world")
c.Assert(images, checker.Contains, "hello-world")
}
func (s *DockerSuite) TestCliLoadFromLocalTarNoTag(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/busybox-notag.gz"
imagePath := fmt.Sprintf("%s/busybox-notag.gz", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(pathExist(imagePath), checker.Equals, true)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "sha256:c75bebcdd211f41b3a460c7bf82970ed6c75acaab9cd4c9a4e125b03ca113798 has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//check image
images, _ := dockerCmd(c, "images")
c.Assert(images, checker.Contains, "c75bebcdd211")
}
func (s *DockerSuite) TestCliLoadFromLocalTarDelta(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
baseURL := "http://image-tarball.s3.amazonaws.com/test/public/busybox.gz"
basePath := fmt.Sprintf("%s/busybox.gz", os.Getenv("IMAGE_DIR"))
deltaURL := "https://image-tarball.s3.amazonaws.com/test/public/busybox2.gz"
deltaPath := fmt.Sprintf("%s/buxybox2.gz", os.Getenv("IMAGE_DIR"))
//download base image tar
wgetCmd := exec.Command("wget", "-cO", basePath, baseURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
c.Assert(pathExist(basePath), checker.Equals, true)
wgetCmd = exec.Command("wget", "-cO", deltaPath, deltaURL)
output, exitCode, err = runCommandWithOutput(wgetCmd)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
c.Assert(pathExist(deltaPath), checker.Equals, true)
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", basePath)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
output, exitCode, err = dockerCmdWithError("load", "-i", deltaPath)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
// //check image
ensureImageIDExist(c, "busybox", "sha256:c75bebcdd211f41b3a460c7bf82970ed6c75acaab9cd4c9a4e125b03ca113798")
ensureImageIDExist(c, "busybox2", "sha256:50a48a50d85a126c96d01528bb836e62ad08555e740b44f299abf3416656bdb5")
}
func (s *DockerSuite) TestCliLoadFromLocalCompressedArchive(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
extAry := [...]string{"tar.gz", "tgz", "tar.bz2", "tar.xz"}
//download image archive
publicURL := ""
imagePath := ""
for _, val := range extAry {
publicURL = "http://image-tarball.s3.amazonaws.com/test/public/helloworld." + val
imagePath = fmt.Sprintf("%s/helloworld.%s", os.Getenv("IMAGE_DIR"), val)
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
_, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(pathExist(imagePath), checker.Equals, true)
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
}
//load image archive
for _, val := range extAry {
imagePath = fmt.Sprintf("%s/helloworld.%s", os.Getenv("IMAGE_DIR"), val)
output, exitCode, err := dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
time.Sleep(1 * time.Second)
}
}
func (s *DockerSuite) TestCliLoadFromLocalTarSize100MB(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/nginx_stable.tar"
imagePath := fmt.Sprintf("%s/nginx_stable.tar", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
c.Assert(pathExist(imagePath), checker.Equals, true)
//ensure nginx:stable not exist
dockerCmdWithError("rmi", "nginx:stable")
images, _ := dockerCmd(c, "images", "nginx:stable")
c.Assert(images, checker.Not(checker.Contains), "nginx")
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//check image
images, _ = dockerCmd(c, "images", "nginx:stable")
c.Assert(images, checker.Contains, "nginx")
}
func (s *DockerSuite) TestCliLoadFromLocalPullAndLoadBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/debian-8_5.tar.gz"
imagePath := fmt.Sprintf("%s/debian-8_5.tar.gz", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
c.Assert(pathExist(imagePath), checker.Equals, true)
//ensure debian:8.5 exist
dockerCmdWithError("pull", "debian:8.5")
images, _ := dockerCmd(c, "images", "debian:8.5")
c.Assert(images, checker.Contains, "debian")
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//check image
images, _ = dockerCmd(c, "images", "debian:8.5")
c.Assert(images, checker.Contains, "debian")
}
//test abnormal///////////////////////////////////////////////////////////////////////////
func (s *DockerSuite) TestCliLoadFromLocalMultipeImage(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
multiImgURL := "http://image-tarball.s3.amazonaws.com/test/public/busybox_alpine.tar"
imagePath := fmt.Sprintf("%s/busybox_alpine.tar", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, multiImgURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(pathExist(imagePath), checker.Equals, true)
c.Assert(err, checker.IsNil)
c.Assert(exitCode, checker.Equals, 0)
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "Loading multiple images from local is not supported")
c.Assert(err, checker.NotNil)
c.Assert(exitCode, checker.Not(checker.Equals), 0)
//ensure image not exist
images, _ := dockerCmd(c, "images", "busybox")
c.Assert(images, checker.Not(checker.Contains), "busybox")
images, _ = dockerCmd(c, "images", "alpine")
c.Assert(images, checker.Not(checker.Contains), "alpine")
}
func (s *DockerSuite) TestCliLoadFromLocalTarEmpty(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
//generate empty image tar
imagePath := fmt.Sprintf("%s/empty.tar", os.Getenv("IMAGE_DIR"))
os.OpenFile(imagePath, os.O_RDONLY|os.O_CREATE, 0666)
f, err := os.OpenFile(imagePath, os.O_CREATE, 0600)
c.Assert(err, checker.IsNil)
f.Close()
//load image tar
output, exitCode, err := dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "manifest.json: no such file or directory")
c.Assert(err, checker.NotNil)
c.Assert(exitCode, checker.Not(checker.Equals), 0)
}
func (s *DockerSuite) TestCliLoadFromLocalTarLegacy(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
publicURL := "http://image-tarball.s3.amazonaws.com/test/public/old/ubuntu_1.8.tar.gz"
imagePath := fmt.Sprintf("%s/ubuntu_1.8.tar.gz", os.Getenv("IMAGE_DIR"))
//download image tar
wgetCmd := exec.Command("wget", "-cO", imagePath, publicURL)
output, exitCode, err := runCommandWithOutput(wgetCmd)
c.Assert(pathExist(imagePath), checker.Equals, true)
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
//load image tar
output, exitCode, err = dockerCmdWithError("load", "-i", imagePath)
c.Assert(output, checker.Contains, "manifest.json: no such file or directory")
c.Assert(err, checker.NotNil)
c.Assert(exitCode, checker.Not(checker.Equals), 0)
}
/*
// TODO
//Prerequisite: update image balance to 1 in tenant collection of hypernetes in mongodb
//db.tenant.update({tenantid:"<tenant_id>"},{$set:{"resourceinfo.balance.images":2}})
func (s *DockerSuite) TestCliLoadFromLocalWithQuota(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
deleteAllImages()
helloworldURL := "http://image-tarball.s3.amazonaws.com/test/public/helloworld.tar"
multiImgURL := "http://image-tarball.s3.amazonaws.com/test/public/busybox_alpine.tar"
ubuntuURL := "http://image-tarball.s3.amazonaws.com/test/public/ubuntu.tar.gz"
exceedQuotaMsg := "Exceeded quota, please either delete images, or email support@hyper.sh to request increased quota"
///// [init] /////
// balance 2, images 0
out, _ := dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 0")
///// [step 1] load new hello-world image /////
// balance 2 -> 1, image: 0 -> 1
dockerCmd(c, "load", "-i", helloworldURL)
images, _ := dockerCmd(c, "images", "hello-world")
c.Assert(images, checker.Contains, "hello-world")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 1")
///// [step 2] load hello-world image again /////
// balance 1 -> 1, image 1 -> 1
output, exitCode, err := dockerCmdWithError("load", "-i", helloworldURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
checkImage(c, true, "hello-world")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 1")
///// [step 3] load multiple image(busybox+alpine) /////
// balance 1 -> 0, image 1 -> 2
output, exitCode, err = dockerCmdWithError("load", "-i", multiImgURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(output, checker.Contains, exceedQuotaMsg)
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
checkImage(c, true, "busybox")
checkImage(c, false, "alpine")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 2")
///// [step 4] load hello-world image again /////
// balance 0 -> 0, image 2 -> 2
output, exitCode, err = dockerCmdWithError("load", "-i", helloworldURL)
c.Assert(output, checker.Contains, exceedQuotaMsg)
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
checkImage(c, true, "hello-world")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 2")
///// [step 5] load new ubuntu image /////
// balance 0 -> 0, image 2 -> 2
output, exitCode, err = dockerCmdWithError("load", "-i", ubuntuURL)
c.Assert(output, checker.Contains, exceedQuotaMsg)
c.Assert(exitCode, checker.Equals, 1)
c.Assert(err, checker.NotNil)
checkImage(c, false, "ubuntu")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 2")
///// [step 6] remove hello-world image /////
// balance 0 -> 1, image 2 -> 1
images, _ = dockerCmd(c, "rmi", "-f", "hello-world")
c.Assert(images, checker.Contains, "Untagged: hello-world:latest")
checkImage(c, false, "hello-world")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 1")
///// [step 7] load new ubuntu image again /////
//balance 1 -> 0, image 1 -> 2
output, exitCode, err = dockerCmdWithError("load", "-i", ubuntuURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
checkImage(c, true, "ubuntu")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 2")
///// [step 8] remove busybox and ubuntu image /////
// balance 0 -> 2, image 2 -> 0
images, _ = dockerCmd(c, "rmi", "-f", "busybox", "ubuntu:14.04")
c.Assert(images, checker.Contains, "Untagged: busybox:latest")
c.Assert(images, checker.Contains, "Untagged: ubuntu:14.04")
checkImage(c, false, "busybox")
checkImage(c, false, "ubuntu")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 0")
///// [step 9] load multiple image(busybox+alpine) again /////
// balance 2 -> 0, image 0 -> 2
output, exitCode, err = dockerCmdWithError("load", "-i", multiImgURL)
c.Assert(output, checker.Contains, "has been loaded.")
c.Assert(exitCode, checker.Equals, 0)
c.Assert(err, checker.IsNil)
checkImage(c, true, "busybox")
checkImage(c, true, "alpine")
out, _ = dockerCmd(c, "info")
c.Assert(out, checker.Contains, "Images: 2")
}
*/

View File

@@ -0,0 +1,37 @@
package main
import (
"bytes"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"os"
"os/exec"
"time"
)
func (s *DockerSuite) TestCliLoginWithoutTTYBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
cmd := exec.Command(dockerBinary, "--region", os.Getenv("DOCKER_HOST"), "login")
// Send to stdin so the process does not get the TTY
cmd.Stdin = bytes.NewBufferString("buffer test string \n")
// run the command and block until it's done
err := cmd.Run()
c.Assert(err, checker.NotNil) //"Expected non nil err when loginning in & TTY not available"
}
/*
// Hyper can not login to private registry
func (s *DockerRegistryAuthSuite) TestCliLoginToPrivateRegistry(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
// wrong credentials
out, _, err := dockerCmdWithError("login", "-u", s.reg.username, "-p", "WRONGPASSWORD", "-e", s.reg.email, privateRegistryURL)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "401 Unauthorized")
// now it's fine
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, "-e", s.reg.email, privateRegistryURL)
}
*/

View File

@@ -0,0 +1,352 @@
package main
import (
//"encoding/json"
"fmt"
//"io"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/jsonlog"
"github.com/go-check/check"
)
//TODO: get exited container log
// This used to work, it test a log of PageSize-1 (gh#4851)
/*func (s *DockerSuite) TestCliLogsContainerSmallerThanPage(c *check.C) {
testRequires(c, DaemonIsLinux)
testLen := 32767
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
out, _ = dockerCmd(c, "logs", id)
c.Assert(out, checker.HasLen, testLen+1)
}*/
//TODO: get exited container log
// Regression test: When going over the PageSize, it used to panic (gh#4851)
/*func (s *DockerSuite) TestCliLogsContainerBiggerThanPage(c *check.C) {
testRequires(c, DaemonIsLinux)
testLen := 32768
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
out, _ = dockerCmd(c, "logs", id)
c.Assert(out, checker.HasLen, testLen+1)
}*/
//TODO: get exited container log
/*// Regression test: When going much over the PageSize, it used to block (gh#4851)
func (s *DockerSuite) TestCliLogsContainerMuchBiggerThanPage(c *check.C) {
testRequires(c, DaemonIsLinux)
testLen := 33000
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
out, _ = dockerCmd(c, "logs", id)
c.Assert(out, checker.HasLen, testLen+1)
}*/
//TODO: get exited container log
func (s *DockerSuite) TestCliLogsTimestamps(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
testLen := 100
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
time.Sleep(5 * time.Second)
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
time.Sleep(5 * time.Second)
out, _ = dockerCmd(c, "logs", "-t", id)
lines := strings.Split(out, "\n")
c.Assert(lines, checker.HasLen, testLen+1)
ts := regexp.MustCompile(`^.* `)
for _, l := range lines {
if l != "" {
_, err := time.Parse(jsonlog.RFC3339NanoFixed+" ", ts.FindString(l))
c.Assert(err, checker.IsNil, check.Commentf("Failed to parse timestamp from %v", l))
// ensure we have padded 0's
c.Assert(l[29], checker.Equals, uint8('Z'))
}
}
}
//TODO: get exited container log
func (s *DockerSuite) TestCliLogsSeparateStderrBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
msg := "stderr_log"
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
time.Sleep(5 * time.Second)
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
time.Sleep(5 * time.Second)
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", id)
c.Assert(stdout, checker.Equals, "")
stderr = strings.TrimSpace(stderr)
c.Assert(stderr, checker.Equals, msg)
}
//TODO: get exited container log
func (s *DockerSuite) TestCliLogsStderrInStdout(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
msg := "stderr_log"
out, _ := dockerCmd(c, "run", "-d", "-t", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
time.Sleep(5 * time.Second)
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
time.Sleep(5 * time.Second)
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", id)
c.Assert(stderr, checker.Equals, "")
stdout = strings.TrimSpace(stdout)
c.Assert(stdout, checker.Equals, msg)
}
//TODO: get exited container log
func (s *DockerSuite) TestCliLogsTailBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
testLen := 100
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
time.Sleep(5 * time.Second)
id := strings.TrimSpace(out)
dockerCmd(c, "stop", id)
time.Sleep(5 * time.Second)
out, _ = dockerCmd(c, "logs", "--tail", "5", id)
lines := strings.Split(out, "\n")
c.Assert(lines, checker.HasLen, 6)
out, _ = dockerCmd(c, "logs", "--tail", "all", id)
lines = strings.Split(out, "\n")
c.Assert(lines, checker.HasLen, testLen+1)
out, _, _ = dockerCmdWithStdoutStderr(c, "logs", "--tail", "random", id)
lines = strings.Split(out, "\n")
c.Assert(lines, checker.HasLen, testLen+1)
}
//TODO: fix #46
func (s *DockerSuite) TestCliLogsSince(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
name := "testlogssince"
dockerCmd(c, "run", "--name="+name, "-d", "busybox", "/bin/sh", "-c", "for i in $(seq 1 30); do sleep 2; echo log$i; done")
time.Sleep(10 * time.Second)
out, _ := dockerCmd(c, "logs", "-t", name)
log2Line := strings.Split(strings.Split(out, "\n")[1], " ")
t, err := time.Parse(time.RFC3339Nano, log2Line[0]) // the timestamp log2 is written
c.Assert(err, checker.IsNil)
since := t.Unix() + 1 // add 1s so log1 & log2 doesn't show up
out, _ = dockerCmd(c, "logs", "-t", fmt.Sprintf("--since=%v", since), name)
// Skip 2 seconds
unexpected := []string{"log1", "log2"}
for _, v := range unexpected {
c.Assert(out, checker.Not(checker.Contains), v, check.Commentf("unexpected log message returned, since=%v", since))
}
// Test to make sure a bad since format is caught by the client
out, _, _ = dockerCmdWithError("logs", "-t", "--since=2006-01-02T15:04:0Z", name)
c.Assert(out, checker.Contains, "cannot parse \"0Z\" as \"05\"", check.Commentf("bad since format passed to server"))
// Test with default value specified and parameter omitted
expected := []string{"log1", "log2", "log3"}
for _, cmd := range []*exec.Cmd{
exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "logs", "-t", name),
exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "logs", "-t", "--since=0", name),
} {
out, _, err = runCommandWithOutput(cmd)
c.Assert(err, checker.IsNil, check.Commentf("failed to log container: %s", out))
for _, v := range expected {
c.Assert(out, checker.Contains, v)
}
}
}
func (s *DockerSuite) TestCliLogsSinceFutureFollow(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", `for i in $(seq 1 50); do date +%s; sleep 1; done`)
time.Sleep(5 * time.Second)
id := strings.TrimSpace(out)
now := daemonTime(c).Unix()
since := now - 5
out, _ = dockerCmd(c, "logs", "-f", fmt.Sprintf("--since=%v", since), id)
lines := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(lines, checker.Not(checker.HasLen), 0)
for _, v := range lines {
ts, err := strconv.ParseInt(v, 10, 64)
c.Assert(err, checker.IsNil, check.Commentf("cannot parse timestamp output from log: '%v'\nout=%s", v, out))
c.Assert((ts+3) >= since, checker.Equals, true, check.Commentf("earlier log found. since=%v logdate=%v", since, ts))
}
}
//TODO: fix Goroutine in multi-tenancy environment
/*func (s *DockerSuite) TestCliLogsFollowGoroutinesWithStdout(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 2; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
type info struct {
NGoroutines int
}
getNGoroutines := func() int {
var i info
status, b, err := sockRequest("GET", "/info", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, 200)
c.Assert(json.Unmarshal(b, &i), checker.IsNil)
return i.NGoroutines
}
nroutines := getNGoroutines()
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "logs", "-f", id)
r, w := io.Pipe()
cmd.Stdout = w
c.Assert(cmd.Start(), checker.IsNil)
// Make sure pipe is written to
chErr := make(chan error)
go func() {
b := make([]byte, 1)
_, err := r.Read(b)
chErr <- err
}()
c.Assert(<-chErr, checker.IsNil)
c.Assert(cmd.Process.Kill(), checker.IsNil)
// NGoroutines is not updated right away, so we need to stop before failing
t := time.After(30 * time.Second)
for {
select {
case <-t:
n := getNGoroutines()
c.Assert(n <= nroutines, checker.Equals, true, check.Commentf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n))
default:
if n := getNGoroutines(); n <= nroutines {
return
}
time.Sleep(200 * time.Millisecond)
}
}
}
func (s *DockerSuite) TestCliLogsFollowGoroutinesNoOutput(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 2; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
type info struct {
NGoroutines int
}
getNGoroutines := func() int {
var i info
status, b, err := sockRequest("GET", "/info", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, 200)
c.Assert(json.Unmarshal(b, &i), checker.IsNil)
return i.NGoroutines
}
nroutines := getNGoroutines()
cmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "logs", "-f", id)
c.Assert(cmd.Start(), checker.IsNil)
time.Sleep(200 * time.Millisecond)
c.Assert(cmd.Process.Kill(), checker.IsNil)
// NGoroutines is not updated right away, so we need to stop before failing
t := time.After(30 * time.Second)
for {
select {
case <-t:
n := getNGoroutines()
c.Assert(n <= nroutines, checker.Equals, true, check.Commentf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n))
default:
if n := getNGoroutines(); n <= nroutines {
return
}
time.Sleep(200 * time.Millisecond)
}
}
}*/
func (s *DockerSuite) TestCliLogsCLIContainerNotFound(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
name := "testlogsnocontainer"
out, _, _ := dockerCmdWithError("logs", name)
message := fmt.Sprintf("Error: No such container: %s\n", name)
c.Assert(out, checker.Equals, message)
}

View File

@@ -0,0 +1,261 @@
package main
import (
"fmt"
"regexp"
"sort"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliPortList(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
// one port
out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", "top")
firstID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", firstID, "80")
err := assertPortList(c, out, []string{"0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "port", firstID)
err = assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", firstID)
// three port
out, _ = dockerCmd(c, "run", "-d",
"-p", "9876:80",
"-p", "9877:81",
"-p", "9878:82",
"busybox", "top")
ID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", ID, "80")
err = assertPortList(c, out, []string{"0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "port", ID)
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9876",
"81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
// more and one port mapped to the same container port
out, _ = dockerCmd(c, "run", "-d",
"-p", "9876:80",
"-p", "9999:80",
"-p", "9877:81",
"-p", "9878:82",
"busybox", "top")
ID = strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", ID, "80")
err = assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"})
// Port list is not correct
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "port", ID)
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9876",
"80/tcp -> 0.0.0.0:9999",
"81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
testRange := func() {
// host port ranges used
IDs := make([]string, 3)
for i := 0; i < 3; i++ {
out, _ = dockerCmd(c, "run", "-d",
"-p", "9090-9092:80",
"busybox", "top")
IDs[i] = strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", IDs[i])
err = assertPortList(c, out, []string{fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090)})
// Port list is not correct
c.Assert(err, checker.IsNil)
}
for i := 0; i < 3; i++ {
dockerCmd(c, "rm", "-f", IDs[i])
}
}
testRange()
// Verify we ran re-use port ranges after they are no longer in use.
testRange()
// test invalid port ranges
for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} {
out, _, err = dockerCmdWithError("run", "-d",
"-p", invalidRange,
"busybox", "top")
// Port range should have returned an error
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
}
// test host range:container range spec.
out, _ = dockerCmd(c, "run", "-d",
"-p", "9800-9803:80-83",
"busybox", "top")
ID = strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", ID)
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9800",
"81/tcp -> 0.0.0.0:9801",
"82/tcp -> 0.0.0.0:9802",
"83/tcp -> 0.0.0.0:9803"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
// test mixing protocols in same port range
out, _ = dockerCmd(c, "run", "-d",
"-p", "8000-8080:80",
"-p", "8000-8080:80/udp",
"busybox", "top")
ID = strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", ID)
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:8000",
"80/udp -> 0.0.0.0:8000"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
}
func assertPortList(c *check.C, out string, expected []string) error {
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != len(expected) {
return fmt.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
}
sort.Strings(lines)
sort.Strings(expected)
for i := 0; i < len(expected); i++ {
if lines[i] != expected[i] {
return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|")
}
}
return nil
}
func stopRemoveContainer(id string, c *check.C) {
dockerCmd(c, "rm", "-f", id)
}
func (s *DockerSuite) TestCliPortUnpublishedPortsInPsOutput(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
// Run busybox with command line expose (equivalent to EXPOSE in image's Dockerfile) for the following ports
port1 := 80
port2 := 443
expose1 := fmt.Sprintf("--expose=%d", port1)
expose2 := fmt.Sprintf("--expose=%d", port2)
dockerCmd(c, "run", "-d", expose1, expose2, "busybox", "sleep", "5")
unpPort1 := fmt.Sprintf("%d/tcp", port1)
unpPort2 := fmt.Sprintf("%d/tcp", port2)
// Run the container forcing to publish the exposed ports
dockerCmd(c, "run", "-d", "-P", expose1, expose2, "busybox", "sleep", "5")
// Check docker ps o/p for last created container reports the exposed ports in the port bindings
expBndRegx1 := regexp.MustCompile(`0.0.0.0:\d+->` + unpPort1)
expBndRegx2 := regexp.MustCompile(`0.0.0.0:\d+->` + unpPort2)
out, _ := dockerCmd(c, "ps", "-n=1")
// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort1) in docker ps output
c.Assert(expBndRegx1.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort1: %s", out, unpPort1))
// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort2) in docker ps output
c.Assert(expBndRegx2.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort2: %s", out, unpPort2))
// Run the container specifying explicit port bindings for the exposed ports
offset := 10000
pFlag1 := fmt.Sprintf("%d:%d", offset+port1, port1)
pFlag2 := fmt.Sprintf("%d:%d", offset+port2, port2)
out, _ = dockerCmd(c, "run", "-d", "-p", pFlag1, "-p", pFlag2, expose1, expose2, "busybox", "sleep", "5")
id := strings.TrimSpace(out)
// Check docker ps o/p for last created container reports the specified port mappings
expBnd1 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port1, unpPort1)
expBnd2 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port2, unpPort2)
out, _ = dockerCmd(c, "ps", "-n=1")
// Cannot find expected port binding (expBnd1) in docker ps output
c.Assert(out, checker.Contains, expBnd1)
// Cannot find expected port binding (expBnd2) in docker ps output
c.Assert(out, checker.Contains, expBnd2)
// Remove container now otherwise it will interfere with next test
stopRemoveContainer(id, c)
// Run the container with explicit port bindings and no exposed ports
out, _ = dockerCmd(c, "run", "-d", "-p", pFlag1, "-p", pFlag2, "busybox", "sleep", "5")
id = strings.TrimSpace(out)
// Check docker ps o/p for last created container reports the specified port mappings
out, _ = dockerCmd(c, "ps", "-n=1")
// Cannot find expected port binding (expBnd1) in docker ps output
c.Assert(out, checker.Contains, expBnd1)
// Cannot find expected port binding (expBnd2) in docker ps output
c.Assert(out, checker.Contains, expBnd2)
// Remove container now otherwise it will interfere with next test
stopRemoveContainer(id, c)
// Run the container with one unpublished exposed port and one explicit port binding
dockerCmd(c, "run", "-d", expose1, "-p", pFlag2, "busybox", "sleep", "5")
// Check docker ps o/p for last created container reports the specified unpublished port and port mapping
out, _ = dockerCmd(c, "ps", "-n=1")
// Missing port binding (expBnd2) in docker ps output
c.Assert(out, checker.Contains, expBnd2)
}
func (s *DockerSuite) TestCliPortHostBindingBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux, NotUserNamespace)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox",
"nc", "-l", "-p", "80")
firstID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", firstID, "80")
err := assertPortList(c, out, []string{"0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
}

View File

@@ -0,0 +1,476 @@
package main
import (
//"fmt"
//"io/ioutil"
//"os"
//"os/exec"
//"path/filepath"
"sort"
//"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliPsListContainersBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := runSleepingContainer(c, "-d")
firstID := strings.TrimSpace(out)
out, _ = runSleepingContainer(c, "-d")
secondID := strings.TrimSpace(out)
// not long running
out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
thirdID := strings.TrimSpace(out)
out, _ = runSleepingContainer(c, "-d")
fourthID := strings.TrimSpace(out)
// make sure the second is running
c.Assert(waitRun(secondID), checker.IsNil)
// make sure third one is not running
dockerCmd(c, "stop", thirdID)
// make sure the forth is running
c.Assert(waitRun(fourthID), checker.IsNil)
// all
out, _ = dockerCmd(c, "ps", "-a")
c.Assert(assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}), checker.Equals, true, check.Commentf("ALL: Container list is not in the correct order: \n%s", out))
// running
out, _ = dockerCmd(c, "ps")
c.Assert(assertContainerList(out, []string{fourthID, secondID, firstID}), checker.Equals, true, check.Commentf("RUNNING: Container list is not in the correct order: \n%s", out))
// from here all flag '-a' is ignored
// limit
out, _ = dockerCmd(c, "ps", "-n=2", "-a")
expected := []string{fourthID, thirdID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT & ALL: Container list is not in the correct order: \n%s", out))
out, _ = dockerCmd(c, "ps", "-n=2")
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out))
// filter since
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-a")
expected = []string{fourthID, thirdID, secondID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE & ALL: Container list is not in the correct order: \n%s", out))
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID)
expected = []string{fourthID, secondID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE: Container list is not in the correct order: \n%s", out))
// filter before
out, _ = dockerCmd(c, "ps", "-f", "before="+thirdID, "-a")
expected = []string{secondID, firstID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE & ALL: Container list is not in the correct order: \n%s", out))
out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID)
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE: Container list is not in the correct order: \n%s", out))
// filter since & before
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-a")
expected = []string{thirdID, secondID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, BEFORE & ALL: Container list is not in the correct order: \n%s", out))
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID)
expected = []string{secondID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, BEFORE: Container list is not in the correct order: \n%s", out))
// filter since & limit
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2", "-a")
expected = []string{fourthID, thirdID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2")
expected = []string{fourthID, thirdID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, LIMIT: Container list is not in the correct order: \n%s", out))
// filter before & limit
out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1", "-a")
expected = []string{thirdID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1")
expected = []string{thirdID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE, LIMIT: Container list is not in the correct order: \n%s", out))
// filter since & filter before & limit
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1", "-a")
expected = []string{thirdID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, BEFORE, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1")
expected = []string{thirdID}
c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE, BEFORE, LIMIT: Container list is not in the correct order: \n%s", out))
}
func assertContainerList(out string, expected []string) bool {
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines)-1 != len(expected) {
return false
}
containerIDIndex := strings.Index(lines[0], "CONTAINER ID")
for i := 0; i < len(expected); i++ {
foundID := lines[i+1][containerIDIndex : containerIDIndex+12]
if foundID != expected[i][:12] {
return false
}
}
return true
}
//TODO: fix container size
/*func (s *DockerSuite) TestCliPsListContainersSize(c *check.C) {
// Problematic on Windows as it doesn't report the size correctly @swernli
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
baseOut, _ := dockerCmd(c, "ps", "-s", "-n=1")
baseLines := strings.Split(strings.Trim(baseOut, "\n "), "\n")
baseSizeIndex := strings.Index(baseLines[0], "SIZE")
baseFoundsize := baseLines[1][baseSizeIndex:]
baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0])
c.Assert(err, checker.IsNil)
name := "test-size"
out, _ := dockerCmd(c, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
id, err := getIDByName(name)
c.Assert(err, checker.IsNil)
runCmd := exec.Command(dockerBinary, "--region="+os.Getenv("DOCKER_HOST"), "ps", "-s", "-n=1")
wait := make(chan struct{})
go func() {
out, _, err = runCommandWithOutput(runCmd)
close(wait)
}()
select {
case <-wait:
case <-time.After(3 * time.Second):
c.Fatalf("Calling \"docker ps -s\" timed out!")
}
c.Assert(err, checker.IsNil)
lines := strings.Split(strings.Trim(out, "\n "), "\n")
c.Assert(lines, checker.HasLen, 2, check.Commentf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines)))
sizeIndex := strings.Index(lines[0], "SIZE")
idIndex := strings.Index(lines[0], "CONTAINER ID")
foundID := lines[1][idIndex : idIndex+12]
c.Assert(foundID, checker.Equals, id[:12], check.Commentf("Expected id %s, got %s", id[:12], foundID))
expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
foundSize := lines[1][sizeIndex:]
c.Assert(foundSize, checker.Contains, expectedSize, check.Commentf("Expected size %q, got %q", expectedSize, foundSize))
}*/
func (s *DockerSuite) TestCliPsListContainersFilterStatusBasic(c *check.C) {
// start exited container
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox")
firstID := strings.TrimSpace(out)
// make sure the exited container is not running
dockerCmd(c, "stop", firstID)
// start running container
out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
secondID := strings.TrimSpace(out)
// filter containers by exited
out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited")
containerOut := strings.TrimSpace(out)
c.Assert(containerOut, checker.Equals, firstID)
out, _ = dockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running")
containerOut = strings.TrimSpace(out)
c.Assert(containerOut, checker.Equals, secondID)
out, _, _ = dockerCmdWithTimeout(time.Second*60, "ps", "-a", "-q", "--filter=status=rubbish")
c.Assert(out, checker.Contains, "Unrecognised filter value for status", check.Commentf("Expected error response due to invalid status filter output: %q", out))
}
func (s *DockerSuite) TestCliPsListContainersFilterID(c *check.C) {
// start container
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox")
firstID := strings.TrimSpace(out)
// start another container
runSleepingContainer(c)
// filter containers by id
out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=id="+firstID)
containerOut := strings.TrimSpace(out)
c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
}
func (s *DockerSuite) TestCliPsListContainersFilterNameBasic(c *check.C) {
// start container
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--name=a-name-to-match", "busybox")
firstID := strings.TrimSpace(out)
// start another container
runSleepingContainer(c, "--name=b-name-to-match")
// filter containers by name
out, _ = dockerCmd(c, "ps", "-a", "-q", "--filter=name=a-name-to-match")
containerOut := strings.TrimSpace(out)
c.Assert(containerOut, checker.Equals, firstID[:12], check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out))
}
func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
actualIDs := []string{}
if out != "" {
actualIDs = strings.Split(out[:len(out)-1], "\n")
}
sort.Strings(actualIDs)
sort.Strings(expectedIDs)
c.Assert(actualIDs, checker.HasLen, len(expectedIDs), check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v:%v, got %v:%v", filterName, len(expectedIDs), expectedIDs, len(actualIDs), actualIDs))
if len(expectedIDs) > 0 {
same := true
for i := range expectedIDs {
if actualIDs[i] != expectedIDs[i] {
c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
same = false
break
}
}
c.Assert(same, checker.Equals, true, check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs))
}
}
func (s *DockerSuite) TestCliPsListContainersFilterLabel(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
// start container
out, _ := dockerCmd(c, "run", "-d", "-l", "match=me", "-l", "second=tag", "busybox")
firstID := strings.TrimSpace(out)
// start another container
out, _ = dockerCmd(c, "run", "-d", "-l", "match=me too", "busybox")
secondID := strings.TrimSpace(out)
// start third container
out, _ = dockerCmd(c, "run", "-d", "-l", "nomatch=me", "busybox")
thirdID := strings.TrimSpace(out)
// filter containers by exact match
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
containerOut := strings.TrimSpace(out)
c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
// filter containers by two labels
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
containerOut = strings.TrimSpace(out)
c.Assert(containerOut, checker.Equals, firstID, check.Commentf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out))
// filter containers by two labels, but expect not found because of AND behavior
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
containerOut = strings.TrimSpace(out)
c.Assert(containerOut, checker.Equals, "", check.Commentf("Expected nothing, got %s for exited filter, output: %q", containerOut, out))
// filter containers by exact key
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
containerOut = strings.TrimSpace(out)
c.Assert(containerOut, checker.Contains, firstID)
c.Assert(containerOut, checker.Contains, secondID)
c.Assert(containerOut, checker.Not(checker.Contains), thirdID)
}
func (s *DockerSuite) TestCliPsListContainersFilterExited(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
runSleepingContainer(c, "--name=sleep")
dockerCmd(c, "run", "--name", "zero1", "busybox", "true")
firstZero, err := getIDByName("zero1")
c.Assert(err, checker.IsNil)
dockerCmd(c, "run", "--name", "zero2", "busybox", "true")
secondZero, err := getIDByName("zero2")
c.Assert(err, checker.IsNil)
out, _, err := dockerCmdWithError("run", "--name", "nonzero1", "busybox", "false")
//TODO: generate err when exited code is not 0
//c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
firstNonZero, err := getIDByName("nonzero1")
c.Assert(err, checker.IsNil)
out, _, err = dockerCmdWithError("run", "--name", "nonzero2", "busybox", "false")
//TODO: generate err when exited code is not 0
//c.Assert(err, checker.NotNil, check.Commentf("Should fail.", out, err))
secondNonZero, err := getIDByName("nonzero2")
c.Assert(err, checker.IsNil)
// filter containers by exited=0
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
ids := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d: %s", len(ids), out))
c.Assert(ids[0], checker.Equals, secondZero, check.Commentf("First in list should be %q, got %q", secondZero, ids[0]))
c.Assert(ids[1], checker.Equals, firstZero, check.Commentf("Second in list should be %q, got %q", firstZero, ids[1]))
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
ids = strings.Split(strings.TrimSpace(out), "\n")
c.Assert(ids, checker.HasLen, 2, check.Commentf("Should be 2 zero exited containers got %d", len(ids)))
c.Assert(ids[0], checker.Equals, secondNonZero, check.Commentf("First in list should be %q, got %q", secondNonZero, ids[0]))
c.Assert(ids[1], checker.Equals, firstNonZero, check.Commentf("Second in list should be %q, got %q", firstNonZero, ids[1]))
}
//TODO: SAME AS ps format multi names
/*func (s *DockerSuite) TestCliPsLinkedWithNoTrunc(c *check.C) {
// Problematic on Windows as it doesn't support links as of Jan 2016
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
runSleepingContainer(c, "--name=first")
runSleepingContainer(c, "--name=second", "--link=first:first")
out, _ := dockerCmd(c, "ps", "--no-trunc")
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
// strip header
lines = lines[1:]
expected := []string{"second", "first,second/first"}
var names []string
for _, l := range lines {
fields := strings.Fields(l)
names = append(names, fields[len(fields)-1])
}
c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array: %v, got: %v", expected, names))
}*/
func (s *DockerSuite) TestCliPsWithSize(c *check.C) {
// Problematic on Windows as it doesn't report the size correctly @swernli
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "-d", "--name", "sizetest", "busybox", "top")
out, _ := dockerCmd(c, "ps", "--size")
c.Assert(out, checker.Contains, "virtual", check.Commentf("docker ps with --size should show virtual size of container"))
}
func (s *DockerSuite) TestCliPsListContainersFilterCreated(c *check.C) {
// create a container
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "create", "busybox")
cID := strings.TrimSpace(out)
shortCID := cID[:12]
// Make sure it DOESN'T show up w/o a '-a' for normal 'ps'
out, _ = dockerCmd(c, "ps", "-q")
c.Assert(out, checker.Not(checker.Contains), shortCID, check.Commentf("Should have not seen '%s' in ps output:\n%s", shortCID, out))
// Make sure it DOES show up as 'Created' for 'ps -a'
out, _ = dockerCmd(c, "ps", "-a")
hits := 0
for _, line := range strings.Split(out, "\n") {
if !strings.Contains(line, shortCID) {
continue
}
hits++
c.Assert(line, checker.Contains, "Created", check.Commentf("Missing 'Created' on '%s'", line))
}
c.Assert(hits, checker.Equals, 1, check.Commentf("Should have seen '%s' in ps -a output once:%d\n%s", shortCID, hits, out))
// filter containers by 'create' - note, no -a needed
out, _ = dockerCmd(c, "ps", "-q", "-f", "status=created")
containerOut := strings.TrimSpace(out)
c.Assert(cID, checker.HasPrefix, containerOut)
}
//TODO: fix ps format multi names
/*func (s *DockerSuite) TestCliPsFormatMultiNames(c *check.C) {
// Problematic on Windows as it doesn't support link as of Jan 2016
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
//create 2 containers and link them
dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
//use the new format capabilities to only list the names and --no-trunc to get all names
out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
expected := []string{"parent", "child,parent/linkedone"}
var names []string
for _, l := range lines {
names = append(names, l)
}
c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with non-truncated names: %v, got: %v", expected, names))
//now list without turning off truncation and make sure we only get the non-link names
out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
lines = strings.Split(strings.TrimSpace(string(out)), "\n")
expected = []string{"parent", "child"}
var truncNames []string
for _, l := range lines {
truncNames = append(truncNames, l)
}
c.Assert(expected, checker.DeepEquals, truncNames, check.Commentf("Expected array with truncated names: %v, got: %v", expected, truncNames))
}*/
func (s *DockerSuite) TestCliPsFormatHeaders(c *check.C) {
// make sure no-container "docker ps" still prints the header row
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
c.Assert(out, checker.Equals, "CONTAINER ID\n", check.Commentf(`Expected 'CONTAINER ID\n', got %v`, out))
// verify that "docker ps" with a container still prints the header row also
runSleepingContainer(c, "--name=test")
out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
c.Assert(out, checker.Equals, "NAMES\ntest\n", check.Commentf(`Expected 'NAMES\ntest\n', got %v`, out))
}

View File

@@ -0,0 +1,220 @@
package main
import (
"fmt"
"regexp"
"strings"
"time"
"github.com/docker/distribution/digest"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// TestPullFromCentralRegistry pulls an image from the central registry and verifies that the client
// prints all expected output.
func (s *DockerHubPullSuite) TestCliPullFromCentralRegistryBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out := s.Cmd(c, "pull", "hello-world")
defer deleteImages("hello-world")
c.Assert(out, checker.Contains, "Using default tag: latest", check.Commentf("expected the 'latest' tag to be automatically assumed"))
c.Assert(out, checker.Contains, "Pulling from library/hello-world", check.Commentf("expected the 'library/' prefix to be automatically assumed"))
c.Assert(out, checker.Contains, "Downloaded newer image for hello-world:latest")
matches := regexp.MustCompile(`Digest: (.+)\n`).FindAllStringSubmatch(out, -1)
c.Assert(len(matches), checker.Equals, 1, check.Commentf("expected exactly one image digest in the output"))
c.Assert(len(matches[0]), checker.Equals, 2, check.Commentf("unexpected number of submatches for the digest"))
_, err := digest.ParseDigest(matches[0][1])
c.Check(err, checker.IsNil, check.Commentf("invalid digest %q in output", matches[0][1]))
// We should have a single entry in images.
img := strings.TrimSpace(s.Cmd(c, "images"))
splitImg := strings.Split(img, "\n")
c.Assert(splitImg, checker.HasLen, 2)
c.Assert(splitImg[1], checker.Matches, `hello-world\s+latest.*?`, check.Commentf("invalid output for `docker images` (expected image and tag name"))
}
// TestPullNonExistingImage pulls non-existing images from the central registry, with different
// combinations of implicit tag and library prefix.
func (s *DockerHubPullSuite) TestCliPullNonExistingImage(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
for _, e := range []struct {
Repo string
Alias string
}{
{"library/asdfasdf", "asdfasdf:foobar"},
{"library/asdfasdf", "library/asdfasdf:foobar"},
{"library/asdfasdf", "asdfasdf"},
{"library/asdfasdf", "asdfasdf:latest"},
{"library/asdfasdf", "library/asdfasdf"},
{"library/asdfasdf", "library/asdfasdf:latest"},
} {
out, err := s.CmdWithError("pull", e.Alias)
c.Assert(err, checker.NotNil, check.Commentf("expected non-zero exit status when pulling non-existing image: %s", out))
// Hub returns 401 rather than 404 for nonexistent repos over
// the v2 protocol - but we should end up falling back to v1,
// which does return a 404.
c.Assert(out, checker.Contains, fmt.Sprintf("Error: image %s not found", e.Repo), check.Commentf("expected image not found error messages"))
// pull -a on a nonexistent registry should fall back as well
if !strings.ContainsRune(e.Alias, ':') {
out, err := s.CmdWithError("pull", e.Alias)
c.Assert(err, checker.NotNil, check.Commentf("expected non-zero exit status when pulling non-existing image: %s", out))
c.Assert(out, checker.Contains, fmt.Sprintf("Error: image %s not found", e.Repo), check.Commentf("expected image not found error messages"))
c.Assert(out, checker.Not(checker.Contains), "unauthorized", check.Commentf(`message should not contain "unauthorized"`))
}
}
}
// TestPullFromCentralRegistryImplicitRefParts pulls an image from the central registry and verifies
// that pulling the same image with different combinations of implicit elements of the the image
// reference (tag, repository, central registry url, ...) doesn't trigger a new pull nor leads to
// multiple images.
func (s *DockerHubPullSuite) TestCliPullFromCentralRegistryImplicitRefParts(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
s.Cmd(c, "pull", "hello-world")
defer deleteImages("hello-world")
for _, i := range []string{
"hello-world",
"hello-world:latest",
"library/hello-world",
"library/hello-world:latest",
"docker.io/library/hello-world",
"index.docker.io/library/hello-world",
} {
out := s.Cmd(c, "pull", i)
c.Assert(out, checker.Contains, "Image is up to date for hello-world:latest")
}
// We should have a single entry in images.
img := strings.TrimSpace(s.Cmd(c, "images"))
splitImg := strings.Split(img, "\n")
c.Assert(splitImg, checker.HasLen, 2)
c.Assert(splitImg[1], checker.Matches, `hello-world\s+latest.*?`, check.Commentf("invalid output for `docker images` (expected image and tag name"))
}
// TestPullScratchNotAllowed verifies that pulling 'scratch' is rejected.
func (s *DockerHubPullSuite) TestCliPullScratchNotAllowed(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, err := s.CmdWithError("pull", "scratch")
c.Assert(err, checker.NotNil, check.Commentf("expected pull of scratch to fail"))
c.Assert(out, checker.Contains, "'scratch' is a reserved name")
c.Assert(out, checker.Not(checker.Contains), "Pulling repository scratch")
}
/*
// TestPullAllTagsFromCentralRegistry pulls using `all-tags` for a given image and verifies that it
// results in more images than a naked pull.
func (s *DockerHubPullSuite) TestCliPullAllTagsFromCentralRegistry(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
s.Cmd(c, "pull", "busybox")
outImageCmd := s.Cmd(c, "images", "busybox")
splitOutImageCmd := strings.Split(strings.TrimSpace(outImageCmd), "\n")
c.Assert(splitOutImageCmd, checker.HasLen, 2)
s.Cmd(c, "pull", "--all-tags=true", "busybox")
outImageAllTagCmd := s.Cmd(c, "images", "busybox")
linesCount := strings.Count(outImageAllTagCmd, "\n")
c.Assert(linesCount, checker.GreaterThan, 2, check.Commentf("pulling all tags should provide more than two images, got %s", outImageAllTagCmd))
// Verify that the line for 'busybox:latest' is left unchanged.
var latestLine string
for _, line := range strings.Split(outImageAllTagCmd, "\n") {
if strings.HasPrefix(line, "busybox") && strings.Contains(line, "latest") {
latestLine = line
break
}
}
c.Assert(latestLine, checker.Not(checker.Equals), "", check.Commentf("no entry for busybox:latest found after pulling all tags"))
splitLatest := strings.Fields(latestLine)
splitCurrent := strings.Fields(splitOutImageCmd[1])
// Clear relative creation times, since these can easily change between
// two invocations of "docker images". Without this, the test can fail
// like this:
// ... obtained []string = []string{"busybox", "latest", "d9551b4026f0", "27", "minutes", "ago", "1.113", "MB"}
// ... expected []string = []string{"busybox", "latest", "d9551b4026f0", "26", "minutes", "ago", "1.113", "MB"}
splitLatest[3] = ""
splitLatest[4] = ""
splitLatest[5] = ""
splitCurrent[3] = ""
splitCurrent[4] = ""
splitCurrent[5] = ""
c.Assert(splitLatest, checker.DeepEquals, splitCurrent, check.Commentf("busybox:latest was changed after pulling all tags"))
}
*/
/*
// TestPullClientDisconnect kills the client during a pull operation and verifies that the operation
// gets cancelled.
//
// Ref: docker/docker#15589
func (s *DockerHubPullSuite) TestCliPullClientDisconnect(c *check.C) {
printTestCaseName(); defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
repoName := "hello-world:latest"
pullCmd := s.MakeCmd("pull", repoName)
stdout, err := pullCmd.StdoutPipe()
c.Assert(err, checker.IsNil)
err = pullCmd.Start()
c.Assert(err, checker.IsNil)
// Cancel as soon as we get some output.
buf := make([]byte, 10)
_, err = stdout.Read(buf)
c.Assert(err, checker.IsNil)
err = pullCmd.Process.Kill()
c.Assert(err, checker.IsNil)
time.Sleep(20 * time.Second)
_, err = s.CmdWithError("inspect", repoName)
c.Assert(err, checker.NotNil, check.Commentf("image was pulled after client disconnected"))
}
*/
func (s *DockerHubPullSuite) TestCliPullFromDaocloudRegistry(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
testRegistry := "daocloud.io"
testRepo := "daocloud/dao-wordpress"
testImage := testRegistry + "/" + testRepo
out := s.Cmd(c, "pull", testImage)
defer deleteImages(testImage)
c.Assert(out, checker.Contains, "Using default tag: latest", check.Commentf("expected the 'latest' tag to be automatically assumed"))
c.Assert(out, checker.Contains, "Pulling from "+testRepo, check.Commentf("expected the 'daocloud/' prefix to be automatically assumed"))
matches := regexp.MustCompile(`Digest: (.+)\n`).FindAllStringSubmatch(out, -1)
c.Assert(len(matches), checker.Equals, 1, check.Commentf("expected exactly one image digest in the output"))
c.Assert(len(matches[0]), checker.Equals, 2, check.Commentf("unexpected number of submatches for the digest"))
_, err := digest.ParseDigest(matches[0][1])
c.Check(err, checker.IsNil, check.Commentf("invalid digest %q in output", matches[0][1]))
// We should have a single entry in images.
img := strings.TrimSpace(s.Cmd(c, "images"))
splitImg := strings.Split(img, "\n")
c.Assert(splitImg, checker.HasLen, 2)
c.Assert(splitImg[1], checker.Matches, `daocloud.io/daocloud/dao-wordpress\s+latest.*?`, check.Commentf("invalid output for ` hyper images` (expected image and tag name"))
}

View File

@@ -0,0 +1,112 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliRenameStoppedContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "--name", "first-name", "-d", "busybox", "sh")
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "stop", cleanedContainerID)
name := inspectField(c, cleanedContainerID, "Name")
newName := "new-name" + stringid.GenerateNonCryptoID()
dockerCmd(c, "rename", "first-name", newName)
name = inspectField(c, cleanedContainerID, "Name")
c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))
}
func (s *DockerSuite) TestCliRenameRunningContainerBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "--name", "first-name", "-d", "busybox", "sh")
newName := "new-name" + stringid.GenerateNonCryptoID()
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "rename", "first-name", newName)
name := inspectField(c, cleanedContainerID, "Name")
c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))
}
func (s *DockerSuite) TestCliRenameRunningContainerAndReuse(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := runSleepingContainer(c, "--name", "first-name")
c.Assert(waitRun("first-name"), check.IsNil)
newName := "new-name"
ContainerID := strings.TrimSpace(out)
dockerCmd(c, "rename", "first-name", newName)
name := inspectField(c, ContainerID, "Name")
c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container"))
out, _ = runSleepingContainer(c, "--name", "first-name")
c.Assert(waitRun("first-name"), check.IsNil)
newContainerID := strings.TrimSpace(out)
name = inspectField(c, newContainerID, "Name")
c.Assert(name, checker.Equals, "/first-name", check.Commentf("Failed to reuse container name"))
}
func (s *DockerSuite) TestCliRenameCheckNames(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name", "first-name", "-d", "busybox", "sh")
newName := "new-name" + stringid.GenerateNonCryptoID()[:32]
dockerCmd(c, "rename", "first-name", newName)
name := inspectField(c, newName, "Name")
c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))
name, err := inspectFieldWithError("first-name", "Name")
c.Assert(err, checker.NotNil, check.Commentf(name))
c.Assert(err.Error(), checker.Contains, "No such image or container: first-name")
}
func (s *DockerSuite) TestCliRenameInvalidName(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
runSleepingContainer(c, "--name", "myname")
out, _, err := dockerCmdWithError("rename", "myname", "new:invalid")
c.Assert(err, checker.NotNil, check.Commentf("Renaming container to invalid name should have failed: %s", out))
c.Assert(out, checker.Contains, "new:invalid is invalid, should be", check.Commentf("%v", err))
out, _, err = dockerCmdWithError("rename", "myname", "")
c.Assert(err, checker.NotNil, check.Commentf("Renaming container to invalid name should have failed: %s", out))
c.Assert(out, checker.Contains, "may be empty", check.Commentf("%v", err))
out, _, err = dockerCmdWithError("rename", "", "newname")
c.Assert(err, checker.NotNil, check.Commentf("Renaming container with empty name should have failed: %s", out))
c.Assert(out, checker.Contains, "may be empty", check.Commentf("%v", err))
out, _ = dockerCmd(c, "ps", "-a")
c.Assert(out, checker.Contains, "myname", check.Commentf("Output of docker ps should have included 'myname': %s", out))
}

View File

@@ -0,0 +1,183 @@
package main
import (
"os"
"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliRestartStoppedContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "echo", "foobar")
time.Sleep(5 * time.Second)
cleanedContainerID := strings.TrimSpace(out)
c.Assert(waitExited(cleanedContainerID, 30*time.Second), checker.IsNil)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
c.Assert(out, checker.Equals, "foobar\n")
dockerCmd(c, "restart", cleanedContainerID)
time.Sleep(5 * time.Second)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
c.Assert(out, checker.Equals, "foobar\n")
}
func (s *DockerSuite) TestCliRestartRunningContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'")
time.Sleep(5 * time.Second)
cleanedContainerID := strings.TrimSpace(out)
c.Assert(waitRun(cleanedContainerID), checker.IsNil)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
c.Assert(out, checker.Equals, "foobar\n")
dockerCmd(c, "restart", "-t", "1", cleanedContainerID)
time.Sleep(5 * time.Second)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
c.Assert(waitRun(cleanedContainerID), checker.IsNil)
c.Assert(out, checker.Equals, "foobar\nfoobar\n")
}
// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
func (s *DockerSuite) TestCliRestartWithVolumesBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "-v", "/test", "busybox", "top")
cleanedContainerID := strings.TrimSpace(out)
out, err := inspectFilter(cleanedContainerID, "len .Mounts")
c.Assert(err, check.IsNil, check.Commentf("failed to inspect %s: %s", cleanedContainerID, out))
out = strings.Trim(out, " \n\r")
c.Assert(out, checker.Equals, "1")
source, err := inspectMountSourceField(cleanedContainerID, "/test")
c.Assert(err, checker.IsNil)
dockerCmd(c, "restart", cleanedContainerID)
out, err = inspectFilter(cleanedContainerID, "len .Mounts")
c.Assert(err, check.IsNil, check.Commentf("failed to inspect %s: %s", cleanedContainerID, out))
out = strings.Trim(out, " \n\r")
c.Assert(out, checker.Equals, "1")
sourceAfterRestart, err := inspectMountSourceField(cleanedContainerID, "/test")
c.Assert(err, checker.IsNil)
c.Assert(source, checker.Equals, sourceAfterRestart)
}
func (s *DockerSuite) TestCliRestartPolicyNO(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--restart=no", "busybox", "false")
id := strings.TrimSpace(string(out))
name := inspectField(c, id, "HostConfig.RestartPolicy.Name")
c.Assert(name, checker.Equals, "no")
}
func (s *DockerSuite) TestCliRestartPolicyAlwaysBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--restart=always", "busybox", "false")
id := strings.TrimSpace(string(out))
name := inspectField(c, id, "HostConfig.RestartPolicy.Name")
c.Assert(name, checker.Equals, "always")
MaximumRetryCount := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount")
// MaximumRetryCount=0 if the restart policy is always
c.Assert(MaximumRetryCount, checker.Equals, "0")
}
func (s *DockerSuite) TestCliRestartPolicyOnFailure(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:1", "busybox", "false")
id := strings.TrimSpace(string(out))
name := inspectField(c, id, "HostConfig.RestartPolicy.Name")
c.Assert(name, checker.Equals, "on-failure")
}
// a good container with --restart=on-failure:3
// MaximumRetryCount!=0; RestartCount=0
func (s *DockerSuite) TestCliRestartContainerRestartwithGoodContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "true")
id := strings.TrimSpace(string(out))
err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 50*time.Second)
c.Assert(err, checker.IsNil)
count := inspectField(c, id, "RestartCount")
c.Assert(count, checker.Equals, "0")
MaximumRetryCount := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount")
c.Assert(MaximumRetryCount, checker.Equals, "3")
}
func (s *DockerSuite) TestCliRestartContainerRestartSuccess(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux, SameHostDaemon)
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "--restart=always", "busybox", "top")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
pidStr := inspectField(c, id, "State.Pid")
pid, err := strconv.Atoi(pidStr)
c.Assert(err, check.IsNil)
p, err := os.FindProcess(pid)
c.Assert(err, check.IsNil)
c.Assert(p, check.NotNil)
err = p.Kill()
c.Assert(err, check.IsNil)
err = waitInspect(id, "{{.RestartCount}}", "1", 50*time.Second)
c.Assert(err, check.IsNil)
err = waitInspect(id, "{{.State.Status}}", "running", 50*time.Second)
c.Assert(err, check.IsNil)
}

View File

@@ -0,0 +1,84 @@
package main
import (
"io/ioutil"
"os"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliRmContainerWithRemovedVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, SameHostDaemon)
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
tempDir, err := ioutil.TempDir("", "test-rm-container-with-removed-volume-")
if err != nil {
c.Fatalf("failed to create temporary directory: %s", tempDir)
}
defer os.RemoveAll(tempDir)
dockerCmd(c, "run", "--name", "losemyvolumes", "-v", tempDir+":"+prefix+slash+"test", "busybox", "true")
err = os.RemoveAll(tempDir)
c.Assert(err, check.IsNil)
dockerCmd(c, "rm", "-v", "losemyvolumes")
}
func (s *DockerSuite) TestCliRmContainerWithVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
deleteAllContainers()
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
pullImageIfNotExist("busybox")
dockerCmd(c, "run", "--name", "foo", "-v", prefix+slash+"srv", "busybox", "true")
dockerCmd(c, "rm", "-v", "foo")
}
func (s *DockerSuite) TestCliRmContainerRunningBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
deleteAllContainers()
createRunningContainer(c, "foo")
_, _, err := dockerCmdWithError("rm", "foo")
c.Assert(err, checker.NotNil, check.Commentf("Expected error, can't rm a running container"))
}
func (s *DockerSuite) TestCliRmContainerForceRemoveRunningBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
deleteAllContainers()
createRunningContainer(c, "foo")
// Stop then remove with -s
dockerCmd(c, "rm", "-f", "foo")
}
func (s *DockerSuite) TestCliRmInvalidContainer(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _, err := dockerCmdWithError("rm", "unknown")
c.Assert(err, checker.NotNil, check.Commentf("Expected error on rm unknown container, got none"))
c.Assert(out, checker.Contains, "No such container")
}
func createRunningContainer(c *check.C, name string) {
runSleepingContainer(c, "-dt", "--name", name)
time.Sleep(1 * time.Second)
}

View File

@@ -0,0 +1,91 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliRmiBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
_, _, err := dockerCmdWithError("rmi", "busybox")
c.Assert(err, checker.IsNil)
images, _ := dockerCmd(c, "images")
c.Assert(images, checker.Not(checker.Contains), "busybox")
}
func (s *DockerSuite) TestCliRmiWithContainerFailsBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
errSubstr := "is using it"
// create a container
pullImageIfNotExist("busybox")
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
cleanedContainerID := strings.TrimSpace(out)
// try to delete the image
out, _, err := dockerCmdWithError("rmi", "busybox")
// Container is using image, should not be able to rmi
c.Assert(err, checker.NotNil)
// Container is using image, error message should contain errSubstr
c.Assert(out, checker.Contains, errSubstr, check.Commentf("Container: %q", cleanedContainerID))
// make sure it didn't delete the busybox name
images, _ := dockerCmd(c, "images")
// The name 'busybox' should not have been removed from images
c.Assert(images, checker.Contains, "busybox")
}
func (s *DockerSuite) TestCliRmiBlank(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
// try to delete a blank image name
out, _, err := dockerCmdWithError("rmi", "")
// Should have failed to delete '' image
c.Assert(err, checker.NotNil)
// Wrong error message generated
c.Assert(out, checker.Not(checker.Contains), "no such id", check.Commentf("out: %s", out))
// Expected error message not generated
c.Assert(out, checker.Contains, "Invalid empty image name\n", check.Commentf("out: %s", out))
out, _, err = dockerCmdWithError("rmi", " ")
// Should have failed to delete ' ' image
c.Assert(err, checker.NotNil)
// Expected error message not generated
c.Assert(out, checker.Contains, "Invalid empty image name\n", check.Commentf("out: %s", out))
}
// #18873
func (s *DockerSuite) TestCliRmiByIDHardConflict(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
// TODO Windows CI. This will work on a TP5 compatible docker which
// has content addressibility fixes. Do not run this on TP4 as it
// will end up deleting the busybox image causing subsequent tests to fail.
dockerCmd(c, "create", "busybox")
imgID := inspectField(c, "busybox:latest", "Id")
_, _, err := dockerCmdWithError("rmi", imgID[:12])
c.Assert(err, checker.NotNil)
// check that tag was not removed
imgID2 := inspectField(c, "busybox:latest", "Id")
c.Assert(imgID, checker.Equals, imgID2)
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
// +build !windows
package main
import (
"bufio"
"os"
"os/exec"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"github.com/kr/pty"
)
// #6509
func (s *DockerSuite) TestCliRunRedirectStdout(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
checkRedirect := func(command string) {
_, tty, err := pty.Open()
c.Assert(err, checker.IsNil, check.Commentf("Could not open pty"))
cmd := exec.Command("sh", "-c", command)
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
c.Assert(cmd.Start(), checker.IsNil)
ch := make(chan error)
go func() {
ch <- cmd.Wait()
close(ch)
}()
select {
case <-time.After(30 * time.Second):
c.Fatal("command timeout")
case err := <-ch:
c.Assert(err, checker.IsNil, check.Commentf("wait err"))
}
}
checkRedirect(dockerBinary + " --region " + os.Getenv("DOCKER_HOST") + " run -it busybox cat /etc/passwd | grep -q root")
checkRedirect(dockerBinary + " --region " + os.Getenv("DOCKER_HOST") + " run busybox cat /etc/passwd | grep -q root")
}
func (s *DockerSuite) TestCliRunAttachDetachBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
name := "attach-detach"
dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat")
cmd := exec.Command(dockerBinary, "--region", os.Getenv("DOCKER_HOST"), "attach", name)
stdout, err := cmd.StdoutPipe()
c.Assert(err, checker.IsNil)
cpty, tty, err := pty.Open()
c.Assert(err, checker.IsNil)
defer cpty.Close()
cmd.Stdin = tty
c.Assert(cmd.Start(), checker.IsNil)
c.Assert(waitRun(name), check.IsNil)
_, err = cpty.Write([]byte("hello\n"))
c.Assert(err, checker.IsNil)
out, err := bufio.NewReader(stdout).ReadString('\n')
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Equals, "hello")
// escape sequence
_, err = cpty.Write([]byte{16})
c.Assert(err, checker.IsNil)
time.Sleep(100 * time.Millisecond)
_, err = cpty.Write([]byte{17})
c.Assert(err, checker.IsNil)
ch := make(chan struct{})
go func() {
cmd.Wait()
ch <- struct{}{}
}()
select {
case <-ch:
case <-time.After(30 * time.Second):
c.Fatal("timed out waiting for container to exit")
}
running := inspectField(c, name, "State.Running")
c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
}
/*
// Hyper does not support shm yet
func (s *DockerSuite) TestCliRunWithDefaultShmSize(c *check.C) {
testRequires(c, DaemonIsLinux)
name := "shm-default"
out, _ := dockerCmd(c, "run", "--name", name, "busybox", "mount")
shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`)
if !shmRegex.MatchString(out) {
c.Fatalf("Expected shm of 64MB in mount command, got %v", out)
}
shmSize := inspectField(c, name, "HostConfig.ShmSize")
c.Assert(shmSize, check.Equals, "67108864")
}
*/

View File

@@ -0,0 +1,66 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// search for repos named "registry" on the central registry
func (s *DockerSuite) TestCliSearchOnCentralRegistry(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, Network, DaemonIsLinux)
out, _ := dockerCmd(c, "search", "busybox")
c.Assert(out, checker.Contains, "Busybox base image.", check.Commentf("couldn't find any repository named (or containing) 'Busybox base image.'"))
}
func (s *DockerSuite) TestCliSearchStarsOptionWithWrongParameterBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _, err := dockerCmdWithError("search", "--stars=a", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "invalid value", check.Commentf("couldn't find the invalid value warning"))
out, _, err = dockerCmdWithError("search", "-s=-1", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "invalid value", check.Commentf("couldn't find the invalid value warning"))
}
func (s *DockerSuite) TestCliSearchCmdOptions(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, Network)
out, _ := dockerCmd(c, "search", "--help")
c.Assert(out, checker.Contains, "Usage:\thyper search [OPTIONS] TERM")
outSearchCmd, _ := dockerCmd(c, "search", "busybox")
outSearchCmdNotrunc, _ := dockerCmd(c, "search", "--no-trunc=true", "busybox")
c.Assert(len(outSearchCmd) > len(outSearchCmdNotrunc), check.Equals, false, check.Commentf("The no-trunc option can't take effect."))
outSearchCmdautomated, _ := dockerCmd(c, "search", "--automated=true", "busybox") //The busybox is a busybox base image, not an AUTOMATED image.
outSearchCmdautomatedSlice := strings.Split(outSearchCmdautomated, "\n")
for i := range outSearchCmdautomatedSlice {
c.Assert(strings.HasPrefix(outSearchCmdautomatedSlice[i], "busybox "), check.Equals, false, check.Commentf("The busybox is not an AUTOMATED image: %s", out))
}
outSearchCmdStars, _ := dockerCmd(c, "search", "-s=2", "busybox")
c.Assert(strings.Count(outSearchCmdStars, "[OK]") > strings.Count(outSearchCmd, "[OK]"), check.Equals, false, check.Commentf("The quantity of images with stars should be less than that of all images: %s", outSearchCmdStars))
dockerCmd(c, "search", "--stars=2", "--automated=true", "--no-trunc=true", "busybox")
}
// search for repos which start with "ubuntu-" on the central registry
func (s *DockerSuite) TestCliSearchOnCentralRegistryWithDash(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, Network, DaemonIsLinux)
dockerCmd(c, "search", "ubuntu-")
}

View File

@@ -0,0 +1,98 @@
package main
import (
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliShareVolumeNamedVolumeBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("hyperhq/nfs-server")
pullImageIfNotExist("busybox")
volName := "testvolume"
_, err := dockerCmd(c, "run", "-d", "--name=volserver", "-v", volName+":/data", "hyperhq/nfs-server")
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "run", "-d", "--name=volclient", "--volumes-from", "volserver", "busybox")
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "exec", "volclient", "ls", "/data")
c.Assert(err, checker.Equals, 0)
}
func (s *DockerSuite) TestCliShareVolumeImplicitVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("hyperhq/nfs-server")
pullImageIfNotExist("busybox")
_, err := dockerCmd(c, "run", "-d", "--name=volserver", "-v", "/data", "hyperhq/nfs-server")
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "run", "-d", "--name=volclient", "--volumes-from", "volserver", "busybox")
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "exec", "volclient", "ls", "/data")
c.Assert(err, checker.Equals, 0)
}
func (s *DockerSuite) TestCliShareVolumePopulatedVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("hyperhq/nfs-server")
pullImageIfNotExist("busybox")
_, err := dockerCmd(c, "run", "-d", "--name=volserver", "-v", "https://github.com/hyperhq/hypercli.git:/data", "hyperhq/nfs-server")
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "run", "-d", "--name=volclient", "--volumes-from", "volserver", "busybox")
c.Assert(err, checker.Equals, 0)
out, err := dockerCmd(c, "exec", "volclient", "ls", "/data")
c.Assert(err, checker.Equals, 0)
c.Assert(out, checker.Contains, "Dockerfile")
}
func (s *DockerSuite) TestCliShareVolumeBadSource(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
_, err := dockerCmd(c, "run", "-d", "--name=volserver", "-v", "/data", "busybox")
c.Assert(err, checker.Equals, 0)
_, _, failErr := dockerCmdWithError("run", "-d", "--name=volclient", "--volumes-from", "volserver", "busybox")
c.Assert(failErr, checker.NotNil)
}
func (s *DockerSuite) TestCliShareVolumeNoSource(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("busybox")
_, _, err := dockerCmdWithError("run", "-d", "--name=volclient", "--volumes-from", "volserver", "busybox")
c.Assert(err, checker.NotNil)
}
func (s *DockerSuite) TestCliShareVolumeNoVolume(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
pullImageIfNotExist("hyperhq/nfs-server")
pullImageIfNotExist("busybox")
_, err := dockerCmd(c, "run", "-d", "--name=volserver", "hyperhq/nfs-server")
c.Assert(err, checker.Equals, 0)
_, err = dockerCmd(c, "run", "-d", "--name=volclient", "--volumes-from", "volserver", "busybox")
c.Assert(err, checker.Equals, 0)
_, _, failErr := dockerCmdWithError("exec", "volclient", "ls", "/data")
c.Assert(failErr, checker.NotNil)
}

View File

@@ -0,0 +1,230 @@
package main
import (
"os/exec"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliSnapshotCreate(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
out, _ = dockerCmd(c, "snapshot", "create", "--volume=test", "--name=test-snap")
name = strings.TrimSpace(out)
c.Assert(name, check.Equals, "test-snap")
out, _, err := dockerCmdWithError("snapshot", "create", "--volume=test", "--name=test-snap")
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "A snapshot named test-snap already exists. Choose a different snapshot name")
dockerCmd(c, "snapshot", "rm", "test-snap")
dockerCmd(c, "volume", "rm", "test")
}
func (s *DockerSuite) TestCliSnapshotInspect(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
c.Assert(
exec.Command(dockerBinary, "snapshot", "inspect", "doesntexist").Run(),
check.Not(check.IsNil),
check.Commentf("snapshot inspect should error on non-existent volume"),
)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
out, _ = dockerCmd(c, "snapshot", "create", "--volume=test")
name = strings.TrimSpace(out)
out, _ = dockerCmd(c, "snapshot", "inspect", "--format='{{ .Name }}'", name)
c.Assert(strings.TrimSpace(out), check.Equals, name)
dockerCmd(c, "snapshot", "create", "--volume=test", "--name=test-snap")
out, _ = dockerCmd(c, "snapshot", "inspect", "--format='{{ .Name }}'", "test-snap")
c.Assert(strings.TrimSpace(out), check.Equals, "test-snap")
dockerCmd(c, "snapshot", "rm", name)
dockerCmd(c, "snapshot", "rm", "test-snap")
dockerCmd(c, "volume", "rm", "test")
}
func (s *DockerSuite) TestCliSnapshotInspectMulti(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
dockerCmd(c, "snapshot", "create", "--volume=test", "--name=test-snap1")
dockerCmd(c, "snapshot", "create", "--volume=test", "--name=test-snap2")
dockerCmd(c, "snapshot", "create", "--volume=test", "--name=not-shown")
out, _, err := dockerCmdWithError("snapshot", "inspect", "--format='{{ .Name }}'", "test-snap1", "test-snap2", "doesntexist", "not-shown")
c.Assert(err, checker.NotNil)
outArr := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(len(outArr), check.Equals, 3, check.Commentf("\n%s", out))
c.Assert(out, checker.Contains, "test-snap1")
c.Assert(out, checker.Contains, "test-snap2")
c.Assert(out, checker.Contains, "Error: No such snapshot: doesntexist")
c.Assert(out, checker.Not(checker.Contains), "not-shown")
dockerCmd(c, "snapshot", "rm", "test-snap1")
dockerCmd(c, "snapshot", "rm", "test-snap2")
dockerCmd(c, "snapshot", "rm", "not-shown")
dockerCmd(c, "volume", "rm", "test")
}
func (s *DockerSuite) TestCliSnapshotLs(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
out, _ = dockerCmd(c, "snapshot", "create", "--volume=test")
id := strings.TrimSpace(out)
dockerCmd(c, "snapshot", "create", "--volume=test", "--name=test-snap")
out, _ = dockerCmd(c, "snapshot", "ls")
outArr := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(len(outArr), check.Equals, 3, check.Commentf("\n%s", out))
// Since there is no guarantee of ordering of volumes, we just make sure the names are in the output
c.Assert(strings.Contains(out, id), check.Equals, true)
c.Assert(strings.Contains(out, "test-snap"), check.Equals, true)
dockerCmd(c, "snapshot", "rm", "test-snap")
dockerCmd(c, "snapshot", "rm", id)
dockerCmd(c, "volume", "rm", "test")
}
func (s *DockerSuite) TestCliSnapshotRm(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
out, _ = dockerCmd(c, "snapshot", "create", "--volume=test")
id := strings.TrimSpace(out)
dockerCmd(c, "snapshot", "create", "--volume=test", "--name", "test-snap")
dockerCmd(c, "snapshot", "rm", id)
dockerCmd(c, "snapshot", "rm", "test-snap")
out, _ = dockerCmd(c, "snapshot", "ls")
outArr := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
c.Assert(
exec.Command("snapshot", "rm", "doesntexist").Run(),
check.Not(check.IsNil),
check.Commentf("snapshot rm should fail with non-existent snapshot"),
)
}
func (s *DockerSuite) TestCliSnapshotNoArgs(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "snapshot")
// no args should produce the cmd usage output
usage := "Usage: hyper snapshot [OPTIONS] [COMMAND]"
c.Assert(out, checker.Contains, usage)
// invalid arg should error and show the command on stderr
_, stderr, _, err := runCommandWithStdoutStderr(exec.Command(dockerBinary, "snapshot", "somearg"))
c.Assert(err, check.NotNil, check.Commentf(stderr))
c.Assert(stderr, checker.Contains, usage)
// invalid flag should error and show the flag error and cmd usage
_, stderr, _, err = runCommandWithStdoutStderr(exec.Command(dockerBinary, "snapshot", "--no-such-flag"))
c.Assert(err, check.NotNil, check.Commentf(stderr))
c.Assert(stderr, checker.Contains, usage)
c.Assert(stderr, checker.Contains, "flag provided but not defined: --no-such-flag")
}
func (s *DockerSuite) TestCliSnapshotInspectTmplError(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
out, _ = dockerCmd(c, "snapshot", "create", "--volume=test")
name = strings.TrimSpace(out)
out, exitCode, err := dockerCmdWithError("snapshot", "inspect", "--format='{{ .FooBar}}'", name)
c.Assert(err, checker.NotNil, check.Commentf("Output: %s", out))
c.Assert(exitCode, checker.Equals, 1, check.Commentf("Output: %s", out))
c.Assert(out, checker.Contains, "Template parsing error")
dockerCmd(c, "snapshot", "rm", name)
dockerCmd(c, "volume", "rm", "test")
}
func (s *DockerSuite) TestCliSnapshotCreateVolBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
dockerCmd(c, "snapshot", "create", "--volume=test", "--name", "test-snap")
dockerCmd(c, "volume", "create", "--name=snap-vol", "--snapshot=test-snap")
out, _ = dockerCmd(c, "volume", "ls")
c.Assert(strings.Contains(out, "snap-vol"), check.Equals, true)
// delete, in the order snapshot, volume, volume
out, _ = dockerCmd(c, "snapshot", "rm", "test-snap")
name = strings.TrimSpace(out)
c.Assert(name, check.Equals, "test-snap")
out, _ = dockerCmd(c, "volume", "rm", "test")
name = strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
out, _ = dockerCmd(c, "volume", "rm", "snap-vol")
name = strings.TrimSpace(out)
c.Assert(name, check.Equals, "snap-vol")
}
func (s *DockerSuite) TestCliSnapshotRmBasedVol(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
dockerCmd(c, "snapshot", "create", "--volume=test", "--name", "test-snap")
out, _, err := dockerCmdWithError("volume", "rm", "test")
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "Volume(test) has (1) snapshots")
dockerCmd(c, "snapshot", "rm", "test-snap")
_, _, err = dockerCmdWithError("volume", "rm", "test")
c.Assert(err, checker.IsNil)
}

View File

@@ -0,0 +1,107 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
/*
func (s *DockerSuite) TestCliStartRecordError(c *check.C) {
// TODO Windows CI: Requires further porting work. Should be possible.
testRequires(c, DaemonIsLinux)
// when container runs successfully, we should not have state.Error
dockerCmd(c, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
stateErr := inspectField(c, "test", "State.Error")
// Expected to not have state error
c.Assert(stateErr, checker.Equals, "")
// Expect this to fail and records error because of ports conflict
out, _, err := dockerCmdWithError("run", "-d", "--name", "test2", "-p", "9999:9999", "busybox", "top")
// err shouldn't be nil because docker run will fail
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
stateErr = inspectField(c, "test2", "State.Error")
c.Assert(stateErr, checker.Contains, "port is already allocated")
// Expect the conflict to be resolved when we stop the initial container
dockerCmd(c, "stop", "test")
dockerCmd(c, "start", "test2")
stateErr = inspectField(c, "test2", "State.Error")
// Expected to not have state error but got one
c.Assert(stateErr, checker.Equals, "")
}
*/
func (s *DockerSuite) TestCliStartMultipleContainersBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
// Windows does not support --link
testRequires(c, DaemonIsLinux)
// run a container named 'parent' and create two container link to `parent`
dockerCmd(c, "run", "-d", "--name", "parent", "busybox", "top")
for _, container := range []string{"child-first", "child-second"} {
dockerCmd(c, "create", "--name", container, "--link", "parent:parent", "busybox", "top")
}
// stop 'parent' container
dockerCmd(c, "stop", "parent")
out := inspectField(c, "parent", "State.Running")
// Container should be stopped
c.Assert(out, checker.Equals, "false")
// start all the three containers, container `child_first` start first which should be failed
// container 'parent' start second and then start container 'child_second'
expOut := "Cannot link to a non running container"
expErr := "failed to start containers: child-first"
out, _, err := dockerCmdWithError("start", "child-first", "parent", "child-second")
// err shouldn't be nil because start will fail
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
// output does not correspond to what was expected
if !(strings.Contains(out, expOut) || strings.Contains(err.Error(), expErr)) {
c.Fatalf("Expected out: %v with err: %v but got out: %v with err: %v", expOut, expErr, out, err)
}
for container, expected := range map[string]string{"parent": "true", "child-first": "false", "child-second": "true"} {
out := inspectField(c, container, "State.Running")
// Container running state wrong
c.Assert(out, checker.Equals, expected)
}
}
func (s *DockerSuite) TestCliStartAttachMultipleContainers(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
// run multiple containers to test
for _, container := range []string{"test1", "test2", "test3"} {
dockerCmd(c, "run", "-d", "--name", container, "busybox", "top")
}
// stop all the containers
for _, container := range []string{"test1", "test2", "test3"} {
dockerCmd(c, "stop", container)
}
// test start and attach multiple containers at once, expected error
for _, option := range []string{"-a", "-i", "-ai"} {
out, _, err := dockerCmdWithError("start", option, "test1", "test2", "test3")
// err shouldn't be nil because start will fail
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
// output does not correspond to what was expected
c.Assert(out, checker.Contains, "You cannot start and attach multiple containers at once.")
}
// confirm the state of all the containers be stopped
for container, expected := range map[string]string{"test1": "false", "test2": "false", "test3": "false"} {
out := inspectField(c, container, "State.Running")
// Container running state wrong
c.Assert(out, checker.Equals, expected)
}
}

View File

@@ -0,0 +1,67 @@
package main
import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// ensure docker version works
func (s *DockerSuite) TestCliVersionEnsureSucceedsBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _ := dockerCmd(c, "version")
stringsToCheck := map[string]int{
"Client:": 1,
"Server:": 1,
" Version:": 2,
" API version:": 2,
" Go version:": 2,
" Git commit:": 2,
" OS/Arch:": 2,
" Built:": 2,
}
for k, v := range stringsToCheck {
c.Assert(strings.Count(out, k), checker.Equals, v, check.Commentf("The count of %v in %s does not match excepted", k, out))
}
}
// ensure the Windows daemon return the correct platform string
func (s *DockerSuite) TestCliVersionPlatform_w(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsWindows)
testVersionPlatform(c, "windows/amd64")
}
// ensure the Linux daemon return the correct platform string
func (s *DockerSuite) TestCliVersionPlatform_l(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
testRequires(c, DaemonIsLinux)
testVersionPlatform(c, "linux")
}
func testVersionPlatform(c *check.C, platform string) {
out, _ := dockerCmd(c, "version")
expected := "OS/Arch: " + platform
split := strings.Split(out, "\n")
c.Assert(len(split) >= 14, checker.Equals, true, check.Commentf("got %d lines from version", len(split)))
// Verify the second 'OS/Arch' matches the platform. Experimental has
// more lines of output than 'regular'
bFound := false
for i := 14; i < len(split); i++ {
if strings.Contains(split[i], expected) {
bFound = true
break
}
}
c.Assert(bFound, checker.Equals, true, check.Commentf("Could not find server '%s' in '%s'", expected, out))
}

View File

@@ -0,0 +1,215 @@
package main
import (
"os/exec"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliVolumeCreate(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
dockerCmd(c, "volume", "create")
_, err := runCommand(exec.Command(dockerBinary, "volume", "create", "-d", "nosuchdriver"))
c.Assert(err, check.Not(check.IsNil))
out, _ := dockerCmd(c, "volume", "create", "--name=test")
name := strings.TrimSpace(out)
c.Assert(name, check.Equals, "test")
}
func (s *DockerSuite) TestCliVolumeInspect(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
c.Assert(
exec.Command(dockerBinary, "volume", "inspect", "doesntexist").Run(),
check.Not(check.IsNil),
check.Commentf("volume inspect should error on non-existent volume"),
)
out, _ := dockerCmd(c, "volume", "create")
name := strings.TrimSpace(out)
out, _ = dockerCmd(c, "volume", "inspect", "--format='{{ .Name }}'", name)
c.Assert(strings.TrimSpace(out), check.Equals, name)
dockerCmd(c, "volume", "create", "--name", "test")
out, _ = dockerCmd(c, "volume", "inspect", "--format='{{ .Name }}'", "test")
c.Assert(strings.TrimSpace(out), check.Equals, "test")
}
func (s *DockerSuite) TestCliVolumeInspectMulti(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
dockerCmd(c, "volume", "create", "--name", "test1")
dockerCmd(c, "volume", "create", "--name", "test2")
dockerCmd(c, "volume", "create", "--name", "not-shown")
out, _, err := dockerCmdWithError("volume", "inspect", "--format='{{ .Name }}'", "test1", "test2", "doesntexist", "not-shown")
c.Assert(err, checker.NotNil)
outArr := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(len(outArr), check.Equals, 3, check.Commentf("\n%s", out))
c.Assert(out, checker.Contains, "test1")
c.Assert(out, checker.Contains, "test2")
c.Assert(out, checker.Contains, "Error: No such volume: doesntexist")
c.Assert(out, checker.Not(checker.Contains), "not-shown")
}
func (s *DockerSuite) TestCliVolumeLs(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
out, _ := dockerCmd(c, "volume", "create")
id := strings.TrimSpace(out)
dockerCmd(c, "volume", "create", "--name", "test")
dockerCmd(c, "run", "-v", prefix+"/foo", "busybox", "ls", "/")
out, _ = dockerCmd(c, "volume", "ls")
outArr := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
// Since there is no guarantee of ordering of volumes, we just make sure the names are in the output
c.Assert(strings.Contains(out, id), check.Equals, true)
c.Assert(strings.Contains(out, "test"), check.Equals, true)
}
func (s *DockerSuite) TestCliVolumeLsFilterDanglingBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
dockerCmd(c, "volume", "create", "--name", "testnotinuse1")
dockerCmd(c, "volume", "create", "--name", "testisinuse1")
dockerCmd(c, "volume", "create", "--name", "testisinuse2")
// Make sure both "created" (but not started), and started
// containers are included in reference counting
dockerCmd(c, "run", "--name", "volume-test1", "-v", "testisinuse1:"+prefix+"/foo", "busybox", "true")
dockerCmd(c, "create", "--name", "volume-test2", "-v", "testisinuse2:"+prefix+"/foo", "busybox", "true")
out, _ := dockerCmd(c, "volume", "ls")
// No filter, all volumes should show
c.Assert(out, checker.Contains, "testnotinuse1", check.Commentf("expected volume 'testnotinuse1' in output"))
c.Assert(out, checker.Contains, "testisinuse1", check.Commentf("expected volume 'testisinuse1' in output"))
c.Assert(out, checker.Contains, "testisinuse2", check.Commentf("expected volume 'testisinuse2' in output"))
out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=false")
// Explicitly disabling dangling
c.Assert(out, checker.Contains, "testnotinuse1", check.Commentf("expected volume 'testnotinuse1' in output"))
c.Assert(out, checker.Contains, "testisinuse1", check.Commentf("expected volume 'testisinuse1' in output"))
c.Assert(out, checker.Contains, "testisinuse2", check.Commentf("expected volume 'testisinuse2' in output"))
out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=true")
// Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output
c.Assert(out, checker.Contains, "testnotinuse1", check.Commentf("expected volume 'testnotinuse1' in output"))
c.Assert(out, check.Not(checker.Contains), "testisinuse1", check.Commentf("volume 'testisinuse1' in output, but not expected"))
c.Assert(out, check.Not(checker.Contains), "testisinuse2", check.Commentf("volume 'testisinuse2' in output, but not expected"))
out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=1")
// Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output, dangling also accept 1
c.Assert(out, checker.Contains, "testnotinuse1", check.Commentf("expected volume 'testnotinuse1' in output"))
c.Assert(out, check.Not(checker.Contains), "testisinuse1", check.Commentf("volume 'testisinuse1' in output, but not expected"))
c.Assert(out, check.Not(checker.Contains), "testisinuse2", check.Commentf("volume 'testisinuse2' in output, but not expected"))
out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=0")
// dangling=0 is same as dangling=false case
c.Assert(out, checker.Contains, "testnotinuse1", check.Commentf("expected volume 'testnotinuse1' in output"))
c.Assert(out, checker.Contains, "testisinuse1", check.Commentf("expected volume 'testisinuse1' in output"))
c.Assert(out, checker.Contains, "testisinuse2", check.Commentf("expected volume 'testisinuse2' in output"))
}
func (s *DockerSuite) TestCliVolumeRmBasic(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
pullImageIfNotExist("busybox")
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
out, _ := dockerCmd(c, "volume", "create")
id := strings.TrimSpace(out)
dockerCmd(c, "volume", "create", "--name", "test")
dockerCmd(c, "volume", "rm", id)
dockerCmd(c, "volume", "rm", "test")
out, _ = dockerCmd(c, "volume", "ls")
outArr := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
volumeID := "testing"
dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar")
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "volume", "rm", "testing"))
c.Assert(
err,
check.Not(check.IsNil),
check.Commentf("Should not be able to remove volume that is in use by a container\n%s", out))
dockerCmd(c, "volume", "inspect", volumeID)
dockerCmd(c, "rm", "-f", "test")
out, _ = dockerCmd(c, "run", "--name=test2", "-v", volumeID+":"+prefix+"/foo", "busybox", "sh", "-c", "cat /foo/bar")
c.Assert(strings.TrimSpace(out), check.Equals, "hello", check.Commentf("volume data was removed"))
dockerCmd(c, "rm", "test2")
dockerCmd(c, "volume", "rm", volumeID)
c.Assert(
exec.Command("volume", "rm", "doesntexist").Run(),
check.Not(check.IsNil),
check.Commentf("volume rm should fail with non-existent volume"),
)
}
func (s *DockerSuite) TestCliVolumeLsWithIncorrectFilterValue(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _, err := dockerCmdWithError("volume", "ls", "-f", "dangling=invalid")
c.Assert(err, check.NotNil)
c.Assert(out, checker.Contains, "Invalid filter")
}
func (s *DockerSuite) TestCliVolumeNoArgs(c *check.C) {
printTestCaseName()
defer printTestDuration(time.Now())
out, _ := dockerCmd(c, "volume")
// no args should produce the cmd usage output
usage := "Usage: hyper volume [OPTIONS] [COMMAND]"
c.Assert(out, checker.Contains, usage)
// invalid arg should error and show the command usage on stderr
_, stderr, _, err := runCommandWithStdoutStderr(exec.Command(dockerBinary, "volume", "somearg"))
c.Assert(err, check.NotNil, check.Commentf(stderr))
c.Assert(stderr, checker.Contains, usage)
// invalid flag should error and show the flag error and cmd usage
_, stderr, _, err = runCommandWithStdoutStderr(exec.Command(dockerBinary, "volume", "--no-such-flag"))
c.Assert(err, check.NotNil, check.Commentf(stderr))
c.Assert(stderr, checker.Contains, usage)
c.Assert(stderr, checker.Contains, "flag provided but not defined: --no-such-flag")
}
func (s *DockerSuite) TestCliVolumeInspectTmplError(c *check.C) {
out, _ := dockerCmd(c, "volume", "create")
name := strings.TrimSpace(out)
out, exitCode, err := dockerCmdWithError("volume", "inspect", "--format='{{ .FooBar }}'", name)
c.Assert(err, checker.NotNil, check.Commentf("Output: %s", out))
c.Assert(exitCode, checker.Equals, 1, check.Commentf("Output: %s", out))
c.Assert(out, checker.Contains, "Template parsing error")
}

View File

View File

@@ -0,0 +1,158 @@
package main
import (
"bufio"
"fmt"
"io"
"os/exec"
"strings"
"sync"
"time"
//"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
const attachWait = 5 * time.Second
//FIXME: attach initialize unproperly? and return empty string?
func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
testRequires(c, DaemonIsLinux)
endGroup := &sync.WaitGroup{}
startGroup := &sync.WaitGroup{}
endGroup.Add(3)
startGroup.Add(3)
err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done")
c.Assert(err, check.IsNil)
startDone := make(chan struct{})
endDone := make(chan struct{})
go func() {
endGroup.Wait()
close(endDone)
}()
go func() {
startGroup.Wait()
close(startDone)
}()
for i := 0; i < 3; i++ {
go func() {
cmd := exec.Command(dockerBinary, "attach", "attacher")
defer func() {
cmd.Wait()
endGroup.Done()
}()
out, err := cmd.StdoutPipe()
if err != nil {
c.Fatal(err)
}
if err := cmd.Start(); err != nil {
c.Fatal(err)
}
time.Sleep(5 * time.Second)
buf := make([]byte, 1024)
if _, err := out.Read(buf); err != nil && err != io.EOF {
c.Fatal(err)
}
startGroup.Done()
if !strings.Contains(string(buf), "hello") {
c.Fatalf("unexpected output %s expected hello\n", string(buf))
}
}()
}
select {
case <-startDone:
case <-time.After(attachWait):
c.Fatalf("Attaches did not initialize properly")
}
dockerCmd(c, "kill", "attacher")
select {
case <-endDone:
case <-time.After(attachWait):
c.Fatalf("Attaches did not finish properly")
}
}
//FIXME: attach should failed ?
func (s *DockerSuite) TestAttachTTYWithoutStdin(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
done := make(chan error)
go func() {
defer close(done)
cmd := exec.Command(dockerBinary, "attach", id)
if _, err := cmd.StdinPipe(); err != nil {
done <- err
return
}
expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil {
done <- fmt.Errorf("attach should have failed")
return
} else if !strings.Contains(out, expected) {
done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected)
return
}
}()
select {
case err := <-done:
c.Assert(err, check.IsNil)
case <-time.After(attachWait):
c.Fatal("attach is running but should have failed")
}
}
//FIXME:#issue77
func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "-i", "busybox", "/bin/cat")
id := strings.TrimSpace(out)
cmd := exec.Command(dockerBinary, "attach", id)
stdin, err := cmd.StdinPipe()
if err != nil {
c.Fatal(err)
}
defer stdin.Close()
stdout, err := cmd.StdoutPipe()
c.Assert(err, check.IsNil)
defer stdout.Close()
c.Assert(cmd.Start(), check.IsNil)
defer cmd.Process.Kill()
_, err = stdin.Write([]byte("hello\n"))
c.Assert(err, check.IsNil)
out, err = bufio.NewReader(stdout).ReadString('\n')
c.Assert(err, check.IsNil)
c.Assert(strings.TrimSpace(out), check.Equals, "hello")
c.Assert(stdin.Close(), check.IsNil)
// Expect container to still be running after stdin is closed
running := inspectField(c, id, "State.Running")
c.Assert(running, check.Equals, "true")
}

View File

@@ -0,0 +1,197 @@
// +build !windows
package main
import (
//"bufio"
"os/exec"
//"strings"
"time"
//"fmt"
"github.com/docker/docker/pkg/integration/checker"
//"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
"github.com/kr/pty"
)
//FIXME:L36 waitRun error? but its ok by hand
func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
name := "detachtest"
cpty, tty, err := pty.Open()
c.Assert(err, checker.IsNil, check.Commentf("Could not open pty: %v", err))
cmd := exec.Command(dockerBinary, "run", "-ti", "--name", name, "busybox")
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
errChan := make(chan error)
go func() {
errChan <- cmd.Run()
close(errChan)
}()
c.Assert(waitRun(name), check.IsNil)
cpty.Write([]byte{16})
time.Sleep(100 * time.Millisecond)
cpty.Write([]byte{17})
select {
case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(5 * time.Second):
c.Fatal("timeout while detaching")
}
cpty, tty, err = pty.Open()
c.Assert(err, checker.IsNil, check.Commentf("Could not open pty: %v", err))
cmd = exec.Command(dockerBinary, "attach", name)
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
err = cmd.Start()
c.Assert(err, checker.IsNil)
bytes := make([]byte, 10)
var nBytes int
readErr := make(chan error, 1)
go func() {
time.Sleep(500 * time.Millisecond)
cpty.Write([]byte("\n"))
time.Sleep(500 * time.Millisecond)
nBytes, err = cpty.Read(bytes)
cpty.Close()
readErr <- err
}()
select {
case err := <-readErr:
c.Assert(err, check.IsNil)
case <-time.After(2 * time.Second):
c.Fatal("timeout waiting for attach read")
}
err = cmd.Wait()
c.Assert(err, checker.IsNil)
c.Assert(string(bytes[:nBytes]), checker.Contains, "/ #")
}
/*
//FIXME:#issue77
// TestAttachDetach checks that attach in tty mode can be detached using the long container ID
func (s *DockerSuite) TestAttachDetach(c *check.C) {
out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
cpty, tty, err := pty.Open()
c.Assert(err, check.IsNil)
defer cpty.Close()
cmd := exec.Command(dockerBinary, "attach", id)
cmd.Stdin = tty
stdout, err := cmd.StdoutPipe()
c.Assert(err, check.IsNil)
defer stdout.Close()
err = cmd.Start()
c.Assert(err, check.IsNil)
c.Assert(waitRun(id), check.IsNil)
_, err = cpty.Write([]byte("hello\n"))
c.Assert(err, check.IsNil)
out, err = bufio.NewReader(stdout).ReadString('\n')
c.Assert(err, check.IsNil)
c.Assert(strings.TrimSpace(out), checker.Equals, "hello", check.Commentf("expected 'hello', got %q", out))
// escape sequence
_, err = cpty.Write([]byte{16})
c.Assert(err, checker.IsNil)
time.Sleep(100 * time.Millisecond)
_, err = cpty.Write([]byte{17})
c.Assert(err, checker.IsNil)
ch := make(chan struct{})
go func() {
cmd.Wait()
ch <- struct{}{}
}()
running := inspectField(c, id, "State.Running")
c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
go func() {
dockerCmd(c, "kill", id)
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
c.Fatal("timed out waiting for container to exit")
}
}
//FIXME:#issue77
// TestAttachDetachTruncatedID checks that attach in tty mode can be detached
func (s *DockerSuite) TestAttachDetachTruncatedID(c *check.C) {
out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat")
id := stringid.TruncateID(strings.TrimSpace(out))
c.Assert(waitRun(id), check.IsNil)
cpty, tty, err := pty.Open()
c.Assert(err, checker.IsNil)
defer cpty.Close()
cmd := exec.Command(dockerBinary, "attach", id)
cmd.Stdin = tty
stdout, err := cmd.StdoutPipe()
c.Assert(err, checker.IsNil)
defer stdout.Close()
err = cmd.Start()
c.Assert(err, checker.IsNil)
time.Sleep(10 * time.Second)
_, err = cpty.Write([]byte("hello\n"))
c.Assert(err, checker.IsNil)
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
fmt.Println(err)
}
c.Assert(strings.TrimSpace(out), checker.Equals, "hello", check.Commentf("expected 'hello', got %q", out))
// escape sequence
_, err = cpty.Write([]byte{16})
c.Assert(err, checker.IsNil)
time.Sleep(100 * time.Millisecond)
_, err = cpty.Write([]byte{17})
c.Assert(err, checker.IsNil)
ch := make(chan struct{})
go func() {
cmd.Wait()
ch <- struct{}{}
}()
running := inspectField(c, id, "State.Running")
c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
go func() {
dockerCmd(c, "kill", id)
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
c.Fatal("timed out waiting for container to exit")
}
}
*/

View File

@@ -0,0 +1,112 @@
package main
import (
"bufio"
"io"
"net"
"net/http"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
// regression gh14320
func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) {
status, body, err := sockRequest("POST", "/containers/doesnotexist/attach", nil)
c.Assert(status, checker.Equals, http.StatusNotFound)
c.Assert(err, checker.IsNil)
expected := "No such container: doesnotexist\n"
c.Assert(string(body), checker.Contains, expected)
}
func (s *DockerSuite) TestGetContainersWsAttachContainerNotFound(c *check.C) {
status, body, err := sockRequest("GET", "/containers/doesnotexist/attach/ws", nil)
c.Assert(status, checker.Equals, http.StatusNotFound)
c.Assert(err, checker.IsNil)
expected := "No such container: doesnotexist"
c.Assert(string(body), checker.Contains, expected)
}
func (s *DockerSuite) TestPostContainersAttach(c *check.C) {
testRequires(c, DaemonIsLinux)
expectSuccess := func(conn net.Conn, br *bufio.Reader, stream string, tty bool) {
defer conn.Close()
expected := []byte("success")
_, err := conn.Write(expected)
c.Assert(err, checker.IsNil)
conn.SetReadDeadline(time.Now().Add(time.Second))
lenHeader := 0
if !tty {
lenHeader = 8
}
actual := make([]byte, len(expected)+lenHeader)
_, err = io.ReadFull(br, actual)
c.Assert(err, checker.IsNil)
if !tty {
fdMap := map[string]byte{
"stdin": 0,
"stdout": 1,
"stderr": 2,
}
c.Assert(actual[0], checker.Equals, fdMap[stream])
}
c.Assert(actual[lenHeader:], checker.DeepEquals, expected, check.Commentf("Attach didn't return the expected data from %s", stream))
}
expectTimeout := func(conn net.Conn, br *bufio.Reader, stream string) {
defer conn.Close()
_, err := conn.Write([]byte{'t'})
c.Assert(err, checker.IsNil)
conn.SetReadDeadline(time.Now().Add(time.Second))
actual := make([]byte, 1)
_, err = io.ReadFull(br, actual)
opErr, ok := err.(*net.OpError)
c.Assert(ok, checker.Equals, true, check.Commentf("Error is expected to be *net.OpError, got %v", err))
c.Assert(opErr.Timeout(), checker.Equals, true, check.Commentf("Read from %s is expected to timeout", stream))
}
// Create a container that only emits stdout.
cid, _ := dockerCmd(c, "run", "-di", "busybox", "cat")
cid = strings.TrimSpace(cid)
// Attach to the container's stdout stream.
conn, br, err := sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain")
c.Assert(err, checker.IsNil)
// Check if the data from stdout can be received.
expectSuccess(conn, br, "stdout", false)
// Attach to the container's stderr stream.
conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain")
c.Assert(err, checker.IsNil)
// Since the container only emits stdout, attaching to stderr should return nothing.
expectTimeout(conn, br, "stdout")
// Test the similar functions of the stderr stream.
cid, _ = dockerCmd(c, "run", "-di", "busybox", "/bin/sh", "-c", "cat >&2")
cid = strings.TrimSpace(cid)
conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain")
c.Assert(err, checker.IsNil)
expectSuccess(conn, br, "stderr", false)
conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain")
c.Assert(err, checker.IsNil)
expectTimeout(conn, br, "stderr")
// Test with tty.
cid, _ = dockerCmd(c, "run", "-dit", "busybox", "/bin/sh", "-c", "cat >&2")
cid = strings.TrimSpace(cid)
// Attach to stdout only.
conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain")
c.Assert(err, checker.IsNil)
expectSuccess(conn, br, "stdout", true)
// Attach without stdout stream.
conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain")
c.Assert(err, checker.IsNil)
// Nothing should be received because both the stdout and stderr of the container will be
// sent to the client as stdout when tty is enabled.
expectTimeout(conn, br, "stdout")
}

View File

@@ -0,0 +1,843 @@
package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
"os"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestContainerApiGetAll(c *check.C) {
startCount, err := getContainerCount()
c.Assert(err, checker.IsNil, check.Commentf("Cannot query container count"))
name := "getall"
dockerCmd(c, "run", "--name", name, "busybox", "true")
status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var inspectJSON []struct {
Names []string
}
err = json.Unmarshal(body, &inspectJSON)
c.Assert(err, checker.IsNil, check.Commentf("unable to unmarshal response body"))
c.Assert(inspectJSON, checker.HasLen, startCount+1)
actual := inspectJSON[0].Names[0]
c.Assert(actual, checker.Equals, "/"+name)
}
// regression test for empty json field being omitted #13691
func (s *DockerSuite) TestContainerApiGetJSONNoFieldsOmitted(c *check.C) {
dockerCmd(c, "run", "busybox", "true")
status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
// 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",
"NetworkSettings",
}
// 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)
}
}
}
type containerPs struct {
Names []string
Ports []map[string]interface{}
}
// regression test for non-empty fields from #13901
func (s *DockerSuite) TestContainerApiPsOmitFields(c *check.C) {
// Problematic for Windows porting due to networking not yet being passed back
testRequires(c, DaemonIsLinux)
name := "pstest"
port := 80
_, code := dockerCmd(c, "pull", singlePortImage)
c.Assert(code, check.Equals, 0)
runSleepingContainerInImage(c, singlePortImage, "--name", name)
debugEndpoint = "/containers/json?all=1"
status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var resp []containerPs
err = json.Unmarshal(body, &resp)
c.Assert(err, checker.IsNil)
var foundContainer *containerPs
for _, container := range resp {
for _, testName := range container.Names {
if "/"+name == testName {
foundContainer = &container
break
}
}
}
c.Assert(foundContainer.Ports, checker.HasLen, 1)
c.Assert(foundContainer.Ports[0]["PrivatePort"], checker.Equals, float64(port))
_, ok := foundContainer.Ports[0]["PublicPort"]
c.Assert(ok, checker.Equals, true)
_, ok = foundContainer.Ports[0]["IP"]
c.Assert(ok, checker.Equals, true)
}
func (s *DockerSuite) TestContainerApiStartVolumeBinds(c *check.C) {
// TODO Windows CI: Investigate further why this fails on Windows to Windows CI.
testRequires(c, DaemonIsLinux)
path := "/foo"
if daemonPlatform == "windows" {
path = `c:\foo`
}
name := "testing"
config := map[string]interface{}{
"Image": "busybox",
"Volumes": map[string]struct{}{path: {}},
}
status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
bindPath := randomTmpDirPath("test", daemonPlatform)
config = map[string]interface{}{
"Binds": []string{bindPath + ":" + path},
}
status, _, err = sockRequest("POST", "/containers/"+name+"/start", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent)
pth, err := inspectMountSourceField(name, path)
c.Assert(err, checker.IsNil)
c.Assert(pth, checker.Equals, bindPath, check.Commentf("expected volume host path to be %s, got %s", bindPath, pth))
}
/*
//FIXME panic
func (s *DockerSuite) TestGetContainerStats(c *check.C) {
// Problematic on Windows as Windows does not support stats
testRequires(c, DaemonIsLinux)
var (
name = "statscontainer"
)
dockerCmd(c, "run", "-d", "--name", name, "busybox", "top")
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(15 * time.Second)
dockerCmd(c, "rm", "-f", name)
// collect the results from the stats stream or timeout and fail
// if the stream was not disconnected.
select {
case <-time.After(20 * time.Second):
c.Fatal("stream was not closed after container was removed")
case sr := <-bc:
c.Assert(sr.err, checker.IsNil)
c.Assert(sr.status, checker.Equals, http.StatusOK)
dec := json.NewDecoder(bytes.NewBuffer(sr.body))
var s *types.Stats
// decode only one object from the stream
c.Assert(dec.Decode(&s), checker.IsNil)
}
}
func (s *DockerSuite) TestGetContainerStatsRmRunning(c *check.C) {
// Problematic on Windows as Windows does not support stats
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
id := strings.TrimSpace(out)
buf := &integration.ChannelBuffer{make(chan []byte, 1)}
defer buf.Close()
chErr := make(chan error, 1)
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() {
select {
case err := <-chErr:
c.Assert(err, checker.IsNil)
default:
return
}
}()
b := make([]byte, 32)
// make sure we've got some stats
_, err := buf.ReadTimeout(b, 2*time.Second)
c.Assert(err, checker.IsNil)
// Now remove without `-f` and make sure we are still pulling stats
_, _, err = dockerCmdWithError("rm", id)
c.Assert(err, checker.Not(checker.IsNil), check.Commentf("rm should have failed but didn't"))
_, err = buf.ReadTimeout(b, 2*time.Second)
c.Assert(err, checker.IsNil)
dockerCmd(c, "kill", id)
}
// 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) {
// Problematic on Windows as Windows does not support stats
testRequires(c, DaemonIsLinux)
name := "statscontainer"
dockerCmd(c, "run", "-d", "--name", name, "busybox", "top")
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)
dockerCmd(c, "rm", "-f", name)
// 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:
c.Assert(sr.err, checker.IsNil)
c.Assert(sr.status, checker.Equals, http.StatusOK)
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) {
// Problematic on Windows as Windows does not support stats
testRequires(c, DaemonIsLinux)
name := "statscontainer"
dockerCmd(c, "run", "-d", "--name", name, "busybox", "top")
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)
dockerCmd(c, "rm", "-f", name)
// 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:
c.Assert(sr.err, checker.IsNil)
c.Assert(sr.status, checker.Equals, http.StatusOK)
s := string(sr.body)
// count occurrences of "read" of types.Stats
c.Assert(strings.Count(s, "read"), checker.Equals, 1, check.Commentf("Expected only one stat streamed, got %d", strings.Count(s, "read")))
}
}
*/
func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) {
// Problematic on Windows as Windows does not support stats
testRequires(c, DaemonIsLinux)
// TODO: this test does nothing because we are c.Assert'ing in goroutine
var (
name = "statscontainer"
)
dockerCmd(c, "create", "--name", name, "busybox", "top")
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.
status, _, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
}()
// allow some time to send request and let daemon deal with it
time.Sleep(1 * time.Second)
}
// #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
func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) {
// TODO Windows to Windows CI - Port this
testRequires(c, DaemonIsLinux)
dockerCmd(c, "create", "-v", "/foo", "--name=one", "busybox")
fooDir, err := inspectMountSourceField("one", "/foo")
c.Assert(err, checker.IsNil)
dockerCmd(c, "create", "-v", "/foo", "--name=two", "busybox")
bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}}
status, _, err := sockRequest("POST", "/containers/two/start", bindSpec)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent)
fooDir2, err := inspectMountSourceField("two", "/foo")
c.Assert(err, checker.IsNil)
c.Assert(fooDir2, checker.Equals, fooDir, check.Commentf("expected volume path to be %s, got: %s", fooDir, fooDir2))
}
func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
"Cmd": []string{"/bin/sh", "-c", "touch /test && ls /test"},
}
status, b, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
type createResp struct {
ID string
}
var container createResp
c.Assert(json.Unmarshal(b, &container), checker.IsNil)
out, _ := dockerCmd(c, "start", "-a", container.ID)
c.Assert(strings.TrimSpace(out), checker.Equals, "/test")
}
func (s *DockerSuite) TestContainerApiCreateEmptyConfig(c *check.C) {
config := map[string]interface{}{}
status, b, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusInternalServerError)
expected := "Config cannot be empty in order to create a container\n"
c.Assert(string(b), checker.Equals, expected)
}
func (s *DockerSuite) TestContainerApiCreateWithHostName(c *check.C) {
// TODO Windows: Port this test once hostname is supported
testRequires(c, DaemonIsLinux)
hostName := "test-host"
config := map[string]interface{}{
"Image": "busybox",
"Hostname": hostName,
}
status, body, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
var container types.ContainerCreateResponse
c.Assert(json.Unmarshal(body, &container), checker.IsNil)
status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var containerJSON types.ContainerJSON
c.Assert(json.Unmarshal(body, &containerJSON), checker.IsNil)
c.Assert(containerJSON.Config.Hostname, checker.Equals, hostName, check.Commentf("Mismatched Hostname"))
}
func (s *DockerSuite) TestContainerApiCreateWithDomainName(c *check.C) {
// TODO Windows: Port this test once domain name is supported
testRequires(c, DaemonIsLinux)
domainName := "test-domain"
config := map[string]interface{}{
"Image": "busybox",
"Domainname": domainName,
}
status, body, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
var container types.ContainerCreateResponse
c.Assert(json.Unmarshal(body, &container), checker.IsNil)
status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
var containerJSON types.ContainerJSON
c.Assert(json.Unmarshal(body, &containerJSON), checker.IsNil)
c.Assert(containerJSON.Config.Domainname, checker.Equals, domainName, check.Commentf("Mismatched Domainname"))
}
func (s *DockerSuite) TestContainerApiVerifyHeader(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
}
create := func(ct string) (*http.Response, io.ReadCloser, error) {
jsonData := bytes.NewBuffer(nil)
c.Assert(json.NewEncoder(jsonData).Encode(config), checker.IsNil)
return sockRequestRaw("POST", "/containers/create", jsonData, ct)
}
// Try with no content-type
res, body, err := create("")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusCreated)
body.Close()
// Try with wrong content-type
res, body, err = create("application/xml")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
body.Close()
// now application/json
res, body, err = create("application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusCreated)
body.Close()
}
// 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"
func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) {
// TODO Windows to Windows CI. Bit of this with alternate fields checked
// can probably be ported.
testRequires(c, DaemonIsLinux)
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}`
res, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusCreated)
b, err := readBody(body)
c.Assert(err, checker.IsNil)
type createResp struct {
ID string
}
var container createResp
c.Assert(json.Unmarshal(b, &container), checker.IsNil)
out := inspectField(c, container.ID, "HostConfig.CpusetCpus")
c.Assert(out, checker.Equals, "")
outMemory := inspectField(c, container.ID, "HostConfig.Memory")
c.Assert(outMemory, checker.Equals, "0")
outMemorySwap := inspectField(c, container.ID, "HostConfig.MemorySwap")
c.Assert(outMemorySwap, checker.Equals, "0")
}
func (s *DockerSuite) TestContainerApiRename(c *check.C) {
// TODO Windows: Enable for TP5. Fails on TP4.
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "--name", "testcontainerapirename", "-d", "busybox", "sh")
containerID := strings.TrimSpace(out)
newName := "testcontainerapirenamenew"
statusCode, _, err := sockRequest("POST", "/containers/"+containerID+"/rename?name="+newName, nil)
c.Assert(err, checker.IsNil)
// 204 No Content is expected, not 200
c.Assert(statusCode, checker.Equals, http.StatusNoContent)
name := inspectField(c, containerID, "Name")
c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container"))
}
func (s *DockerSuite) TestContainerApiKill(c *check.C) {
name := "test-api-kill"
runSleepingContainer(c, "-i", "--name", name)
status, _, err := sockRequest("POST", "/containers/"+name+"/kill", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent)
state := inspectField(c, name, "State.Running")
c.Assert(state, checker.Equals, "false", check.Commentf("got wrong State from container %s: %q", name, state))
}
func (s *DockerSuite) TestContainerApiRestart(c *check.C) {
// TODO Windows to Windows CI. This is flaky due to the timing
testRequires(c, DaemonIsLinux)
name := "test-api-restart"
dockerCmd(c, "run", "-di", "--name", name, "busybox", "top")
status, _, err := sockRequest("POST", "/containers/"+name+"/restart?t=1", nil)
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)
}
func (s *DockerSuite) TestContainerApiRestartNotimeoutParam(c *check.C) {
// TODO Windows to Windows CI. This is flaky due to the timing
testRequires(c, DaemonIsLinux)
name := "test-api-restart-no-timeout-param"
out, _ := dockerCmd(c, "run", "-di", "--name", name, "busybox", "top")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
status, _, err := sockRequest("POST", "/containers/"+name+"/restart", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent)
c.Assert(waitInspect(name, "{{ .State.Restarting }} {{ .State.Running }}", "false true", 50*time.Second), checker.IsNil)
}
func (s *DockerSuite) TestContainerApiStart(c *check.C) {
name := "testing-start"
config := map[string]interface{}{
"Image": "busybox",
"Cmd": append([]string{"/bin/sh", "-c"}, defaultSleepCommand...),
"OpenStdin": true,
}
status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
conf := make(map[string]interface{})
status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent)
// second call to start should give 304
status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNotModified)
}
func (s *DockerSuite) TestContainerApiStop(c *check.C) {
name := "test-api-stop"
runSleepingContainer(c, "-i", "--name", name)
status, _, err := sockRequest("POST", "/containers/"+name+"/stop?t=30", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNoContent)
c.Assert(waitInspect(name, "{{ .State.Running }}", "false", 60*time.Second), checker.IsNil)
// second call to start should give 304
status, _, err = sockRequest("POST", "/containers/"+name+"/stop?t=30", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNotModified)
}
func (s *DockerSuite) TestContainerApiDeleteForce(c *check.C) {
out, _ := runSleepingContainer(c)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
status, _, err := sockRequest("DELETE", "/containers/"+id+"?force=1", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
}
func (s *DockerSuite) TestContainerApiDeleteRemoveLinks(c *check.C) {
// Windows does not support links
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "--name", "tlink1", "busybox", "top")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
time.Sleep(5 * time.Second)
out, _ = dockerCmd(c, "run", "--link", "tlink1:tlink1", "--name", "tlink2", "-d", "busybox", "top")
id2 := strings.TrimSpace(out)
c.Assert(waitRun(id2), checker.IsNil)
links := inspectFieldJSON(c, id2, "HostConfig.Links")
c.Assert(links, checker.Equals, "[\"/tlink1:/tlink2/tlink1\"]", check.Commentf("expected to have links between containers"))
status, b, err := sockRequest("DELETE", "/containers/tlink2/tlink1?link=1", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNoContent, check.Commentf(string(b)))
linksPostRm := inspectFieldJSON(c, id2, "HostConfig.Links")
c.Assert(linksPostRm, checker.Equals, "null", check.Commentf("call to api deleteContainer links should have removed the specified links"))
}
func (s *DockerSuite) TestContainerApiDeleteConflict(c *check.C) {
out, _ := runSleepingContainer(c)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
status, _, err := sockRequest("DELETE", "/containers/"+id, nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusConflict)
}
func (s *DockerSuite) TestContainerApiDeleteRemoveVolume(c *check.C) {
testRequires(c, SameHostDaemon)
vol := "/testvolume"
if daemonPlatform == "windows" {
vol = `c:\testvolume`
}
out, _ := runSleepingContainer(c, "-v", vol)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
source, err := inspectMountSourceField(id, vol)
_, err = os.Stat(source)
c.Assert(err, checker.IsNil)
status, _, err := sockRequest("DELETE", "/containers/"+id+"?v=1&force=1", nil)
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))
}
func (s *DockerSuite) TestContainerApiPostContainerStop(c *check.C) {
out, _ := runSleepingContainer(c)
containerID := strings.TrimSpace(out)
c.Assert(waitRun(containerID), checker.IsNil)
statusCode, _, err := sockRequest("POST", "/containers/"+containerID+"/stop", nil)
c.Assert(err, checker.IsNil)
// 204 No Content is expected, not 200
c.Assert(statusCode, checker.Equals, http.StatusNoContent)
c.Assert(waitInspect(containerID, "{{ .State.Running }}", "false", 5*time.Second), checker.IsNil)
}
// #14170
func (s *DockerSuite) TestPostContainerApiCreateWithStringOrSliceEntrypoint(c *check.C) {
config := struct {
Image string
Entrypoint string
Cmd []string
}{"busybox", "echo", []string{"hello", "world"}}
status, _, err := sockRequest("POST", "/containers/create?name=echotest", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
out, _ := dockerCmd(c, "start", "-a", "echotest")
c.Assert(strings.TrimSpace(out), checker.Equals, "hello world")
config2 := struct {
Image string
Entrypoint []string
Cmd []string
}{"busybox", []string{"echo"}, []string{"hello", "world"}}
_, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2)
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "start", "-a", "echotest2")
c.Assert(strings.TrimSpace(out), checker.Equals, "hello world")
}
// #14170
func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *check.C) {
config := struct {
Image string
Entrypoint string
Cmd string
}{"busybox", "echo", "hello world"}
status, _, err := sockRequest("POST", "/containers/create?name=echotest", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
out, _ := dockerCmd(c, "start", "-a", "echotest")
c.Assert(strings.TrimSpace(out), checker.Equals, "hello world")
config2 := struct {
Image string
Cmd []string
}{"busybox", []string{"echo", "hello", "world"}}
_, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2)
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "start", "-a", "echotest2")
c.Assert(strings.TrimSpace(out), checker.Equals, "hello world")
}
/*
//Hyper does not support Cap
// regression #14318
func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *check.C) {
// Windows doesn't support CapAdd/CapDrop
testRequires(c, DaemonIsLinux)
config := struct {
Image string
CapAdd string
CapDrop string
}{"busybox", "NET_ADMIN", "SYS_ADMIN"}
status, _, err := sockRequest("POST", "/containers/create?name=capaddtest0", config)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
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)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
}
*/
func (s *DockerSuite) TestContainerApiGetContainersJSONEmpty(c *check.C) {
debugEndpoint = "/containers/json?all=1"
status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(string(body), checker.Equals, "[]\n")
}
/*
//Hyper does not need a json request body in start api for backwards compatibility
// #14640
func (s *DockerSuite) TestPostContainersStartWithoutLinksInHostConfig(c *check.C) {
// TODO Windows: Windows doesn't support supplying a hostconfig on start.
// An alternate test could be written to validate the negative testing aspect of this
testRequires(c, DaemonIsLinux)
name := "test-host-config-links"
dockerCmd(c, append([]string{"create", "--name", name, "busybox"}, defaultSleepCommand...)...)
hc := inspectFieldJSON(c, name, "HostConfig")
config := `{"HostConfig":` + hc + `}`
res, b, err := sockRequestRaw("POST", "/containers/"+name+"/start", strings.NewReader(config), "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent)
b.Close()
}
// #14640
func (s *DockerSuite) TestPostContainersStartWithLinksInHostConfig(c *check.C) {
// TODO Windows: Windows doesn't support supplying a hostconfig on start.
// An alternate test could be written to validate the negative testing aspect of this
testRequires(c, DaemonIsLinux)
name := "test-host-config-links"
dockerCmd(c, "run", "--name", "foo", "-d", "busybox", "top")
dockerCmd(c, "create", "--name", name, "--link", "foo:bar", "busybox", "top")
hc := inspectFieldJSON(c, name, "HostConfig")
config := `{"HostConfig":` + hc + `}`
res, b, err := sockRequestRaw("POST", "/containers/"+name+"/start", strings.NewReader(config), "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent)
b.Close()
}
// #14640
func (s *DockerSuite) TestPostContainersStartWithLinksInHostConfigIdLinked(c *check.C) {
// Windows does not support links
testRequires(c, DaemonIsLinux)
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 := inspectFieldJSON(c, name, "HostConfig")
config := `{"HostConfig":` + hc + `}`
res, b, err := sockRequestRaw("POST", "/containers/"+name+"/start", strings.NewReader(config), "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent)
b.Close()
}
func (s *DockerSuite) TestContainerApiGetContainersJSONEmpty(c *check.C) {
debugEndpoint = "/containers/json?all=1"
status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(string(body), checker.Equals, "[]\n")
}
func (s *DockerSuite) TestStartWithNilDNS(c *check.C) {
// TODO Windows: Add once DNS is supported
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 := inspectFieldJSON(c, containerID, "HostConfig.Dns")
c.Assert(dns, checker.Equals, "[]")
}
*/

View File

@@ -0,0 +1,138 @@
package main
import (
"bufio"
"os/exec"
"regexp"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestStatsNoStream(c *check.C) {
// Windows does not support stats
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), checker.IsNil)
statsCmd := exec.Command(dockerBinary, "stats", "--no-stream", id)
type output struct {
out []byte
err error
}
ch := make(chan output)
go func() {
out, err := statsCmd.Output()
ch <- output{out, err}
}()
select {
case outerr := <-ch:
c.Assert(outerr.err, checker.IsNil, check.Commentf("Error running stats: %v", outerr.err))
c.Assert(string(outerr.out), checker.Contains, id) //running container wasn't present in output
case <-time.After(3 * time.Second):
statsCmd.Process.Kill()
c.Fatalf("stats did not return immediately when not streaming")
}
}
// NEED TO BE FIXED
func (s *DockerSuite) TestStatsContainerNotFound(c *check.C) {
// Windows does not support stats
testRequires(c, DaemonIsLinux)
out, _, err := dockerCmdWithError("stats", "notfound")
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "No such container: notfound", check.Commentf("Expected to fail on not found container stats, got %q instead", out))
out, _, err = dockerCmdWithError("stats", "--no-stream", "notfound")
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "No such container: notfound", check.Commentf("Expected to fail on not found container stats with --no-stream, got %q instead", out))
}
func (s *DockerSuite) TestStatsAllRunningNoStream(c *check.C) {
// Windows does not support stats
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
id1 := strings.TrimSpace(out)[:12]
c.Assert(waitRun(id1), check.IsNil)
out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
id2 := strings.TrimSpace(out)[:12]
c.Assert(waitRun(id2), check.IsNil)
out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
id3 := strings.TrimSpace(out)[:12]
c.Assert(waitRun(id3), check.IsNil)
dockerCmd(c, "stop", id3)
out, _ = dockerCmd(c, "stats", "--no-stream")
if !strings.Contains(out, id1) || !strings.Contains(out, id2) {
c.Fatalf("Expected stats output to contain both %s and %s, got %s", id1, id2, out)
}
if strings.Contains(out, id3) {
c.Fatalf("Did not expect %s in stats, got %s", id3, out)
}
}
func (s *DockerSuite) TestStatsAllNoStream(c *check.C) {
// Windows does not support stats
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
id1 := strings.TrimSpace(out)[:12]
c.Assert(waitRun(id1), check.IsNil)
dockerCmd(c, "stop", id1)
out, _ = dockerCmd(c, "run", "-d", "busybox", "top")
id2 := strings.TrimSpace(out)[:12]
c.Assert(waitRun(id2), check.IsNil)
out, _ = dockerCmd(c, "stats", "--all", "--no-stream")
if !strings.Contains(out, id1) || !strings.Contains(out, id2) {
c.Fatalf("Expected stats output to contain both %s and %s, got %s", id1, id2, out)
}
}
// NEED TO BE FIXED
func (s *DockerSuite) TestStatsAllNewContainersAdded(c *check.C) {
// Windows does not support stats
testRequires(c, DaemonIsLinux)
id := make(chan string)
addedChan := make(chan struct{})
dockerCmd(c, "run", "-d", "busybox", "top")
statsCmd := exec.Command(dockerBinary, "stats")
stdout, err := statsCmd.StdoutPipe()
c.Assert(err, check.IsNil)
c.Assert(statsCmd.Start(), check.IsNil)
defer statsCmd.Process.Kill()
go func() {
containerID := <-id
matchID := regexp.MustCompile(containerID)
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
switch {
case matchID.MatchString(scanner.Text()):
close(addedChan)
}
}
}()
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
c.Assert(waitRun(strings.TrimSpace(out)), check.IsNil)
id <- strings.TrimSpace(out)[:12]
select {
case <-time.After(100 * time.Second):
c.Fatal("failed to observe new container created added to stats")
case <-addedChan:
// ignore, done
}
}

View File

View File

@@ -0,0 +1,164 @@
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"github.com/docker/distribution/digest"
"github.com/go-check/check"
)
const (
v2binary = "registry-v2"
v2binarySchema1 = "registry-v2-schema1"
)
type testRegistryV2 struct {
cmd *exec.Cmd
dir string
username string
password string
email string
}
func newTestRegistryV2(c *check.C, schema1, auth bool) (*testRegistryV2, error) {
tmp, err := ioutil.TempDir("", "registry-test-")
if err != nil {
return nil, err
}
template := `version: 0.1
loglevel: debug
storage:
filesystem:
rootdirectory: %s
http:
addr: %s
%s`
var (
htpasswd string
username string
password string
email string
)
if auth {
htpasswdPath := filepath.Join(tmp, "htpasswd")
// generated with: htpasswd -Bbn testuser testpassword
userpasswd := "testuser:$2y$05$sBsSqk0OpSD1uTZkHXc4FeJ0Z70wLQdAX/82UiHuQOKbNbBrzs63m"
username = "testuser"
password = "testpassword"
email = "test@test.org"
if err := ioutil.WriteFile(htpasswdPath, []byte(userpasswd), os.FileMode(0644)); err != nil {
return nil, err
}
htpasswd = fmt.Sprintf(`auth:
htpasswd:
realm: basic-realm
path: %s
`, htpasswdPath)
}
confPath := filepath.Join(tmp, "config.yaml")
config, err := os.Create(confPath)
if err != nil {
return nil, err
}
if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL, htpasswd); err != nil {
os.RemoveAll(tmp)
return nil, err
}
binary := v2binary
if schema1 {
binary = v2binarySchema1
}
cmd := exec.Command(binary, confPath)
if err := cmd.Start(); err != nil {
os.RemoveAll(tmp)
if os.IsNotExist(err) {
c.Skip(err.Error())
}
return nil, err
}
return &testRegistryV2{
cmd: cmd,
dir: tmp,
username: username,
password: password,
email: email,
}, nil
}
func (t *testRegistryV2) Ping() error {
// We always ping through HTTP for our test registry.
resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL))
if err != nil {
return err
}
resp.Body.Close()
fail := resp.StatusCode != http.StatusOK
if t.username != "" {
// unauthorized is a _good_ status when pinging v2/ and it needs auth
fail = fail && resp.StatusCode != http.StatusUnauthorized
}
if fail {
return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
}
return nil
}
func (t *testRegistryV2) Close() {
t.cmd.Process.Kill()
os.RemoveAll(t.dir)
}
func (t *testRegistryV2) getBlobFilename(blobDigest digest.Digest) string {
// Split the digest into it's algorithm and hex components.
dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex()
// The path to the target blob data looks something like:
// baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data"
return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", t.dir, dgstAlg, dgstHex[:2], dgstHex)
}
func (t *testRegistryV2) readBlobContents(c *check.C, blobDigest digest.Digest) []byte {
// Load the target manifest blob.
manifestBlob, err := ioutil.ReadFile(t.getBlobFilename(blobDigest))
if err != nil {
c.Fatalf("unable to read blob: %s", err)
}
return manifestBlob
}
func (t *testRegistryV2) writeBlobContents(c *check.C, blobDigest digest.Digest, data []byte) {
if err := ioutil.WriteFile(t.getBlobFilename(blobDigest), data, os.FileMode(0644)); err != nil {
c.Fatalf("unable to write malicious data blob: %s", err)
}
}
func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest) (undo func()) {
tempFile, err := ioutil.TempFile("", "registry-temp-blob-")
if err != nil {
c.Fatalf("unable to get temporary blob file: %s", err)
}
tempFile.Close()
blobFilename := t.getBlobFilename(blobDigest)
// Move the existing data file aside, so that we can replace it with a
// another blob of data.
if err := os.Rename(blobFilename, tempFile.Name()); err != nil {
os.Remove(tempFile.Name())
c.Fatalf("unable to move data blob: %s", err)
}
return func() {
os.Rename(tempFile.Name(), blobFilename)
os.Remove(tempFile.Name())
}
}

View File

@@ -0,0 +1,55 @@
package main
import (
"net/http"
"net/http/httptest"
"regexp"
"strings"
"sync"
"github.com/go-check/check"
)
type handlerFunc func(w http.ResponseWriter, r *http.Request)
type testRegistry struct {
server *httptest.Server
hostport string
handlers map[string]handlerFunc
mu sync.Mutex
}
func (tr *testRegistry) registerHandler(path string, h handlerFunc) {
tr.mu.Lock()
defer tr.mu.Unlock()
tr.handlers[path] = h
}
func newTestRegistry(c *check.C) (*testRegistry, error) {
testReg := &testRegistry{handlers: make(map[string]handlerFunc)}
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
url := r.URL.String()
var matched bool
var err error
for re, function := range testReg.handlers {
matched, err = regexp.MatchString(re, url)
if err != nil {
c.Fatal("Error with handler regexp")
}
if matched {
function(w, r)
break
}
}
if !matched {
c.Fatalf("Unable to match %s with regexp", url)
}
}))
testReg.server = ts
testReg.hostport = strings.Replace(ts.URL, "http://", "", 1)
return testReg, nil
}

View File

@@ -0,0 +1,148 @@
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/go-check/check"
)
type testCondition func() bool
type testRequirement struct {
Condition testCondition
SkipMessage string
}
// List test requirements
var (
DaemonIsWindows = testRequirement{
func() bool { return daemonPlatform == "windows" },
"Test requires a Windows daemon",
}
DaemonIsLinux = testRequirement{
func() bool { return daemonPlatform == "linux" },
"Test requires a Linux daemon",
}
NotArm = testRequirement{
func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm" },
"Test requires a daemon not running on ARM",
}
SameHostDaemon = testRequirement{
func() bool { return isLocalDaemon },
"Test requires docker daemon to run on the same machine as CLI",
}
UnixCli = testRequirement{
func() bool { return isUnixCli },
"Test requires posix utilities or functionality to run.",
}
ExecSupport = testRequirement{
func() bool { return supportsExec },
"Test requires 'docker exec' capabilities on the tested daemon.",
}
Network = testRequirement{
func() bool {
// Set a timeout on the GET at 15s
var timeout = time.Duration(15 * time.Second)
var url = "https://hub.docker.com"
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
panic(fmt.Sprintf("Timeout for GET request on %s", url))
}
if resp != nil {
resp.Body.Close()
}
return err == nil
},
"Test requires network availability, environment variable set to none to run in a non-network enabled mode.",
}
Apparmor = testRequirement{
func() bool {
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
return err == nil && len(buf) > 1 && buf[0] == 'Y'
},
"Test requires apparmor is enabled.",
}
RegistryHosting = testRequirement{
func() bool {
// for now registry binary is built only if we're running inside
// container through `make test`. Figure that out by testing if
// registry binary is in PATH.
_, err := exec.LookPath(v2binary)
return err == nil
},
fmt.Sprintf("Test requires an environment that can host %s in the same host", v2binary),
}
NotaryHosting = testRequirement{
func() bool {
// for now notary binary is built only if we're running inside
// container through `make test`. Figure that out by testing if
// notary-server binary is in PATH.
_, err := exec.LookPath(notaryBinary)
return err == nil
},
fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryBinary),
}
NotOverlay = testRequirement{
func() bool {
cmd := exec.Command("grep", "^overlay / overlay", "/proc/mounts")
if err := cmd.Run(); err != nil {
return true
}
return false
},
"Test requires underlying root filesystem not be backed by overlay.",
}
IPv6 = testRequirement{
func() bool {
cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
if err := cmd.Run(); err != nil {
return true
}
return false
},
"Test requires support for IPv6",
}
NotGCCGO = testRequirement{
func() bool {
out, err := exec.Command("go", "version").Output()
if err == nil && strings.Contains(string(out), "gccgo") {
return false
}
return true
},
"Test requires native Golang compiler instead of GCCGO",
}
NotUserNamespace = testRequirement{
func() bool {
root := os.Getenv("DOCKER_REMAP_ROOT")
if root != "" {
return false
}
return true
},
"Test cannot be run when remapping root",
}
)
// testRequires checks if the environment satisfies the requirements
// for the test to run or skips the tests.
func testRequires(c *check.C, requirements ...testRequirement) {
for _, r := range requirements {
if !r.Condition() {
fmt.Printf("\n [Skip] - %s", r.SkipMessage)
c.Skip(r.SkipMessage)
}
}
}

View File

@@ -0,0 +1,88 @@
// +build !windows
package main
import (
"github.com/docker/docker/pkg/sysinfo"
)
var (
// SysInfo stores information about which features a kernel supports.
SysInfo *sysinfo.SysInfo
cpuCfsPeriod = testRequirement{
func() bool {
return SysInfo.CPUCfsPeriod
},
"Test requires an environment that supports cgroup cfs period.",
}
cpuCfsQuota = testRequirement{
func() bool {
return SysInfo.CPUCfsQuota
},
"Test requires an environment that supports cgroup cfs quota.",
}
cpuShare = testRequirement{
func() bool {
return SysInfo.CPUShares
},
"Test requires an environment that supports cgroup cpu shares.",
}
oomControl = testRequirement{
func() bool {
return SysInfo.OomKillDisable
},
"Test requires Oom control enabled.",
}
kernelMemorySupport = testRequirement{
func() bool {
return SysInfo.KernelMemory
},
"Test requires an environment that supports cgroup kernel memory.",
}
memoryLimitSupport = testRequirement{
func() bool {
return SysInfo.MemoryLimit
},
"Test requires an environment that supports cgroup memory limit.",
}
memoryReservationSupport = testRequirement{
func() bool {
return SysInfo.MemoryReservation
},
"Test requires an environment that supports cgroup memory reservation.",
}
swapMemorySupport = testRequirement{
func() bool {
return SysInfo.SwapLimit
},
"Test requires an environment that supports cgroup swap memory limit.",
}
memorySwappinessSupport = testRequirement{
func() bool {
return SysInfo.MemorySwappiness
},
"Test requires an environment that supports cgroup memory swappiness.",
}
blkioWeight = testRequirement{
func() bool {
return SysInfo.BlkioWeight
},
"Test requires an environment that supports blkio weight.",
}
cgroupCpuset = testRequirement{
func() bool {
return SysInfo.Cpuset
},
"Test requires an environment that supports cgroup cpuset.",
}
seccompEnabled = testRequirement{
func() bool {
return supportsSeccomp && SysInfo.Seccomp
},
"Test requires that seccomp support be enabled in the daemon.",
}
)
func init() {
SysInfo = sysinfo.New(true)
}

View File

View File

@@ -0,0 +1,257 @@
package main
import (
"archive/tar"
"bytes"
"net/http"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestBuildApiDockerfilePath(c *check.C) {
// Test to make sure we stop people from trying to leave the
// build context when specifying the path to the dockerfile
buffer := new(bytes.Buffer)
tw := tar.NewWriter(buffer)
defer tw.Close()
dockerfile := []byte("FROM busybox")
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: int64(len(dockerfile)),
})
//failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(dockerfile)
// failed to write tar file content
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
res, body, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
out, err := readBody(body)
c.Assert(err, checker.IsNil)
// Didn't complain about leaving build context
c.Assert(string(out), checker.Contains, "Forbidden path outside the build context")
}
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
testRequires(c, NotUserNamespace)
testRequires(c, DaemonIsLinux)
server, err := fakeStorage(map[string]string{
"testD": `FROM busybox
COPY * /tmp/
RUN find / -name ba*
RUN find /tmp/`,
})
c.Assert(err, checker.IsNil)
defer server.Close()
res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
c.Assert(err, checker.IsNil)
// Make sure Dockerfile exists.
// Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL
out := string(buf)
c.Assert(out, checker.Contains, "/tmp/Dockerfile")
c.Assert(out, checker.Not(checker.Contains), "baz")
}
func (s *DockerSuite) TestBuildApiRemoteTarballContext(c *check.C) {
testRequires(c, DaemonIsLinux)
buffer := new(bytes.Buffer)
tw := tar.NewWriter(buffer)
defer tw.Close()
dockerfile := []byte("FROM busybox")
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: int64(len(dockerfile)),
})
// failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(dockerfile)
// failed to write tar file content
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
"testT.tar": buffer,
})
c.Assert(err, checker.IsNil)
defer server.Close()
res, b, err := sockRequestRaw("POST", "/build?remote="+server.URL()+"/testT.tar", nil, "application/tar")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
b.Close()
}
func (s *DockerSuite) TestBuildApiRemoteTarballContextWithCustomDockerfile(c *check.C) {
testRequires(c, DaemonIsLinux)
buffer := new(bytes.Buffer)
tw := tar.NewWriter(buffer)
defer tw.Close()
dockerfile := []byte(`FROM busybox
RUN echo 'wrong'`)
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: int64(len(dockerfile)),
})
// failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(dockerfile)
// failed to write tar file content
c.Assert(err, checker.IsNil)
custom := []byte(`FROM busybox
RUN echo 'right'
`)
err = tw.WriteHeader(&tar.Header{
Name: "custom",
Size: int64(len(custom)),
})
// failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(custom)
// failed to write tar file content
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
"testT.tar": buffer,
})
c.Assert(err, checker.IsNil)
defer server.Close()
url := "/build?dockerfile=custom&remote=" + server.URL() + "/testT.tar"
res, body, err := sockRequestRaw("POST", url, nil, "application/tar")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
defer body.Close()
content, err := readBody(body)
c.Assert(err, checker.IsNil)
// Build used the wrong dockerfile.
c.Assert(string(content), checker.Not(checker.Contains), "wrong")
}
func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
testRequires(c, DaemonIsLinux)
git, err := newFakeGit("repo", map[string]string{
"dockerfile": `FROM busybox
RUN echo from dockerfile`,
}, false)
c.Assert(err, checker.IsNil)
defer git.Close()
res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
c.Assert(err, checker.IsNil)
out := string(buf)
c.Assert(out, checker.Contains, "from dockerfile")
}
func (s *DockerSuite) TestBuildApiBuildGitWithF(c *check.C) {
testRequires(c, DaemonIsLinux)
git, err := newFakeGit("repo", map[string]string{
"baz": `FROM busybox
RUN echo from baz`,
"Dockerfile": `FROM busybox
RUN echo from Dockerfile`,
}, false)
c.Assert(err, checker.IsNil)
defer git.Close()
// Make sure it tries to 'dockerfile' query param value
res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
c.Assert(err, checker.IsNil)
out := string(buf)
c.Assert(out, checker.Contains, "from baz")
}
func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) {
testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows
git, err := newFakeGit("repo", map[string]string{
"Dockerfile": `FROM busybox
RUN echo from Dockerfile`,
"dockerfile": `FROM busybox
RUN echo from dockerfile`,
}, false)
c.Assert(err, checker.IsNil)
defer git.Close()
// Make sure it tries to 'dockerfile' query param value
res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
c.Assert(err, checker.IsNil)
out := string(buf)
c.Assert(out, checker.Contains, "from Dockerfile")
}
func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
// Test to make sure we stop people from trying to leave the
// build context when specifying a symlink as the path to the dockerfile
buffer := new(bytes.Buffer)
tw := tar.NewWriter(buffer)
defer tw.Close()
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Typeflag: tar.TypeSymlink,
Linkname: "/etc/passwd",
})
// failed to write tar file header
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
out, err := readBody(body)
c.Assert(err, checker.IsNil)
// The reason the error is "Cannot locate specified Dockerfile" is because
// in the builder, the symlink is resolved within the context, therefore
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
// a nonexistent file.
c.Assert(string(out), checker.Contains, "Cannot locate specified Dockerfile: Dockerfile", check.Commentf("Didn't complain about leaving build context"))
}

View File

@@ -0,0 +1,73 @@
package main
import (
"encoding/json"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/go-check/check"
)
func (s *DockerSuite) TestEventsApiEmptyOutput(c *check.C) {
type apiResp struct {
resp *http.Response
err error
}
chResp := make(chan *apiResp)
go func() {
resp, body, err := sockRequestRaw("GET", "/events", nil, "")
body.Close()
chResp <- &apiResp{resp, err}
}()
select {
case r := <-chResp:
c.Assert(r.err, checker.IsNil)
c.Assert(r.resp.StatusCode, checker.Equals, http.StatusOK)
case <-time.After(3 * time.Second):
c.Fatal("timeout waiting for events api to respond, should have responded immediately")
}
}
func (s *DockerSuite) TestEventsApiBackwardsCompatible(c *check.C) {
since := daemonTime(c).Unix()
ts := strconv.FormatInt(since, 10)
out, _ := dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top")
containerID := strings.TrimSpace(out)
c.Assert(waitRun(containerID), checker.IsNil)
q := url.Values{}
q.Set("since", ts)
_, body, err := sockRequestRaw("GET", "/events?"+q.Encode(), nil, "")
c.Assert(err, checker.IsNil)
defer body.Close()
dec := json.NewDecoder(body)
var containerCreateEvent *jsonmessage.JSONMessage
for {
var event jsonmessage.JSONMessage
if err := dec.Decode(&event); err != nil {
if err == io.EOF {
break
}
c.Fatal(err)
}
if event.Status == "create" && event.ID == containerID {
containerCreateEvent = &event
break
}
}
c.Assert(containerCreateEvent, checker.Not(checker.IsNil))
c.Assert(containerCreateEvent.Status, checker.Equals, "create")
c.Assert(containerCreateEvent.ID, checker.Equals, containerID)
c.Assert(containerCreateEvent.From, checker.Equals, "busybox")
}

View File

@@ -0,0 +1,335 @@
package main
import (
"encoding/json"
"fmt"
"net"
"net/http"
"net/url"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"github.com/docker/engine-api/types/network"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiNetworkGetDefaults(c *check.C) {
testRequires(c, DaemonIsLinux)
// By default docker daemon creates 3 networks. check if they are present
defaults := []string{"bridge", "host", "none"}
for _, nn := range defaults {
c.Assert(isNetworkAvailable(c, nn), checker.Equals, true)
}
}
func (s *DockerSuite) TestApiNetworkCreateDelete(c *check.C) {
testRequires(c, DaemonIsLinux)
// Create a network
name := "testnetwork"
config := types.NetworkCreate{
Name: name,
CheckDuplicate: true,
}
id := createNetwork(c, config, true)
c.Assert(isNetworkAvailable(c, name), checker.Equals, true)
// delete the network and make sure it is deleted
deleteNetwork(c, id, true)
c.Assert(isNetworkAvailable(c, name), checker.Equals, false)
}
func (s *DockerSuite) TestApiNetworkCreateCheckDuplicate(c *check.C) {
testRequires(c, DaemonIsLinux)
name := "testcheckduplicate"
configOnCheck := types.NetworkCreate{
Name: name,
CheckDuplicate: true,
}
configNotCheck := types.NetworkCreate{
Name: name,
CheckDuplicate: false,
}
// Creating a new network first
createNetwork(c, configOnCheck, true)
c.Assert(isNetworkAvailable(c, name), checker.Equals, true)
// Creating another network with same name and CheckDuplicate must fail
createNetwork(c, configOnCheck, false)
// Creating another network with same name and not CheckDuplicate must succeed
createNetwork(c, configNotCheck, true)
}
func (s *DockerSuite) TestApiNetworkFilter(c *check.C) {
testRequires(c, DaemonIsLinux)
nr := getNetworkResource(c, getNetworkIDByName(c, "bridge"))
c.Assert(nr.Name, checker.Equals, "bridge")
}
func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
testRequires(c, DaemonIsLinux)
// Inspect default bridge network
nr := getNetworkResource(c, "bridge")
c.Assert(nr.Name, checker.Equals, "bridge")
// run a container and attach it to the default bridge network
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
containerID := strings.TrimSpace(out)
containerIP := findContainerIP(c, "test", "bridge")
// inspect default bridge network again and make sure the container is connected
nr = getNetworkResource(c, nr.ID)
c.Assert(nr.Driver, checker.Equals, "bridge")
c.Assert(nr.Scope, checker.Equals, "local")
c.Assert(nr.IPAM.Driver, checker.Equals, "default")
c.Assert(len(nr.Containers), checker.Equals, 1)
c.Assert(nr.Containers[containerID], checker.NotNil)
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
c.Assert(err, checker.IsNil)
c.Assert(ip.String(), checker.Equals, containerIP)
// IPAM configuration inspect
ipam := network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{{Subnet: "172.28.0.0/16", IPRange: "172.28.5.0/24", Gateway: "172.28.5.254"}},
}
config := types.NetworkCreate{
Name: "br0",
Driver: "bridge",
IPAM: ipam,
Options: map[string]string{"foo": "bar", "opts": "dopts"},
}
id0 := createNetwork(c, config, true)
c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, true)
nr = getNetworkResource(c, id0)
c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
c.Assert(nr.Options["foo"], checker.Equals, "bar")
c.Assert(nr.Options["opts"], checker.Equals, "dopts")
// delete the network and make sure it is deleted
deleteNetwork(c, id0, true)
c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, false)
}
func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
testRequires(c, DaemonIsLinux)
// Create test network
name := "testnetwork"
config := types.NetworkCreate{
Name: name,
}
id := createNetwork(c, config, true)
nr := getNetworkResource(c, id)
c.Assert(nr.Name, checker.Equals, name)
c.Assert(nr.ID, checker.Equals, id)
c.Assert(len(nr.Containers), checker.Equals, 0)
// run a container
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
containerID := strings.TrimSpace(out)
// connect the container to the test network
connectNetwork(c, nr.ID, containerID)
// inspect the network to make sure container is connected
nr = getNetworkResource(c, nr.ID)
c.Assert(len(nr.Containers), checker.Equals, 1)
c.Assert(nr.Containers[containerID], checker.NotNil)
// check if container IP matches network inspect
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
c.Assert(err, checker.IsNil)
containerIP := findContainerIP(c, "test", "testnetwork")
c.Assert(ip.String(), checker.Equals, containerIP)
// disconnect container from the network
disconnectNetwork(c, nr.ID, containerID)
nr = getNetworkResource(c, nr.ID)
c.Assert(nr.Name, checker.Equals, name)
c.Assert(len(nr.Containers), checker.Equals, 0)
// delete the network
deleteNetwork(c, nr.ID, true)
}
func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
testRequires(c, DaemonIsLinux)
// test0 bridge network
ipam0 := network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{{Subnet: "192.178.0.0/16", IPRange: "192.178.128.0/17", Gateway: "192.178.138.100"}},
}
config0 := types.NetworkCreate{
Name: "test0",
Driver: "bridge",
IPAM: ipam0,
}
id0 := createNetwork(c, config0, true)
c.Assert(isNetworkAvailable(c, "test0"), checker.Equals, true)
ipam1 := network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{{Subnet: "192.178.128.0/17", Gateway: "192.178.128.1"}},
}
// test1 bridge network overlaps with test0
config1 := types.NetworkCreate{
Name: "test1",
Driver: "bridge",
IPAM: ipam1,
}
createNetwork(c, config1, false)
c.Assert(isNetworkAvailable(c, "test1"), checker.Equals, false)
ipam2 := network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{{Subnet: "192.169.0.0/16", Gateway: "192.169.100.100"}},
}
// test2 bridge network does not overlap
config2 := types.NetworkCreate{
Name: "test2",
Driver: "bridge",
IPAM: ipam2,
}
createNetwork(c, config2, true)
c.Assert(isNetworkAvailable(c, "test2"), checker.Equals, true)
// remove test0 and retry to create test1
deleteNetwork(c, id0, true)
createNetwork(c, config1, true)
c.Assert(isNetworkAvailable(c, "test1"), checker.Equals, true)
// for networks w/o ipam specified, docker will choose proper non-overlapping subnets
createNetwork(c, types.NetworkCreate{Name: "test3"}, true)
c.Assert(isNetworkAvailable(c, "test3"), checker.Equals, true)
createNetwork(c, types.NetworkCreate{Name: "test4"}, true)
c.Assert(isNetworkAvailable(c, "test4"), checker.Equals, true)
createNetwork(c, types.NetworkCreate{Name: "test5"}, true)
c.Assert(isNetworkAvailable(c, "test5"), checker.Equals, true)
for i := 1; i < 6; i++ {
deleteNetwork(c, fmt.Sprintf("test%d", i), true)
}
}
func (s *DockerSuite) TestApiCreateDeletePredefinedNetworks(c *check.C) {
testRequires(c, DaemonIsLinux)
createDeletePredefinedNetwork(c, "bridge")
createDeletePredefinedNetwork(c, "none")
createDeletePredefinedNetwork(c, "host")
}
func createDeletePredefinedNetwork(c *check.C, name string) {
// Create pre-defined network
config := types.NetworkCreate{
Name: name,
CheckDuplicate: true,
}
shouldSucceed := false
createNetwork(c, config, shouldSucceed)
deleteNetwork(c, name, shouldSucceed)
}
func isNetworkAvailable(c *check.C, name string) bool {
status, body, err := sockRequest("GET", "/networks", nil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
nJSON := []types.NetworkResource{}
err = json.Unmarshal(body, &nJSON)
c.Assert(err, checker.IsNil)
for _, n := range nJSON {
if n.Name == name {
return true
}
}
return false
}
func getNetworkIDByName(c *check.C, name string) string {
var (
v = url.Values{}
filterArgs = filters.NewArgs()
)
filterArgs.Add("name", name)
filterJSON, err := filters.ToParam(filterArgs)
c.Assert(err, checker.IsNil)
v.Set("filters", filterJSON)
status, body, err := sockRequest("GET", "/networks?"+v.Encode(), nil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
nJSON := []types.NetworkResource{}
err = json.Unmarshal(body, &nJSON)
c.Assert(err, checker.IsNil)
c.Assert(len(nJSON), checker.Equals, 1)
return nJSON[0].ID
}
func getNetworkResource(c *check.C, id string) *types.NetworkResource {
_, obj, err := sockRequest("GET", "/networks/"+id, nil)
c.Assert(err, checker.IsNil)
nr := types.NetworkResource{}
err = json.Unmarshal(obj, &nr)
c.Assert(err, checker.IsNil)
return &nr
}
func createNetwork(c *check.C, config types.NetworkCreate, shouldSucceed bool) string {
status, resp, err := sockRequest("POST", "/networks/create", config)
if !shouldSucceed {
c.Assert(status, checker.Not(checker.Equals), http.StatusCreated)
return ""
}
c.Assert(status, checker.Equals, http.StatusCreated)
c.Assert(err, checker.IsNil)
var nr types.NetworkCreateResponse
err = json.Unmarshal(resp, &nr)
c.Assert(err, checker.IsNil)
return nr.ID
}
func connectNetwork(c *check.C, nid, cid string) {
config := types.NetworkConnect{
Container: cid,
}
status, _, err := sockRequest("POST", "/networks/"+nid+"/connect", config)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
}
func disconnectNetwork(c *check.C, nid, cid string) {
config := types.NetworkConnect{
Container: cid,
}
status, _, err := sockRequest("POST", "/networks/"+nid+"/disconnect", config)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
}
func deleteNetwork(c *check.C, id string, shouldSucceed bool) {
status, _, err := sockRequest("DELETE", "/networks/"+id, nil)
if !shouldSucceed {
c.Assert(status, checker.Not(checker.Equals), http.StatusOK)
return
}
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
}

View File

@@ -0,0 +1,44 @@
package main
import (
"net/http"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestResizeApiResponse(c *check.C) {
out, _ := runSleepingContainer(c, "-d")
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/containers/" + cleanedContainerID + "/resize?h=40&w=40"
status, _, err := sockRequest("POST", endpoint, nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestResizeApiHeightWidthNoInt(c *check.C) {
out, _ := runSleepingContainer(c, "-d")
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/containers/" + cleanedContainerID + "/resize?h=foo&w=bar"
status, _, err := sockRequest("POST", endpoint, nil)
c.Assert(status, check.Equals, http.StatusInternalServerError)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestResizeApiResponseWhenContainerNotStarted(c *check.C) {
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
cleanedContainerID := strings.TrimSpace(out)
// make sure the exited container is not running
dockerCmd(c, "wait", cleanedContainerID)
endpoint := "/containers/" + cleanedContainerID + "/resize?h=40&w=40"
status, body, err := sockRequest("POST", endpoint, nil)
c.Assert(status, check.Equals, http.StatusInternalServerError)
c.Assert(err, check.IsNil)
c.Assert(string(body), checker.Contains, "is not running", check.Commentf("resize should fail with message 'Container is not running'"))
}

View File

@@ -0,0 +1,102 @@
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"net/http/httputil"
"os"
"os/exec"
"strconv"
"strings"
"time"
"github.com/docker/docker/api"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiOptionsRoute(c *check.C) {
status, _, err := sockRequest("OPTIONS", "/", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
}
func (s *DockerSuite) TestApiGetEnabledCors(c *check.C) {
res, body, err := sockRequestRaw("GET", "/version", nil, "")
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
body.Close()
// TODO: @runcom incomplete tests, why old integration tests had this headers
// and here none of the headers below are in the response?
//c.Log(res.Header)
//c.Assert(res.Header.Get("Access-Control-Allow-Origin"), check.Equals, "*")
//c.Assert(res.Header.Get("Access-Control-Allow-Headers"), check.Equals, "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
}
func (s *DockerSuite) TestApiVersionStatusCode(c *check.C) {
conn, err := sockConn(time.Duration(10 * time.Second))
c.Assert(err, checker.IsNil)
client := httputil.NewClientConn(conn, nil)
defer client.Close()
req, err := http.NewRequest("GET", "/v999.0/version", nil)
c.Assert(err, checker.IsNil)
req.Header.Set("User-Agent", "Docker-Client/999.0 (os)")
res, err := client.Do(req)
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
}
func (s *DockerSuite) TestApiClientVersionNewerThanServer(c *check.C) {
v := strings.Split(api.DefaultVersion.String(), ".")
vMinInt, err := strconv.Atoi(v[1])
c.Assert(err, checker.IsNil)
vMinInt++
v[1] = strconv.Itoa(vMinInt)
version := strings.Join(v, ".")
status, body, err := sockRequest("GET", "/v"+version+"/version", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusBadRequest)
expected := fmt.Sprintf("client is newer than server (client API version: %s, server API version: %s)", version, api.DefaultVersion)
c.Assert(strings.TrimSpace(string(body)), checker.Equals, expected)
}
func (s *DockerSuite) TestApiClientVersionOldNotSupported(c *check.C) {
v := strings.Split(api.MinVersion.String(), ".")
vMinInt, err := strconv.Atoi(v[1])
c.Assert(err, checker.IsNil)
vMinInt--
v[1] = strconv.Itoa(vMinInt)
version := strings.Join(v, ".")
status, body, err := sockRequest("GET", "/v"+version+"/version", nil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusBadRequest)
expected := fmt.Sprintf("client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", version, api.MinVersion)
c.Assert(strings.TrimSpace(string(body)), checker.Equals, expected)
}
func (s *DockerSuite) TestApiDockerApiVersion(c *check.C) {
var svrVersion string
server := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
url := r.URL.Path
svrVersion = url
}))
defer server.Close()
// Test using the env var first
cmd := exec.Command(dockerBinary, "--region="+server.URL[7:], "version")
cmd.Env = append([]string{"DOCKER_API_VERSION=xxx"}, os.Environ()...)
out, _, _ := runCommandWithOutput(cmd)
c.Assert(svrVersion, check.Equals, "/vxxx/version")
if !strings.Contains(out, "API version: xxx") {
c.Fatalf("Out didn't have 'xxx' for the API version, had:\n%s", out)
}
}

Some files were not shown because too many files have changed in this diff Show More