Merge branch 'master' of github.com:docker/docker into journald

Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)
This commit is contained in:
Dan Walsh 2015-04-22 17:37:26 -04:00
commit b88b2fa72e
130 changed files with 8735 additions and 5203 deletions

View file

@ -179,7 +179,7 @@ Under the hood, Docker is built on the following components:
Contributing to Docker
======================
[![GoDoc](https://godoc.org/github.com/docker/docker?status.png)](https://godoc.org/github.com/docker/docker)
[![GoDoc](https://godoc.org/github.com/docker/docker?status.svg)](https://godoc.org/github.com/docker/docker)
[![Jenkins Build Status](https://jenkins.dockerproject.com/job/Docker%20Master/badge/icon)](https://jenkins.dockerproject.com/job/Docker%20Master/)
Want to hack on Docker? Awesome! We have [instructions to help you get

View file

@ -97,6 +97,11 @@ func (cli *DockerCli) Cmd(args ...string) error {
return cli.CmdHelp()
}
// Subcmd is a subcommand of the main "docker" command.
// A subcommand represents an action that can be performed
// from the Docker command line client.
//
// To see all available subcommands, run "docker --help".
func (cli *DockerCli) Subcmd(name, signature, description string, exitOnError bool) *flag.FlagSet {
var errorHandling flag.ErrorHandling
if exitOnError {
@ -121,6 +126,8 @@ func (cli *DockerCli) Subcmd(name, signature, description string, exitOnError bo
return flags
}
// CheckTtyInput checks if we are trying to attach to a container tty
// from a non-tty client input stream, and if so, returns an error.
func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error {
// In order to attach to a container tty, input stream for the client must
// be a tty itself: redirecting or piping the client standard input is

View file

@ -19,19 +19,19 @@ import (
)
// FIXME: --viz and --tree are deprecated. Remove them in a future version.
func (cli *DockerCli) WalkTree(noTrunc bool, images []*types.Image, byParent map[string][]*types.Image, prefix string, printNode func(cli *DockerCli, noTrunc bool, image *types.Image, prefix string)) {
func (cli *DockerCli) walkTree(noTrunc bool, images []*types.Image, byParent map[string][]*types.Image, prefix string, printNode func(cli *DockerCli, noTrunc bool, image *types.Image, prefix string)) {
length := len(images)
if length > 1 {
for index, image := range images {
if index+1 == length {
printNode(cli, noTrunc, image, prefix+"└─")
if subimages, exists := byParent[image.ID]; exists {
cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
cli.walkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
}
} else {
printNode(cli, noTrunc, image, prefix+"\u251C─")
if subimages, exists := byParent[image.ID]; exists {
cli.WalkTree(noTrunc, subimages, byParent, prefix+"\u2502 ", printNode)
cli.walkTree(noTrunc, subimages, byParent, prefix+"\u2502 ", printNode)
}
}
}
@ -39,7 +39,7 @@ func (cli *DockerCli) WalkTree(noTrunc bool, images []*types.Image, byParent map
for _, image := range images {
printNode(cli, noTrunc, image, prefix+"└─")
if subimages, exists := byParent[image.ID]; exists {
cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
cli.walkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
}
}
}
@ -181,9 +181,9 @@ func (cli *DockerCli) CmdImages(args ...string) error {
if startImage != nil {
root := []*types.Image{startImage}
cli.WalkTree(*noTrunc, root, byParent, "", printNode)
cli.walkTree(*noTrunc, root, byParent, "", printNode)
} else if matchName == "" {
cli.WalkTree(*noTrunc, roots, byParent, "", printNode)
cli.walkTree(*noTrunc, roots, byParent, "", printNode)
}
if *flViz {
fmt.Fprintf(cli.out, " base [style=invisible]\n}\n")

View file

@ -7,6 +7,9 @@ import (
flag "github.com/docker/docker/pkg/mflag"
)
// CmdRm removes one or more containers.
//
// Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
func (cli *DockerCli) CmdRm(args ...string) error {
cmd := cli.Subcmd("rm", "CONTAINER [CONTAINER...]", "Remove one or more containers", true)
v := cmd.Bool([]string{"v", "-volumes"}, false, "Remove the volumes associated with the container")

View file

@ -14,6 +14,7 @@ import (
"github.com/docker/docker/registry"
)
// ByStars sorts search results in ascending order by number of stars.
type ByStars []registry.SearchResult
func (r ByStars) Len() int { return len(r) }

View file

@ -29,9 +29,10 @@ import (
)
var (
ErrConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
errConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
)
// HTTPClient creates a new HTP client with the cli's client transport instance.
func (cli *DockerCli) HTTPClient() *http.Client {
return &http.Client{Transport: cli.transport}
}
@ -93,7 +94,7 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m
}
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return nil, "", statusCode, ErrConnectionRefused
return nil, "", statusCode, errConnectionRefused
}
if cli.tlsConfig == nil {
@ -250,7 +251,7 @@ func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
stream, _, err := cli.call("GET", "/containers/"+containerID+"/json", nil, nil)
if err != nil {
// If we can't connect, then the daemon probably died.
if err != ErrConnectionRefused {
if err != errConnectionRefused {
return false, -1, err
}
return false, -1, nil
@ -271,7 +272,7 @@ func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
stream, _, err := cli.call("GET", "/exec/"+execID+"/json", nil, nil)
if err != nil {
// If we can't connect, then the daemon probably died.
if err != ErrConnectionRefused {
if err != errConnectionRefused {
return false, -1, err
}
return false, -1, nil

View file

@ -223,14 +223,6 @@ func httpError(w http.ResponseWriter, err error) {
http.Error(w, err.Error(), statusCode)
}
// writeJSONEnv writes the engine.Env values to the http response stream as a
// json encoded body.
func writeJSONEnv(w http.ResponseWriter, code int, v engine.Env) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
return v.Encode(w)
}
// writeJSON writes the value v to the http response stream as json with standard
// json encoding.
func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
@ -716,7 +708,7 @@ func (s *Server) postCommit(eng *engine.Engine, version version.Version, w http.
Config: c,
}
imgID, err := builder.Commit(s.daemon, eng, cont, containerCommitConfig)
imgID, err := builder.Commit(s.daemon, cont, containerCommitConfig)
if err != nil {
return err
}
@ -772,7 +764,7 @@ func (s *Server) postImagesCreate(eng *engine.Engine, version version.Version, w
imagePullConfig.Json = false
}
if err := s.daemon.Repositories().Pull(image, tag, imagePullConfig, eng); err != nil {
if err := s.daemon.Repositories().Pull(image, tag, imagePullConfig); err != nil {
return err
}
} else { //import
@ -793,7 +785,7 @@ func (s *Server) postImagesCreate(eng *engine.Engine, version version.Version, w
imageImportConfig.Json = false
}
newConfig, err := builder.BuildFromConfig(s.daemon, eng, &runconfig.Config{}, imageImportConfig.Changes)
newConfig, err := builder.BuildFromConfig(s.daemon, &runconfig.Config{}, imageImportConfig.Changes)
if err != nil {
return err
}
@ -1335,7 +1327,7 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R
}()
}
if err := builder.Build(s.daemon, eng, buildConfig); err != nil {
if err := builder.Build(s.daemon, buildConfig); err != nil {
// Do not write the error in the http output if it's still empty.
// This prevents from writing a 200(OK) when there is an interal error.
if !output.Flushed() {

View file

@ -31,7 +31,6 @@ import (
"github.com/docker/docker/builder/command"
"github.com/docker/docker/builder/parser"
"github.com/docker/docker/daemon"
"github.com/docker/docker/engine"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/streamformatter"
"github.com/docker/docker/pkg/stringid"
@ -80,7 +79,6 @@ func init() {
// processing as it evaluates the parsing result.
type Builder struct {
Daemon *daemon.Daemon
Engine *engine.Engine
// effectively stdio for the run. Because it is not stdio, I said
// "Effectively". Do not use stdio anywhere in this package for any reason.

View file

@ -454,7 +454,7 @@ func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
Json: b.StreamFormatter.Json(),
}
if err := b.Daemon.Repositories().Pull(remote, tag, imagePullConfig, b.Engine); err != nil {
if err := b.Daemon.Repositories().Pull(remote, tag, imagePullConfig); err != nil {
return nil, err
}

View file

@ -13,7 +13,6 @@ import (
"github.com/docker/docker/api"
"github.com/docker/docker/builder/parser"
"github.com/docker/docker/daemon"
"github.com/docker/docker/engine"
"github.com/docker/docker/graph"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/httputils"
@ -83,7 +82,7 @@ func NewBuildConfig() *Config {
}
}
func Build(d *daemon.Daemon, e *engine.Engine, buildConfig *Config) error {
func Build(d *daemon.Daemon, buildConfig *Config) error {
var (
repoName string
tag string
@ -150,7 +149,6 @@ func Build(d *daemon.Daemon, e *engine.Engine, buildConfig *Config) error {
builder := &Builder{
Daemon: d,
Engine: e,
OutStream: &streamformatter.StdoutFormater{
Writer: buildConfig.Stdout,
StreamFormatter: sf,
@ -188,7 +186,7 @@ func Build(d *daemon.Daemon, e *engine.Engine, buildConfig *Config) error {
return nil
}
func BuildFromConfig(d *daemon.Daemon, e *engine.Engine, c *runconfig.Config, changes []string) (*runconfig.Config, error) {
func BuildFromConfig(d *daemon.Daemon, c *runconfig.Config, changes []string) (*runconfig.Config, error) {
ast, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n")))
if err != nil {
return nil, err
@ -203,7 +201,6 @@ func BuildFromConfig(d *daemon.Daemon, e *engine.Engine, c *runconfig.Config, ch
builder := &Builder{
Daemon: d,
Engine: e,
Config: c,
OutStream: ioutil.Discard,
ErrStream: ioutil.Discard,
@ -219,13 +216,13 @@ func BuildFromConfig(d *daemon.Daemon, e *engine.Engine, c *runconfig.Config, ch
return builder.Config, nil
}
func Commit(d *daemon.Daemon, eng *engine.Engine, name string, c *daemon.ContainerCommitConfig) (string, error) {
func Commit(d *daemon.Daemon, name string, c *daemon.ContainerCommitConfig) (string, error) {
container, err := d.Get(name)
if err != nil {
return "", err
}
newConfig, err := BuildFromConfig(d, eng, c.Config, c.Changes)
newConfig, err := BuildFromConfig(d, c.Config, c.Changes)
if err != nil {
return "", err
}

View file

@ -179,11 +179,13 @@ func (container *Container) readHostConfig() error {
return nil
}
data, err := ioutil.ReadFile(pth)
f, err := os.Open(pth)
if err != nil {
return err
}
return json.Unmarshal(data, container.hostConfig)
defer f.Close()
return json.NewDecoder(f).Decode(&container.hostConfig)
}
func (container *Container) WriteHostConfig() error {

View file

@ -108,7 +108,6 @@ type Daemon struct {
containerGraph *graphdb.Database
driver graphdriver.Driver
execDriver execdriver.Driver
trustStore *trust.TrustStore
statsCollector *statsCollector
defaultLogConfig runconfig.LogConfig
RegistryService *registry.Service
@ -129,9 +128,6 @@ func (daemon *Daemon) Install(eng *engine.Engine) error {
if err := daemon.Repositories().Install(eng); err != nil {
return err
}
if err := daemon.trustStore.Install(eng); err != nil {
return err
}
// FIXME: this hack is necessary for legacy integration tests to access
// the daemon object.
eng.HackSetGlobalVar("httpapi.daemon", daemon)
@ -194,8 +190,6 @@ func (daemon *Daemon) load(id string) (*Container, error) {
return container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
}
container.readHostConfig()
return container, nil
}
@ -903,22 +897,29 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine, registryService
return nil, err
}
eventsService := events.New()
logrus.Debug("Creating repository list")
repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, trustKey, registryService, eventsService)
if err != nil {
return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
}
trustDir := path.Join(config.Root, "trust")
if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) {
return nil, err
}
t, err := trust.NewTrustStore(trustDir)
trustService, err := trust.NewTrustStore(trustDir)
if err != nil {
return nil, fmt.Errorf("could not create trust store: %s", err)
}
eventsService := events.New()
logrus.Debug("Creating repository list")
tagCfg := &graph.TagStoreConfig{
Graph: g,
Key: trustKey,
Registry: registryService,
Events: eventsService,
Trust: trustService,
}
repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), tagCfg)
if err != nil {
return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
}
if !config.DisableNetwork {
if err := bridge.InitDriver(&config.Bridge); err != nil {
return nil, fmt.Errorf("Error initializing Bridge: %v", err)
@ -980,7 +981,6 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine, registryService
sysInitPath: sysInitPath,
execDriver: ed,
eng: eng,
trustStore: t,
statsCollector: newStatsCollector(1 * time.Second),
defaultLogConfig: config.LogConfig,
RegistryService: registryService,

View file

@ -22,7 +22,7 @@ Using an existing container's name or ID you can create a new image.
**-c** , **--change**=[]
Apply specified Dockerfile instructions while committing the image
Supported Dockerfile instructions: `ADD`|`CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`FROM`|`MAINTAINER`|`RUN`|`USER`|`LABEL`|`VOLUME`|`WORKDIR`|`COPY`
Supported Dockerfile instructions: `CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`ONBUILD`|`USER`|`VOLUME`|`WORKDIR`
**--help**
Print usage statement

View file

@ -13,7 +13,7 @@ URL|- [REPOSITORY[:TAG]]
# OPTIONS
**-c**, **--change**=[]
Apply specified Dockerfile instructions while importing the image
Supported Dockerfile instructions: `ADD`|`CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`FROM`|`MAINTAINER`|`RUN`|`USER`|`LABEL`|`VOLUME`|`WORKDIR`|`COPY`
Supported Dockerfile instructions: `CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`ONBUILD`|`USER`|`VOLUME`|`WORKDIR`
# DESCRIPTION
Create a new filesystem image from the contents of a tarball (`.tar`,

View file

@ -870,7 +870,8 @@ If this behavior is undesired, set the 'p' option to false.
The `--change` option will apply `Dockerfile` instructions to the image
that is created.
Supported `Dockerfile` instructions: `ADD`|`CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`FROM`|`MAINTAINER`|`RUN`|`USER`|`LABEL`|`VOLUME`|`WORKDIR`|`COPY`
Supported `Dockerfile` instructions:
`CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`ONBUILD`|`USER`|`VOLUME`|`WORKDIR`
#### Commit a container
@ -1380,8 +1381,8 @@ the `-` parameter to take the data from `STDIN`.
The `--change` option will apply `Dockerfile` instructions to the image
that is created.
Supported `Dockerfile` instructions: `CMD`, `ENTRYPOINT`, `ENV`, `EXPOSE`,
`ONBUILD`, `USER`, `VOLUME`, `WORKDIR`
Supported `Dockerfile` instructions:
`CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`ONBUILD`|`USER`|`VOLUME`|`WORKDIR`
#### Examples

View file

@ -25,8 +25,8 @@ System*](/terms/layer/#union-file-system). Data volumes provide several
useful features for persistent or shared data:
- Volumes are initialized when a container is created. If the container's
base image contains data at the specified mount point, that data is
copied into the new volume.
base image contains data at the specified mount point, that existing data is
copied into the new volume upon volume initialization.
- Data volumes can be shared and reused among containers.
- Changes to a data volume are made directly.
- Changes to a data volume will not be included when you update an image.

View file

@ -139,19 +139,16 @@ func (s *TagStore) exportImage(eng *engine.Engine, name, tempdir string) error {
if err != nil {
return err
}
job = eng.Job("image_tarlayer", n)
job.Stdout.Add(fsTar)
if err := job.Run(); err != nil {
if err := s.ImageTarLayer(n, fsTar); err != nil {
return err
}
// find parent
job = eng.Job("image_get", n)
info, _ := job.Stdout.AddEnv()
if err := job.Run(); err != nil {
img, err := s.LookupImage(n)
if err != nil {
return err
}
n = info.Get("Parent")
n = img.Parent
}
return nil
}

View file

@ -1,4 +1,4 @@
package docker
package graph
import (
"errors"
@ -11,9 +11,7 @@ import (
"github.com/docker/docker/autogen/dockerversion"
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/graph"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/stringid"
)
@ -47,6 +45,7 @@ func TestMount(t *testing.T) {
if _, err := driver.Get(image.ID, ""); err != nil {
t.Fatal(err)
}
}
func TestInit(t *testing.T) {
@ -166,18 +165,6 @@ func TestDeletePrefix(t *testing.T) {
assertNImages(graph, t, 0)
}
func createTestImage(graph *graph.Graph, t *testing.T) *image.Image {
archive, err := fakeTar()
if err != nil {
t.Fatal(err)
}
img, err := graph.Create(archive, "", "", "Test image", "", nil, nil)
if err != nil {
t.Fatal(err)
}
return img
}
func TestDelete(t *testing.T) {
graph, _ := tempGraph(t)
defer nukeGraph(graph)
@ -277,11 +264,19 @@ func TestByParent(t *testing.T) {
}
}
/*
* HELPER FUNCTIONS
*/
func createTestImage(graph *Graph, t *testing.T) *image.Image {
archive, err := fakeTar()
if err != nil {
t.Fatal(err)
}
img, err := graph.Create(archive, "", "", "Test image", "", nil, nil)
if err != nil {
t.Fatal(err)
}
return img
}
func assertNImages(graph *graph.Graph, t *testing.T, n int) {
func assertNImages(graph *Graph, t *testing.T, n int) {
if images, err := graph.Map(); err != nil {
t.Fatal(err)
} else if actualN := len(images); actualN != n {
@ -289,7 +284,7 @@ func assertNImages(graph *graph.Graph, t *testing.T, n int) {
}
}
func tempGraph(t *testing.T) (*graph.Graph, graphdriver.Driver) {
func tempGraph(t *testing.T) (*Graph, graphdriver.Driver) {
tmp, err := ioutil.TempDir("", "docker-graph-")
if err != nil {
t.Fatal(err)
@ -298,22 +293,14 @@ func tempGraph(t *testing.T) (*graph.Graph, graphdriver.Driver) {
if err != nil {
t.Fatal(err)
}
graph, err := graph.NewGraph(tmp, driver)
graph, err := NewGraph(tmp, driver)
if err != nil {
t.Fatal(err)
}
return graph, driver
}
func nukeGraph(graph *graph.Graph) {
func nukeGraph(graph *Graph) {
graph.Driver().Cleanup()
os.RemoveAll(graph.Root)
}
func testArchive(t *testing.T) archive.Archive {
archive, err := fakeTar()
if err != nil {
t.Fatal(err)
}
return archive
}

View file

@ -80,7 +80,7 @@ func (s *TagStore) CmdLoad(job *engine.Job) error {
}
func (s *TagStore) recursiveLoad(eng *engine.Engine, address, tmpImageDir string) error {
if err := eng.Job("image_get", address).Run(); err != nil {
if _, err := s.LookupImage(address); err != nil {
logrus.Debugf("Loading %s", address)
imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))

View file

@ -1,14 +1,13 @@
package graph
import (
"bytes"
"encoding/json"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/digest"
"github.com/docker/docker/engine"
"github.com/docker/docker/registry"
"github.com/docker/docker/trust"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
)
@ -18,7 +17,7 @@ import (
// contains no signatures by a trusted key for the name in the manifest, the
// image is not considered verified. The parsed manifest object and a boolean
// for whether the manifest is verified is returned.
func (s *TagStore) loadManifest(eng *engine.Engine, manifestBytes []byte, dgst, ref string) (*registry.ManifestData, bool, error) {
func (s *TagStore) loadManifest(manifestBytes []byte, dgst, ref string) (*registry.ManifestData, bool, error) {
sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures")
if err != nil {
return nil, false, fmt.Errorf("error parsing payload: %s", err)
@ -69,32 +68,28 @@ func (s *TagStore) loadManifest(eng *engine.Engine, manifestBytes []byte, dgst,
var verified bool
for _, key := range keys {
job := eng.Job("trust_key_check")
b, err := key.MarshalJSON()
if err != nil {
return nil, false, fmt.Errorf("error marshalling public key: %s", err)
}
namespace := manifest.Name
if namespace[0] != '/' {
namespace = "/" + namespace
}
stdoutBuffer := bytes.NewBuffer(nil)
job.Args = append(job.Args, namespace)
job.Setenv("PublicKey", string(b))
// Check key has read/write permission (0x03)
job.SetenvInt("Permission", 0x03)
job.Stdout.Add(stdoutBuffer)
if err = job.Run(); err != nil {
return nil, false, fmt.Errorf("error running key check: %s", err)
b, err := key.MarshalJSON()
if err != nil {
return nil, false, fmt.Errorf("error marshalling public key: %s", err)
}
result := engine.Tail(stdoutBuffer, 1)
logrus.Debugf("Key check result: %q", result)
if result == "verified" {
verified = true
// Check key has read/write permission (0x03)
v, err := s.trustService.CheckKey(namespace, b, 0x03)
if err != nil {
vErr, ok := err.(trust.NotVerifiedError)
if !ok {
return nil, false, fmt.Errorf("error running key check: %s", err)
}
logrus.Debugf("Key check result: %v", vErr)
}
verified = v
if verified {
logrus.Debug("Key check result: verified")
}
}
return &manifest, verified, nil
}

View file

@ -12,7 +12,6 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/digest"
"github.com/docker/docker/engine"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/progressreader"
"github.com/docker/docker/pkg/streamformatter"
@ -29,7 +28,7 @@ type ImagePullConfig struct {
OutStream io.Writer
}
func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConfig, eng *engine.Engine) error {
func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConfig) error {
var (
sf = streamformatter.NewStreamFormatter(imagePullConfig.Json)
)
@ -70,14 +69,11 @@ func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConf
if len(repoInfo.Index.Mirrors) == 0 && (repoInfo.Index.Official || endpoint.Version == registry.APIVersion2) {
if repoInfo.Official {
j := eng.Job("trust_update_base")
if err = j.Run(); err != nil {
logrus.Errorf("error updating trust base graph: %s", err)
}
s.trustService.UpdateBase()
}
logrus.Debugf("pulling v2 repository with local name %q", repoInfo.LocalName)
if err := s.pullV2Repository(eng, r, imagePullConfig.OutStream, repoInfo, tag, sf, imagePullConfig.Parallel); err == nil {
if err := s.pullV2Repository(r, imagePullConfig.OutStream, repoInfo, tag, sf, imagePullConfig.Parallel); err == nil {
s.eventsService.Log("pull", logName, "")
return nil
} else if err != registry.ErrDoesNotExist && err != ErrV2RegistryUnavailable {
@ -372,7 +368,7 @@ type downloadInfo struct {
err chan error
}
func (s *TagStore) pullV2Repository(eng *engine.Engine, r *registry.Session, out io.Writer, repoInfo *registry.RepositoryInfo, tag string, sf *streamformatter.StreamFormatter, parallel bool) error {
func (s *TagStore) pullV2Repository(r *registry.Session, out io.Writer, repoInfo *registry.RepositoryInfo, tag string, sf *streamformatter.StreamFormatter, parallel bool) error {
endpoint, err := r.V2RegistryEndpoint(repoInfo.Index)
if err != nil {
if repoInfo.Index.Official {
@ -396,14 +392,14 @@ func (s *TagStore) pullV2Repository(eng *engine.Engine, r *registry.Session, out
return registry.ErrDoesNotExist
}
for _, t := range tags {
if downloaded, err := s.pullV2Tag(eng, r, out, endpoint, repoInfo, t, sf, parallel, auth); err != nil {
if downloaded, err := s.pullV2Tag(r, out, endpoint, repoInfo, t, sf, parallel, auth); err != nil {
return err
} else if downloaded {
layersDownloaded = true
}
}
} else {
if downloaded, err := s.pullV2Tag(eng, r, out, endpoint, repoInfo, tag, sf, parallel, auth); err != nil {
if downloaded, err := s.pullV2Tag(r, out, endpoint, repoInfo, tag, sf, parallel, auth); err != nil {
return err
} else if downloaded {
layersDownloaded = true
@ -418,7 +414,7 @@ func (s *TagStore) pullV2Repository(eng *engine.Engine, r *registry.Session, out
return nil
}
func (s *TagStore) pullV2Tag(eng *engine.Engine, r *registry.Session, out io.Writer, endpoint *registry.Endpoint, repoInfo *registry.RepositoryInfo, tag string, sf *streamformatter.StreamFormatter, parallel bool, auth *registry.RequestAuthorization) (bool, error) {
func (s *TagStore) pullV2Tag(r *registry.Session, out io.Writer, endpoint *registry.Endpoint, repoInfo *registry.RepositoryInfo, tag string, sf *streamformatter.StreamFormatter, parallel bool, auth *registry.RequestAuthorization) (bool, error) {
logrus.Debugf("Pulling tag from V2 registry: %q", tag)
manifestBytes, manifestDigest, err := r.GetV2ImageManifest(endpoint, repoInfo.RemoteName, tag, auth)
@ -428,7 +424,7 @@ func (s *TagStore) pullV2Tag(eng *engine.Engine, r *registry.Session, out io.Wri
// loadManifest ensures that the manifest payload has the expected digest
// if the tag is a digest reference.
manifest, verified, err := s.loadManifest(eng, manifestBytes, manifestDigest, tag)
manifest, verified, err := s.loadManifest(manifestBytes, manifestDigest, tag)
if err != nil {
return false, fmt.Errorf("error verifying manifest: %s", err)
}

View file

@ -6,19 +6,15 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/engine"
"github.com/docker/docker/image"
)
func (s *TagStore) Install(eng *engine.Engine) error {
for name, handler := range map[string]engine.Handler{
"image_set": s.CmdSet,
"image_get": s.CmdGet,
"image_inspect": s.CmdLookup,
"image_tarlayer": s.CmdTarLayer,
"image_export": s.CmdImageExport,
"viz": s.CmdViz,
"load": s.CmdLoad,
"push": s.CmdPush,
"image_inspect": s.CmdLookup,
"image_export": s.CmdImageExport,
"viz": s.CmdViz,
"load": s.CmdLoad,
"push": s.CmdPush,
} {
if err := eng.Register(name, handler); err != nil {
return fmt.Errorf("Could not register %q: %v", name, err)
@ -27,93 +23,6 @@ func (s *TagStore) Install(eng *engine.Engine) error {
return nil
}
// CmdSet stores a new image in the graph.
// Images are stored in the graph using 4 elements:
// - A user-defined ID
// - A collection of metadata describing the image
// - A directory tree stored as a tar archive (also called the "layer")
// - A reference to a "parent" ID on top of which the layer should be applied
//
// NOTE: even though the parent ID is only useful in relation to the layer and how
// to apply it (ie you could represent the full directory tree as 'parent_layer + layer',
// it is treated as a top-level property of the image. This is an artifact of early
// design and should probably be cleaned up in the future to simplify the design.
//
// Syntax: image_set ID
// Input:
// - Layer content must be streamed in tar format on stdin. An empty input is
// valid and represents a nil layer.
//
// - Image metadata must be passed in the command environment.
// 'json': a json-encoded object with all image metadata.
// It will be stored as-is, without any encoding/decoding artifacts.
// That is a requirement of the current registry client implementation,
// because a re-encoded json might invalidate the image checksum at
// the next upload, even with functionaly identical content.
func (s *TagStore) CmdSet(job *engine.Job) error {
if len(job.Args) != 1 {
return fmt.Errorf("usage: %s NAME", job.Name)
}
var (
imgJSON = []byte(job.Getenv("json"))
layer = job.Stdin
)
if len(imgJSON) == 0 {
return fmt.Errorf("mandatory key 'json' is not set")
}
// We have to pass an *image.Image object, even though it will be completely
// ignored in favor of the redundant json data.
// FIXME: the current prototype of Graph.Register is redundant.
img, err := image.NewImgJSON(imgJSON)
if err != nil {
return err
}
if err := s.graph.Register(img, layer); err != nil {
return err
}
return nil
}
// CmdGet returns information about an image.
// If the image doesn't exist, an empty object is returned, to allow
// checking for an image's existence.
func (s *TagStore) CmdGet(job *engine.Job) error {
if len(job.Args) != 1 {
return fmt.Errorf("usage: %s NAME", job.Name)
}
name := job.Args[0]
res := &engine.Env{}
img, err := s.LookupImage(name)
// Note: if the image doesn't exist, LookupImage returns
// nil, nil.
if err != nil {
return err
}
if img != nil {
// We don't directly expose all fields of the Image objects,
// to maintain a clean public API which we can maintain over
// time even if the underlying structure changes.
// We should have done this with the Image object to begin with...
// but we didn't, so now we're doing it here.
//
// Fields that we're probably better off not including:
// - Config/ContainerConfig. Those structs have the same sprawl problem,
// so we shouldn't include them wholesale either.
// - Comment: initially created to fulfill the "every image is a git commit"
// metaphor, in practice people either ignore it or use it as a
// generic description field which it isn't. On deprecation shortlist.
res.SetAuto("Created", img.Created)
res.SetJson("Author", img.Author)
res.Set("Os", img.OS)
res.Set("Architecture", img.Architecture)
res.Set("DockerVersion", img.DockerVersion)
res.SetJson("Id", img.ID)
res.SetJson("Parent", img.Parent)
}
res.WriteTo(job.Stdout)
return nil
}
// CmdLookup return an image encoded in JSON
func (s *TagStore) CmdLookup(job *engine.Job) error {
if len(job.Args) != 1 {
@ -152,12 +61,8 @@ func (s *TagStore) CmdLookup(job *engine.Job) error {
return fmt.Errorf("No such image: %s", name)
}
// CmdTarLayer return the tarLayer of the image
func (s *TagStore) CmdTarLayer(job *engine.Job) error {
if len(job.Args) != 1 {
return fmt.Errorf("usage: %s NAME", job.Name)
}
name := job.Args[0]
// ImageTarLayer return the tarLayer of the image
func (s *TagStore) ImageTarLayer(name string, dest io.Writer) error {
if image, err := s.LookupImage(name); err == nil && image != nil {
fs, err := image.TarLayer()
if err != nil {
@ -165,7 +70,7 @@ func (s *TagStore) CmdTarLayer(job *engine.Job) error {
}
defer fs.Close()
written, err := io.Copy(job.Stdout, fs)
written, err := io.Copy(dest, fs)
if err != nil {
return err
}

View file

@ -18,6 +18,7 @@ import (
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/registry"
"github.com/docker/docker/trust"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
)
@ -42,6 +43,7 @@ type TagStore struct {
pushingPool map[string]chan struct{}
registryService *registry.Service
eventsService *events.Events
trustService *trust.TrustStore
}
type Repository map[string]string
@ -64,7 +66,15 @@ func (r Repository) Contains(u Repository) bool {
return true
}
func NewTagStore(path string, graph *Graph, key libtrust.PrivateKey, registryService *registry.Service, eventsService *events.Events) (*TagStore, error) {
type TagStoreConfig struct {
Graph *Graph
Key libtrust.PrivateKey
Registry *registry.Service
Events *events.Events
Trust *trust.TrustStore
}
func NewTagStore(path string, cfg *TagStoreConfig) (*TagStore, error) {
abspath, err := filepath.Abs(path)
if err != nil {
return nil, err
@ -72,13 +82,14 @@ func NewTagStore(path string, graph *Graph, key libtrust.PrivateKey, registrySer
store := &TagStore{
path: abspath,
graph: graph,
trustKey: key,
graph: cfg.Graph,
trustKey: cfg.Key,
Repositories: make(map[string]Repository),
pullingPool: make(map[string]chan struct{}),
pushingPool: make(map[string]chan struct{}),
registryService: registryService,
eventsService: eventsService,
registryService: cfg.Registry,
eventsService: cfg.Events,
trustService: cfg.Trust,
}
// Load the json file if it exists, otherwise create it.
if err := store.reload(); os.IsNotExist(err) {

View file

@ -60,7 +60,11 @@ func mkTestTagStore(root string, t *testing.T) *TagStore {
if err != nil {
t.Fatal(err)
}
store, err := NewTagStore(path.Join(root, "tags"), graph, nil, nil, events.New())
tagCfg := &TagStoreConfig{
Graph: graph,
Events: events.New(),
}
store, err := NewTagStore(path.Join(root, "tags"), tagCfg)
if err != nil {
t.Fatal(err)
}

View file

@ -60,7 +60,7 @@ for HIER in $(cut -d: -f2 /proc/1/cgroup); do
mkdir -p "$CGROUP/$HIER"
if ! mountpoint -q $CGROUP/$HIER; then
if ! mountpoint -q "$CGROUP/$HIER"; then
mount -n -t cgroup -o "$OHIER" cgroup "$CGROUP/$HIER"
fi

View file

@ -126,7 +126,7 @@ do_install() {
exit 0
;;
ubuntu|debian|linuxmint|'elementary os')
ubuntu|debian|linuxmint|'elementary os'|kali)
export DEBIAN_FRONTEND=noninteractive
did_apt_get_update=

View file

@ -24,10 +24,12 @@ set -e
set -o pipefail
export DOCKER_PKG='github.com/docker/docker'
export SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export MAKEDIR="$SCRIPTDIR/make"
# We're a nice, sexy, little shell script, and people might try to run us;
# but really, they shouldn't. We want to be in a container!
if [ "$(pwd)" != "/go/src/$DOCKER_PKG" ] || [ -z "$DOCKER_CROSSPLATFORMS" ]; then
if [ "$PWD" != "/go/src/$DOCKER_PKG" ] || [ -z "$DOCKER_CROSSPLATFORMS" ]; then
{
echo "# WARNING! I don't seem to be running in the Docker container."
echo "# The result of this command might be an incorrect build, and will not be"
@ -62,7 +64,7 @@ DEFAULT_BUNDLES=(
ubuntu
)
VERSION=$(cat ./VERSION)
VERSION=$(< ./VERSION)
if command -v git &> /dev/null && git rev-parse &> /dev/null; then
GITCOMMIT=$(git rev-parse --short HEAD)
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
@ -82,7 +84,7 @@ if [ "$AUTO_GOPATH" ]; then
rm -rf .gopath
mkdir -p .gopath/src/"$(dirname "${DOCKER_PKG}")"
ln -sf ../../../.. .gopath/src/"${DOCKER_PKG}"
export GOPATH="$(pwd)/.gopath:$(pwd)/vendor"
export GOPATH="${PWD}/.gopath:${PWD}/vendor"
fi
if [ ! "$GOPATH" ]; then
@ -110,7 +112,7 @@ fi
# Use these flags when compiling the tests and final binary
IAMSTATIC='true'
source "$(dirname "$BASH_SOURCE")/make/.go-autogen"
source "$SCRIPTDIR/make/.go-autogen"
LDFLAGS='-w'
LDFLAGS_STATIC='-linkmode external'
@ -251,7 +253,7 @@ bundle() {
bundlescript=$1
bundle=$(basename $bundlescript)
echo "---> Making bundle: $bundle (in bundles/$VERSION/$bundle)"
mkdir -p bundles/$VERSION/$bundle
mkdir -p "bundles/$VERSION/$bundle"
source "$bundlescript" "$(pwd)/bundles/$VERSION/$bundle"
}
@ -261,23 +263,22 @@ main() {
mkdir -p bundles
if [ -e "bundles/$VERSION" ]; then
echo "bundles/$VERSION already exists. Removing."
rm -fr bundles/$VERSION && mkdir bundles/$VERSION || exit 1
rm -fr "bundles/$VERSION" && mkdir "bundles/$VERSION" || exit 1
echo
fi
if [ "$(go env GOHOSTOS)" != 'windows' ]; then
# Windows and symlinks don't get along well
ln -sfT $VERSION bundles/latest
ln -sfT "$VERSION" bundles/latest
fi
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ $# -lt 1 ]; then
bundles=(${DEFAULT_BUNDLES[@]})
else
bundles=($@)
fi
for bundle in ${bundles[@]}; do
bundle $SCRIPTDIR/make/$bundle
bundle "$SCRIPTDIR/make/$bundle"
echo
done
}

View file

@ -2,7 +2,7 @@
set -e
IAMSTATIC="true"
source "$(dirname "$BASH_SOURCE")/.go-autogen"
source "${MAKEDIR}/.go-autogen"
# dockerinit still needs to be a static binary, even if docker is dynamic
go build \
@ -30,4 +30,4 @@ else
fi
# sha1 our new dockerinit to ensure separate docker and dockerinit always run in a perfect pair compiled for one another
export DOCKER_INITSHA1="$($sha1sum $DEST/dockerinit-$VERSION | cut -d' ' -f1)"
export DOCKER_INITSHA1=$($sha1sum "$DEST/dockerinit-$VERSION" | cut -d' ' -f1)

View file

@ -2,7 +2,7 @@
set -e
IAMSTATIC="true"
source "$(dirname "$BASH_SOURCE")/.go-autogen"
source "${MAKEDIR}/.go-autogen"
# dockerinit still needs to be a static binary, even if docker is dynamic
go build --compiler=gccgo \
@ -28,4 +28,4 @@ else
fi
# sha1 our new dockerinit to ensure separate docker and dockerinit always run in a perfect pair compiled for one another
export DOCKER_INITSHA1="$($sha1sum $DEST/dockerinit-$VERSION | cut -d' ' -f1)"
export DOCKER_INITSHA1=$($sha1sum "$DEST/dockerinit-$VERSION" | cut -d' ' -f1)

View file

@ -2,8 +2,8 @@
for pidFile in $(find "$DEST" -name docker.pid); do
pid=$(set -x; cat "$pidFile")
( set -x; kill $pid )
if ! wait $pid; then
( set -x; kill "$pid" )
if ! wait "$pid"; then
echo >&2 "warning: PID $pid from $pidFile had a nonzero exit code"
fi
done

View file

@ -11,7 +11,7 @@ if [[ "$(uname -s)" == CYGWIN* ]]; then
DEST=$(cygpath -mw $DEST)
fi
source "$(dirname "$BASH_SOURCE")/.go-autogen"
source "${MAKEDIR}/.go-autogen"
go build \
-o "$DEST/$BINARY_FULLNAME" \

View file

@ -5,7 +5,7 @@ DEST=$1
# subshell so that we can export PATH without breaking other things
(
source "$(dirname "$BASH_SOURCE")/.integration-daemon-start"
source "${MAKEDIR}/.integration-daemon-start"
# we need to wrap up everything in between integration-daemon-start and
# integration-daemon-stop to make sure we kill the daemon and don't hang,
@ -76,7 +76,7 @@ DEST=$1
# clean up after ourselves
rm -f Dockerfile.build
source "$(dirname "$BASH_SOURCE")/.integration-daemon-stop"
source "${MAKEDIR}/.integration-daemon-stop"
[ -z "$didFail" ] # "set -e" ftw
) 2>&1 | tee -a $DEST/test.log

View file

@ -28,6 +28,6 @@ for platform in $DOCKER_CROSSPLATFORMS; do
export LDFLAGS_STATIC_DOCKER="" # we just need a simple client for these platforms
export BUILDFLAGS=( "${ORIG_BUILDFLAGS[@]/ daemon/}" ) # remove the "daemon" build tag from platforms that aren't supported
fi
source "$(dirname "$BASH_SOURCE")/binary" "$DEST/$platform"
source "${MAKEDIR}/binary" "$DEST/$platform"
)
done

View file

@ -4,7 +4,7 @@ set -e
DEST=$1
if [ -z "$DOCKER_CLIENTONLY" ]; then
source "$(dirname "$BASH_SOURCE")/.dockerinit"
source "${MAKEDIR}/.dockerinit"
hash_files "$DEST/dockerinit-$VERSION"
else
@ -18,5 +18,5 @@ fi
export LDFLAGS_STATIC_DOCKER=''
export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary
export BUILDFLAGS=( "${BUILDFLAGS[@]/static_build /}" ) # we're not building a "static" binary here
source "$(dirname "$BASH_SOURCE")/binary"
source "${MAKEDIR}/binary"
)

View file

@ -4,7 +4,7 @@ set -e
DEST=$1
if [ -z "$DOCKER_CLIENTONLY" ]; then
source "$(dirname "$BASH_SOURCE")/.dockerinit-gccgo"
source "${MAKEDIR}/.dockerinit-gccgo"
hash_files "$DEST/dockerinit-$VERSION"
else
@ -19,5 +19,5 @@ fi
export LDFLAGS_STATIC_DOCKER=''
export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary
export BUILDFLAGS=( "${BUILDFLAGS[@]/static_build /}" ) # we're not building a "static" binary here
source "$(dirname "$BASH_SOURCE")/gccgo"
source "${MAKEDIR}/gccgo"
)

View file

@ -6,7 +6,7 @@ BINARY_NAME="docker-$VERSION"
BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
source "$(dirname "$BASH_SOURCE")/.go-autogen"
source "${MAKEDIR}/.go-autogen"
if [[ "${BUILDFLAGS[@]}" =~ 'netgo ' ]]; then
EXTLDFLAGS_STATIC_DOCKER+=' -lnetgo'

View file

@ -5,7 +5,7 @@ DEST=$1
# subshell so that we can export PATH without breaking other things
(
source "$(dirname "$BASH_SOURCE")/.integration-daemon-start"
source "${MAKEDIR}/.integration-daemon-start"
# we need to wrap up everything in between integration-daemon-start and
# integration-daemon-stop to make sure we kill the daemon and don't hang,
@ -24,7 +24,7 @@ DEST=$1
didFail=1
fi
source "$(dirname "$BASH_SOURCE")/.integration-daemon-stop"
source "${MAKEDIR}/.integration-daemon-stop"
[ -z "$didFail" ] # "set -e" ftw
) 2>&1 | tee -a $DEST/test.log

View file

@ -5,7 +5,7 @@ DEST=$1
INIT=$DEST/../dynbinary/dockerinit-$VERSION
[ -x "$INIT" ] || {
source "$(dirname "$BASH_SOURCE")/.dockerinit"
source "${MAKEDIR}/.dockerinit"
INIT="$DEST/dockerinit"
}
export TEST_DOCKERINIT_PATH="$INIT"
@ -22,4 +22,4 @@ bundle_test_integration() {
# spews when it is given packages that aren't used
bundle_test_integration 2>&1 \
| grep --line-buffered -v '^warning: no packages being tested depend on ' \
| tee -a $DEST/test.log
| tee -a "$DEST/test.log"

View file

@ -9,23 +9,23 @@ bundle_test_integration_cli() {
# subshell so that we can export PATH without breaking other things
(
source "$(dirname "$BASH_SOURCE")/.integration-daemon-start"
source "${MAKEDIR}/.integration-daemon-start"
# we need to wrap up everything in between integration-daemon-start and
# integration-daemon-stop to make sure we kill the daemon and don't hang,
# even and especially on test failures
didFail=
if ! {
source "$(dirname "$BASH_SOURCE")/.ensure-frozen-images"
source "$(dirname "$BASH_SOURCE")/.ensure-httpserver"
source "$(dirname "$BASH_SOURCE")/.ensure-emptyfs"
source "${MAKEDIR}/.ensure-frozen-images"
source "${MAKEDIR}/.ensure-httpserver"
source "${MAKEDIR}/.ensure-emptyfs"
bundle_test_integration_cli
}; then
didFail=1
fi
source "$(dirname "$BASH_SOURCE")/.integration-daemon-stop"
source "${MAKEDIR}/.integration-daemon-stop"
[ -z "$didFail" ] # "set -e" ftw
) 2>&1 | tee -a $DEST/test.log
) 2>&1 | tee -a "$DEST/test.log"

View file

@ -39,12 +39,12 @@ bundle_test_unit() {
mkdir -p "$HOME/.parallel"
touch "$HOME/.parallel/ignored_vars"
echo "$TESTDIRS" | parallel --jobs "$PARALLEL_JOBS" --env _ "$(dirname "$BASH_SOURCE")/.go-compile-test-dir"
echo "$TESTDIRS" | parallel --jobs "$PARALLEL_JOBS" --env _ "${MAKEDIR}/.go-compile-test-dir"
rm -rf "$HOME"
else
# aww, no "parallel" available - fall back to boring
for test_dir in $TESTDIRS; do
"$(dirname "$BASH_SOURCE")/.go-compile-test-dir" "$test_dir" || true
"${MAKEDIR}/.go-compile-test-dir" "$test_dir" || true
# don't let one directory that fails to build tank _all_ our tests!
done
fi
@ -85,4 +85,4 @@ go_run_test_dir() {
fi
}
bundle_test_unit 2>&1 | tee -a $DEST/test.log
bundle_test_unit 2>&1 | tee -a "$DEST/test.log"

View file

@ -40,26 +40,26 @@ bundle_ubuntu() {
DIR=$DEST/build
# Include our udev rules
mkdir -p $DIR/etc/udev/rules.d
cp contrib/udev/80-docker.rules $DIR/etc/udev/rules.d/
mkdir -p "$DIR/etc/udev/rules.d"
cp contrib/udev/80-docker.rules "$DIR/etc/udev/rules.d/"
# Include our init scripts
mkdir -p $DIR/etc/init
cp contrib/init/upstart/docker.conf $DIR/etc/init/
mkdir -p $DIR/etc/init.d
cp contrib/init/sysvinit-debian/docker $DIR/etc/init.d/
mkdir -p $DIR/etc/default
cp contrib/init/sysvinit-debian/docker.default $DIR/etc/default/docker
mkdir -p $DIR/lib/systemd/system
cp contrib/init/systemd/docker.{service,socket} $DIR/lib/systemd/system/
mkdir -p "$DIR/etc/init"
cp contrib/init/upstart/docker.conf "$DIR/etc/init/"
mkdir -p "$DIR/etc/init.d"
cp contrib/init/sysvinit-debian/docker "$DIR/etc/init.d/"
mkdir -p "$DIR/etc/default"
cp contrib/init/sysvinit-debian/docker.default "$DIR/etc/default/docker"
mkdir -p "$DIR/lib/systemd/system"
cp contrib/init/systemd/docker.{service,socket} "$DIR/lib/systemd/system/"
# Include contributed completions
mkdir -p $DIR/etc/bash_completion.d
cp contrib/completion/bash/docker $DIR/etc/bash_completion.d/
mkdir -p $DIR/usr/share/zsh/vendor-completions
cp contrib/completion/zsh/_docker $DIR/usr/share/zsh/vendor-completions/
mkdir -p $DIR/etc/fish/completions
cp contrib/completion/fish/docker.fish $DIR/etc/fish/completions/
mkdir -p "$DIR/etc/bash_completion.d"
cp contrib/completion/bash/docker "$DIR/etc/bash_completion.d/"
mkdir -p "$DIR/usr/share/zsh/vendor-completions"
cp contrib/completion/zsh/_docker "$DIR/usr/share/zsh/vendor-completions/"
mkdir -p "$DIR/etc/fish/completions"
cp contrib/completion/fish/docker.fish "$DIR/etc/fish/completions/"
# Include contributed man pages
docs/man/md2man-all.sh -q
@ -76,11 +76,11 @@ bundle_ubuntu() {
# Copy the binary
# This will fail if the binary bundle hasn't been built
mkdir -p $DIR/usr/bin
cp $DEST/../binary/docker-$VERSION $DIR/usr/bin/docker
mkdir -p "$DIR/usr/bin"
cp "$DEST/../binary/docker-$VERSION" "$DIR/usr/bin/docker"
# Generate postinst/prerm/postrm scripts
cat > $DEST/postinst <<'EOF'
cat > "$DEST/postinst" <<'EOF'
#!/bin/sh
set -e
set -u
@ -104,7 +104,7 @@ service docker $_dh_action 2>/dev/null || true
#DEBHELPER#
EOF
cat > $DEST/prerm <<'EOF'
cat > "$DEST/prerm" <<'EOF'
#!/bin/sh
set -e
set -u
@ -113,7 +113,7 @@ service docker stop 2>/dev/null || true
#DEBHELPER#
EOF
cat > $DEST/postrm <<'EOF'
cat > "$DEST/postrm" <<'EOF'
#!/bin/sh
set -e
set -u
@ -131,18 +131,18 @@ fi
#DEBHELPER#
EOF
# TODO swaths of these were borrowed from debhelper's auto-inserted stuff, because we're still using fpm - we need to use debhelper instead, and somehow reconcile Ubuntu that way
chmod +x $DEST/postinst $DEST/prerm $DEST/postrm
chmod +x "$DEST/postinst" "$DEST/prerm" "$DEST/postrm"
(
# switch directories so we create *.deb in the right folder
cd $DEST
cd "$DEST"
# create lxc-docker-VERSION package
fpm -s dir -C $DIR \
--name lxc-docker-$VERSION --version "$PKGVERSION" \
--after-install $DEST/postinst \
--before-remove $DEST/prerm \
--after-remove $DEST/postrm \
fpm -s dir -C "$DIR" \
--name "lxc-docker-$VERSION" --version "$PKGVERSION" \
--after-install "$DEST/postinst" \
--before-remove "$DEST/prerm" \
--after-remove "$DEST/postrm" \
--architecture "$PACKAGE_ARCHITECTURE" \
--prefix / \
--depends iptables \
@ -184,8 +184,8 @@ EOF
)
# clean up after ourselves so we have a clean output directory
rm $DEST/postinst $DEST/prerm $DEST/postrm
rm -r $DIR
rm "$DEST/postinst" "$DEST/prerm" "$DEST/postrm"
rm -r "$DIR"
}
bundle_ubuntu

View file

@ -1,6 +1,6 @@
#!/bin/bash
source "$(dirname "$BASH_SOURCE")/.validate"
source "${MAKEDIR}/.validate"
adds=$(validate_diff --numstat | awk '{ s += $1 } END { print s }')
dels=$(validate_diff --numstat | awk '{ s += $2 } END { print s }')

View file

@ -1,6 +1,6 @@
#!/bin/bash
source "$(dirname "$BASH_SOURCE")/.validate"
source "${MAKEDIR}/.validate"
IFS=$'\n'
files=( $(validate_diff --diff-filter=ACMR --name-only -- '*.go' | grep -v '^vendor/' || true) )

View file

@ -1,6 +1,6 @@
#!/bin/bash
source "$(dirname "$BASH_SOURCE")/.validate"
source "${MAKEDIR}/.validate"
IFS=$'\n'
files=( $(validate_diff --diff-filter=ACMR --name-only -- 'MAINTAINERS' || true) )

View file

@ -1,6 +1,6 @@
#!/bin/bash
source "$(dirname "$BASH_SOURCE")/.validate"
source "${MAKEDIR}/.validate"
IFS=$'\n'
files=( $(validate_diff --diff-filter=ACMR --name-only -- '*.go' | grep -v '^vendor/' || true) )

View file

@ -60,7 +60,7 @@ if [ "$1" != '--release-regardless-of-test-failure' ]; then
)
fi
VERSION=$(cat VERSION)
VERSION=$(< VERSION)
BUCKET=$AWS_S3_BUCKET
# These are the 2 keys we've used to sign the deb's
@ -71,23 +71,23 @@ BUCKET=$AWS_S3_BUCKET
setup_s3() {
# Try creating the bucket. Ignore errors (it might already exist).
s3cmd mb s3://$BUCKET 2>/dev/null || true
s3cmd mb "s3://$BUCKET" 2>/dev/null || true
# Check access to the bucket.
# s3cmd has no useful exit status, so we cannot check that.
# Instead, we check if it outputs anything on standard output.
# (When there are problems, it uses standard error instead.)
s3cmd info s3://$BUCKET | grep -q .
s3cmd info "s3://$BUCKET" | grep -q .
# Make the bucket accessible through website endpoints.
s3cmd ws-create --ws-index index --ws-error error s3://$BUCKET
s3cmd ws-create --ws-index index --ws-error error "s3://$BUCKET"
}
# write_to_s3 uploads the contents of standard input to the specified S3 url.
write_to_s3() {
DEST=$1
F=`mktemp`
cat > $F
s3cmd --acl-public --mime-type='text/plain' put $F $DEST
rm -f $F
cat > "$F"
s3cmd --acl-public --mime-type='text/plain' put "$F" "$DEST"
rm -f "$F"
}
s3_url() {
@ -246,20 +246,20 @@ release_build() {
# 1. A full APT repository is published at $BUCKET/ubuntu/
# 2. Instructions for using the APT repository are uploaded at $BUCKET/ubuntu/index
release_ubuntu() {
[ -e bundles/$VERSION/ubuntu ] || {
[ -e "bundles/$VERSION/ubuntu" ] || {
echo >&2 './hack/make.sh must be run before release_ubuntu'
exit 1
}
# Sign our packages
dpkg-sig -g "--passphrase $GPG_PASSPHRASE" -k releasedocker \
--sign builder bundles/$VERSION/ubuntu/*.deb
--sign builder "bundles/$VERSION/ubuntu/"*.deb
# Setup the APT repo
APTDIR=bundles/$VERSION/ubuntu/apt
mkdir -p $APTDIR/conf $APTDIR/db
s3cmd sync s3://$BUCKET/ubuntu/db/ $APTDIR/db/ || true
cat > $APTDIR/conf/distributions <<EOF
mkdir -p "$APTDIR/conf" "$APTDIR/db"
s3cmd sync "s3://$BUCKET/ubuntu/db/" "$APTDIR/db/" || true
cat > "$APTDIR/conf/distributions" <<EOF
Codename: docker
Components: main
Architectures: amd64 i386
@ -267,19 +267,19 @@ EOF
# Add the DEB package to the APT repo
DEBFILE=bundles/$VERSION/ubuntu/lxc-docker*.deb
reprepro -b $APTDIR includedeb docker $DEBFILE
reprepro -b "$APTDIR" includedeb docker "$DEBFILE"
# Sign
for F in $(find $APTDIR -name Release); do
gpg -u releasedocker --passphrase $GPG_PASSPHRASE \
gpg -u releasedocker --passphrase "$GPG_PASSPHRASE" \
--armor --sign --detach-sign \
--output $F.gpg $F
--output "$F.gpg" "$F"
done
# Upload keys
s3cmd sync $HOME/.gnupg/ s3://$BUCKET/ubuntu/.gnupg/
gpg --armor --export releasedocker > bundles/$VERSION/ubuntu/gpg
s3cmd --acl-public put bundles/$VERSION/ubuntu/gpg s3://$BUCKET/gpg
s3cmd sync "$HOME/.gnupg/" "s3://$BUCKET/ubuntu/.gnupg/"
gpg --armor --export releasedocker > "bundles/$VERSION/ubuntu/gpg"
s3cmd --acl-public put "bundles/$VERSION/ubuntu/gpg" "s3://$BUCKET/gpg"
local gpgFingerprint=36A1D7869245C8950F966E92D8576A8BA88D21E9
if [[ $BUCKET == test* ]]; then
@ -287,7 +287,7 @@ EOF
fi
# Upload repo
s3cmd --acl-public sync $APTDIR/ s3://$BUCKET/ubuntu/
s3cmd --acl-public sync "$APTDIR/" "s3://$BUCKET/ubuntu/"
cat <<EOF | write_to_s3 s3://$BUCKET/ubuntu/index
# Check that HTTPS transport is available to APT
if [ ! -e /usr/lib/apt/methods/https ]; then
@ -312,14 +312,14 @@ EOF
# Add redirect at /ubuntu/info for URL-backwards-compatibility
rm -rf /tmp/emptyfile && touch /tmp/emptyfile
s3cmd --acl-public --add-header='x-amz-website-redirect-location:/ubuntu/' --mime-type='text/plain' put /tmp/emptyfile s3://$BUCKET/ubuntu/info
s3cmd --acl-public --add-header='x-amz-website-redirect-location:/ubuntu/' --mime-type='text/plain' put /tmp/emptyfile "s3://$BUCKET/ubuntu/info"
echo "APT repository uploaded. Instructions available at $(s3_url)/ubuntu"
}
# Upload binaries and tgz files to S3
release_binaries() {
[ -e bundles/$VERSION/cross/linux/amd64/docker-$VERSION ] || {
[ -e "bundles/$VERSION/cross/linux/amd64/docker-$VERSION" ] || {
echo >&2 './hack/make.sh must be run before release_binaries'
exit 1
}
@ -341,29 +341,29 @@ EOF
# Add redirect at /builds/info for URL-backwards-compatibility
rm -rf /tmp/emptyfile && touch /tmp/emptyfile
s3cmd --acl-public --add-header='x-amz-website-redirect-location:/builds/' --mime-type='text/plain' put /tmp/emptyfile s3://$BUCKET/builds/info
s3cmd --acl-public --add-header='x-amz-website-redirect-location:/builds/' --mime-type='text/plain' put /tmp/emptyfile "s3://$BUCKET/builds/info"
if [ -z "$NOLATEST" ]; then
echo "Advertising $VERSION on $BUCKET as most recent version"
echo $VERSION | write_to_s3 s3://$BUCKET/latest
echo "$VERSION" | write_to_s3 "s3://$BUCKET/latest"
fi
}
# Upload the index script
release_index() {
sed "s,url='https://get.docker.com/',url='$(s3_url)/'," hack/install.sh | write_to_s3 s3://$BUCKET/index
sed "s,url='https://get.docker.com/',url='$(s3_url)/'," hack/install.sh | write_to_s3 "s3://$BUCKET/index"
}
release_test() {
if [ -e "bundles/$VERSION/test" ]; then
s3cmd --acl-public sync bundles/$VERSION/test/ s3://$BUCKET/test/
s3cmd --acl-public sync "bundles/$VERSION/test/" "s3://$BUCKET/test/"
fi
}
setup_gpg() {
# Make sure that we have our keys
mkdir -p $HOME/.gnupg/
s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ $HOME/.gnupg/ || true
mkdir -p "$HOME/.gnupg/"
s3cmd sync "s3://$BUCKET/ubuntu/.gnupg/" "$HOME/.gnupg/" || true
gpg --list-keys releasedocker >/dev/null || {
gpg --gen-key --batch <<EOF
Key-Type: RSA

View file

@ -57,6 +57,8 @@ clone git github.com/Sirupsen/logrus v0.7.2
clone git github.com/go-fsnotify/fsnotify v1.0.4
clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673
# get Go tip's archive/tar, for xattr support and improved performance
# TODO after Go 1.4 drops, bump our minimum supported version and drop this vendored dep
if [ "$1" = '--go' ]; then

View file

@ -0,0 +1,34 @@
package main
import (
"fmt"
"testing"
"time"
"github.com/go-check/check"
)
func Test(t *testing.T) { check.TestingT(t) }
type TimerSuite struct {
start time.Time
}
func (s *TimerSuite) SetUpTest(c *check.C) {
s.start = time.Now()
}
func (s *TimerSuite) TearDownTest(c *check.C) {
fmt.Printf("%-60s%.2f\n", c.TestName(), time.Since(s.start).Seconds())
}
type DockerSuite struct {
TimerSuite
}
func (s *DockerSuite) TearDownTest(c *check.C) {
deleteAllContainers()
s.TimerSuite.TearDownTest(c)
}
var _ = check.Suite(&DockerSuite{})

View file

@ -4,23 +4,23 @@ import (
"bytes"
"os/exec"
"strings"
"testing"
"time"
"github.com/go-check/check"
"code.google.com/p/go.net/websocket"
)
func TestGetContainersAttachWebsocket(t *testing.T) {
func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-dit", "busybox", "cat")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
rwc, err := sockConn(time.Duration(10 * time.Second))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -29,12 +29,12 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
"http://localhost",
)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
ws, err := websocket.NewClient(config, rwc)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer ws.Close()
@ -43,7 +43,7 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
outChan := make(chan string)
go func() {
if _, err := ws.Read(actual); err != nil {
t.Fatal(err)
c.Fatal(err)
}
outChan <- "done"
}()
@ -51,7 +51,7 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
inChan := make(chan string)
go func() {
if _, err := ws.Write(expected); err != nil {
t.Fatal(err)
c.Fatal(err)
}
inChan <- "done"
}()
@ -60,8 +60,6 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
<-outChan
if !bytes.Equal(expected, actual) {
t.Fatal("Expected output on websocket to match input")
c.Fatal("Expected output on websocket to match input")
}
logDone("container attach websocket - can echo input via cat")
}

View file

@ -7,65 +7,59 @@ import (
"net/http"
"os/exec"
"strings"
"testing"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"github.com/go-check/check"
)
func TestContainerApiGetAll(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiGetAll(c *check.C) {
startCount, err := getContainerCount()
if err != nil {
t.Fatalf("Cannot query container count: %v", err)
c.Fatalf("Cannot query container count: %v", err)
}
name := "getall"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
_, body, err := sockRequest("GET", "/containers/json?all=1", nil)
if err != nil {
t.Fatalf("GET all containers sockRequest failed: %v", err)
c.Fatalf("GET all containers sockRequest failed: %v", err)
}
var inspectJSON []struct {
Names []string
}
if err = json.Unmarshal(body, &inspectJSON); err != nil {
t.Fatalf("unable to unmarshal response body: %v", err)
c.Fatalf("unable to unmarshal response body: %v", err)
}
if len(inspectJSON) != startCount+1 {
t.Fatalf("Expected %d container(s), %d found (started with: %d)", startCount+1, len(inspectJSON), startCount)
c.Fatalf("Expected %d container(s), %d found (started with: %d)", startCount+1, len(inspectJSON), startCount)
}
if actual := inspectJSON[0].Names[0]; actual != "/"+name {
t.Fatalf("Container Name mismatch. Expected: %q, received: %q\n", "/"+name, actual)
c.Fatalf("Container Name mismatch. Expected: %q, received: %q\n", "/"+name, actual)
}
logDone("container REST API - check GET json/all=1")
}
func TestContainerApiGetExport(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiGetExport(c *check.C) {
name := "exportcontainer"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
_, body, err := sockRequest("GET", "/containers/"+name+"/export", nil)
if err != nil {
t.Fatalf("GET containers/export sockRequest failed: %v", err)
c.Fatalf("GET containers/export sockRequest failed: %v", err)
}
found := false
@ -75,7 +69,7 @@ func TestContainerApiGetExport(t *testing.T) {
if err == io.EOF {
break
}
t.Fatal(err)
c.Fatal(err)
}
if h.Name == "test" {
found = true
@ -84,25 +78,21 @@ func TestContainerApiGetExport(t *testing.T) {
}
if !found {
t.Fatalf("The created test file has not been found in the exported image")
c.Fatalf("The created test file has not been found in the exported image")
}
logDone("container REST API - check GET containers/export")
}
func TestContainerApiGetChanges(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiGetChanges(c *check.C) {
name := "changescontainer"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "rm", "/etc/passwd")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
_, body, err := sockRequest("GET", "/containers/"+name+"/changes", nil)
if err != nil {
t.Fatalf("GET containers/changes sockRequest failed: %v", err)
c.Fatalf("GET containers/changes sockRequest failed: %v", err)
}
changes := []struct {
@ -110,7 +100,7 @@ func TestContainerApiGetChanges(t *testing.T) {
Path string
}{}
if err = json.Unmarshal(body, &changes); err != nil {
t.Fatalf("unable to unmarshal response body: %v", err)
c.Fatalf("unable to unmarshal response body: %v", err)
}
// Check the changelog for removal of /etc/passwd
@ -121,14 +111,11 @@ func TestContainerApiGetChanges(t *testing.T) {
}
}
if !success {
t.Fatalf("/etc/passwd has been removed but is not present in the diff")
c.Fatalf("/etc/passwd has been removed but is not present in the diff")
}
logDone("container REST API - check GET containers/changes")
}
func TestContainerApiStartVolumeBinds(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiStartVolumeBinds(c *check.C) {
name := "testing"
config := map[string]interface{}{
"Image": "busybox",
@ -136,7 +123,7 @@ func TestContainerApiStartVolumeBinds(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
bindPath := randomUnixTmpDirPath("test")
@ -144,24 +131,21 @@ func TestContainerApiStartVolumeBinds(t *testing.T) {
"Binds": []string{bindPath + ":/tmp"},
}
if status, _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
pth, err := inspectFieldMap(name, "Volumes", "/tmp")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if pth != bindPath {
t.Fatalf("expected volume host path to be %s, got %s", bindPath, pth)
c.Fatalf("expected volume host path to be %s, got %s", bindPath, pth)
}
logDone("container REST API - check volume binds on start")
}
// Test for GH#10618
func TestContainerApiStartDupVolumeBinds(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiStartDupVolumeBinds(c *check.C) {
name := "testdups"
config := map[string]interface{}{
"Image": "busybox",
@ -169,7 +153,7 @@ func TestContainerApiStartDupVolumeBinds(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
bindPath1 := randomUnixTmpDirPath("test1")
@ -179,22 +163,19 @@ func TestContainerApiStartDupVolumeBinds(t *testing.T) {
"Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"},
}
if _, body, err := sockRequest("POST", "/containers/"+name+"/start", config); err == nil {
t.Fatal("expected container start to fail when duplicate volume binds to same container path")
c.Fatal("expected container start to fail when duplicate volume binds to same container path")
} else {
if !strings.Contains(string(body), "Duplicate volume") {
t.Fatalf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)
c.Fatalf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)
}
}
logDone("container REST API - check for duplicate volume binds error on start")
}
func TestContainerApiStartVolumesFrom(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiStartVolumesFrom(c *check.C) {
volName := "voltst"
volPath := "/tmp"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
name := "testing"
@ -204,41 +185,38 @@ func TestContainerApiStartVolumesFrom(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
config = map[string]interface{}{
"VolumesFrom": []string{volName},
}
if status, _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
pth, err := inspectFieldMap(name, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
pth2, err := inspectFieldMap(volName, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if pth != pth2 {
t.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
c.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
}
logDone("container REST API - check VolumesFrom on start")
}
// Ensure that volumes-from has priority over binds/anything else
// This is pretty much the same as TestRunApplyVolumesFromBeforeVolumes, except with passing the VolumesFrom and the bind on start
func TestVolumesFromHasPriority(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestVolumesFromHasPriority(c *check.C) {
volName := "voltst2"
volPath := "/tmp"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
name := "testing"
@ -248,7 +226,7 @@ func TestVolumesFromHasPriority(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
bindPath := randomUnixTmpDirPath("test")
@ -257,34 +235,31 @@ func TestVolumesFromHasPriority(t *testing.T) {
"Binds": []string{bindPath + ":/tmp"},
}
if status, _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
pth, err := inspectFieldMap(name, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
pth2, err := inspectFieldMap(volName, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if pth != pth2 {
t.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
c.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
}
logDone("container REST API - check VolumesFrom has priority")
}
func TestGetContainerStats(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestGetContainerStats(c *check.C) {
var (
name = "statscontainer"
runCmd = exec.Command(dockerBinary, "run", "-d", "--name", name, "busybox", "top")
)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
type b struct {
body []byte
@ -299,38 +274,36 @@ func TestGetContainerStats(t *testing.T) {
// allow some time to stream the stats from the container
time.Sleep(4 * time.Second)
if _, err := runCommand(exec.Command(dockerBinary, "rm", "-f", name)); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// collect the results from the stats stream or timeout and fail
// if the stream was not disconnected.
select {
case <-time.After(2 * time.Second):
t.Fatal("stream was not closed after container was removed")
c.Fatal("stream was not closed after container was removed")
case sr := <-bc:
if sr.err != nil {
t.Fatal(sr.err)
c.Fatal(sr.err)
}
dec := json.NewDecoder(bytes.NewBuffer(sr.body))
var s *types.Stats
// decode only one object from the stream
if err := dec.Decode(&s); err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
logDone("container REST API - check GET containers/stats")
}
func TestGetStoppedContainerStats(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) {
var (
name = "statscontainer"
runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top")
)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
go func() {
@ -338,17 +311,15 @@ func TestGetStoppedContainerStats(t *testing.T) {
// just send request and see if panic or error would happen on daemon side.
_, _, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
}()
// allow some time to send request and let daemon deal with it
time.Sleep(1 * time.Second)
logDone("container REST API - check GET stopped containers/stats")
}
func TestBuildApiDockerfilePath(t *testing.T) {
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)
@ -360,33 +331,31 @@ func TestBuildApiDockerfilePath(t *testing.T) {
Name: "Dockerfile",
Size: int64(len(dockerfile)),
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
c.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write(dockerfile); err != nil {
t.Fatalf("failed to write tar file content: %v", err)
c.Fatalf("failed to write tar file content: %v", err)
}
if err := tw.Close(); err != nil {
t.Fatalf("failed to close tar archive: %v", err)
c.Fatalf("failed to close tar archive: %v", err)
}
_, body, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
if err == nil {
out, _ := readBody(body)
t.Fatalf("Build was supposed to fail: %s", out)
c.Fatalf("Build was supposed to fail: %s", out)
}
out, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !strings.Contains(string(out), "must be within the build context") {
t.Fatalf("Didn't complain about leaving build context: %s", out)
c.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile path")
}
func TestBuildApiDockerFileRemote(t *testing.T) {
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
server, err := fakeStorage(map[string]string{
"testD": `FROM busybox
COPY * /tmp/
@ -394,17 +363,17 @@ RUN find / -name ba*
RUN find /tmp/`,
})
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer server.Close()
_, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json")
if err != nil {
t.Fatalf("Build failed: %s", err)
c.Fatalf("Build failed: %s", err)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Make sure Dockerfile exists.
@ -412,41 +381,37 @@ RUN find /tmp/`,
out := string(buf)
if !strings.Contains(out, "/tmp/Dockerfile") ||
strings.Contains(out, "baz") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build with -f from remote")
}
func TestBuildApiLowerDockerfile(t *testing.T) {
func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
git, err := fakeGIT("repo", map[string]string{
"dockerfile": `FROM busybox
RUN echo from dockerfile`,
}, false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer git.Close()
_, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
if err != nil {
buf, _ := readBody(body)
t.Fatalf("Build failed: %s\n%q", err, buf)
c.Fatalf("Build failed: %s\n%q", err, buf)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out := string(buf)
if !strings.Contains(out, "from dockerfile") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build with lower dockerfile")
}
func TestBuildApiBuildGitWithF(t *testing.T) {
func (s *DockerSuite) TestBuildApiBuildGitWithF(c *check.C) {
git, err := fakeGIT("repo", map[string]string{
"baz": `FROM busybox
RUN echo from baz`,
@ -454,7 +419,7 @@ RUN echo from baz`,
RUN echo from Dockerfile`,
}, false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer git.Close()
@ -462,23 +427,21 @@ RUN echo from Dockerfile`,
_, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json")
if err != nil {
buf, _ := readBody(body)
t.Fatalf("Build failed: %s\n%q", err, buf)
c.Fatalf("Build failed: %s\n%q", err, buf)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out := string(buf)
if !strings.Contains(out, "from baz") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build from git w/F")
}
func TestBuildApiDoubleDockerfile(t *testing.T) {
testRequires(t, UnixCli) // dockerfile overwrites Dockerfile on Windows
func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) {
testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows
git, err := fakeGIT("repo", map[string]string{
"Dockerfile": `FROM busybox
RUN echo from Dockerfile`,
@ -486,29 +449,27 @@ RUN echo from Dockerfile`,
RUN echo from dockerfile`,
}, false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer git.Close()
// Make sure it tries to 'dockerfile' query param value
_, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
if err != nil {
t.Fatalf("Build failed: %s", err)
c.Fatalf("Build failed: %s", err)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out := string(buf)
if !strings.Contains(out, "from Dockerfile") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build with two dockerfiles")
}
func TestBuildApiDockerfileSymlink(t *testing.T) {
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)
@ -520,20 +481,20 @@ func TestBuildApiDockerfileSymlink(t *testing.T) {
Typeflag: tar.TypeSymlink,
Linkname: "/etc/passwd",
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
c.Fatalf("failed to write tar file header: %v", err)
}
if err := tw.Close(); err != nil {
t.Fatalf("failed to close tar archive: %v", err)
c.Fatalf("failed to close tar archive: %v", err)
}
_, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
if err == nil {
out, _ := readBody(body)
t.Fatalf("Build was supposed to fail: %s", out)
c.Fatalf("Build was supposed to fail: %s", out)
}
out, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// The reason the error is "Cannot locate specified Dockerfile" is because
@ -541,96 +502,89 @@ func TestBuildApiDockerfileSymlink(t *testing.T) {
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
// a nonexistent file.
if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
t.Fatalf("Didn't complain about leaving build context: %s", out)
c.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile symlink path")
}
// #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 TestPostContainerBindNormalVolume(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=one", "busybox"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
fooDir, err := inspectFieldMap("one", "Volumes", "/foo")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=two", "busybox"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}}
if status, _, err := sockRequest("POST", "/containers/two/start", bindSpec); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
fooDir2, err := inspectFieldMap("two", "Volumes", "/foo")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if fooDir2 != fooDir {
t.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2)
c.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2)
}
logDone("container REST API - can use path from normal volume as bind-mount to overwrite another volume")
}
func TestContainerApiPause(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiPause(c *check.C) {
defer unpauseAllContainers()
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sleep", "30")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
ContainerID := strings.TrimSpace(out)
if status, _, err := sockRequest("POST", "/containers/"+ContainerID+"/pause", nil); err != nil && status != http.StatusNoContent {
t.Fatalf("POST a container pause: sockRequest failed: %v", err)
c.Fatalf("POST a container pause: sockRequest failed: %v", err)
}
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != 1 || stringid.TruncateID(ContainerID) != pausedContainers[0] {
t.Fatalf("there should be one paused container and not %d", len(pausedContainers))
c.Fatalf("there should be one paused container and not %d", len(pausedContainers))
}
if status, _, err := sockRequest("POST", "/containers/"+ContainerID+"/unpause", nil); err != nil && status != http.StatusNoContent {
t.Fatalf("POST a container pause: sockRequest failed: %v", err)
c.Fatalf("POST a container pause: sockRequest failed: %v", err)
}
pausedContainers, err = getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if pausedContainers != nil {
t.Fatalf("There should be no paused container.")
c.Fatalf("There should be no paused container.")
}
logDone("container REST API - check POST containers/pause and unpause")
}
func TestContainerApiTop(t *testing.T) {
defer deleteAllContainers()
out, _ := dockerCmd(t, "run", "-d", "-i", "busybox", "/bin/sh", "-c", "cat")
id := strings.TrimSpace(out)
func (s *DockerSuite) TestContainerApiTop(c *check.C) {
out, err := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "top").CombinedOutput()
if err != nil {
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
type topResp struct {
@ -640,40 +594,41 @@ func TestContainerApiTop(t *testing.T) {
var top topResp
_, b, err := sockRequest("GET", "/containers/"+id+"/top?ps_args=aux", nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := json.Unmarshal(b, &top); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if len(top.Titles) != 11 {
t.Fatalf("expected 11 titles, found %d: %v", len(top.Titles), top.Titles)
c.Fatalf("expected 11 titles, found %d: %v", len(top.Titles), top.Titles)
}
if top.Titles[0] != "USER" || top.Titles[10] != "COMMAND" {
t.Fatalf("expected `USER` at `Titles[0]` and `COMMAND` at Titles[10]: %v", top.Titles)
c.Fatalf("expected `USER` at `Titles[0]` and `COMMAND` at Titles[10]: %v", top.Titles)
}
if len(top.Processes) != 2 {
t.Fatalf("expeted 2 processes, found %d: %v", len(top.Processes), top.Processes)
c.Fatalf("expected 2 processes, found %d: %v", len(top.Processes), top.Processes)
}
if top.Processes[0][10] != "/bin/sh -c cat" {
t.Fatalf("expected `/bin/sh -c cat`, found: %s", top.Processes[0][10])
if top.Processes[0][10] != "/bin/sh -c top" {
c.Fatalf("expected `/bin/sh -c top`, found: %s", top.Processes[0][10])
}
if top.Processes[1][10] != "cat" {
t.Fatalf("expected `cat`, found: %s", top.Processes[1][10])
if top.Processes[1][10] != "top" {
c.Fatalf("expected `top`, found: %s", top.Processes[1][10])
}
logDone("containers REST API - GET /containers/<id>/top")
}
func TestContainerApiCommit(t *testing.T) {
out, _ := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "touch /test")
id := strings.TrimSpace(out)
func (s *DockerSuite) TestContainerApiCommit(c *check.C) {
out, err := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "touch /test").CombinedOutput()
if err != nil {
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name := "testcommit"
_, b, err := sockRequest("POST", "/commit?repo="+name+"&testtag=tag&container="+id, nil)
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
t.Fatal(err)
c.Fatal(err)
}
type resp struct {
@ -681,22 +636,25 @@ func TestContainerApiCommit(t *testing.T) {
}
var img resp
if err := json.Unmarshal(b, &img); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer deleteImages(img.Id)
out, err = inspectField(img.Id, "Config.Cmd")
if out != "[/bin/sh -c touch /test]" {
t.Fatalf("got wrong Cmd from commit: %q", out)
cmd, err := inspectField(img.Id, "Config.Cmd")
if err != nil {
c.Fatal(err)
}
if cmd != "[/bin/sh -c touch /test]" {
c.Fatalf("got wrong Cmd from commit: %q", cmd)
}
// sanity check, make sure the image is what we think it is
dockerCmd(t, "run", img.Id, "ls", "/test")
logDone("containers REST API - POST /commit")
out, err = exec.Command(dockerBinary, "run", img.Id, "ls", "/test").CombinedOutput()
if err != nil {
c.Fatal(out, err)
}
}
func TestContainerApiCreate(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
"Cmd": []string{"/bin/sh", "-c", "touch /test && ls /test"},
@ -704,26 +662,26 @@ func TestContainerApiCreate(t *testing.T) {
_, b, err := sockRequest("POST", "/containers/create", config)
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
t.Fatal(err)
c.Fatal(err)
}
type createResp struct {
Id string
}
var container createResp
if err := json.Unmarshal(b, &container); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, _ := dockerCmd(t, "start", "-a", container.Id)
if strings.TrimSpace(out) != "/test" {
t.Fatalf("expected output `/test`, got %q", out)
out, err := exec.Command(dockerBinary, "start", "-a", container.Id).CombinedOutput()
if err != nil {
c.Fatal(out, err)
}
if strings.TrimSpace(string(out)) != "/test" {
c.Fatalf("expected output `/test`, got %q", out)
}
logDone("containers REST API - POST /containers/create")
}
func TestContainerApiVerifyHeader(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiVerifyHeader(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
}
@ -731,7 +689,7 @@ func TestContainerApiVerifyHeader(t *testing.T) {
create := func(ct string) (int, io.ReadCloser, error) {
jsonData := bytes.NewBuffer(nil)
if err := json.NewEncoder(jsonData).Encode(config); err != nil {
t.Fatal(err)
c.Fatal(err)
}
return sockRequestRaw("POST", "/containers/create", jsonData, ct)
}
@ -740,14 +698,14 @@ func TestContainerApiVerifyHeader(t *testing.T) {
_, body, err := create("")
if err == nil {
b, _ := readBody(body)
t.Fatalf("expected error when content-type is not set: %q", string(b))
c.Fatalf("expected error when content-type is not set: %q", string(b))
}
body.Close()
// Try with wrong content-type
_, body, err = create("application/xml")
if err == nil {
b, _ := readBody(body)
t.Fatalf("expected error when content-type is not set: %q", string(b))
c.Fatalf("expected error when content-type is not set: %q", string(b))
}
body.Close()
@ -755,16 +713,14 @@ func TestContainerApiVerifyHeader(t *testing.T) {
_, body, err = create("application/json")
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
b, _ := readBody(body)
t.Fatalf("%v - %q", err, string(b))
c.Fatalf("%v - %q", err, string(b))
}
body.Close()
logDone("containers REST API - verify create header")
}
// 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 TestContainerApiPostCreateNull(t *testing.T) {
func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) {
config := `{
"Hostname":"",
"Domainname":"",
@ -792,33 +748,31 @@ func TestContainerApiPostCreateNull(t *testing.T) {
_, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
b, _ := readBody(body)
t.Fatal(err, string(b))
c.Fatal(err, string(b))
}
b, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
type createResp struct {
Id string
}
var container createResp
if err := json.Unmarshal(b, &container); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err := inspectField(container.Id, "HostConfig.CpusetCpus")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if out != "" {
t.Fatalf("expected empty string, got %q", out)
c.Fatalf("expected empty string, got %q", out)
}
logDone("containers REST API - Create Null")
}
func TestCreateWithTooLowMemoryLimit(t *testing.T) {
func (s *DockerSuite) TestCreateWithTooLowMemoryLimit(c *check.C) {
defer deleteAllContainers()
config := `{
"Image": "busybox",
@ -831,22 +785,21 @@ func TestCreateWithTooLowMemoryLimit(t *testing.T) {
_, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
b, err2 := readBody(body)
if err2 != nil {
t.Fatal(err2)
c.Fatal(err2)
}
if err == nil || !strings.Contains(string(b), "Minimum memory limit allowed is 4MB") {
t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
c.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
}
logDone("container REST API - create can't set too low memory limit")
}
func TestStartWithTooLowMemoryLimit(t *testing.T) {
func (s *DockerSuite) TestStartWithTooLowMemoryLimit(c *check.C) {
defer deleteAllContainers()
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "busybox"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
containerID := strings.TrimSpace(out)
@ -859,12 +812,10 @@ func TestStartWithTooLowMemoryLimit(t *testing.T) {
_, body, err := sockRequestRaw("POST", "/containers/"+containerID+"/start", strings.NewReader(config), "application/json")
b, err2 := readBody(body)
if err2 != nil {
t.Fatal(err2)
c.Fatal(err2)
}
if err == nil || !strings.Contains(string(b), "Minimum memory limit allowed is 4MB") {
t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
c.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
}
logDone("container REST API - start can't set too low memory limit")
}

View file

@ -4,26 +4,24 @@ import (
"net/http"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestExecResizeApiHeightWidthNoInt(t *testing.T) {
func (s *DockerSuite) TestExecResizeApiHeightWidthNoInt(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar"
status, _, err := sockRequest("POST", endpoint, nil)
if err == nil {
t.Fatal("Expected exec resize Request to fail")
c.Fatal("Expected exec resize Request to fail")
}
if status != http.StatusInternalServerError {
t.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
c.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
}
logDone("container exec resize - height, width no int fail")
}

View file

@ -6,22 +6,20 @@ import (
"bytes"
"fmt"
"os/exec"
"testing"
"github.com/go-check/check"
)
// Regression test for #9414
func TestExecApiCreateNoCmd(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecApiCreateNoCmd(c *check.C) {
name := "exec_test"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
_, body, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": nil})
if err == nil || !bytes.Contains(body, []byte("No exec command specified")) {
t.Fatalf("Expected error when creating exec command with no Cmd specified: %q", err)
c.Fatalf("Expected error when creating exec command with no Cmd specified: %q", err)
}
logDone("exec create API - returns error when missing Cmd")
}

View file

@ -3,50 +3,50 @@ package main
import (
"encoding/json"
"net/url"
"os/exec"
"strings"
"testing"
"github.com/docker/docker/api/types"
"github.com/go-check/check"
)
func TestLegacyImages(t *testing.T) {
func (s *DockerSuite) TestLegacyImages(c *check.C) {
_, body, err := sockRequest("GET", "/v1.6/images/json", nil)
if err != nil {
t.Fatalf("Error on GET: %s", err)
c.Fatalf("Error on GET: %s", err)
}
images := []types.LegacyImage{}
if err = json.Unmarshal(body, &images); err != nil {
t.Fatalf("Error on unmarshal: %s", err)
c.Fatalf("Error on unmarshal: %s", err)
}
if len(images) == 0 || images[0].Tag == "" || images[0].Repository == "" {
t.Fatalf("Bad data: %q", images)
c.Fatalf("Bad data: %q", images)
}
logDone("images - checking legacy json")
}
func TestApiImagesFilter(t *testing.T) {
func (s *DockerSuite) TestApiImagesFilter(c *check.C) {
name := "utest:tag1"
name2 := "utest/docker:tag2"
name3 := "utest:5000/docker:tag3"
defer deleteImages(name, name2, name3)
dockerCmd(t, "tag", "busybox", name)
dockerCmd(t, "tag", "busybox", name2)
dockerCmd(t, "tag", "busybox", name3)
for _, n := range []string{name, name2, name3} {
if out, err := exec.Command(dockerBinary, "tag", "busybox", n).CombinedOutput(); err != nil {
c.Fatal(err, out)
}
}
type image struct{ RepoTags []string }
getImages := func(filter string) []image {
v := url.Values{}
v.Set("filter", filter)
_, b, err := sockRequest("GET", "/images/json?"+v.Encode(), nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
var images []image
if err := json.Unmarshal(b, &images); err != nil {
t.Fatal(err)
c.Fatal(err)
}
return images
@ -54,48 +54,49 @@ func TestApiImagesFilter(t *testing.T) {
errMsg := "incorrect number of matches returned"
if images := getImages("utest*/*"); len(images[0].RepoTags) != 2 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
if images := getImages("utest"); len(images[0].RepoTags) != 1 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
if images := getImages("utest*"); len(images[0].RepoTags) != 1 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
if images := getImages("*5000*/*"); len(images[0].RepoTags) != 1 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
logDone("images - filter param is applied")
}
func TestApiImagesSaveAndLoad(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestApiImagesSaveAndLoad(c *check.C) {
testRequires(c, Network)
out, err := buildImage("saveandload", "FROM hello-world\nENV FOO bar", false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
id := strings.TrimSpace(out)
defer deleteImages("saveandload")
_, body, err := sockRequestRaw("GET", "/images/"+id+"/get", nil, "")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer body.Close()
dockerCmd(t, "rmi", id)
if out, err := exec.Command(dockerBinary, "rmi", id).CombinedOutput(); err != nil {
c.Fatal(err, out)
}
_, loadBody, err := sockRequestRaw("POST", "/images/load", body, "application/x-tar")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer loadBody.Close()
out, _ = dockerCmd(t, "inspect", "--format='{{ .Id }}'", id)
if strings.TrimSpace(out) != id {
t.Fatal("load did not work properly")
inspectOut, err := exec.Command(dockerBinary, "inspect", "--format='{{ .Id }}'", id).CombinedOutput()
if err != nil {
c.Fatal(err, inspectOut)
}
if strings.TrimSpace(string(inspectOut)) != id {
c.Fatal("load did not work properly")
}
logDone("images API - save and load")
}

View file

@ -3,15 +3,16 @@ package main
import (
"net/http"
"strings"
"testing"
"github.com/go-check/check"
)
func TestInfoApi(t *testing.T) {
func (s *DockerSuite) TestInfoApi(c *check.C) {
endpoint := "/info"
statusCode, body, err := sockRequest("GET", endpoint, nil)
if err != nil || statusCode != http.StatusOK {
t.Fatalf("Expected %d from info request, got %d", http.StatusOK, statusCode)
c.Fatalf("Expected %d from info request, got %d", http.StatusOK, statusCode)
}
// always shown fields
@ -30,9 +31,7 @@ func TestInfoApi(t *testing.T) {
out := string(body)
for _, linePrefix := range stringsToCheck {
if !strings.Contains(out, linePrefix) {
t.Errorf("couldn't find string %v in output", linePrefix)
c.Errorf("couldn't find string %v in output", linePrefix)
}
}
logDone("container REST API - check GET /info")
}

View file

@ -4,16 +4,15 @@ import (
"encoding/json"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestInspectApiContainerResponse(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestInspectApiContainerResponse(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -29,12 +28,12 @@ func TestInspectApiContainerResponse(t *testing.T) {
}
_, body, err := sockRequest("GET", endpoint, nil)
if err != nil {
t.Fatalf("sockRequest failed for %s version: %v", testVersion, err)
c.Fatalf("sockRequest failed for %s version: %v", testVersion, err)
}
var inspectJSON map[string]interface{}
if err = json.Unmarshal(body, &inspectJSON); err != nil {
t.Fatalf("unable to unmarshal body for %s version: %v", testVersion, err)
c.Fatalf("unable to unmarshal body for %s version: %v", testVersion, err)
}
keys := []string{"State", "Created", "Path", "Args", "Config", "Image", "NetworkSettings", "ResolvConfPath", "HostnamePath", "HostsPath", "LogPath", "Name", "Driver", "ExecDriver", "MountLabel", "ProcessLabel", "Volumes", "VolumesRW"}
@ -47,14 +46,12 @@ func TestInspectApiContainerResponse(t *testing.T) {
for _, key := range keys {
if _, ok := inspectJSON[key]; !ok {
t.Fatalf("%s does not exist in response for %s version", key, testVersion)
c.Fatalf("%s does not exist in response for %s version", key, testVersion)
}
}
//Issue #6830: type not properly converted to JSON/back
if _, ok := inspectJSON["Path"].(bool); ok {
t.Fatalf("Path of `true` should not be converted to boolean `true` via JSON marshalling")
c.Fatalf("Path of `true` should not be converted to boolean `true` via JSON marshalling")
}
}
logDone("container json - check keys in container json response")
}

View file

@ -5,49 +5,44 @@ import (
"fmt"
"net/http"
"os/exec"
"testing"
"github.com/go-check/check"
)
func TestLogsApiWithStdout(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLogsApiWithStdout(c *check.C) {
name := "logs_test"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "--name", name, "busybox", "bin/sh", "-c", "sleep 10 && echo "+name)
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
statusCode, body, err := sockRequest("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&timestamps=1", name), nil)
if err != nil || statusCode != http.StatusOK {
t.Fatalf("Expected %d from logs request, got %d", http.StatusOK, statusCode)
c.Fatalf("Expected %d from logs request, got %d", http.StatusOK, statusCode)
}
if !bytes.Contains(body, []byte(name)) {
t.Fatalf("Expected %s, got %s", name, string(body[:]))
c.Fatalf("Expected %s, got %s", name, string(body[:]))
}
logDone("logs API - with stdout ok")
}
func TestLogsApiNoStdoutNorStderr(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLogsApiNoStdoutNorStderr(c *check.C) {
name := "logs_test"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
statusCode, body, err := sockRequest("GET", fmt.Sprintf("/containers/%s/logs", name), nil)
if err == nil || statusCode != http.StatusBadRequest {
t.Fatalf("Expected %d from logs request, got %d", http.StatusBadRequest, statusCode)
c.Fatalf("Expected %d from logs request, got %d", http.StatusBadRequest, statusCode)
}
expected := "Bad parameters: you must choose at least one stream"
if !bytes.Contains(body, []byte(expected)) {
t.Fatalf("Expected %s, got %s", expected, string(body[:]))
c.Fatalf("Expected %s, got %s", expected, string(body[:]))
}
logDone("logs API - returns error when no stdout nor stderr specified")
}

View file

@ -4,72 +4,64 @@ import (
"net/http"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestResizeApiResponse(t *testing.T) {
func (s *DockerSuite) TestResizeApiResponse(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/containers/" + cleanedContainerID + "/resize?h=40&w=40"
_, _, err = sockRequest("POST", endpoint, nil)
if err != nil {
t.Fatalf("resize Request failed %v", err)
c.Fatalf("resize Request failed %v", err)
}
logDone("container resize - when started")
}
func TestResizeApiHeightWidthNoInt(t *testing.T) {
func (s *DockerSuite) TestResizeApiHeightWidthNoInt(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/containers/" + cleanedContainerID + "/resize?h=foo&w=bar"
status, _, err := sockRequest("POST", endpoint, nil)
if err == nil {
t.Fatal("Expected resize Request to fail")
c.Fatal("Expected resize Request to fail")
}
if status != http.StatusInternalServerError {
t.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
c.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
}
logDone("container resize - height, width no int fail")
}
func TestResizeApiResponseWhenContainerNotStarted(t *testing.T) {
func (s *DockerSuite) TestResizeApiResponseWhenContainerNotStarted(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
// make sure the exited container is not running
runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
endpoint := "/containers/" + cleanedContainerID + "/resize?h=40&w=40"
_, body, err := sockRequest("POST", endpoint, nil)
if err == nil {
t.Fatalf("resize should fail when container is not started")
c.Fatalf("resize should fail when container is not started")
}
if !strings.Contains(string(body), "Cannot resize container") && !strings.Contains(string(body), cleanedContainerID) {
t.Fatalf("resize should fail with message 'Cannot resize container' but instead received %s", string(body))
c.Fatalf("resize should fail with message 'Cannot resize container' but instead received %s", string(body))
}
logDone("container resize - when not started should not resize")
}

View file

@ -2,23 +2,23 @@ package main
import (
"encoding/json"
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/autogen/dockerversion"
"github.com/go-check/check"
)
func TestGetVersion(t *testing.T) {
func (s *DockerSuite) TestGetVersion(c *check.C) {
_, body, err := sockRequest("GET", "/version", nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
var v types.Version
if err := json.Unmarshal(body, &v); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if v.Version != dockerversion.VERSION {
t.Fatal("Version mismatch")
c.Fatal("Version mismatch")
}
}

View file

@ -6,14 +6,14 @@ import (
"os/exec"
"strings"
"sync"
"testing"
"time"
"github.com/go-check/check"
)
const attachWait = 5 * time.Second
func TestAttachMultipleAndRestart(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
endGroup := &sync.WaitGroup{}
startGroup := &sync.WaitGroup{}
@ -21,7 +21,7 @@ func TestAttachMultipleAndRestart(t *testing.T) {
startGroup.Add(3)
if err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done"); err != nil {
t.Fatal(err)
c.Fatal(err)
}
startDone := make(chan struct{})
@ -39,32 +39,32 @@ func TestAttachMultipleAndRestart(t *testing.T) {
for i := 0; i < 3; i++ {
go func() {
c := exec.Command(dockerBinary, "attach", "attacher")
cmd := exec.Command(dockerBinary, "attach", "attacher")
defer func() {
c.Wait()
cmd.Wait()
endGroup.Done()
}()
out, err := c.StdoutPipe()
out, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := c.Start(); err != nil {
t.Fatal(err)
if err := cmd.Start(); err != nil {
c.Fatal(err)
}
buf := make([]byte, 1024)
if _, err := out.Read(buf); err != nil && err != io.EOF {
t.Fatal(err)
c.Fatal(err)
}
startGroup.Done()
if !strings.Contains(string(buf), "hello") {
t.Fatalf("unexpected output %s expected hello\n", string(buf))
c.Fatalf("unexpected output %s expected hello\n", string(buf))
}
}()
}
@ -72,41 +72,39 @@ func TestAttachMultipleAndRestart(t *testing.T) {
select {
case <-startDone:
case <-time.After(attachWait):
t.Fatalf("Attaches did not initialize properly")
c.Fatalf("Attaches did not initialize properly")
}
cmd := exec.Command(dockerBinary, "kill", "attacher")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
select {
case <-endDone:
case <-time.After(attachWait):
t.Fatalf("Attaches did not finish properly")
c.Fatalf("Attaches did not finish properly")
}
logDone("attach - multiple attach")
}
func TestAttachTtyWithoutStdin(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to start container: %v (%v)", out, err)
c.Fatalf("failed to start container: %v (%v)", out, err)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer func() {
cmd := exec.Command(dockerBinary, "kill", id)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatalf("failed to kill container: %v (%v)", out, err)
c.Fatalf("failed to kill container: %v (%v)", out, err)
}
}()
@ -116,70 +114,67 @@ func TestAttachTtyWithoutStdin(t *testing.T) {
cmd := exec.Command(dockerBinary, "attach", id)
if _, err := cmd.StdinPipe(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil {
t.Fatal("attach should have failed")
c.Fatal("attach should have failed")
} else if !strings.Contains(out, expected) {
t.Fatalf("attach failed with error %q: expected %q", out, expected)
c.Fatalf("attach failed with error %q: expected %q", out, expected)
}
}()
select {
case <-done:
case <-time.After(attachWait):
t.Fatal("attach is running but should have failed")
c.Fatal("attach is running but should have failed")
}
logDone("attach - forbid piped stdin to tty enabled container")
}
func TestAttachDisconnect(t *testing.T) {
defer deleteAllContainers()
out, _ := dockerCmd(t, "run", "-di", "busybox", "/bin/cat")
func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat")
id := strings.TrimSpace(out)
cmd := exec.Command(dockerBinary, "attach", id)
stdin, err := cmd.StdinPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdin.Close()
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cmd.Process.Kill()
if _, err := stdin.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
if err := stdin.Close(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Expect container to still be running after stdin is closed
running, err := inspectField(id, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
logDone("attach - disconnect")
}

View file

@ -6,26 +6,25 @@ import (
"bufio"
"os/exec"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
"github.com/kr/pty"
)
// #9860
func TestAttachClosedOnContainerStop(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-dti", "busybox", "sleep", "2")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to start container: %v (%v)", out, err)
c.Fatalf("failed to start container: %v (%v)", out, err)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
done := make(chan struct{})
@ -35,7 +34,7 @@ func TestAttachClosedOnContainerStop(t *testing.T) {
_, tty, err := pty.Open()
if err != nil {
t.Fatalf("could not open pty: %v", err)
c.Fatalf("could not open pty: %v", err)
}
attachCmd := exec.Command(dockerBinary, "attach", id)
attachCmd.Stdin = tty
@ -43,31 +42,29 @@ func TestAttachClosedOnContainerStop(t *testing.T) {
attachCmd.Stderr = tty
if err := attachCmd.Run(); err != nil {
t.Fatalf("attach returned error %s", err)
c.Fatalf("attach returned error %s", err)
}
}()
waitCmd := exec.Command(dockerBinary, "wait", id)
if out, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
select {
case <-done:
case <-time.After(attachWait):
t.Fatal("timed out without attach returning")
c.Fatal("timed out without attach returning")
}
logDone("attach - return after container finished")
}
func TestAttachAfterDetach(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
name := "detachtest"
cpty, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command(dockerBinary, "run", "-ti", "--name", name, "busybox")
cmd.Stdin = tty
@ -77,14 +74,14 @@ func TestAttachAfterDetach(t *testing.T) {
detached := make(chan struct{})
go func() {
if err := cmd.Run(); err != nil {
t.Fatalf("attach returned error %s", err)
c.Fatalf("attach returned error %s", err)
}
close(detached)
}()
time.Sleep(500 * time.Millisecond)
if err := waitRun(name); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty.Write([]byte{16})
time.Sleep(100 * time.Millisecond)
@ -94,7 +91,7 @@ func TestAttachAfterDetach(t *testing.T) {
cpty, tty, err = pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd = exec.Command(dockerBinary, "attach", name)
@ -103,7 +100,7 @@ func TestAttachAfterDetach(t *testing.T) {
cmd.Stderr = tty
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
bytes := make([]byte, 10)
@ -123,34 +120,33 @@ func TestAttachAfterDetach(t *testing.T) {
select {
case err := <-readErr:
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
case <-time.After(2 * time.Second):
t.Fatal("timeout waiting for attach read")
c.Fatal("timeout waiting for attach read")
}
if err := cmd.Wait(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !strings.Contains(string(bytes[:nBytes]), "/ #") {
t.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes]))
c.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes]))
}
logDone("attach - reconnect after detaching")
}
// TestAttachDetach checks that attach in tty mode can be detached using the long container ID
func TestAttachDetach(t *testing.T) {
out, _ := dockerCmd(t, "run", "-itd", "busybox", "cat")
func (s *DockerSuite) TestAttachDetach(c *check.C) {
out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat")
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cpty.Close()
@ -158,34 +154,34 @@ func TestAttachDetach(t *testing.T) {
cmd.Stdin = tty
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := waitRun(id); err != nil {
t.Fatalf("error waiting for container to start: %v", err)
c.Fatalf("error waiting for container to start: %v", err)
}
if _, err := cpty.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
// escape sequence
if _, err := cpty.Write([]byte{16}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
if _, err := cpty.Write([]byte{17}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
ch := make(chan struct{})
@ -196,36 +192,35 @@ func TestAttachDetach(t *testing.T) {
running, err := inspectField(id, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
go func() {
dockerCmd(t, "kill", id)
dockerCmd(c, "kill", id)
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
t.Fatal("timed out waiting for container to exit")
c.Fatal("timed out waiting for container to exit")
}
logDone("attach - detach")
}
// TestAttachDetachTruncatedID checks that attach in tty mode can be detached
func TestAttachDetachTruncatedID(t *testing.T) {
out, _ := dockerCmd(t, "run", "-itd", "busybox", "cat")
func (s *DockerSuite) TestAttachDetachTruncatedID(c *check.C) {
out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat")
id := stringid.TruncateID(strings.TrimSpace(out))
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cpty.Close()
@ -233,31 +228,31 @@ func TestAttachDetachTruncatedID(t *testing.T) {
cmd.Stdin = tty
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := cpty.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
// escape sequence
if _, err := cpty.Write([]byte{16}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
if _, err := cpty.Write([]byte{17}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
ch := make(chan struct{})
@ -268,21 +263,20 @@ func TestAttachDetachTruncatedID(t *testing.T) {
running, err := inspectField(id, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
go func() {
dockerCmd(t, "kill", id)
dockerCmd(c, "kill", id)
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
t.Fatal("timed out waiting for container to exit")
c.Fatal("timed out waiting for container to exit")
}
logDone("attach - detach truncated ID")
}

File diff suppressed because it is too large Load diff

View file

@ -5,9 +5,9 @@ import (
"os/exec"
"regexp"
"strings"
"testing"
"github.com/docker/docker/utils"
"github.com/go-check/check"
)
var (
@ -22,15 +22,15 @@ func setupImage() (string, error) {
func setupImageWithTag(tag string) (string, error) {
containerName := "busyboxbydigest"
c := exec.Command(dockerBinary, "run", "-d", "-e", "digest=1", "--name", containerName, "busybox")
if _, err := runCommand(c); err != nil {
cmd := exec.Command(dockerBinary, "run", "-d", "-e", "digest=1", "--name", containerName, "busybox")
if _, err := runCommand(cmd); err != nil {
return "", err
}
// tag the image to upload it to the private registry
repoAndTag := utils.ImageReference(repoName, tag)
c = exec.Command(dockerBinary, "commit", containerName, repoAndTag)
if out, _, err := runCommandWithOutput(c); err != nil {
cmd = exec.Command(dockerBinary, "commit", containerName, repoAndTag)
if out, _, err := runCommandWithOutput(cmd); err != nil {
return "", fmt.Errorf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoAndTag)
@ -41,15 +41,15 @@ func setupImageWithTag(tag string) (string, error) {
}
// push the image
c = exec.Command(dockerBinary, "push", repoAndTag)
out, _, err := runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "push", repoAndTag)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
return "", fmt.Errorf("pushing the image to the private registry has failed: %s, %v", out, err)
}
// delete our local repo that we previously tagged
c = exec.Command(dockerBinary, "rmi", repoAndTag)
if out, _, err := runCommandWithOutput(c); err != nil {
cmd = exec.Command(dockerBinary, "rmi", repoAndTag)
if out, _, err := runCommandWithOutput(cmd); err != nil {
return "", fmt.Errorf("error deleting images prior to real test: %s, %v", out, err)
}
@ -63,194 +63,189 @@ func setupImageWithTag(tag string) (string, error) {
return pushDigest, nil
}
func TestPullByTagDisplaysDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPullByTagDisplaysDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
// pull from the registry using the tag
c := exec.Command(dockerBinary, "pull", repoName)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", repoName)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by tag: %s, %v", out, err)
c.Fatalf("error pulling by tag: %s, %v", out, err)
}
defer deleteImages(repoName)
// the pull output includes "Digest: <digest>", so find that
matches := digestRegex.FindStringSubmatch(out)
if len(matches) != 2 {
t.Fatalf("unable to parse digest from pull output: %s", out)
c.Fatalf("unable to parse digest from pull output: %s", out)
}
pullDigest := matches[1]
// make sure the pushed and pull digests match
if pushDigest != pullDigest {
t.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
c.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
}
logDone("by_digest - pull by tag displays digest")
}
func TestPullByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPullByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
// pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
defer deleteImages(imageReference)
// the pull output includes "Digest: <digest>", so find that
matches := digestRegex.FindStringSubmatch(out)
if len(matches) != 2 {
t.Fatalf("unable to parse digest from pull output: %s", out)
c.Fatalf("unable to parse digest from pull output: %s", out)
}
pullDigest := matches[1]
// make sure the pushed and pull digests match
if pushDigest != pullDigest {
t.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
c.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
}
logDone("by_digest - pull by digest")
}
func TestCreateByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestCreateByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
containerName := "createByDigest"
c := exec.Command(dockerBinary, "create", "--name", containerName, imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "create", "--name", containerName, imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error creating by digest: %s, %v", out, err)
c.Fatalf("error creating by digest: %s, %v", out, err)
}
defer deleteContainer(containerName)
res, err := inspectField(containerName, "Config.Image")
if err != nil {
t.Fatalf("failed to get Config.Image: %s, %v", out, err)
c.Fatalf("failed to get Config.Image: %s, %v", out, err)
}
if res != imageReference {
t.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
c.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
}
logDone("by_digest - create by digest")
}
func TestRunByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestRunByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
containerName := "runByDigest"
c := exec.Command(dockerBinary, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest")
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error run by digest: %s, %v", out, err)
c.Fatalf("error run by digest: %s, %v", out, err)
}
defer deleteContainer(containerName)
foundRegex := regexp.MustCompile("found=([^\n]+)")
matches := foundRegex.FindStringSubmatch(out)
if len(matches) != 2 {
t.Fatalf("error locating expected 'found=1' output: %s", out)
c.Fatalf("error locating expected 'found=1' output: %s", out)
}
if matches[1] != "1" {
t.Fatalf("Expected %q, got %q", "1", matches[1])
c.Fatalf("Expected %q, got %q", "1", matches[1])
}
res, err := inspectField(containerName, "Config.Image")
if err != nil {
t.Fatalf("failed to get Config.Image: %s, %v", out, err)
c.Fatalf("failed to get Config.Image: %s, %v", out, err)
}
if res != imageReference {
t.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
c.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
}
logDone("by_digest - run by digest")
}
func TestRemoveImageByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestRemoveImageByDigest(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// make sure inspect runs ok
if _, err := inspectField(imageReference, "Id"); err != nil {
t.Fatalf("failed to inspect image: %v", err)
c.Fatalf("failed to inspect image: %v", err)
}
// do the delete
if err := deleteImages(imageReference); err != nil {
t.Fatalf("unexpected error deleting image: %v", err)
c.Fatalf("unexpected error deleting image: %v", err)
}
// try to inspect again - it should error this time
if _, err := inspectField(imageReference, "Id"); err == nil {
t.Fatalf("unexpected nil err trying to inspect what should be a non-existent image")
c.Fatalf("unexpected nil err trying to inspect what should be a non-existent image")
} else if !strings.Contains(err.Error(), "No such image") {
t.Fatalf("expected 'No such image' output, got %v", err)
c.Fatalf("expected 'No such image' output, got %v", err)
}
logDone("by_digest - remove image by digest")
}
func TestBuildByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestBuildByDigest(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// get the image id
imageID, err := inspectField(imageReference, "Id")
if err != nil {
t.Fatalf("error getting image id: %v", err)
c.Fatalf("error getting image id: %v", err)
}
// do the build
@ -261,275 +256,270 @@ func TestBuildByDigest(t *testing.T) {
CMD ["/bin/echo", "Hello World"]`, imageReference),
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// get the build's image id
res, err := inspectField(name, "Config.Image")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// make sure they match
if res != imageID {
t.Fatalf("Image %s, expected %s", res, imageID)
c.Fatalf("Image %s, expected %s", res, imageID)
}
logDone("by_digest - build by digest")
}
func TestTagByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestTagByDigest(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// tag it
tag := "tagbydigest"
c = exec.Command(dockerBinary, "tag", imageReference, tag)
if _, err := runCommand(c); err != nil {
t.Fatalf("unexpected error tagging: %v", err)
cmd = exec.Command(dockerBinary, "tag", imageReference, tag)
if _, err := runCommand(cmd); err != nil {
c.Fatalf("unexpected error tagging: %v", err)
}
expectedID, err := inspectField(imageReference, "Id")
if err != nil {
t.Fatalf("error getting original image id: %v", err)
c.Fatalf("error getting original image id: %v", err)
}
tagID, err := inspectField(tag, "Id")
if err != nil {
t.Fatalf("error getting tagged image id: %v", err)
c.Fatalf("error getting tagged image id: %v", err)
}
if tagID != expectedID {
t.Fatalf("expected image id %q, got %q", expectedID, tagID)
c.Fatalf("expected image id %q, got %q", expectedID, tagID)
}
logDone("by_digest - tag by digest")
}
func TestListImagesWithoutDigests(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestListImagesWithoutDigests(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
c = exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
if strings.Contains(out, "DIGEST") {
t.Fatalf("list output should not have contained DIGEST header: %s", out)
c.Fatalf("list output should not have contained DIGEST header: %s", out)
}
logDone("by_digest - list images - digest header not displayed by default")
}
func TestListImagesWithDigests(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestListImagesWithDigests(c *check.C) {
defer setupRegistry(c)()
defer deleteImages(repoName+":tag1", repoName+":tag2")
// setup image1
digest1, err := setupImageWithTag("tag1")
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1)
defer deleteImages(imageReference1)
t.Logf("imageReference1 = %s", imageReference1)
c.Logf("imageReference1 = %s", imageReference1)
// pull image1 by digest
c := exec.Command(dockerBinary, "pull", imageReference1)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference1)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure repo shown, tag=<none>, digest = $digest1
re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
if !re1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// setup image2
digest2, err := setupImageWithTag("tag2")
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2)
defer deleteImages(imageReference2)
t.Logf("imageReference2 = %s", imageReference2)
c.Logf("imageReference2 = %s", imageReference2)
// pull image1 by digest
c = exec.Command(dockerBinary, "pull", imageReference1)
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", imageReference1)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// pull image2 by digest
c = exec.Command(dockerBinary, "pull", imageReference2)
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", imageReference2)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure repo shown, tag=<none>, digest = $digest1
if !re1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// make sure repo shown, tag=<none>, digest = $digest2
re2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
if !re2.MatchString(out) {
t.Fatalf("expected %q: %s", re2.String(), out)
c.Fatalf("expected %q: %s", re2.String(), out)
}
// pull tag1
c = exec.Command(dockerBinary, "pull", repoName+":tag1")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", repoName+":tag1")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling tag1: %s, %v", out, err)
c.Fatalf("error pulling tag1: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
reWithTag1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*<none>\s`)
reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
if !reWithTag1.MatchString(out) {
t.Fatalf("expected %q: %s", reWithTag1.String(), out)
c.Fatalf("expected %q: %s", reWithTag1.String(), out)
}
if !reWithDigest1.MatchString(out) {
t.Fatalf("expected %q: %s", reWithDigest1.String(), out)
c.Fatalf("expected %q: %s", reWithDigest1.String(), out)
}
// make sure image 2 has repo, <none>, digest
if !re2.MatchString(out) {
t.Fatalf("expected %q: %s", re2.String(), out)
c.Fatalf("expected %q: %s", re2.String(), out)
}
// pull tag 2
c = exec.Command(dockerBinary, "pull", repoName+":tag2")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", repoName+":tag2")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling tag2: %s, %v", out, err)
c.Fatalf("error pulling tag2: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure image 1 has repo, tag, digest
if !reWithTag1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// make sure image 2 has repo, tag, digest
reWithTag2 := regexp.MustCompile(`\s*` + repoName + `\s*tag2\s*<none>\s`)
reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
if !reWithTag2.MatchString(out) {
t.Fatalf("expected %q: %s", reWithTag2.String(), out)
c.Fatalf("expected %q: %s", reWithTag2.String(), out)
}
if !reWithDigest2.MatchString(out) {
t.Fatalf("expected %q: %s", reWithDigest2.String(), out)
c.Fatalf("expected %q: %s", reWithDigest2.String(), out)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure image 1 has repo, tag, digest
if !reWithTag1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// make sure image 2 has repo, tag, digest
if !reWithTag2.MatchString(out) {
t.Fatalf("expected %q: %s", re2.String(), out)
c.Fatalf("expected %q: %s", re2.String(), out)
}
// make sure busybox has tag, but not digest
busyboxRe := regexp.MustCompile(`\s*busybox\s*latest\s*<none>\s`)
if !busyboxRe.MatchString(out) {
t.Fatalf("expected %q: %s", busyboxRe.String(), out)
c.Fatalf("expected %q: %s", busyboxRe.String(), out)
}
logDone("by_digest - list images with digests")
}
func TestDeleteImageByIDOnlyPulledByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestDeleteImageByIDOnlyPulledByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
// pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// just in case...
defer deleteImages(imageReference)
imageID, err := inspectField(imageReference, ".Id")
if err != nil {
t.Fatalf("error inspecting image id: %v", err)
c.Fatalf("error inspecting image id: %v", err)
}
c = exec.Command(dockerBinary, "rmi", imageID)
if _, err := runCommand(c); err != nil {
t.Fatalf("error deleting image by id: %v", err)
cmd = exec.Command(dockerBinary, "rmi", imageID)
if _, err := runCommand(cmd); err != nil {
c.Fatalf("error deleting image by id: %v", err)
}
logDone("by_digest - delete image by id only pulled by digest")
}

View file

@ -3,96 +3,94 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestCommitAfterContainerIsDone(t *testing.T) {
func (s *DockerSuite) TestCommitAfterContainerIsDone(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
waitCmd := exec.Command(dockerBinary, "wait", cleanedContainerID)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("failed to inspect image: %s, %v", out, err)
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
deleteImages(cleanedImageID)
logDone("commit - echo foo and commit the image")
}
func TestCommitWithoutPause(t *testing.T) {
func (s *DockerSuite) TestCommitWithoutPause(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
waitCmd := exec.Command(dockerBinary, "wait", cleanedContainerID)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", "-p=false", cleanedContainerID)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("failed to inspect image: %s, %v", out, err)
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
deleteImages(cleanedImageID)
logDone("commit - echo foo and commit the image with --pause=false")
}
//test commit a paused container should not unpause it after commit
func TestCommitPausedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitPausedContainer(c *check.C) {
defer unpauseAllContainers()
cmd := exec.Command(dockerBinary, "run", "-i", "-d", "busybox")
out, _, _, err := runCommandWithStdoutStderr(cmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %q", err, out)
c.Fatalf("failed to run container: %v, output: %q", err, out)
}
cleanedContainerID := strings.TrimSpace(out)
cmd = exec.Command(dockerBinary, "pause", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(cmd)
if err != nil {
t.Fatalf("failed to pause container: %v, output: %q", err, out)
c.Fatalf("failed to pause container: %v, output: %q", err, out)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
defer deleteImages(cleanedImageID)
@ -100,28 +98,26 @@ func TestCommitPausedContainer(t *testing.T) {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Paused}}", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(cmd)
if err != nil {
t.Fatalf("failed to inspect container: %v, output: %q", err, out)
c.Fatalf("failed to inspect container: %v, output: %q", err, out)
}
if !strings.Contains(out, "true") {
t.Fatalf("commit should not unpause a paused container")
c.Fatalf("commit should not unpause a paused container")
}
logDone("commit - commit a paused container will not unpause it")
}
func TestCommitNewFile(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitNewFile(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "commiter", "busybox", "/bin/sh", "-c", "echo koye > /foo")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit", "commiter")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
imageID = strings.Trim(imageID, "\r\n")
defer deleteImages(imageID)
@ -130,22 +126,20 @@ func TestCommitNewFile(t *testing.T) {
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.Trim(out, "\r\n"); actual != "koye" {
t.Fatalf("expected output koye received %q", actual)
c.Fatalf("expected output koye received %q", actual)
}
logDone("commit - commit file and read")
}
func TestCommitHardlink(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitHardlink(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-t", "--name", "hardlinks", "busybox", "sh", "-c", "touch file1 && ln file1 file2 && ls -di file1 file2")
firstOuput, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
chunks := strings.Split(strings.TrimSpace(firstOuput), " ")
@ -158,13 +152,13 @@ func TestCommitHardlink(t *testing.T) {
}
}
if !found {
t.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
c.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
}
cmd = exec.Command(dockerBinary, "commit", "hardlinks", "hardlinks")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(imageID, err)
c.Fatal(imageID, err)
}
imageID = strings.Trim(imageID, "\r\n")
defer deleteImages(imageID)
@ -172,7 +166,7 @@ func TestCommitHardlink(t *testing.T) {
cmd = exec.Command(dockerBinary, "run", "-t", "hardlinks", "ls", "-di", "file1", "file2")
secondOuput, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
chunks = strings.Split(strings.TrimSpace(secondOuput), " ")
@ -185,48 +179,44 @@ func TestCommitHardlink(t *testing.T) {
}
}
if !found {
t.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
c.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
}
logDone("commit - commit hardlinks")
}
func TestCommitTTY(t *testing.T) {
func (s *DockerSuite) TestCommitTTY(c *check.C) {
defer deleteImages("ttytest")
defer deleteAllContainers()
cmd := exec.Command(dockerBinary, "run", "-t", "--name", "tty", "busybox", "/bin/ls")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit", "tty", "ttytest")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
imageID = strings.Trim(imageID, "\r\n")
cmd = exec.Command(dockerBinary, "run", "ttytest", "/bin/ls")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("commit - commit tty")
}
func TestCommitWithHostBindMount(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitWithHostBindMount(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "bind-commit", "-v", "/dev/null:/winning", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit", "bind-commit", "bindtest")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(imageID, err)
c.Fatal(imageID, err)
}
imageID = strings.Trim(imageID, "\r\n")
@ -235,18 +225,16 @@ func TestCommitWithHostBindMount(t *testing.T) {
cmd = exec.Command(dockerBinary, "run", "bindtest", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("commit - commit bind mounted file")
}
func TestCommitChange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitChange(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "test", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit",
@ -257,7 +245,7 @@ func TestCommitChange(t *testing.T) {
"test", "test-commit")
imageId, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(imageId, err)
c.Fatal(imageId, err)
}
imageId = strings.Trim(imageId, "\r\n")
defer deleteImages(imageId)
@ -270,29 +258,27 @@ func TestCommitChange(t *testing.T) {
for conf, value := range expected {
res, err := inspectField(imageId, conf)
if err != nil {
t.Errorf("failed to get value %s, error: %s", conf, err)
c.Errorf("failed to get value %s, error: %s", conf, err)
}
if res != value {
t.Errorf("%s('%s'), expected %s", conf, res, value)
c.Errorf("%s('%s'), expected %s", conf, res, value)
}
}
logDone("commit - commit --change")
}
// TODO: commit --run is deprecated, remove this once --run is removed
func TestCommitMergeConfigRun(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitMergeConfigRun(c *check.C) {
name := "commit-test"
out, _ := dockerCmd(t, "run", "-d", "-e=FOO=bar", "busybox", "/bin/sh", "-c", "echo testing > /tmp/foo")
out, _ := dockerCmd(c, "run", "-d", "-e=FOO=bar", "busybox", "/bin/sh", "-c", "echo testing > /tmp/foo")
id := strings.TrimSpace(out)
dockerCmd(t, "commit", `--run={"Cmd": ["cat", "/tmp/foo"]}`, id, "commit-test")
dockerCmd(c, "commit", `--run={"Cmd": ["cat", "/tmp/foo"]}`, id, "commit-test")
defer deleteImages("commit-test")
out, _ = dockerCmd(t, "run", "--name", name, "commit-test")
out, _ = dockerCmd(c, "run", "--name", name, "commit-test")
if strings.TrimSpace(out) != "testing" {
t.Fatal("run config in commited container was not merged")
c.Fatal("run config in commited container was not merged")
}
type cfg struct {
@ -301,11 +287,11 @@ func TestCommitMergeConfigRun(t *testing.T) {
}
config1 := cfg{}
if err := inspectFieldAndMarshall(id, "Config", &config1); err != nil {
t.Fatal(err)
c.Fatal(err)
}
config2 := cfg{}
if err := inspectFieldAndMarshall(name, "Config", &config2); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Env has at least PATH loaded as well here, so let's just grab the FOO one
@ -324,8 +310,7 @@ func TestCommitMergeConfigRun(t *testing.T) {
}
if len(config1.Env) != len(config2.Env) || env1 != env2 && env2 != "" {
t.Fatalf("expected envs to match: %v - %v", config1.Env, config2.Env)
c.Fatalf("expected envs to match: %v - %v", config1.Env, config2.Env)
}
logDone("commit - configs are merged with --run")
}

View file

@ -7,13 +7,13 @@ import (
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/docker/docker/pkg/homedir"
"github.com/go-check/check"
)
func TestConfigHttpHeader(t *testing.T) {
testRequires(t, UnixCli) // Can't set/unset HOME on windows right now
func (s *DockerSuite) TestConfigHttpHeader(c *check.C) {
testRequires(c, UnixCli) // Can't set/unset HOME on windows right now
// We either need a level of Go that supports Unsetenv (for cases
// when HOME/USERPROFILE isn't set), or we need to be able to use
// os/user but user.Current() only works if we aren't statically compiling
@ -44,15 +44,13 @@ func TestConfigHttpHeader(t *testing.T) {
err := ioutil.WriteFile(tmpCfg, []byte(data), 0600)
if err != nil {
t.Fatalf("Err creating file(%s): %v", tmpCfg, err)
c.Fatalf("Err creating file(%s): %v", tmpCfg, err)
}
cmd := exec.Command(dockerBinary, "-H="+server.URL[7:], "ps")
out, _, _ := runCommandWithOutput(cmd)
if headers["Myheader"] == nil || headers["Myheader"][0] != "MyValue" {
t.Fatalf("Missing/bad header: %q\nout:%v", headers, out)
c.Fatalf("Missing/bad header: %q\nout:%v", headers, out)
}
logDone("config - add new http headers")
}

View file

@ -9,7 +9,8 @@ import (
"path"
"path/filepath"
"strings"
"testing"
"github.com/go-check/check"
)
const (
@ -24,27 +25,27 @@ const (
// Test for #5656
// Check that garbage paths don't escape the container's rootfs
func TestCpGarbagePath(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
func (s *DockerSuite) TestCpGarbagePath(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -53,7 +54,7 @@ func TestCpGarbagePath(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -61,49 +62,48 @@ func TestCpGarbagePath(t *testing.T) {
path := path.Join("../../../../../../../../../../../../", cpFullPath)
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- garbage path can escape container rootfs")
c.Errorf("output matched host file -- garbage path can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for garbage path")
c.Errorf("output doesn't match the input for garbage path")
}
logDone("cp - garbage paths relative to container's rootfs")
}
// Check that relative paths are relative to the container's rootfs
func TestCpRelativePath(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
func (s *DockerSuite) TestCpRelativePath(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -113,7 +113,7 @@ func TestCpRelativePath(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -125,52 +125,51 @@ func TestCpRelativePath(t *testing.T) {
// get this unix-path manipulation on windows with filepath.
relPath = cpFullPath[1:]
} else {
t.Fatalf("path %s was assumed to be an absolute path", cpFullPath)
c.Fatalf("path %s was assumed to be an absolute path", cpFullPath)
}
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+relPath, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+relPath, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- relative path can escape container rootfs")
c.Errorf("output matched host file -- relative path can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for relative path")
c.Errorf("output doesn't match the input for relative path")
}
logDone("cp - relative paths relative to container's rootfs")
}
// Check that absolute paths are relative to the container's rootfs
func TestCpAbsolutePath(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
func (s *DockerSuite) TestCpAbsolutePath(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -180,7 +179,7 @@ func TestCpAbsolutePath(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -188,50 +187,49 @@ func TestCpAbsolutePath(t *testing.T) {
path := cpFullPath
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- absolute path can escape container rootfs")
c.Errorf("output matched host file -- absolute path can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for absolute path")
c.Errorf("output doesn't match the input for absolute path")
}
logDone("cp - absolute paths relative to container's rootfs")
}
// Test for #5619
// Check that absolute symlinks are still relative to the container's rootfs
func TestCpAbsoluteSymlink(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpFullPath+" container_path")
func (s *DockerSuite) TestCpAbsoluteSymlink(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpFullPath+" container_path")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -241,7 +239,7 @@ func TestCpAbsoluteSymlink(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -249,50 +247,49 @@ func TestCpAbsoluteSymlink(t *testing.T) {
path := path.Join("/", "container_path")
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- absolute symlink can escape container rootfs")
c.Errorf("output matched host file -- absolute symlink can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for absolute symlink")
c.Errorf("output doesn't match the input for absolute symlink")
}
logDone("cp - absolute symlink relative to container's rootfs")
}
// Test for #5619
// Check that symlinks which are part of the resource path are still relative to the container's rootfs
func TestCpSymlinkComponent(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpTestPath+" container_path")
func (s *DockerSuite) TestCpSymlinkComponent(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpTestPath+" container_path")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -302,7 +299,7 @@ func TestCpSymlinkComponent(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -310,268 +307,263 @@ func TestCpSymlinkComponent(t *testing.T) {
path := path.Join("/", "container_path", cpTestName)
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- symlink path component can escape container rootfs")
c.Errorf("output matched host file -- symlink path component can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for symlink path component")
c.Errorf("output doesn't match the input for symlink path component")
}
logDone("cp - symlink path components relative to container's rootfs")
}
// Check that cp with unprivileged user doesn't return any error
func TestCpUnprivilegedUser(t *testing.T) {
testRequires(t, UnixCli) // uses chmod/su: not available on windows
func (s *DockerSuite) TestCpUnprivilegedUser(c *check.C) {
testRequires(c, UnixCli) // uses chmod/su: not available on windows
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "touch "+cpTestName)
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "touch "+cpTestName)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpdir)
if err = os.Chmod(tmpdir, 0777); err != nil {
t.Fatal(err)
c.Fatal(err)
}
path := cpTestName
_, _, err = runCommandWithOutput(exec.Command("su", "unprivilegeduser", "-c", dockerBinary+" cp "+cleanedContainerID+":"+path+" "+tmpdir))
if err != nil {
t.Fatalf("couldn't copy with unprivileged user: %s:%s %s", cleanedContainerID, path, err)
c.Fatalf("couldn't copy with unprivileged user: %s:%s %s", cleanedContainerID, path, err)
}
logDone("cp - unprivileged user")
}
func TestCpSpecialFiles(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCpSpecialFiles(c *check.C) {
testRequires(c, SameHostDaemon)
outDir, err := ioutil.TempDir("", "cp-test-special-files")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(outDir)
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "touch /foo")
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "touch /foo")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
// Copy actual /etc/resolv.conf
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/etc/resolv.conf", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/etc/resolv.conf", outDir)
expected, err := ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/resolv.conf")
actual, err := ioutil.ReadFile(outDir + "/resolv.conf")
if !bytes.Equal(actual, expected) {
t.Fatalf("Expected copied file to be duplicate of the container resolvconf")
c.Fatalf("Expected copied file to be duplicate of the container resolvconf")
}
// Copy actual /etc/hosts
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/etc/hosts", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/etc/hosts", outDir)
expected, err = ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/hosts")
actual, err = ioutil.ReadFile(outDir + "/hosts")
if !bytes.Equal(actual, expected) {
t.Fatalf("Expected copied file to be duplicate of the container hosts")
c.Fatalf("Expected copied file to be duplicate of the container hosts")
}
// Copy actual /etc/resolv.conf
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/etc/hostname", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/etc/hostname", outDir)
expected, err = ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/hostname")
actual, err = ioutil.ReadFile(outDir + "/hostname")
if !bytes.Equal(actual, expected) {
t.Fatalf("Expected copied file to be duplicate of the container resolvconf")
c.Fatalf("Expected copied file to be duplicate of the container resolvconf")
}
logDone("cp - special files (resolv.conf, hosts, hostname)")
}
func TestCpVolumePath(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCpVolumePath(c *check.C) {
testRequires(c, SameHostDaemon)
tmpDir, err := ioutil.TempDir("", "cp-test-volumepath")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpDir)
outDir, err := ioutil.TempDir("", "cp-test-volumepath-out")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(outDir)
_, err = os.Create(tmpDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, exitCode := dockerCmd(t, "run", "-d", "-v", "/foo", "-v", tmpDir+"/test:/test", "-v", tmpDir+":/baz", "busybox", "/bin/sh", "-c", "touch /foo/bar")
out, exitCode := dockerCmd(c, "run", "-d", "-v", "/foo", "-v", tmpDir+"/test:/test", "-v", tmpDir+":/baz", "busybox", "/bin/sh", "-c", "touch /foo/bar")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer dockerCmd(t, "rm", "-fv", cleanedContainerID)
defer dockerCmd(c, "rm", "-fv", cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
// Copy actual volume path
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/foo", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/foo", outDir)
stat, err := os.Stat(outDir + "/foo")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !stat.IsDir() {
t.Fatal("expected copied content to be dir")
c.Fatal("expected copied content to be dir")
}
stat, err = os.Stat(outDir + "/foo/bar")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if stat.IsDir() {
t.Fatal("Expected file `bar` to be a file")
c.Fatal("Expected file `bar` to be a file")
}
// Copy file nested in volume
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/foo/bar", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/foo/bar", outDir)
stat, err = os.Stat(outDir + "/bar")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if stat.IsDir() {
t.Fatal("Expected file `bar` to be a file")
c.Fatal("Expected file `bar` to be a file")
}
// Copy Bind-mounted dir
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/baz", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/baz", outDir)
stat, err = os.Stat(outDir + "/baz")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !stat.IsDir() {
t.Fatal("Expected `baz` to be a dir")
c.Fatal("Expected `baz` to be a dir")
}
// Copy file nested in bind-mounted dir
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/baz/test", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/baz/test", outDir)
fb, err := ioutil.ReadFile(outDir + "/baz/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
fb2, err := ioutil.ReadFile(tmpDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !bytes.Equal(fb, fb2) {
t.Fatalf("Expected copied file to be duplicate of bind-mounted file")
c.Fatalf("Expected copied file to be duplicate of bind-mounted file")
}
// Copy bind-mounted file
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/test", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/test", outDir)
fb, err = ioutil.ReadFile(outDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
fb2, err = ioutil.ReadFile(tmpDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !bytes.Equal(fb, fb2) {
t.Fatalf("Expected copied file to be duplicate of bind-mounted file")
c.Fatalf("Expected copied file to be duplicate of bind-mounted file")
}
logDone("cp - volume path")
}
func TestCpToDot(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
func (s *DockerSuite) TestCpToDot(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpdir)
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.Chdir(cwd)
if err := os.Chdir(tmpdir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/test", ".")
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/test", ".")
content, err := ioutil.ReadFile("./test")
if string(content) != "lololol\n" {
t.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
c.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
}
logDone("cp - to dot path")
}
func TestCpToStdout(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
func (s *DockerSuite) TestCpToStdout(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
if exitCode != 0 {
t.Fatalf("failed to create a container:%s\n", out)
c.Fatalf("failed to create a container:%s\n", out)
}
cID := strings.TrimSpace(out)
defer deleteContainer(cID)
out, _ = dockerCmd(t, "wait", cID)
out, _ = dockerCmd(c, "wait", cID)
if strings.TrimSpace(out) != "0" {
t.Fatalf("failed to set up container:%s\n", out)
c.Fatalf("failed to set up container:%s\n", out)
}
out, _, err := runCommandPipelineWithOutput(
@ -579,40 +571,38 @@ func TestCpToStdout(t *testing.T) {
exec.Command("tar", "-vtf", "-"))
if err != nil {
t.Fatalf("Failed to run commands: %s", err)
c.Fatalf("Failed to run commands: %s", err)
}
if !strings.Contains(out, "test") || !strings.Contains(out, "-rw") {
t.Fatalf("Missing file from tar TOC:\n%s", out)
c.Fatalf("Missing file from tar TOC:\n%s", out)
}
logDone("cp - to stdout")
}
func TestCpNameHasColon(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCpNameHasColon(c *check.C) {
testRequires(c, SameHostDaemon)
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /te:s:t")
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /te:s:t")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpdir)
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/te:s:t", tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/te:s:t", tmpdir)
content, err := ioutil.ReadFile(tmpdir + "/te:s:t")
if string(content) != "lololol\n" {
t.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
c.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
}
logDone("cp - copy filename has ':'")
}

View file

@ -6,20 +6,19 @@ import (
"os/exec"
"reflect"
"strings"
"testing"
"time"
"github.com/docker/docker/nat"
"github.com/go-check/check"
)
// Make sure we can create a simple container with some args
func TestCreateArgs(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateArgs(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "busybox", "command", "arg1", "arg2", "arg with space")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -27,7 +26,7 @@ func TestCreateArgs(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -38,40 +37,38 @@ func TestCreateArgs(t *testing.T) {
Image string
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.Path != "command" {
t.Fatalf("Unexpected container path. Expected command, received: %s", c.Path)
cont := containers[0]
if cont.Path != "command" {
c.Fatalf("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 != c.Args[i] {
if arg != cont.Args[i] {
b = true
break
}
}
if len(c.Args) != len(expected) || b {
t.Fatalf("Unexpected args. Expected %v, received: %v", expected, c.Args)
if len(cont.Args) != len(expected) || b {
c.Fatalf("Unexpected args. Expected %v, received: %v", expected, cont.Args)
}
logDone("create - args")
}
// Make sure we can set hostconfig options too
func TestCreateHostConfig(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateHostConfig(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "-P", "busybox", "echo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -79,7 +76,7 @@ func TestCreateHostConfig(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -88,31 +85,29 @@ func TestCreateHostConfig(t *testing.T) {
}
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.HostConfig == nil {
t.Fatalf("Expected HostConfig, got none")
cont := containers[0]
if cont.HostConfig == nil {
c.Fatalf("Expected HostConfig, got none")
}
if !c.HostConfig.PublishAllPorts {
t.Fatalf("Expected PublishAllPorts, got false")
if !cont.HostConfig.PublishAllPorts {
c.Fatalf("Expected PublishAllPorts, got false")
}
logDone("create - hostconfig")
}
func TestCreateWithPortRange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateWithPortRange(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "-p", "3300-3303:3300-3303/tcp", "busybox", "echo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -120,7 +115,7 @@ func TestCreateWithPortRange(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -129,39 +124,37 @@ func TestCreateWithPortRange(t *testing.T) {
}
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.HostConfig == nil {
t.Fatalf("Expected HostConfig, got none")
cont := containers[0]
if cont.HostConfig == nil {
c.Fatalf("Expected HostConfig, got none")
}
if len(c.HostConfig.PortBindings) != 4 {
t.Fatalf("Expected 4 ports bindings, got %d", len(c.HostConfig.PortBindings))
if len(cont.HostConfig.PortBindings) != 4 {
c.Fatalf("Expected 4 ports bindings, got %d", len(cont.HostConfig.PortBindings))
}
for k, v := range c.HostConfig.PortBindings {
for k, v := range cont.HostConfig.PortBindings {
if len(v) != 1 {
t.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
c.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
}
if k.Port() != v[0].HostPort {
t.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
c.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
}
}
logDone("create - port range")
}
func TestCreateWithiLargePortRange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateWithiLargePortRange(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "-p", "1-65535:1-65535/tcp", "busybox", "echo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -169,7 +162,7 @@ func TestCreateWithiLargePortRange(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -178,40 +171,38 @@ func TestCreateWithiLargePortRange(t *testing.T) {
}
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.HostConfig == nil {
t.Fatalf("Expected HostConfig, got none")
cont := containers[0]
if cont.HostConfig == nil {
c.Fatalf("Expected HostConfig, got none")
}
if len(c.HostConfig.PortBindings) != 65535 {
t.Fatalf("Expected 65535 ports bindings, got %d", len(c.HostConfig.PortBindings))
if len(cont.HostConfig.PortBindings) != 65535 {
c.Fatalf("Expected 65535 ports bindings, got %d", len(cont.HostConfig.PortBindings))
}
for k, v := range c.HostConfig.PortBindings {
for k, v := range cont.HostConfig.PortBindings {
if len(v) != 1 {
t.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
c.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
}
if k.Port() != v[0].HostPort {
t.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
c.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
}
}
logDone("create - large port range")
}
// "test123" should be printed by docker create + start
func TestCreateEchoStdout(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateEchoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "busybox", "echo", "test123")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -219,62 +210,58 @@ func TestCreateEchoStdout(t *testing.T) {
runCmd = exec.Command(dockerBinary, "start", "-ai", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "test123\n" {
t.Errorf("container should've printed 'test123', got %q", out)
c.Errorf("container should've printed 'test123', got %q", out)
}
logDone("create - echo test123")
}
func TestCreateVolumesCreated(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestCreateVolumesCreated(c *check.C) {
testRequires(c, SameHostDaemon)
name := "test_create_volume"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "--name", name, "-v", "/foo", "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
dir, err := inspectFieldMap(name, "Volumes", "/foo")
if err != nil {
t.Fatalf("Error getting volume host path: %q", err)
c.Fatalf("Error getting volume host path: %q", err)
}
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
t.Fatalf("Volume was not created")
c.Fatalf("Volume was not created")
}
if err != nil {
t.Fatalf("Error statting volume host path: %q", err)
c.Fatalf("Error statting volume host path: %q", err)
}
logDone("create - volumes are created")
}
func TestCreateLabels(t *testing.T) {
func (s *DockerSuite) TestCreateLabels(c *check.C) {
name := "test_create_labels"
expected := map[string]string{"k1": "v1", "k2": "v2"}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "--name", name, "-l", "k1=v1", "--label", "k2=v2", "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
actual := make(map[string]string)
err := inspectFieldAndMarshall(name, "Config.Labels", &actual)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %s got %s", expected, actual)
c.Fatalf("Expected %s got %s", expected, actual)
}
deleteAllContainers()
logDone("create - labels")
}
func TestCreateLabelFromImage(t *testing.T) {
func (s *DockerSuite) TestCreateLabelFromImage(c *check.C) {
imageName := "testcreatebuildlabel"
defer deleteImages(imageName)
_, err := buildImage(imageName,
@ -282,34 +269,32 @@ func TestCreateLabelFromImage(t *testing.T) {
LABEL k1=v1 k2=v2`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
name := "test_create_labels_from_image"
expected := map[string]string{"k2": "x", "k3": "v3", "k1": "v1"}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "--name", name, "-l", "k2=x", "--label", "k3=v3", imageName)); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
actual := make(map[string]string)
err = inspectFieldAndMarshall(name, "Config.Labels", &actual)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %s got %s", expected, actual)
c.Fatalf("Expected %s got %s", expected, actual)
}
deleteAllContainers()
logDone("create - labels from image")
}
func TestCreateHostnameWithNumber(t *testing.T) {
out, _ := dockerCmd(t, "run", "-h", "web.0", "busybox", "hostname")
func (s *DockerSuite) TestCreateHostnameWithNumber(c *check.C) {
out, _ := dockerCmd(c, "run", "-h", "web.0", "busybox", "hostname")
if strings.TrimSpace(out) != "web.0" {
t.Fatalf("hostname not set, expected `web.0`, got: %s", out)
c.Fatalf("hostname not set, expected `web.0`, got: %s", out)
}
logDone("create - use hostname with number")
}

File diff suppressed because it is too large Load diff

View file

@ -3,16 +3,17 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// ensure that an added file shows up in docker diff
func TestDiffFilenameShownInOutput(t *testing.T) {
func (s *DockerSuite) TestDiffFilenameShownInOutput(c *check.C) {
containerCmd := `echo foo > /root/bar`
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", containerCmd)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to start the container: %s, %v", out, err)
c.Fatalf("failed to start the container: %s, %v", out, err)
}
cleanCID := strings.TrimSpace(out)
@ -20,7 +21,7 @@ func TestDiffFilenameShownInOutput(t *testing.T) {
diffCmd := exec.Command(dockerBinary, "diff", cleanCID)
out, _, err = runCommandWithOutput(diffCmd)
if err != nil {
t.Fatalf("failed to run diff: %s %v", out, err)
c.Fatalf("failed to run diff: %s %v", out, err)
}
found := false
@ -31,15 +32,12 @@ func TestDiffFilenameShownInOutput(t *testing.T) {
}
}
if !found {
t.Errorf("couldn't find the new file in docker diff's output: %v", out)
c.Errorf("couldn't find the new file in docker diff's output: %v", out)
}
deleteContainer(cleanCID)
logDone("diff - check if created file shows up")
}
// test to ensure GH #3840 doesn't occur any more
func TestDiffEnsureDockerinitFilesAreIgnored(t *testing.T) {
func (s *DockerSuite) TestDiffEnsureDockerinitFilesAreIgnored(c *check.C) {
// this is a list of files which shouldn't show up in `docker diff`
dockerinitFiles := []string{"/etc/resolv.conf", "/etc/hostname", "/etc/hosts", "/.dockerinit", "/.dockerenv"}
@ -49,7 +47,7 @@ func TestDiffEnsureDockerinitFilesAreIgnored(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", containerCmd)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanCID := strings.TrimSpace(out)
@ -57,26 +55,22 @@ func TestDiffEnsureDockerinitFilesAreIgnored(t *testing.T) {
diffCmd := exec.Command(dockerBinary, "diff", cleanCID)
out, _, err = runCommandWithOutput(diffCmd)
if err != nil {
t.Fatalf("failed to run diff: %s, %v", out, err)
c.Fatalf("failed to run diff: %s, %v", out, err)
}
deleteContainer(cleanCID)
for _, filename := range dockerinitFiles {
if strings.Contains(out, filename) {
t.Errorf("found file which should've been ignored %v in diff output", filename)
c.Errorf("found file which should've been ignored %v in diff output", filename)
}
}
}
logDone("diff - check if ignored files show up in diff")
}
func TestDiffEnsureOnlyKmsgAndPtmx(t *testing.T) {
func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sleep", "0")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanCID := strings.TrimSpace(out)
@ -84,9 +78,8 @@ func TestDiffEnsureOnlyKmsgAndPtmx(t *testing.T) {
diffCmd := exec.Command(dockerBinary, "diff", cleanCID)
out, _, err = runCommandWithOutput(diffCmd)
if err != nil {
t.Fatalf("failed to run diff: %s, %v", out, err)
c.Fatalf("failed to run diff: %s, %v", out, err)
}
deleteContainer(cleanCID)
expected := map[string]bool{
"C /dev": true,
@ -109,9 +102,7 @@ func TestDiffEnsureOnlyKmsgAndPtmx(t *testing.T) {
for _, line := range strings.Split(out, "\n") {
if line != "" && !expected[line] {
t.Errorf("%q is shown in the diff but shouldn't", line)
c.Errorf("%q is shown in the diff but shouldn't", line)
}
}
logDone("diff - ensure that only kmsg and ptmx in diff")
}

View file

@ -7,20 +7,21 @@ import (
"regexp"
"strconv"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
func TestEventsUntag(t *testing.T) {
func (s *DockerSuite) TestEventsUntag(c *check.C) {
image := "busybox"
dockerCmd(t, "tag", image, "utest:tag1")
dockerCmd(t, "tag", image, "utest:tag2")
dockerCmd(t, "rmi", "utest:tag1")
dockerCmd(t, "rmi", "utest:tag2")
dockerCmd(c, "tag", image, "utest:tag1")
dockerCmd(c, "tag", image, "utest:tag2")
dockerCmd(c, "rmi", "utest:tag1")
dockerCmd(c, "rmi", "utest:tag2")
eventsCmd := exec.Command(dockerBinary, "events", "--since=1")
out, exitCode, _, err := runCommandWithOutputForDuration(eventsCmd, time.Duration(time.Millisecond*200))
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events - exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events - exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
nEvents := len(events)
@ -29,126 +30,119 @@ func TestEventsUntag(t *testing.T) {
// looking for.
for _, v := range events[nEvents-3 : nEvents-1] {
if !strings.Contains(v, "untag") {
t.Fatalf("event should be untag, not %#v", v)
c.Fatalf("event should be untag, not %#v", v)
}
}
logDone("events - untags are logged")
}
func TestEventsContainerFailStartDie(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestEventsContainerFailStartDie(c *check.C) {
out, _ := dockerCmd(t, "images", "-q")
out, _ := dockerCmd(c, "images", "-q")
image := strings.Split(out, "\n")[0]
eventsCmd := exec.Command(dockerBinary, "run", "--name", "testeventdie", image, "blerg")
_, _, err := runCommandWithOutput(eventsCmd)
if err == nil {
t.Fatalf("Container run with command blerg should have failed, but it did not")
c.Fatalf("Container run with command blerg should have failed, but it did not")
}
eventsCmd = exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd = exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
c.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
c.Fatalf("event should be die, not %#v", dieEvent)
}
logDone("events - container unwilling to start logs die")
}
func TestEventsLimit(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestEventsLimit(c *check.C) {
for i := 0; i < 30; i++ {
dockerCmd(t, "run", "busybox", "echo", strconv.Itoa(i))
dockerCmd(c, "run", "busybox", "echo", strconv.Itoa(i))
}
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ := runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
nEvents := len(events) - 1
if nEvents != 64 {
t.Fatalf("events should be limited to 64, but received %d", nEvents)
c.Fatalf("events should be limited to 64, but received %d", nEvents)
}
logDone("events - limited to 64 entries")
}
func TestEventsContainerEvents(t *testing.T) {
dockerCmd(t, "run", "--rm", "busybox", "true")
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
func (s *DockerSuite) TestEventsContainerEvents(c *check.C) {
dockerCmd(c, "run", "--rm", "busybox", "true")
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) < 4 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
createEvent := strings.Fields(events[len(events)-4])
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
destroyEvent := strings.Fields(events[len(events)-1])
if createEvent[len(createEvent)-1] != "create" {
t.Fatalf("event should be create, not %#v", createEvent)
c.Fatalf("event should be create, not %#v", createEvent)
}
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
c.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
c.Fatalf("event should be die, not %#v", dieEvent)
}
if destroyEvent[len(destroyEvent)-1] != "destroy" {
t.Fatalf("event should be destroy, not %#v", destroyEvent)
c.Fatalf("event should be destroy, not %#v", destroyEvent)
}
logDone("events - container create, start, die, destroy is logged")
}
func TestEventsContainerEventsSinceUnixEpoch(t *testing.T) {
dockerCmd(t, "run", "--rm", "busybox", "true")
func (s *DockerSuite) TestEventsContainerEventsSinceUnixEpoch(c *check.C) {
dockerCmd(c, "run", "--rm", "busybox", "true")
timeBeginning := time.Unix(0, 0).Format(time.RFC3339Nano)
timeBeginning = strings.Replace(timeBeginning, "Z", ".000000000Z", -1)
eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since='%s'", timeBeginning),
fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) < 4 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
createEvent := strings.Fields(events[len(events)-4])
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
destroyEvent := strings.Fields(events[len(events)-1])
if createEvent[len(createEvent)-1] != "create" {
t.Fatalf("event should be create, not %#v", createEvent)
c.Fatalf("event should be create, not %#v", createEvent)
}
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
c.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
c.Fatalf("event should be die, not %#v", dieEvent)
}
if destroyEvent[len(destroyEvent)-1] != "destroy" {
t.Fatalf("event should be destroy, not %#v", destroyEvent)
c.Fatalf("event should be destroy, not %#v", destroyEvent)
}
logDone("events - container create, start, die, destroy since Unix Epoch time")
}
func TestEventsImageUntagDelete(t *testing.T) {
func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) {
name := "testimageevents"
defer deleteImages(name)
_, err := buildImage(name,
@ -156,67 +150,64 @@ func TestEventsImageUntagDelete(t *testing.T) {
MAINTAINER "docker"`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := deleteImages(name); err != nil {
t.Fatal(err)
c.Fatal(err)
}
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) < 2 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
untagEvent := strings.Fields(events[len(events)-2])
deleteEvent := strings.Fields(events[len(events)-1])
if untagEvent[len(untagEvent)-1] != "untag" {
t.Fatalf("untag should be untag, not %#v", untagEvent)
c.Fatalf("untag should be untag, not %#v", untagEvent)
}
if deleteEvent[len(deleteEvent)-1] != "delete" {
t.Fatalf("delete should be delete, not %#v", deleteEvent)
c.Fatalf("delete should be delete, not %#v", deleteEvent)
}
logDone("events - image untag, delete is logged")
}
func TestEventsImagePull(t *testing.T) {
since := daemonTime(t).Unix()
testRequires(t, Network)
func (s *DockerSuite) TestEventsImagePull(c *check.C) {
since := daemonTime(c).Unix()
testRequires(c, Network)
defer deleteImages("hello-world")
pullCmd := exec.Command(dockerBinary, "pull", "hello-world")
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("pulling the hello-world image from has failed: %s, %v", out, err)
c.Fatalf("pulling the hello-world image from has failed: %s, %v", out, err)
}
eventsCmd := exec.Command(dockerBinary, "events",
fmt.Sprintf("--since=%d", since),
fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ := runCommandWithOutput(eventsCmd)
events := strings.Split(strings.TrimSpace(out), "\n")
event := strings.TrimSpace(events[len(events)-1])
if !strings.HasSuffix(event, "hello-world:latest: pull") {
t.Fatalf("Missing pull event - got:%q", event)
c.Fatalf("Missing pull event - got:%q", event)
}
logDone("events - image pull is logged")
}
func TestEventsImageImport(t *testing.T) {
defer deleteAllContainers()
since := daemonTime(t).Unix()
func (s *DockerSuite) TestEventsImageImport(c *check.C) {
since := daemonTime(c).Unix()
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -225,25 +216,24 @@ func TestEventsImageImport(t *testing.T) {
exec.Command(dockerBinary, "import", "-"),
)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
c.Errorf("import failed with errors: %v, output: %q", err, out)
}
eventsCmd := exec.Command(dockerBinary, "events",
fmt.Sprintf("--since=%d", since),
fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(strings.TrimSpace(out), "\n")
event := strings.TrimSpace(events[len(events)-1])
if !strings.HasSuffix(event, ": import") {
t.Fatalf("Missing import event - got:%q", event)
c.Fatalf("Missing import event - got:%q", event)
}
logDone("events - image import is logged")
}
func TestEventsFilters(t *testing.T) {
func (s *DockerSuite) TestEventsFilters(c *check.C) {
parseEvents := func(out, match string) {
events := strings.Split(out, "\n")
events = events[:len(events)-1]
@ -251,67 +241,65 @@ func TestEventsFilters(t *testing.T) {
eventFields := strings.Fields(event)
eventName := eventFields[len(eventFields)-1]
if ok, err := regexp.MatchString(match, eventName); err != nil || !ok {
t.Fatalf("event should match %s, got %#v, err: %v", match, eventFields, err)
c.Fatalf("event should match %s, got %#v, err: %v", match, eventFields, err)
}
}
}
since := daemonTime(t).Unix()
since := daemonTime(c).Unix()
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(t).Unix()), "--filter", "event=die"))
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die"))
if err != nil {
t.Fatalf("Failed to get events: %s", err)
c.Fatalf("Failed to get events: %s", err)
}
parseEvents(out, "die")
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(t).Unix()), "--filter", "event=die", "--filter", "event=start"))
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die", "--filter", "event=start"))
if err != nil {
t.Fatalf("Failed to get events: %s", err)
c.Fatalf("Failed to get events: %s", err)
}
parseEvents(out, "((die)|(start))")
// make sure we at least got 2 start events
count := strings.Count(out, "start")
if count < 2 {
t.Fatalf("should have had 2 start events but had %d, out: %s", count, out)
c.Fatalf("should have had 2 start events but had %d, out: %s", count, out)
}
logDone("events - filters")
}
func TestEventsFilterImageName(t *testing.T) {
since := daemonTime(t).Unix()
defer deleteAllContainers()
func (s *DockerSuite) TestEventsFilterImageName(c *check.C) {
since := daemonTime(c).Unix()
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_1", "-d", "busybox:latest", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
container1 := strings.TrimSpace(out)
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_2", "-d", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
container2 := strings.TrimSpace(out)
s := "busybox"
eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(t).Unix()), "--filter", fmt.Sprintf("image=%s", s))
name := "busybox"
eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", fmt.Sprintf("image=%s", name))
out, _, err = runCommandWithOutput(eventsCmd)
if err != nil {
t.Fatalf("Failed to get events, error: %s(%s)", err, out)
c.Fatalf("Failed to get events, error: %s(%s)", err, out)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) == 0 {
t.Fatalf("Expected events but found none for the image busybox:latest")
c.Fatalf("Expected events but found none for the image busybox:latest")
}
count1 := 0
count2 := 0
@ -324,27 +312,25 @@ func TestEventsFilterImageName(t *testing.T) {
}
}
if count1 == 0 || count2 == 0 {
t.Fatalf("Expected events from each container but got %d from %s and %d from %s", count1, container1, count2, container2)
c.Fatalf("Expected events from each container but got %d from %s and %d from %s", count1, container1, count2, container2)
}
logDone("events - filters using image")
}
func TestEventsFilterContainer(t *testing.T) {
defer deleteAllContainers()
since := fmt.Sprintf("%d", daemonTime(t).Unix())
func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
since := fmt.Sprintf("%d", daemonTime(c).Unix())
nameID := make(map[string]string)
for _, name := range []string{"container_1", "container_2"} {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", name, "busybox", "true"))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
nameID[name] = strings.TrimSpace(out)
waitInspect(name, "{{.State.Runing }}", "false", 5)
}
until := fmt.Sprintf("%d", daemonTime(t).Unix())
until := fmt.Sprintf("%d", daemonTime(c).Unix())
checkEvents := func(id string, events []string) error {
if len(events) != 3 { // create, start, die
@ -370,32 +356,31 @@ func TestEventsFilterContainer(t *testing.T) {
eventsCmd := exec.Command(dockerBinary, "events", "--since", since, "--until", until, "--filter", "container="+name)
out, _, err := runCommandWithOutput(eventsCmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
events := strings.Split(strings.TrimSuffix(out, "\n"), "\n")
if err := checkEvents(ID, events); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// filter by ID's
eventsCmd = exec.Command(dockerBinary, "events", "--since", since, "--until", until, "--filter", "container="+ID)
out, _, err = runCommandWithOutput(eventsCmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
events = strings.Split(strings.TrimSuffix(out, "\n"), "\n")
if err := checkEvents(ID, events); err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
logDone("events - filters using container name")
}
func TestEventsStreaming(t *testing.T) {
start := daemonTime(t).Unix()
func (s *DockerSuite) TestEventsStreaming(c *check.C) {
start := daemonTime(c).Unix()
finish := make(chan struct{})
defer close(finish)
@ -409,11 +394,11 @@ func TestEventsStreaming(t *testing.T) {
eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(start, 10))
stdout, err := eventsCmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
err = eventsCmd.Start()
if err != nil {
t.Fatalf("failed to start 'docker events': %s", err)
c.Fatalf("failed to start 'docker events': %s", err)
}
go func() {
@ -444,35 +429,35 @@ func TestEventsStreaming(t *testing.T) {
err = eventsCmd.Wait()
if err != nil && !IsKilled(err) {
t.Fatalf("docker events had bad exit status: %s", err)
c.Fatalf("docker events had bad exit status: %s", err)
}
}()
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox:latest", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
id <- cleanedContainerID
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container create in timely fashion")
c.Fatal("failed to observe container create in timely fashion")
case <-eventCreate:
// ignore, done
}
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container start in timely fashion")
c.Fatal("failed to observe container start in timely fashion")
case <-eventStart:
// ignore, done
}
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container die in timely fashion")
c.Fatal("failed to observe container die in timely fashion")
case <-eventDie:
// ignore, done
}
@ -480,15 +465,14 @@ func TestEventsStreaming(t *testing.T) {
rmCmd := exec.Command(dockerBinary, "rm", cleanedContainerID)
out, _, err = runCommandWithOutput(rmCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container destroy in timely fashion")
c.Fatal("failed to observe container destroy in timely fashion")
case <-eventDestroy:
// ignore, done
}
logDone("events - streamed to stdout")
}

View file

@ -8,48 +8,46 @@ import (
"io/ioutil"
"os"
"os/exec"
"testing"
"unicode"
"github.com/go-check/check"
"github.com/kr/pty"
)
// #5979
func TestEventsRedirectStdout(t *testing.T) {
since := daemonTime(t).Unix()
dockerCmd(t, "run", "busybox", "true")
defer deleteAllContainers()
func (s *DockerSuite) TestEventsRedirectStdout(c *check.C) {
since := daemonTime(c).Unix()
dockerCmd(c, "run", "busybox", "true")
file, err := ioutil.TempFile("", "")
if err != nil {
t.Fatalf("could not create temp file: %v", err)
c.Fatalf("could not create temp file: %v", err)
}
defer os.Remove(file.Name())
command := fmt.Sprintf("%s events --since=%d --until=%d > %s", dockerBinary, since, daemonTime(t).Unix(), file.Name())
command := fmt.Sprintf("%s events --since=%d --until=%d > %s", dockerBinary, since, daemonTime(c).Unix(), file.Name())
_, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
if err := cmd.Run(); err != nil {
t.Fatalf("run err for command %q: %v", command, err)
c.Fatalf("run err for command %q: %v", command, err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
for _, c := range scanner.Text() {
if unicode.IsControl(c) {
t.Fatalf("found control character %v", []byte(string(c)))
for _, ch := range scanner.Text() {
if unicode.IsControl(ch) {
c.Fatalf("found control character %v", []byte(string(ch)))
}
}
}
if err := scanner.Err(); err != nil {
t.Fatalf("Scan err for command %q: %v", command, err)
c.Fatalf("Scan err for command %q: %v", command, err)
}
logDone("events - redirect stdout")
}

View file

@ -12,38 +12,36 @@ import (
"sort"
"strings"
"sync"
"testing"
"time"
"github.com/go-check/check"
)
func TestExec(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExec(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/tmp/file")
out, _, err := runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if expected := "test"; out != expected {
t.Errorf("container exec should've printed %q but printed %q", expected, out)
c.Errorf("container exec should've printed %q but printed %q", expected, out)
}
logDone("exec - basic test")
}
func TestExecInteractiveStdinClose(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecInteractiveStdinClose(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "busybox", "/bin/cat"))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
contId := strings.TrimSpace(out)
@ -55,16 +53,16 @@ func TestExecInteractiveStdinClose(t *testing.T) {
cmd := exec.Command(dockerBinary, "exec", "-i", contId, "/bin/ls", "/")
cmd.Stdin = os.Stdin
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
if string(out) == "" {
t.Fatalf("Output was empty, likely blocked by standard input")
c.Fatalf("Output was empty, likely blocked by standard input")
}
returnchan <- struct{}{}
@ -73,163 +71,153 @@ func TestExecInteractiveStdinClose(t *testing.T) {
select {
case <-returnchan:
case <-time.After(10 * time.Second):
t.Fatal("timed out running docker exec")
c.Fatal("timed out running docker exec")
}
logDone("exec - interactive mode closes stdin after execution")
}
func TestExecInteractive(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecInteractive(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "-i", "testing", "sh")
stdin, err := execCmd.StdinPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
stdout, err := execCmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := execCmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := stdin.Write([]byte("cat /tmp/file\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
r := bufio.NewReader(stdout)
line, err := r.ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
line = strings.TrimSpace(line)
if line != "test" {
t.Fatalf("Output should be 'test', got '%q'", line)
c.Fatalf("Output should be 'test', got '%q'", line)
}
if err := stdin.Close(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
finish := make(chan struct{})
go func() {
if err := execCmd.Wait(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
close(finish)
}()
select {
case <-finish:
case <-time.After(1 * time.Second):
t.Fatal("docker exec failed to exit on stdin close")
c.Fatal("docker exec failed to exit on stdin close")
}
logDone("exec - Interactive test")
}
func TestExecAfterContainerRestart(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecAfterContainerRestart(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "exec", cleanedContainerID, "echo", "hello")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
outStr := strings.TrimSpace(out)
if outStr != "hello" {
t.Errorf("container should've printed hello, instead printed %q", outStr)
c.Errorf("container should've printed hello, instead printed %q", outStr)
}
logDone("exec - exec running container after container restart")
}
func TestExecAfterDaemonRestart(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestExecAfterDaemonRestart(c *check.C) {
testRequires(c, SameHostDaemon)
d := NewDaemon(t)
d := NewDaemon(c)
if err := d.StartWithBusybox(); err != nil {
t.Fatalf("Could not start daemon with busybox: %v", err)
c.Fatalf("Could not start daemon with busybox: %v", err)
}
defer d.Stop()
if out, err := d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil {
t.Fatalf("Could not run top: err=%v\n%s", err, out)
c.Fatalf("Could not run top: err=%v\n%s", err, out)
}
if err := d.Restart(); err != nil {
t.Fatalf("Could not restart daemon: %v", err)
c.Fatalf("Could not restart daemon: %v", err)
}
if out, err := d.Cmd("start", "top"); err != nil {
t.Fatalf("Could not start top after daemon restart: err=%v\n%s", err, out)
c.Fatalf("Could not start top after daemon restart: err=%v\n%s", err, out)
}
out, err := d.Cmd("exec", "top", "echo", "hello")
if err != nil {
t.Fatalf("Could not exec on container top: err=%v\n%s", err, out)
c.Fatalf("Could not exec on container top: err=%v\n%s", err, out)
}
outStr := strings.TrimSpace(string(out))
if outStr != "hello" {
t.Errorf("container should've printed hello, instead printed %q", outStr)
c.Errorf("container should've printed hello, instead printed %q", outStr)
}
logDone("exec - exec running container after daemon restart")
}
// Regression test for #9155, #9044
func TestExecEnv(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecEnv(c *check.C) {
runCmd := exec.Command(dockerBinary, "run",
"-e", "LALA=value1",
"-e", "LALA=value2",
"-d", "--name", "testing", "busybox", "top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "testing", "env")
out, _, err := runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if strings.Contains(out, "LALA=value1") ||
!strings.Contains(out, "LALA=value2") ||
!strings.Contains(out, "HOME=/root") {
t.Errorf("exec env(%q), expect %q, %q", out, "LALA=value2", "HOME=/root")
c.Errorf("exec env(%q), expect %q, %q", out, "LALA=value2", "HOME=/root")
}
logDone("exec - exec inherits correct env")
}
func TestExecExitStatus(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecExitStatus(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// Test normal (non-detached) case first
@ -237,20 +225,18 @@ func TestExecExitStatus(t *testing.T) {
ec, _ := runCommand(cmd)
if ec != 23 {
t.Fatalf("Should have had an ExitCode of 23, not: %d", ec)
c.Fatalf("Should have had an ExitCode of 23, not: %d", ec)
}
logDone("exec - exec non-zero ExitStatus")
}
func TestExecPausedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecPausedContainer(c *check.C) {
defer unpauseAllContainers()
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ContainerID := strings.TrimSpace(out)
@ -258,82 +244,78 @@ func TestExecPausedContainer(t *testing.T) {
pausedCmd := exec.Command(dockerBinary, "pause", "testing")
out, _, _, err = runCommandWithStdoutStderr(pausedCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "-i", "-t", ContainerID, "echo", "hello")
out, _, err = runCommandWithOutput(execCmd)
if err == nil {
t.Fatal("container should fail to exec new command if it is paused")
c.Fatal("container should fail to exec new command if it is paused")
}
expected := ContainerID + " is paused, unpause the container before exec"
if !strings.Contains(out, expected) {
t.Fatal("container should not exec new command if it is paused")
c.Fatal("container should not exec new command if it is paused")
}
logDone("exec - exec should not exec a pause container")
}
// regression test for #9476
func TestExecTtyCloseStdin(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecTtyCloseStdin(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "-it", "--name", "exec_tty_stdin", "busybox")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd = exec.Command(dockerBinary, "exec", "-i", "exec_tty_stdin", "cat")
stdinRw, err := cmd.StdinPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
stdinRw.Write([]byte("test"))
stdinRw.Close()
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd = exec.Command(dockerBinary, "top", "exec_tty_stdin")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
outArr := strings.Split(out, "\n")
if len(outArr) > 3 || strings.Contains(out, "nsenter-exec") {
// This is the really bad part
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rm", "-f", "exec_tty_stdin")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
t.Fatalf("exec process left running\n\t %s", out)
c.Fatalf("exec process left running\n\t %s", out)
}
logDone("exec - stdin is closed properly with tty enabled")
}
func TestExecTtyWithoutStdin(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecTtyWithoutStdin(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to start container: %v (%v)", out, err)
c.Fatalf("failed to start container: %v (%v)", out, err)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer func() {
cmd := exec.Command(dockerBinary, "kill", id)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatalf("failed to kill container: %v (%v)", out, err)
c.Fatalf("failed to kill container: %v (%v)", out, err)
}
}()
@ -343,86 +325,80 @@ func TestExecTtyWithoutStdin(t *testing.T) {
cmd := exec.Command(dockerBinary, "exec", "-ti", id, "true")
if _, err := cmd.StdinPipe(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil {
t.Fatal("exec should have failed")
c.Fatal("exec should have failed")
} else if !strings.Contains(out, expected) {
t.Fatalf("exec failed with error %q: expected %q", out, expected)
c.Fatalf("exec failed with error %q: expected %q", out, expected)
}
}()
select {
case <-done:
case <-time.After(3 * time.Second):
t.Fatal("exec is running but should have failed")
c.Fatal("exec is running but should have failed")
}
logDone("exec - forbid piped stdin to tty enabled container")
}
func TestExecParseError(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecParseError(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// Test normal (non-detached) case first
cmd := exec.Command(dockerBinary, "exec", "top")
if _, stderr, code, err := runCommandWithStdoutStderr(cmd); err == nil || !strings.Contains(stderr, "See '"+dockerBinary+" exec --help'") || code == 0 {
t.Fatalf("Should have thrown error & point to help: %s", stderr)
c.Fatalf("Should have thrown error & point to help: %s", stderr)
}
logDone("exec - error on parseExec should point to help")
}
func TestExecStopNotHanging(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecStopNotHanging(c *check.C) {
if out, err := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top").CombinedOutput(); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if err := exec.Command(dockerBinary, "exec", "testing", "top").Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
wait := make(chan struct{})
go func() {
if out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput(); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
close(wait)
}()
select {
case <-time.After(3 * time.Second):
t.Fatal("Container stop timed out")
c.Fatal("Container stop timed out")
case <-wait:
}
logDone("exec - container with exec not hanging on stop")
}
func TestExecCgroup(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecCgroup(c *check.C) {
var cmd *exec.Cmd
cmd = exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
_, err := runCommand(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "exec", "testing", "cat", "/proc/1/cgroup")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerCgroups := sort.StringSlice(strings.Split(string(out), "\n"))
var wg sync.WaitGroup
var s sync.Mutex
var mu sync.Mutex
execCgroups := []sort.StringSlice{}
// exec a few times concurrently to get consistent failure
for i := 0; i < 5; i++ {
@ -431,13 +407,13 @@ func TestExecCgroup(t *testing.T) {
cmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/proc/self/cgroup")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cg := sort.StringSlice(strings.Split(string(out), "\n"))
s.Lock()
mu.Lock()
execCgroups = append(execCgroups, cg)
s.Unlock()
mu.Unlock()
wg.Done()
}()
}
@ -454,86 +430,81 @@ func TestExecCgroup(t *testing.T) {
for _, name := range containerCgroups {
fmt.Printf(" %s\n", name)
}
t.Fatal("cgroups mismatched")
c.Fatal("cgroups mismatched")
}
}
logDone("exec - exec has the container cgroups")
}
func TestInspectExecID(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestInspectExecID(c *check.C) {
out, exitCode, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "top"))
if exitCode != 0 || err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
id := strings.TrimSuffix(out, "\n")
out, err = inspectField(id, "ExecIDs")
if err != nil {
t.Fatalf("failed to inspect container: %s, %v", out, err)
c.Fatalf("failed to inspect container: %s, %v", out, err)
}
if out != "<no value>" {
t.Fatalf("ExecIDs should be empty, got: %s", out)
c.Fatalf("ExecIDs should be empty, got: %s", out)
}
exitCode, err = runCommand(exec.Command(dockerBinary, "exec", "-d", id, "ls", "/"))
if exitCode != 0 || err != nil {
t.Fatalf("failed to exec in container: %s, %v", out, err)
c.Fatalf("failed to exec in container: %s, %v", out, err)
}
out, err = inspectField(id, "ExecIDs")
if err != nil {
t.Fatalf("failed to inspect container: %s, %v", out, err)
c.Fatalf("failed to inspect container: %s, %v", out, err)
}
out = strings.TrimSuffix(out, "\n")
if out == "[]" || out == "<no value>" {
t.Fatalf("ExecIDs should not be empty, got: %s", out)
c.Fatalf("ExecIDs should not be empty, got: %s", out)
}
logDone("inspect - inspect a container with ExecIDs")
}
func TestLinksPingLinkedContainersOnRename(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksPingLinkedContainersOnRename(c *check.C) {
var out string
out, _ = dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
out, _ = dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
idA := strings.TrimSpace(out)
if idA == "" {
t.Fatal(out, "id should not be nil")
c.Fatal(out, "id should not be nil")
}
out, _ = dockerCmd(t, "run", "-d", "--link", "container1:alias1", "--name", "container2", "busybox", "top")
out, _ = dockerCmd(c, "run", "-d", "--link", "container1:alias1", "--name", "container2", "busybox", "top")
idB := strings.TrimSpace(out)
if idB == "" {
t.Fatal(out, "id should not be nil")
c.Fatal(out, "id should not be nil")
}
execCmd := exec.Command(dockerBinary, "exec", "container2", "ping", "-c", "1", "alias1", "-W", "1")
out, _, err := runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
dockerCmd(t, "rename", "container1", "container_new")
dockerCmd(c, "rename", "container1", "container_new")
execCmd = exec.Command(dockerBinary, "exec", "container2", "ping", "-c", "1", "alias1", "-W", "1")
out, _, err = runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("links - ping linked container upon rename")
}
func TestRunExecDir(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestRunExecDir(c *check.C) {
testRequires(c, SameHostDaemon)
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(out)
execDir := filepath.Join(execDriverPath, id)
@ -542,92 +513,90 @@ func TestRunExecDir(t *testing.T) {
{
fi, err := os.Stat(execDir)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !fi.IsDir() {
t.Fatalf("%q must be a directory", execDir)
c.Fatalf("%q must be a directory", execDir)
}
fi, err = os.Stat(stateFile)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
stopCmd := exec.Command(dockerBinary, "stop", id)
out, _, err = runCommandWithOutput(stopCmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
{
_, err := os.Stat(execDir)
if err == nil {
t.Fatal(err)
c.Fatal(err)
}
if err == nil {
t.Fatalf("Exec directory %q exists for removed container!", execDir)
c.Fatalf("Exec directory %q exists for removed container!", execDir)
}
if !os.IsNotExist(err) {
t.Fatalf("Error should be about non-existing, got %s", err)
c.Fatalf("Error should be about non-existing, got %s", err)
}
}
startCmd := exec.Command(dockerBinary, "start", id)
out, _, err = runCommandWithOutput(startCmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
{
fi, err := os.Stat(execDir)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !fi.IsDir() {
t.Fatalf("%q must be a directory", execDir)
c.Fatalf("%q must be a directory", execDir)
}
fi, err = os.Stat(stateFile)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
rmCmd := exec.Command(dockerBinary, "rm", "-f", id)
out, _, err = runCommandWithOutput(rmCmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
{
_, err := os.Stat(execDir)
if err == nil {
t.Fatal(err)
c.Fatal(err)
}
if err == nil {
t.Fatalf("Exec directory %q is exists for removed container!", execDir)
c.Fatalf("Exec directory %q is exists for removed container!", execDir)
}
if !os.IsNotExist(err) {
t.Fatalf("Error should be about non-existing, got %s", err)
c.Fatalf("Error should be about non-existing, got %s", err)
}
}
logDone("run - check execdriver dir behavior")
}
func TestRunMutableNetworkFiles(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestRunMutableNetworkFiles(c *check.C) {
testRequires(c, SameHostDaemon)
for _, fn := range []string{"resolv.conf", "hosts"} {
deleteAllContainers()
content, err := runCommandAndReadContainerFile(fn, exec.Command(dockerBinary, "run", "-d", "--name", "c1", "busybox", "sh", "-c", fmt.Sprintf("echo success >/etc/%s && top", fn)))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(string(content)) != "success" {
t.Fatal("Content was not what was modified in the container", string(content))
c.Fatal("Content was not what was modified in the container", string(content))
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "c2", "busybox", "top"))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
contID := strings.TrimSpace(out)
@ -636,88 +605,83 @@ func TestRunMutableNetworkFiles(t *testing.T) {
f, err := os.OpenFile(netFilePath, os.O_WRONLY|os.O_SYNC|os.O_APPEND, 0644)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := f.Seek(0, 0); err != nil {
f.Close()
t.Fatal(err)
c.Fatal(err)
}
if err := f.Truncate(0); err != nil {
f.Close()
t.Fatal(err)
c.Fatal(err)
}
if _, err := f.Write([]byte("success2\n")); err != nil {
f.Close()
t.Fatal(err)
c.Fatal(err)
}
f.Close()
res, err := exec.Command(dockerBinary, "exec", contID, "cat", "/etc/"+fn).CombinedOutput()
if err != nil {
t.Fatalf("Output: %s, error: %s", res, err)
c.Fatalf("Output: %s, error: %s", res, err)
}
if string(res) != "success2\n" {
t.Fatalf("Expected content of %s: %q, got: %q", fn, "success2\n", res)
c.Fatalf("Expected content of %s: %q, got: %q", fn, "success2\n", res)
}
}
logDone("run - mutable network files")
}
func TestExecWithUser(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecWithUser(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd := exec.Command(dockerBinary, "exec", "-u", "1", "parent", "id")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if !strings.Contains(out, "uid=1(daemon) gid=1(daemon)") {
t.Fatalf("exec with user by id expected daemon user got %s", out)
c.Fatalf("exec with user by id expected daemon user got %s", out)
}
cmd = exec.Command(dockerBinary, "exec", "-u", "root", "parent", "id")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if !strings.Contains(out, "uid=0(root) gid=0(root)") {
t.Fatalf("exec with user by root expected root user got %s", out)
c.Fatalf("exec with user by root expected root user got %s", out)
}
logDone("exec - with user")
}
func TestExecWithPrivileged(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecWithPrivileged(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "--cap-drop=ALL", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd := exec.Command(dockerBinary, "exec", "parent", "sh", "-c", "mknod /tmp/sda b 8 0")
out, _, err := runCommandWithOutput(cmd)
if err == nil || !strings.Contains(out, "Operation not permitted") {
t.Fatalf("exec mknod in --cap-drop=ALL container without --privileged should failed")
c.Fatalf("exec mknod in --cap-drop=ALL container without --privileged should failed")
}
cmd = exec.Command(dockerBinary, "exec", "--privileged", "parent", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.TrimSpace(out); actual != "ok" {
t.Fatalf("exec mknod in --cap-drop=ALL container with --privileged failed: %v, output: %q", err, out)
c.Fatalf("exec mknod in --cap-drop=ALL container with --privileged failed: %v, output: %q", err, out)
}
logDone("exec - exec command in a container with privileged")
}

View file

@ -4,11 +4,12 @@ import (
"os"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// export an image and try to import it into a new one
func TestExportContainerAndImportImage(t *testing.T) {
func (s *DockerSuite) TestExportContainerAndImportImage(c *check.C) {
containerID := "testexportcontainerandimportimage"
defer deleteImages("repo/testexp:v1")
@ -17,39 +18,38 @@ func TestExportContainerAndImportImage(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", containerID, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
inspectCmd := exec.Command(dockerBinary, "inspect", containerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %s %s ", containerID, err)
c.Fatalf("output should've been a container id: %s %s ", containerID, err)
}
exportCmd := exec.Command(dockerBinary, "export", containerID)
if out, _, err = runCommandWithOutput(exportCmd); err != nil {
t.Fatalf("failed to export container: %s, %v", out, err)
c.Fatalf("failed to export container: %s, %v", out, err)
}
importCmd := exec.Command(dockerBinary, "import", "-", "repo/testexp:v1")
importCmd.Stdin = strings.NewReader(out)
out, _, err = runCommandWithOutput(importCmd)
if err != nil {
t.Fatalf("failed to import image: %s, %v", out, err)
c.Fatalf("failed to import image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd = exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been an image id: %s, %v", out, err)
c.Fatalf("output should've been an image id: %s, %v", out, err)
}
logDone("export - export/import a container/image")
}
// Used to test output flag in the export command
func TestExportContainerWithOutputAndImportImage(t *testing.T) {
func (s *DockerSuite) TestExportContainerWithOutputAndImportImage(c *check.C) {
containerID := "testexportcontainerwithoutputandimportimage"
defer deleteImages("repo/testexp:v1")
@ -58,40 +58,39 @@ func TestExportContainerWithOutputAndImportImage(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", containerID, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
inspectCmd := exec.Command(dockerBinary, "inspect", containerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %s %s ", containerID, err)
c.Fatalf("output should've been a container id: %s %s ", containerID, err)
}
defer os.Remove("testexp.tar")
exportCmd := exec.Command(dockerBinary, "export", "--output=testexp.tar", containerID)
if out, _, err = runCommandWithOutput(exportCmd); err != nil {
t.Fatalf("failed to export container: %s, %v", out, err)
c.Fatalf("failed to export container: %s, %v", out, err)
}
out, _, err = runCommandWithOutput(exec.Command("cat", "testexp.tar"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
importCmd := exec.Command(dockerBinary, "import", "-", "repo/testexp:v1")
importCmd.Stdin = strings.NewReader(out)
out, _, err = runCommandWithOutput(importCmd)
if err != nil {
t.Fatalf("failed to import image: %s, %v", out, err)
c.Fatalf("failed to import image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd = exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been an image id: %s, %v", out, err)
c.Fatalf("output should've been an image id: %s, %v", out, err)
}
logDone("export - export/import a container/image with output flag")
}

View file

@ -5,13 +5,13 @@ import (
"os/exec"
"runtime"
"strings"
"testing"
"unicode"
"github.com/docker/docker/pkg/homedir"
"github.com/go-check/check"
)
func TestHelpTextVerify(t *testing.T) {
func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
// 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
@ -51,26 +51,26 @@ func TestHelpTextVerify(t *testing.T) {
helpCmd.Env = newEnvs
out, ec, err := runCommandWithOutput(helpCmd)
if err != nil || ec != 0 {
t.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
c.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
}
lines := strings.Split(out, "\n")
for _, line := range lines {
if len(line) > 80 {
t.Fatalf("Line is too long(%d chars):\n%s", len(line), line)
c.Fatalf("Line is too long(%d chars):\n%s", len(line), line)
}
// All lines should not end with a space
if strings.HasSuffix(line, " ") {
t.Fatalf("Line should not end with a space: %s", line)
c.Fatalf("Line should not end with a space: %s", line)
}
if scanForHome && strings.Contains(line, `=`+home) {
t.Fatalf("Line should use '%q' instead of %q:\n%s", homedir.GetShortcutString(), home, line)
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] != '/' {
t.Fatalf("Main help should not have used home shortcut:\n%s", line)
c.Fatalf("Main help should not have used home shortcut:\n%s", line)
}
}
}
@ -82,11 +82,11 @@ func TestHelpTextVerify(t *testing.T) {
helpCmd.Env = newEnvs
out, ec, err = runCommandWithOutput(helpCmd)
if err != nil || ec != 0 {
t.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
c.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
}
i := strings.Index(out, "Commands:")
if i < 0 {
t.Fatalf("Missing 'Commands:' in:\n%s", out)
c.Fatalf("Missing 'Commands:' in:\n%s", out)
}
// Grab all chars starting at "Commands:"
@ -106,39 +106,39 @@ func TestHelpTextVerify(t *testing.T) {
helpCmd.Env = newEnvs
out, ec, err := runCommandWithOutput(helpCmd)
if err != nil || ec != 0 {
t.Fatalf("Error on %q help: %s\nexit code:%d", cmd, out, ec)
c.Fatalf("Error on %q help: %s\nexit code:%d", cmd, out, ec)
}
lines := strings.Split(out, "\n")
for _, line := range lines {
if len(line) > 80 {
t.Fatalf("Help for %q is too long(%d chars):\n%s", cmd,
c.Fatalf("Help for %q is too long(%d chars):\n%s", cmd,
len(line), line)
}
if scanForHome && strings.Contains(line, `"`+home) {
t.Fatalf("Help for %q should use ~ instead of %q on:\n%s",
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] != '/' {
t.Fatalf("Help for %q should not have used ~:\n%s", cmd, line)
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
if strings.HasPrefix(line, " ") {
t.Fatalf("Help for %q should not have a multi-line option: %s", cmd, line)
c.Fatalf("Help for %q should not have a multi-line option: %s", cmd, line)
}
// Options should NOT end with a period
if strings.HasPrefix(line, " -") && strings.HasSuffix(line, ".") {
t.Fatalf("Help for %q should not end with a period: %s", cmd, line)
c.Fatalf("Help for %q should not end with a period: %s", cmd, line)
}
// Options should NOT end with a space
if strings.HasSuffix(line, " ") {
t.Fatalf("Help for %q should not end with a space: %s", cmd, line)
c.Fatalf("Help for %q should not end with a space: %s", cmd, line)
}
}
@ -146,10 +146,9 @@ func TestHelpTextVerify(t *testing.T) {
expected := 39
if len(cmds) != expected {
t.Fatalf("Wrong # of cmds(%d), it should be: %d\nThe list:\n%q",
c.Fatalf("Wrong # of cmds(%d), it should be: %d\nThe list:\n%q",
len(cmds), expected, cmds)
}
}
logDone("help - verify text")
}

View file

@ -4,12 +4,13 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// 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 TestBuildHistory(t *testing.T) {
func (s *DockerSuite) TestBuildHistory(c *check.C) {
name := "testbuildhistory"
defer deleteImages(name)
_, err := buildImage(name, `FROM busybox
@ -42,12 +43,12 @@ RUN echo "Z"`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, exitCode, err := runCommandWithOutput(exec.Command(dockerBinary, "history", "testbuildhistory"))
if err != nil || exitCode != 0 {
t.Fatalf("failed to get image history: %s, %v", out, err)
c.Fatalf("failed to get image history: %s, %v", out, err)
}
actualValues := strings.Split(out, "\n")[1:27]
@ -58,32 +59,29 @@ RUN echo "Z"`,
actualValue := actualValues[i]
if !strings.Contains(actualValue, echoValue) {
t.Fatalf("Expected layer \"%s\", but was: %s", expectedValues[i], actualValue)
c.Fatalf("Expected layer \"%s\", but was: %s", expectedValues[i], actualValue)
}
}
logDone("history - build history")
}
func TestHistoryExistentImage(t *testing.T) {
func (s *DockerSuite) TestHistoryExistentImage(c *check.C) {
historyCmd := exec.Command(dockerBinary, "history", "busybox")
_, exitCode, err := runCommandWithOutput(historyCmd)
if err != nil || exitCode != 0 {
t.Fatal("failed to get image history")
c.Fatal("failed to get image history")
}
logDone("history - history on existent image must pass")
}
func TestHistoryNonExistentImage(t *testing.T) {
func (s *DockerSuite) TestHistoryNonExistentImage(c *check.C) {
historyCmd := exec.Command(dockerBinary, "history", "testHistoryNonExistentImage")
_, exitCode, err := runCommandWithOutput(historyCmd)
if err == nil || exitCode == 0 {
t.Fatal("history on a non-existent image didn't result in a non-zero exit status")
c.Fatal("history on a non-existent image didn't result in a non-zero exit status")
}
logDone("history - history on non-existent image must pass")
}
func TestHistoryImageWithComment(t *testing.T) {
func (s *DockerSuite) TestHistoryImageWithComment(c *check.C) {
name := "testhistoryimagewithcomment"
defer deleteContainer(name)
defer deleteImages(name)
@ -93,26 +91,26 @@ func TestHistoryImageWithComment(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
waitCmd := exec.Command(dockerBinary, "wait", name)
if out, _, err := runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
comment := "This_is_a_comment"
commitCmd := exec.Command(dockerBinary, "commit", "-m="+comment, name, name)
if out, _, err := runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
// test docker history <image id> to check comment messages
historyCmd := exec.Command(dockerBinary, "history", name)
out, exitCode, err := runCommandWithOutput(historyCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to get image history: %s, %v", out, err)
c.Fatalf("failed to get image history: %s, %v", out, err)
}
outputTabs := strings.Fields(strings.Split(out, "\n")[1])
@ -120,8 +118,7 @@ func TestHistoryImageWithComment(t *testing.T) {
actualValue := outputTabs[len(outputTabs)-1]
if !strings.Contains(actualValue, comment) {
t.Fatalf("Expected comments %q, but found %q", comment, actualValue)
c.Fatalf("Expected comments %q, but found %q", comment, actualValue)
}
logDone("history - history on image with comment")
}

View file

@ -6,27 +6,26 @@ import (
"reflect"
"sort"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
)
func TestImagesEnsureImageIsListed(t *testing.T) {
func (s *DockerSuite) TestImagesEnsureImageIsListed(c *check.C) {
imagesCmd := exec.Command(dockerBinary, "images")
out, _, err := runCommandWithOutput(imagesCmd)
if err != nil {
t.Fatalf("listing images failed with errors: %s, %v", out, err)
c.Fatalf("listing images failed with errors: %s, %v", out, err)
}
if !strings.Contains(out, "busybox") {
t.Fatal("images should've listed busybox")
c.Fatal("images should've listed busybox")
}
logDone("images - busybox should be listed")
}
func TestImagesOrderedByCreationDate(t *testing.T) {
func (s *DockerSuite) TestImagesOrderedByCreationDate(c *check.C) {
defer deleteImages("order:test_a")
defer deleteImages("order:test_c")
defer deleteImages("order:test_b")
@ -34,56 +33,53 @@ func TestImagesOrderedByCreationDate(t *testing.T) {
`FROM scratch
MAINTAINER dockerio1`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(time.Second)
id2, err := buildImage("order:test_c",
`FROM scratch
MAINTAINER dockerio2`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(time.Second)
id3, err := buildImage("order:test_b",
`FROM scratch
MAINTAINER dockerio3`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "images", "-q", "--no-trunc"))
if err != nil {
t.Fatalf("listing images failed with errors: %s, %v", out, err)
c.Fatalf("listing images failed with errors: %s, %v", out, err)
}
imgs := strings.Split(out, "\n")
if imgs[0] != id3 {
t.Fatalf("First image must be %s, got %s", id3, imgs[0])
c.Fatalf("First image must be %s, got %s", id3, imgs[0])
}
if imgs[1] != id2 {
t.Fatalf("Second image must be %s, got %s", id2, imgs[1])
c.Fatalf("Second image must be %s, got %s", id2, imgs[1])
}
if imgs[2] != id1 {
t.Fatalf("Third image must be %s, got %s", id1, imgs[2])
c.Fatalf("Third image must be %s, got %s", id1, imgs[2])
}
logDone("images - ordering by creation date")
}
func TestImagesErrorWithInvalidFilterNameTest(t *testing.T) {
func (s *DockerSuite) TestImagesErrorWithInvalidFilterNameTest(c *check.C) {
imagesCmd := exec.Command(dockerBinary, "images", "-f", "FOO=123")
out, _, err := runCommandWithOutput(imagesCmd)
if !strings.Contains(out, "Invalid filter") {
t.Fatalf("error should occur when listing images with invalid filter name FOO, %s, %v", out, err)
c.Fatalf("error should occur when listing images with invalid filter name FOO, %s, %v", out, err)
}
logDone("images - invalid filter name check working")
}
func TestImagesFilterLabel(t *testing.T) {
func (s *DockerSuite) TestImagesFilterLabel(c *check.C) {
imageName1 := "images_filter_test1"
imageName2 := "images_filter_test2"
imageName3 := "images_filter_test3"
defer deleteAllContainers()
defer deleteImages(imageName1)
defer deleteImages(imageName2)
defer deleteImages(imageName3)
@ -91,51 +87,49 @@ func TestImagesFilterLabel(t *testing.T) {
`FROM scratch
LABEL match me`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
image2ID, err := buildImage(imageName2,
`FROM scratch
LABEL match="me too"`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
image3ID, err := buildImage(imageName3,
`FROM scratch
LABEL nomatch me`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd := exec.Command(dockerBinary, "images", "--no-trunc", "-q", "-f", "label=match")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.TrimSpace(out)
if (!strings.Contains(out, image1ID) && !strings.Contains(out, image2ID)) || strings.Contains(out, image3ID) {
t.Fatalf("Expected ids %s,%s got %s", image1ID, image2ID, out)
c.Fatalf("Expected ids %s,%s got %s", image1ID, image2ID, out)
}
cmd = exec.Command(dockerBinary, "images", "--no-trunc", "-q", "-f", "label=match=me too")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.TrimSpace(out)
if out != image2ID {
t.Fatalf("Expected %s got %s", image2ID, out)
c.Fatalf("Expected %s got %s", image2ID, out)
}
logDone("images - filter label")
}
func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) {
imageName := "images_filter_test"
defer deleteAllContainers()
defer deleteImages(imageName)
buildImage(imageName,
`FROM scratch
@ -156,7 +150,7 @@ func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
cmd := exec.Command(dockerBinary, "images", "-q", "-f", filter)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
listing := strings.Split(out, "\n")
sort.Strings(listing)
@ -172,50 +166,47 @@ func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
}
fmt.Print("")
}
t.Fatalf("All output must be the same")
c.Fatalf("All output must be the same")
}
}
logDone("images - white space trimming and lower casing")
}
func TestImagesEnsureDanglingImageOnlyListedOnce(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestImagesEnsureDanglingImageOnlyListedOnce(c *check.C) {
// create container 1
c := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error running busybox: %s, %v", out, err)
c.Fatalf("error running busybox: %s, %v", out, err)
}
containerId1 := strings.TrimSpace(out)
// tag as foobox
c = exec.Command(dockerBinary, "commit", containerId1, "foobox")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "commit", containerId1, "foobox")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error tagging foobox: %s", err)
c.Fatalf("error tagging foobox: %s", err)
}
imageId := stringid.TruncateID(strings.TrimSpace(out))
defer deleteImages(imageId)
// overwrite the tag, making the previous image dangling
c = exec.Command(dockerBinary, "tag", "-f", "busybox", "foobox")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "tag", "-f", "busybox", "foobox")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error tagging foobox: %s", err)
c.Fatalf("error tagging foobox: %s", err)
}
defer deleteImages("foobox")
c = exec.Command(dockerBinary, "images", "-q", "-f", "dangling=true")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "-q", "-f", "dangling=true")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("listing images failed with errors: %s, %v", out, err)
c.Fatalf("listing images failed with errors: %s, %v", out, err)
}
if e, a := 1, strings.Count(out, imageId); e != a {
t.Fatalf("expected 1 dangling image, got %d: %s", a, out)
c.Fatalf("expected 1 dangling image, got %d: %s", a, out)
}
logDone("images - dangling image only listed once")
}

View file

@ -3,14 +3,15 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestImportDisplay(t *testing.T) {
func (s *DockerSuite) TestImportDisplay(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
@ -20,11 +21,11 @@ func TestImportDisplay(t *testing.T) {
exec.Command(dockerBinary, "import", "-"),
)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
c.Errorf("import failed with errors: %v, output: %q", err, out)
}
if n := strings.Count(out, "\n"); n != 1 {
t.Fatalf("display is messed up: %d '\\n' instead of 1:\n%s", n, out)
c.Fatalf("display is messed up: %d '\\n' instead of 1:\n%s", n, out)
}
image := strings.TrimSpace(out)
defer deleteImages(image)
@ -32,12 +33,11 @@ func TestImportDisplay(t *testing.T) {
runCmd = exec.Command(dockerBinary, "run", "--rm", image, "true")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
if out != "" {
t.Fatalf("command output should've been nothing, was %q", out)
c.Fatalf("command output should've been nothing, was %q", out)
}
logDone("import - display is fine, imported image runs")
}

View file

@ -3,15 +3,16 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// ensure docker info succeeds
func TestInfoEnsureSucceeds(t *testing.T) {
func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
versionCmd := exec.Command(dockerBinary, "info")
out, exitCode, err := runCommandWithOutput(versionCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to execute docker info: %s, %v", out, err)
c.Fatalf("failed to execute docker info: %s, %v", out, err)
}
// always shown fields
@ -29,9 +30,8 @@ func TestInfoEnsureSucceeds(t *testing.T) {
for _, linePrefix := range stringsToCheck {
if !strings.Contains(out, linePrefix) {
t.Errorf("couldn't find string %v in output", linePrefix)
c.Errorf("couldn't find string %v in output", linePrefix)
}
}
logDone("info - verify that it works")
}

View file

@ -3,21 +3,21 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestInspectImage(t *testing.T) {
func (s *DockerSuite) TestInspectImage(c *check.C) {
imageTest := "emptyfs"
imageTestID := "511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158"
imagesCmd := exec.Command(dockerBinary, "inspect", "--format='{{.Id}}'", imageTest)
out, exitCode, err := runCommandWithOutput(imagesCmd)
if exitCode != 0 || err != nil {
t.Fatalf("failed to inspect image: %s, %v", out, err)
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
if id := strings.TrimSuffix(out, "\n"); id != imageTestID {
t.Fatalf("Expected id: %s for image: %s but received id: %s", imageTestID, imageTest, id)
c.Fatalf("Expected id: %s for image: %s but received id: %s", imageTestID, imageTest, id)
}
logDone("inspect - inspect an image")
}

View file

@ -3,73 +3,72 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestKillContainer(t *testing.T) {
func (s *DockerSuite) TestKillContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
listRunningContainersCmd := exec.Command(dockerBinary, "ps", "-q")
out, _, err = runCommandWithOutput(listRunningContainersCmd)
if err != nil {
t.Fatalf("failed to list running containers: %s, %v", out, err)
c.Fatalf("failed to list running containers: %s, %v", out, err)
}
if strings.Contains(out, cleanedContainerID) {
t.Fatal("killed container is still running")
c.Fatal("killed container is still running")
}
deleteContainer(cleanedContainerID)
logDone("kill - kill container running top")
}
func TestKillDifferentUserContainer(t *testing.T) {
func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-u", "daemon", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
listRunningContainersCmd := exec.Command(dockerBinary, "ps", "-q")
out, _, err = runCommandWithOutput(listRunningContainersCmd)
if err != nil {
t.Fatalf("failed to list running containers: %s, %v", out, err)
c.Fatalf("failed to list running containers: %s, %v", out, err)
}
if strings.Contains(out, cleanedContainerID) {
t.Fatal("killed container is still running")
c.Fatal("killed container is still running")
}
deleteContainer(cleanedContainerID)
logDone("kill - kill container running top from a different user")
}

View file

@ -8,89 +8,81 @@ import (
"reflect"
"regexp"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/iptables"
"github.com/go-check/check"
)
func TestLinksEtcHostsRegularFile(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !strings.HasPrefix(out, "-") {
t.Errorf("/etc/hosts should be a regular file")
c.Errorf("/etc/hosts should be a regular file")
}
logDone("link - /etc/hosts is a regular file")
}
func TestLinksEtcHostsContentMatch(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksEtcHostsContentMatch(c *check.C) {
testRequires(c, SameHostDaemon)
runCmd := exec.Command(dockerBinary, "run", "--net=host", "busybox", "cat", "/etc/hosts")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
hosts, err := ioutil.ReadFile("/etc/hosts")
if os.IsNotExist(err) {
t.Skip("/etc/hosts does not exist, skip this test")
c.Skip("/etc/hosts does not exist, skip this test")
}
if out != string(hosts) {
t.Errorf("container")
c.Errorf("container")
}
logDone("link - /etc/hosts matches hosts copy")
}
func TestLinksPingUnlinkedContainers(t *testing.T) {
func (s *DockerSuite) TestLinksPingUnlinkedContainers(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
exitCode, err := runCommand(runCmd)
if exitCode == 0 {
t.Fatal("run ping did not fail")
c.Fatal("run ping did not fail")
} else if exitCode != 1 {
t.Fatalf("run ping failed with errors: %v", err)
c.Fatalf("run ping failed with errors: %v", err)
}
logDone("links - ping unlinked container")
}
// Test for appropriate error when calling --link with an invalid target container
func TestLinksInvalidContainerTarget(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksInvalidContainerTarget(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--link", "bogus:alias", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err == nil {
t.Fatal("an invalid container target should produce an error")
c.Fatal("an invalid container target should produce an error")
}
if !strings.Contains(out, "Could not get container") {
t.Fatalf("error output expected 'Could not get container', but got %q instead; err: %v", out, err)
c.Fatalf("error output expected 'Could not get container', but got %q instead; err: %v", out, err)
}
logDone("links - linking to non-existent container should not work")
}
func TestLinksPingLinkedContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksPingLinkedContainers(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "container1", "--hostname", "fred", "busybox", "top")
if _, err := runCommand(runCmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "-d", "--name", "container2", "--hostname", "wilma", "busybox", "top")
if _, err := runCommand(runCmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
runArgs := []string{"run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "sh", "-c"}
@ -98,74 +90,68 @@ func TestLinksPingLinkedContainers(t *testing.T) {
// test ping by alias, ping by name, and ping by hostname
// 1. Ping by alias
dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
// 2. Ping by container name
dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
// 3. Ping by hostname
dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
logDone("links - ping linked container")
}
func TestLinksPingLinkedContainersAfterRename(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksPingLinkedContainersAfterRename(c *check.C) {
out, _ := dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
out, _ := dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
idA := strings.TrimSpace(out)
out, _ = dockerCmd(t, "run", "-d", "--name", "container2", "busybox", "top")
out, _ = dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
idB := strings.TrimSpace(out)
dockerCmd(t, "rename", "container1", "container_new")
dockerCmd(t, "run", "--rm", "--link", "container_new:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
dockerCmd(t, "kill", idA)
dockerCmd(t, "kill", idB)
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 1 && ping -c 1 alias2 -W 1")
dockerCmd(c, "kill", idA)
dockerCmd(c, "kill", idB)
logDone("links - ping linked container after rename")
}
func TestLinksIpTablesRulesWhenLinkAndUnlink(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) {
testRequires(c, SameHostDaemon)
dockerCmd(t, "run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
childIP := findContainerIP(t, "child")
parentIP := findContainerIP(t, "parent")
childIP := findContainerIP(c, "child")
parentIP := findContainerIP(c, "parent")
sourceRule := []string{"-i", "docker0", "-o", "docker0", "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"}
destinationRule := []string{"-i", "docker0", "-o", "docker0", "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"}
if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) {
t.Fatal("Iptables rules not found")
c.Fatal("Iptables rules not found")
}
dockerCmd(t, "rm", "--link", "parent/http")
dockerCmd(c, "rm", "--link", "parent/http")
if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) {
t.Fatal("Iptables rules should be removed when unlink")
c.Fatal("Iptables rules should be removed when unlink")
}
dockerCmd(t, "kill", "child")
dockerCmd(t, "kill", "parent")
dockerCmd(c, "kill", "child")
dockerCmd(c, "kill", "parent")
logDone("link - verify iptables when link and unlink")
}
func TestLinksInspectLinksStarted(t *testing.T) {
func (s *DockerSuite) TestLinksInspectLinksStarted(c *check.C) {
var (
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
result []string
)
defer deleteAllContainers()
dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
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, err := inspectFieldJSON("testinspectlink", "HostConfig.Links")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
err = unmarshalJSON([]byte(links), &result)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
output := convertSliceOfStringsToMap(result)
@ -173,28 +159,26 @@ func TestLinksInspectLinksStarted(t *testing.T) {
equal := reflect.DeepEqual(output, expected)
if !equal {
t.Fatalf("Links %s, expected %s", result, expected)
c.Fatalf("Links %s, expected %s", result, expected)
}
logDone("link - links in started container inspect")
}
func TestLinksInspectLinksStopped(t *testing.T) {
func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) {
var (
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
result []string
)
defer deleteAllContainers()
dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
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, err := inspectFieldJSON("testinspectlink", "HostConfig.Links")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
err = unmarshalJSON([]byte(links), &result)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
output := convertSliceOfStringsToMap(result)
@ -202,47 +186,42 @@ func TestLinksInspectLinksStopped(t *testing.T) {
equal := reflect.DeepEqual(output, expected)
if !equal {
t.Fatalf("Links %s, but expected %s", result, expected)
c.Fatalf("Links %s, but expected %s", result, expected)
}
logDone("link - links in stopped container inspect")
}
func TestLinksNotStartedParentNotFail(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksNotStartedParentNotFail(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "--name=first", "busybox", "top")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "create", "--name=second", "--link=first:first", "busybox", "top")
out, _, _, err = runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "start", "first")
out, _, _, err = runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("link - container start successfully updating stopped parent links")
}
func TestLinksHostsFilesInject(t *testing.T) {
testRequires(t, SameHostDaemon, ExecSupport)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksHostsFilesInject(c *check.C) {
testRequires(c, SameHostDaemon, ExecSupport)
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "--name", "one", "busybox", "top"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
idOne := strings.TrimSpace(out)
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "--name", "two", "--link", "one:onetwo", "busybox", "top"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
idTwo := strings.TrimSpace(out)
@ -251,89 +230,83 @@ func TestLinksHostsFilesInject(t *testing.T) {
contentOne, err := readContainerFileWithExec(idOne, "/etc/hosts")
if err != nil {
t.Fatal(err, string(contentOne))
c.Fatal(err, string(contentOne))
}
contentTwo, err := readContainerFileWithExec(idTwo, "/etc/hosts")
if err != nil {
t.Fatal(err, string(contentTwo))
c.Fatal(err, string(contentTwo))
}
if !strings.Contains(string(contentTwo), "onetwo") {
t.Fatal("Host is not present in updated hosts file", string(contentTwo))
c.Fatal("Host is not present in updated hosts file", string(contentTwo))
}
logDone("link - ensure containers hosts files are updated with the link alias.")
}
func TestLinksNetworkHostContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--net", "host", "--name", "host_container", "busybox", "top"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true"))
if err == nil || !strings.Contains(out, "--net=host can't be used with links. This would result in undefined behavior.") {
t.Fatalf("Running container linking to a container with --net host should have failed: %s", out)
c.Fatalf("Running container linking to a container with --net host should have failed: %s", out)
}
logDone("link - error thrown when linking to container with --net host")
}
func TestLinksUpdateOnRestart(t *testing.T) {
testRequires(t, SameHostDaemon, ExecSupport)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksUpdateOnRestart(c *check.C) {
testRequires(c, SameHostDaemon, ExecSupport)
if out, err := exec.Command(dockerBinary, "run", "-d", "--name", "one", "busybox", "top").CombinedOutput(); err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
out, err := exec.Command(dockerBinary, "run", "-d", "--name", "two", "--link", "one:onetwo", "--link", "one:one", "busybox", "top").CombinedOutput()
if err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
id := strings.TrimSpace(string(out))
realIP, err := inspectField("one", "NetworkSettings.IPAddress")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
content, err := readContainerFileWithExec(id, "/etc/hosts")
if err != nil {
t.Fatal(err, string(content))
c.Fatal(err, string(content))
}
getIP := func(hosts []byte, hostname string) string {
re := regexp.MustCompile(fmt.Sprintf(`(\S*)\t%s`, regexp.QuoteMeta(hostname)))
matches := re.FindSubmatch(hosts)
if matches == nil {
t.Fatalf("Hostname %s have no matches in hosts", hostname)
c.Fatalf("Hostname %s have no matches in hosts", hostname)
}
return string(matches[1])
}
if ip := getIP(content, "one"); ip != realIP {
t.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
}
if ip := getIP(content, "onetwo"); ip != realIP {
t.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
}
if out, err := exec.Command(dockerBinary, "restart", "one").CombinedOutput(); err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
realIP, err = inspectField("one", "NetworkSettings.IPAddress")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
content, err = readContainerFileWithExec(id, "/etc/hosts")
if err != nil {
t.Fatal(err, string(content))
c.Fatal(err, string(content))
}
if ip := getIP(content, "one"); ip != realIP {
t.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
}
if ip := getIP(content, "onetwo"); ip != realIP {
t.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
}
logDone("link - ensure containers hosts files are updated on restart")
}

View file

@ -3,10 +3,11 @@ package main
import (
"bytes"
"os/exec"
"testing"
"github.com/go-check/check"
)
func TestLoginWithoutTTY(t *testing.T) {
func (s *DockerSuite) TestLoginWithoutTTY(c *check.C) {
cmd := exec.Command(dockerBinary, "login")
// Send to stdin so the process does not get the TTY
@ -14,8 +15,7 @@ func TestLoginWithoutTTY(t *testing.T) {
// run the command and block until it's done
if err := cmd.Run(); err == nil {
t.Fatal("Expected non nil err when loginning in & TTY not available")
c.Fatal("Expected non nil err when loginning in & TTY not available")
}
logDone("login - login without TTY")
}

View file

@ -5,19 +5,19 @@ import (
"os/exec"
"regexp"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/timeutils"
"github.com/go-check/check"
)
// This used to work, it test a log of PageSize-1 (gh#4851)
func TestLogsContainerSmallerThanPage(t *testing.T) {
func (s *DockerSuite) TestLogsContainerSmallerThanPage(c *check.C) {
testLen := 32767
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -26,25 +26,24 @@ func TestLogsContainerSmallerThanPage(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if len(out) != testLen+1 {
t.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs container running echo smaller than page size")
}
// Regression test: When going over the PageSize, it used to panic (gh#4851)
func TestLogsContainerBiggerThanPage(t *testing.T) {
func (s *DockerSuite) TestLogsContainerBiggerThanPage(c *check.C) {
testLen := 32768
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -53,25 +52,24 @@ func TestLogsContainerBiggerThanPage(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if len(out) != testLen+1 {
t.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs container running echo bigger than page size")
}
// Regression test: When going much over the PageSize, it used to block (gh#4851)
func TestLogsContainerMuchBiggerThanPage(t *testing.T) {
func (s *DockerSuite) TestLogsContainerMuchBiggerThanPage(c *check.C) {
testLen := 33000
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -80,25 +78,24 @@ func TestLogsContainerMuchBiggerThanPage(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if len(out) != testLen+1 {
t.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs container running echo much bigger than page size")
}
func TestLogsTimestamps(t *testing.T) {
func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
testLen := 100
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -107,13 +104,13 @@ func TestLogsTimestamps(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", "-t", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines := strings.Split(out, "\n")
if len(lines) != testLen+1 {
t.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
ts := regexp.MustCompile(`^.* `)
@ -122,26 +119,25 @@ func TestLogsTimestamps(t *testing.T) {
if l != "" {
_, err := time.Parse(timeutils.RFC3339NanoFixed+" ", ts.FindString(l))
if err != nil {
t.Fatalf("Failed to parse timestamp from %v: %v", l, err)
c.Fatalf("Failed to parse timestamp from %v: %v", l, err)
}
if l[29] != 'Z' { // ensure we have padded 0's
t.Fatalf("Timestamp isn't padded properly: %s", l)
c.Fatalf("Timestamp isn't padded properly: %s", l)
}
}
}
deleteContainer(cleanedContainerID)
logDone("logs - logs with timestamps")
}
func TestLogsSeparateStderr(t *testing.T) {
func (s *DockerSuite) TestLogsSeparateStderr(c *check.C) {
msg := "stderr_log"
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -150,30 +146,29 @@ func TestLogsSeparateStderr(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
stdout, stderr, _, err := runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if stdout != "" {
t.Fatalf("Expected empty stdout stream, got %v", stdout)
c.Fatalf("Expected empty stdout stream, got %v", stdout)
}
stderr = strings.TrimSpace(stderr)
if stderr != msg {
t.Fatalf("Expected %v in stderr stream, got %v", msg, stderr)
c.Fatalf("Expected %v in stderr stream, got %v", msg, stderr)
}
deleteContainer(cleanedContainerID)
logDone("logs - separate stderr (without pseudo-tty)")
}
func TestLogsStderrInStdout(t *testing.T) {
func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
msg := "stderr_log"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -182,30 +177,29 @@ func TestLogsStderrInStdout(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
stdout, stderr, _, err := runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if stderr != "" {
t.Fatalf("Expected empty stderr stream, got %v", stdout)
c.Fatalf("Expected empty stderr stream, got %v", stdout)
}
stdout = strings.TrimSpace(stdout)
if stdout != msg {
t.Fatalf("Expected %v in stdout stream, got %v", msg, stdout)
c.Fatalf("Expected %v in stdout stream, got %v", msg, stdout)
}
deleteContainer(cleanedContainerID)
logDone("logs - stderr in stdout (with pseudo-tty)")
}
func TestLogsTail(t *testing.T) {
func (s *DockerSuite) TestLogsTail(c *check.C) {
testLen := 100
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -214,49 +208,48 @@ func TestLogsTail(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", "--tail", "5", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines := strings.Split(out, "\n")
if len(lines) != 6 {
t.Fatalf("Expected log %d lines, received %d\n", 6, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", 6, len(lines))
}
logsCmd = exec.Command(dockerBinary, "logs", "--tail", "all", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines = strings.Split(out, "\n")
if len(lines) != testLen+1 {
t.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
logsCmd = exec.Command(dockerBinary, "logs", "--tail", "random", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines = strings.Split(out, "\n")
if len(lines) != testLen+1 {
t.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs tail")
}
func TestLogsFollowStopped(t *testing.T) {
func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -264,34 +257,33 @@ func TestLogsFollowStopped(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
if err := logsCmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
c := make(chan struct{})
ch := make(chan struct{})
go func() {
if err := logsCmd.Wait(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
close(c)
close(ch)
}()
select {
case <-c:
case <-ch:
case <-time.After(1 * time.Second):
t.Fatal("Following logs is hanged")
c.Fatal("Following logs is hanged")
}
deleteContainer(cleanedContainerID)
logDone("logs - logs follow stopped container")
}
// Regression test for #8832
func TestLogsFollowSlowStdoutConsumer(t *testing.T) {
func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", `usleep 200000;yes X | head -c 200000`)
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -308,30 +300,29 @@ func TestLogsFollowSlowStdoutConsumer(t *testing.T) {
stdout, err := logCmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := logCmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// First read slowly
bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// After the container has finished we can continue reading fast
bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
actual := bytes1 + bytes2
expected := 200000
if actual != expected {
t.Fatalf("Invalid bytes read: %d, expected %d", actual, expected)
c.Fatalf("Invalid bytes read: %d, expected %d", actual, expected)
}
logDone("logs - follow slow consumer")
}

View file

@ -5,32 +5,32 @@ import (
"net"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestNetworkNat(t *testing.T) {
testRequires(t, SameHostDaemon, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestNetworkNat(c *check.C) {
testRequires(c, SameHostDaemon, NativeExecDriver)
iface, err := net.InterfaceByName("eth0")
if err != nil {
t.Skipf("Test not running with `make test`. Interface eth0 not found: %s", err)
c.Skip(fmt.Sprintf("Test not running with `make test`. Interface eth0 not found: %v", err))
}
ifaceAddrs, err := iface.Addrs()
if err != nil || len(ifaceAddrs) == 0 {
t.Fatalf("Error retrieving addresses for eth0: %v (%d addresses)", err, len(ifaceAddrs))
c.Fatalf("Error retrieving addresses for eth0: %v (%d addresses)", err, len(ifaceAddrs))
}
ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String())
if err != nil {
t.Fatalf("Error retrieving the up for eth0: %s", err)
c.Fatalf("Error retrieving the up for eth0: %s", err)
}
runCmd := exec.Command(dockerBinary, "run", "-dt", "-p", "8080:8080", "busybox", "nc", "-lp", "8080")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -38,25 +38,24 @@ func TestNetworkNat(t *testing.T) {
runCmd = exec.Command(dockerBinary, "run", "busybox", "sh", "-c", fmt.Sprintf("echo hello world | nc -w 30 %s 8080", ifaceIP))
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to retrieve logs for container: %s, %v", out, err)
c.Fatalf("failed to retrieve logs for container: %s, %v", out, err)
}
out = strings.Trim(out, "\r\n")
if expected := "hello world"; out != expected {
t.Fatalf("Unexpected output. Expected: %q, received: %q for iface %s", expected, out, ifaceIP)
c.Fatalf("Unexpected output. Expected: %q, received: %q for iface %s", expected, out, ifaceIP)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
logDone("network - make sure nat works through the host")
}

View file

@ -4,78 +4,76 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestPause(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPause(c *check.C) {
defer unpauseAllContainers()
name := "testeventpause"
out, _ := dockerCmd(t, "images", "-q")
out, _ := dockerCmd(c, "images", "-q")
image := strings.Split(out, "\n")[0]
dockerCmd(t, "run", "-d", "--name", name, image, "top")
dockerCmd(c, "run", "-d", "--name", name, image, "top")
dockerCmd(t, "pause", name)
dockerCmd(c, "pause", name)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != 1 {
t.Fatalf("there should be one paused container and not %d", len(pausedContainers))
c.Fatalf("there should be one paused container and not %d", len(pausedContainers))
}
dockerCmd(t, "unpause", name)
dockerCmd(c, "unpause", name)
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
pauseEvent := strings.Fields(events[len(events)-3])
unpauseEvent := strings.Fields(events[len(events)-2])
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
c.Fatalf("event should be pause, not %#v", pauseEvent)
}
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
logDone("pause - pause/unpause is logged")
}
func TestPauseMultipleContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) {
defer unpauseAllContainers()
containers := []string{
"testpausewithmorecontainers1",
"testpausewithmorecontainers2",
}
out, _ := dockerCmd(t, "images", "-q")
out, _ := dockerCmd(c, "images", "-q")
image := strings.Split(out, "\n")[0]
for _, name := range containers {
dockerCmd(t, "run", "-d", "--name", name, image, "top")
dockerCmd(c, "run", "-d", "--name", name, image, "top")
}
dockerCmd(t, append([]string{"pause"}, containers...)...)
dockerCmd(c, append([]string{"pause"}, containers...)...)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != len(containers) {
t.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
c.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
}
dockerCmd(t, append([]string{"unpause"}, containers...)...)
dockerCmd(c, append([]string{"unpause"}, containers...)...)
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= len(containers)*3-2 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
pauseEvents := make([][]string, len(containers))
@ -87,14 +85,13 @@ func TestPauseMultipleContainers(t *testing.T) {
for _, pauseEvent := range pauseEvents {
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
c.Fatalf("event should be pause, not %#v", pauseEvent)
}
}
for _, unpauseEvent := range unpauseEvents {
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
}
logDone("pause - multi pause/unpause is logged")
}

View file

@ -5,42 +5,42 @@ import (
"os/exec"
"sort"
"strings"
"testing"
"github.com/go-check/check"
)
func TestPortList(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPortList(c *check.C) {
// one port
runCmd := exec.Command(dockerBinary, "run", "-d", "-p", "9876:80", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", firstID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "port", firstID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"80/tcp -> 0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "rm", "-f", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// three port
@ -51,36 +51,36 @@ func TestPortList(t *testing.T) {
"busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", ID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "port", ID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{
if !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"}) {
t.Error("Port list is not correct")
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "rm", "-f", ID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// more and one port mapped to the same container port
@ -92,46 +92,45 @@ func TestPortList(t *testing.T) {
"busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ID = strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", ID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "port", ID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{
if !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"}) {
t.Error("Port list is not correct\n", out)
c.Error("Port list is not correct\n", out)
}
runCmd = exec.Command(dockerBinary, "rm", "-f", ID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("port - test port list")
}
func assertPortList(t *testing.T, out string, expected []string) bool {
func assertPortList(c *check.C, out string, expected []string) bool {
//lines := strings.Split(out, "\n")
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != len(expected) {
t.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
c.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
return false
}
sort.Strings(lines)
@ -139,7 +138,7 @@ func assertPortList(t *testing.T, out string, expected []string) bool {
for i := 0; i < len(expected); i++ {
if lines[i] != expected[i] {
t.Error("|" + lines[i] + "!=" + expected[i] + "|")
c.Error("|" + lines[i] + "!=" + expected[i] + "|")
return false
}
}
@ -147,84 +146,78 @@ func assertPortList(t *testing.T, out string, expected []string) bool {
return true
}
func TestPortHostBinding(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPortHostBinding(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "-p", "9876:80", "busybox",
"nc", "-l", "-p", "80")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", firstID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", "9876")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "rm", "-f", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", "9876")
if out, _, err = runCommandWithOutput(runCmd); err == nil {
t.Error("Port is still bound after the Container is removed")
c.Error("Port is still bound after the Container is removed")
}
logDone("port - test host binding done")
}
func TestPortExposeHostBinding(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "-P", "--expose", "80", "busybox",
"nc", "-l", "-p", "80")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", firstID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
_, exposedPort, err := net.SplitHostPort(out)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort))
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "rm", "-f", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort))
if out, _, err = runCommandWithOutput(runCmd); err == nil {
t.Error("Port is still bound after the Container is removed")
c.Error("Port is still bound after the Container is removed")
}
logDone("port - test port expose done")
}

View file

@ -4,30 +4,30 @@ import (
"net"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestCliProxyDisableProxyUnixSock(t *testing.T) {
testRequires(t, SameHostDaemon) // test is valid when DOCKER_HOST=unix://..
func (s *DockerSuite) TestCliProxyDisableProxyUnixSock(c *check.C) {
testRequires(c, SameHostDaemon) // test is valid when DOCKER_HOST=unix://..
cmd := exec.Command(dockerBinary, "info")
cmd.Env = appendBaseEnv([]string{"HTTP_PROXY=http://127.0.0.1:9999"})
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
logDone("cli proxy - HTTP_PROXY is not used when connecting to unix sock")
}
// Can't use localhost here since go has a special case to not use proxy if connecting to localhost
// See https://golang.org/pkg/net/http/#ProxyFromEnvironment
func TestCliProxyProxyTCPSock(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCliProxyProxyTCPSock(c *check.C) {
testRequires(c, SameHostDaemon)
// get the IP to use to connect since we can't use localhost
addrs, err := net.InterfaceAddrs()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
var ip string
for _, addr := range addrs {
@ -40,25 +40,24 @@ func TestCliProxyProxyTCPSock(t *testing.T) {
}
if ip == "" {
t.Fatal("could not find ip to connect to")
c.Fatal("could not find ip to connect to")
}
d := NewDaemon(t)
d := NewDaemon(c)
if err := d.Start("-H", "tcp://"+ip+":2375"); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd := exec.Command(dockerBinary, "info")
cmd.Env = []string{"DOCKER_HOST=tcp://" + ip + ":2375", "HTTP_PROXY=127.0.0.1:9999"}
if out, _, err := runCommandWithOutput(cmd); err == nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
// Test with no_proxy
cmd.Env = append(cmd.Env, "NO_PROXY="+ip)
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "info")); err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
logDone("cli proxy - HTTP_PROXY is used for TCP sock")
}

View file

@ -6,24 +6,24 @@ import (
"reflect"
"strconv"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
func TestPsListContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainers(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondID := strings.TrimSpace(out)
@ -31,53 +31,53 @@ func TestPsListContainers(t *testing.T) {
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
thirdID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
fourthID := strings.TrimSpace(out)
// make sure the second is running
if err := waitRun(secondID); err != nil {
t.Fatalf("waiting for container failed: %v", err)
c.Fatalf("waiting for container failed: %v", err)
}
// make sure third one is not running
runCmd = exec.Command(dockerBinary, "wait", thirdID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// make sure the forth is running
if err := waitRun(fourthID); err != nil {
t.Fatalf("waiting for container failed: %v", err)
c.Fatalf("waiting for container failed: %v", err)
}
// all
runCmd = exec.Command(dockerBinary, "ps", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// running
runCmd = exec.Command(dockerBinary, "ps")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, []string{fourthID, secondID, firstID}) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// from here all flag '-a' is ignored
@ -86,156 +86,155 @@ func TestPsListContainers(t *testing.T) {
runCmd = exec.Command(dockerBinary, "ps", "-n=2", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected := []string{fourthID, thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "-n=2")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{fourthID, thirdID, secondID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// before
runCmd = exec.Command(dockerBinary, "ps", "--before", thirdID, "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{secondID, firstID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--before", thirdID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & before
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID, "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{thirdID, secondID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & limit
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "-n=2", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{fourthID, thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "-n=2")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// before & limit
runCmd = exec.Command(dockerBinary, "ps", "--before", fourthID, "-n=1", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--before", fourthID, "-n=1")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & before & limit
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID, "-n=1", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID, "-n=1")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
logDone("ps - test ps options")
}
func assertContainerList(out string, expected []string) bool {
@ -255,8 +254,7 @@ func assertContainerList(out string, expected []string) bool {
return true
}
func TestPsListContainersSize(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello")
runCommandWithOutput(cmd)
@ -267,18 +265,18 @@ func TestPsListContainersSize(t *testing.T) {
baseFoundsize := baseLines[1][baseSizeIndex:]
baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0])
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
name := "test_size"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
id, err := getIDByName(name)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "ps", "-s", "-n=1")
@ -290,54 +288,52 @@ func TestPsListContainersSize(t *testing.T) {
select {
case <-wait:
case <-time.After(3 * time.Second):
t.Fatalf("Calling \"docker ps -s\" timed out!")
c.Fatalf("Calling \"docker ps -s\" timed out!")
}
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != 2 {
t.Fatalf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines))
c.Fatalf("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]
if foundID != id[:12] {
t.Fatalf("Expected id %s, got %s", id[:12], foundID)
c.Fatalf("Expected id %s, got %s", id[:12], foundID)
}
expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
foundSize := lines[1][sizeIndex:]
if foundSize != expectedSize {
t.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
c.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
}
logDone("ps - test ps size")
}
func TestPsListContainersFilterStatus(t *testing.T) {
func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
// FIXME: this should test paused, but it makes things hang and its wonky
// this is because paused containers can't be controlled by signals
defer deleteAllContainers()
// start exited container
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// make sure the exited cintainer is not running
runCmd = exec.Command(dockerBinary, "wait", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// start running container
runCmd = exec.Command(dockerBinary, "run", "-itd", "busybox")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondID := strings.TrimSpace(out)
@ -345,313 +341,302 @@ func TestPsListContainersFilterStatus(t *testing.T) {
runCmd = exec.Command(dockerBinary, "ps", "-q", "--filter=status=exited")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=status=running")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if containerOut != secondID[:12] {
t.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
}
logDone("ps - test ps filter status")
}
func TestPsListContainersFilterID(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
// start container
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// start another container
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// filter containers by id
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=id="+firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
logDone("ps - test ps filter id")
}
func TestPsListContainersFilterName(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
// start container
runCmd := exec.Command(dockerBinary, "run", "-d", "--name=a_name_to_match", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// start another container
runCmd = exec.Command(dockerBinary, "run", "-d", "--name=b_name_to_match", "busybox", "top")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// filter containers by name
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=name=a_name_to_match")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
logDone("ps - test ps filter name")
}
func TestPsListContainersFilterLabel(t *testing.T) {
func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
// start container
runCmd := exec.Command(dockerBinary, "run", "-d", "-l", "match=me", "-l", "second=tag", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// start another container
runCmd = exec.Command(dockerBinary, "run", "-d", "-l", "match=me too", "busybox")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondID := strings.TrimSpace(out)
// start third container
runCmd = exec.Command(dockerBinary, "run", "-d", "-l", "nomatch=me", "busybox")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
thirdID := strings.TrimSpace(out)
// filter containers by exact match
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
}
// filter containers by two labels
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if containerOut != firstID {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
c.Fatalf("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
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if containerOut != "" {
t.Fatalf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)
c.Fatalf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)
}
// filter containers by exact key
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if (!strings.Contains(containerOut, firstID) || !strings.Contains(containerOut, secondID)) || strings.Contains(containerOut, thirdID) {
t.Fatalf("Expected ids %s,%s, got %s for exited filter, output: %q", firstID, secondID, containerOut, out)
c.Fatalf("Expected ids %s,%s, got %s for exited filter, output: %q", firstID, secondID, containerOut, out)
}
deleteAllContainers()
logDone("ps - test ps filter label")
}
func TestPsListContainersFilterExited(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "zero1", "busybox", "true")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstZero, err := getIDByName("zero1")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "zero2", "busybox", "true")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondZero, err := getIDByName("zero2")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "nonzero1", "busybox", "false")
if out, _, err := runCommandWithOutput(runCmd); err == nil {
t.Fatal("Should fail.", out, err)
c.Fatal("Should fail.", out, err)
}
firstNonZero, err := getIDByName("nonzero1")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "nonzero2", "busybox", "false")
if out, _, err := runCommandWithOutput(runCmd); err == nil {
t.Fatal("Should fail.", out, err)
c.Fatal("Should fail.", out, err)
}
secondNonZero, err := getIDByName("nonzero2")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// filter containers by exited=0
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ids := strings.Split(strings.TrimSpace(out), "\n")
if len(ids) != 2 {
t.Fatalf("Should be 2 zero exited containers got %d: %s", len(ids), out)
c.Fatalf("Should be 2 zero exited containers got %d: %s", len(ids), out)
}
if ids[0] != secondZero {
t.Fatalf("First in list should be %q, got %q", secondZero, ids[0])
c.Fatalf("First in list should be %q, got %q", secondZero, ids[0])
}
if ids[1] != firstZero {
t.Fatalf("Second in list should be %q, got %q", firstZero, ids[1])
c.Fatalf("Second in list should be %q, got %q", firstZero, ids[1])
}
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ids = strings.Split(strings.TrimSpace(out), "\n")
if len(ids) != 2 {
t.Fatalf("Should be 2 zero exited containerst got %d", len(ids))
c.Fatalf("Should be 2 zero exited containerst got %d", len(ids))
}
if ids[0] != secondNonZero {
t.Fatalf("First in list should be %q, got %q", secondNonZero, ids[0])
c.Fatalf("First in list should be %q, got %q", secondNonZero, ids[0])
}
if ids[1] != firstNonZero {
t.Fatalf("Second in list should be %q, got %q", firstNonZero, ids[1])
c.Fatalf("Second in list should be %q, got %q", firstNonZero, ids[1])
}
logDone("ps - test ps filter exited")
}
func TestPsRightTagName(t *testing.T) {
func (s *DockerSuite) TestPsRightTagName(c *check.C) {
tag := "asybox:shmatest"
defer deleteAllContainers()
defer deleteImages(tag)
if out, err := exec.Command(dockerBinary, "tag", "busybox", tag).CombinedOutput(); err != nil {
t.Fatalf("Failed to tag image: %s, out: %q", err, out)
c.Fatalf("Failed to tag image: %s, out: %q", err, out)
}
var id1 string
if out, err := exec.Command(dockerBinary, "run", "-d", "busybox", "top").CombinedOutput(); err != nil {
t.Fatalf("Failed to run container: %s, out: %q", err, out)
c.Fatalf("Failed to run container: %s, out: %q", err, out)
} else {
id1 = strings.TrimSpace(string(out))
}
var id2 string
if out, err := exec.Command(dockerBinary, "run", "-d", tag, "top").CombinedOutput(); err != nil {
t.Fatalf("Failed to run container: %s, out: %q", err, out)
c.Fatalf("Failed to run container: %s, out: %q", err, out)
} else {
id2 = strings.TrimSpace(string(out))
}
var imageID string
if out, err := exec.Command(dockerBinary, "inspect", "-f", "{{.Id}}", "busybox").CombinedOutput(); err != nil {
t.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
c.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
} else {
imageID = strings.TrimSpace(string(out))
}
var id3 string
if out, err := exec.Command(dockerBinary, "run", "-d", imageID, "top").CombinedOutput(); err != nil {
t.Fatalf("Failed to run container: %s, out: %q", err, out)
c.Fatalf("Failed to run container: %s, out: %q", err, out)
} else {
id3 = strings.TrimSpace(string(out))
}
out, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
if err != nil {
t.Fatalf("Failed to run 'ps': %s, out: %q", err, out)
c.Fatalf("Failed to run 'ps': %s, out: %q", err, out)
}
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
// skip header
lines = lines[1:]
if len(lines) != 3 {
t.Fatalf("There should be 3 running container, got %d", len(lines))
c.Fatalf("There should be 3 running container, got %d", len(lines))
}
for _, line := range lines {
f := strings.Fields(line)
switch f[0] {
case id1:
if f[1] != "busybox" {
t.Fatalf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])
c.Fatalf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])
}
case id2:
if f[1] != tag {
t.Fatalf("Expected %s tag for id %s, got %s", tag, id2, f[1])
c.Fatalf("Expected %s tag for id %s, got %s", tag, id2, f[1])
}
case id3:
if f[1] != imageID {
t.Fatalf("Expected %s imageID for id %s, got %s", tag, id3, f[1])
c.Fatalf("Expected %s imageID for id %s, got %s", tag, id3, f[1])
}
default:
t.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
}
}
logDone("ps - right tags for containers")
}
func TestPsLinkedWithNoTrunc(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
if out, err := exec.Command(dockerBinary, "run", "--name=first", "-d", "busybox", "top").CombinedOutput(); err != nil {
t.Fatalf("Output: %s, err: %s", out, err)
c.Fatalf("Output: %s, err: %s", out, err)
}
if out, err := exec.Command(dockerBinary, "run", "--name=second", "--link=first:first", "-d", "busybox", "top").CombinedOutput(); err != nil {
t.Fatalf("Output: %s, err: %s", out, err)
c.Fatalf("Output: %s, err: %s", out, err)
}
out, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
if err != nil {
t.Fatalf("Output: %s, err: %s", out, err)
c.Fatalf("Output: %s, err: %s", out, err)
}
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
// strip header
@ -663,28 +648,26 @@ func TestPsLinkedWithNoTrunc(t *testing.T) {
names = append(names, fields[len(fields)-1])
}
if !reflect.DeepEqual(expected, names) {
t.Fatalf("Expected array: %v, got: %v", expected, names)
c.Fatalf("Expected array: %v, got: %v", expected, names)
}
}
func TestPsGroupPortRange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsGroupPortRange(c *check.C) {
portRange := "3800-3900"
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "porttest", "-p", portRange+":"+portRange, "busybox", "top"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "ps"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// check that the port range is in the output
if !strings.Contains(string(out), portRange) {
t.Fatalf("docker ps output should have had the port range %q: %s", portRange, string(out))
c.Fatalf("docker ps output should have had the port range %q: %s", portRange, string(out))
}
logDone("ps - port range")
}

View file

@ -4,12 +4,13 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// See issue docker/docker#8141
func TestPullImageWithAliases(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPullImageWithAliases(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
defer deleteImages(repoName)
@ -22,40 +23,39 @@ func TestPullImageWithAliases(t *testing.T) {
// Tag and push the same image multiple times.
for _, repo := range repos {
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "tag", "busybox", repo)); err != nil {
t.Fatalf("Failed to tag image %v: error %v, output %q", repos, err, out)
c.Fatalf("Failed to tag image %v: error %v, output %q", repos, err, out)
}
defer deleteImages(repo)
if out, err := exec.Command(dockerBinary, "push", repo).CombinedOutput(); err != nil {
t.Fatalf("Failed to push image %v: error %v, output %q", repo, err, string(out))
c.Fatalf("Failed to push image %v: error %v, output %q", repo, err, string(out))
}
}
// Clear local images store.
args := append([]string{"rmi"}, repos...)
if out, err := exec.Command(dockerBinary, args...).CombinedOutput(); err != nil {
t.Fatalf("Failed to clean images: error %v, output %q", err, string(out))
c.Fatalf("Failed to clean images: error %v, output %q", err, string(out))
}
// Pull a single tag and verify it doesn't bring down all aliases.
pullCmd := exec.Command(dockerBinary, "pull", repos[0])
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("Failed to pull %v: error %v, output %q", repoName, err, out)
c.Fatalf("Failed to pull %v: error %v, output %q", repoName, err, out)
}
if err := exec.Command(dockerBinary, "inspect", repos[0]).Run(); err != nil {
t.Fatalf("Image %v was not pulled down", repos[0])
c.Fatalf("Image %v was not pulled down", repos[0])
}
for _, repo := range repos[1:] {
if err := exec.Command(dockerBinary, "inspect", repo).Run(); err == nil {
t.Fatalf("Image %v shouldn't have been pulled down", repo)
c.Fatalf("Image %v shouldn't have been pulled down", repo)
}
}
logDone("pull - image with aliases")
}
// pulling library/hello-world should show verified message
func TestPullVerified(t *testing.T) {
t.Skip("Skipping hub dependent test")
func (s *DockerSuite) TestPullVerified(c *check.C) {
c.Skip("Skipping hub dependent test")
// Image must be pulled from central repository to get verified message
// unless keychain is manually updated to contain the daemon's sign key.
@ -68,49 +68,46 @@ func TestPullVerified(t *testing.T) {
pullCmd := exec.Command(dockerBinary, "pull", verifiedName)
if out, exitCode, err := runCommandWithOutput(pullCmd); err != nil || !strings.Contains(out, expected) {
if err != nil || exitCode != 0 {
t.Skipf("pulling the '%s' image from the registry has failed: %s", verifiedName, err)
c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err))
}
t.Fatalf("pulling a verified image failed. expected: %s\ngot: %s, %v", expected, out, err)
c.Fatalf("pulling a verified image failed. expected: %s\ngot: %s, %v", expected, out, err)
}
// pull it again
pullCmd = exec.Command(dockerBinary, "pull", verifiedName)
if out, exitCode, err := runCommandWithOutput(pullCmd); err != nil || strings.Contains(out, expected) {
if err != nil || exitCode != 0 {
t.Skipf("pulling the '%s' image from the registry has failed: %s", verifiedName, err)
c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err))
}
t.Fatalf("pulling a verified image failed. unexpected verify message\ngot: %s, %v", out, err)
c.Fatalf("pulling a verified image failed. unexpected verify message\ngot: %s, %v", out, err)
}
logDone("pull - pull verified")
}
// pulling an image from the central registry should work
func TestPullImageFromCentralRegistry(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestPullImageFromCentralRegistry(c *check.C) {
testRequires(c, Network)
defer deleteImages("hello-world")
pullCmd := exec.Command(dockerBinary, "pull", "hello-world")
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("pulling the hello-world image from the registry has failed: %s, %v", out, err)
c.Fatalf("pulling the hello-world image from the registry has failed: %s, %v", out, err)
}
logDone("pull - pull hello-world")
}
// pulling a non-existing image from the central registry should return a non-zero exit code
func TestPullNonExistingImage(t *testing.T) {
func (s *DockerSuite) TestPullNonExistingImage(c *check.C) {
pullCmd := exec.Command(dockerBinary, "pull", "fooblahblah1234")
if out, _, err := runCommandWithOutput(pullCmd); err == nil {
t.Fatalf("expected non-zero exit status when pulling non-existing image: %s", out)
c.Fatalf("expected non-zero exit status when pulling non-existing image: %s", out)
}
logDone("pull - pull fooblahblah1234 (non-existing image)")
}
// pulling an image from the central registry using official names should work
// ensure all pulls result in the same image
func TestPullImageOfficialNames(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestPullImageOfficialNames(c *check.C) {
testRequires(c, Network)
names := []string{
"docker.io/hello-world",
@ -123,7 +120,7 @@ func TestPullImageOfficialNames(t *testing.T) {
pullCmd := exec.Command(dockerBinary, "pull", name)
out, exitCode, err := runCommandWithOutput(pullCmd)
if err != nil || exitCode != 0 {
t.Errorf("pulling the '%s' image from the registry has failed: %s", name, err)
c.Errorf("pulling the '%s' image from the registry has failed: %s", name, err)
continue
}
@ -131,10 +128,9 @@ func TestPullImageOfficialNames(t *testing.T) {
imagesCmd := exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(imagesCmd)
if err != nil {
t.Errorf("listing images failed with errors: %v", err)
c.Errorf("listing images failed with errors: %v", err)
} else if strings.Contains(out, name) {
t.Errorf("images should not have listed '%s'", name)
c.Errorf("images should not have listed '%s'", name)
}
}
logDone("pull - pull official names")
}

View file

@ -6,72 +6,68 @@ import (
"os"
"os/exec"
"strings"
"testing"
"time"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"github.com/go-check/check"
)
// pulling an image from the central registry should work
func TestPushBusyboxImage(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushBusyboxImage(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
// tag the image to upload it to the private registry
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoName)
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - busybox to private registry")
}
// pushing an image without a prefix should throw an error
func TestPushUnprefixedRepo(t *testing.T) {
func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) {
pushCmd := exec.Command(dockerBinary, "push", "busybox")
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
t.Fatalf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out)
c.Fatalf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out)
}
logDone("push - unprefixed busybox repo must not pass")
}
func TestPushUntagged(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushUntagged(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
expected := "Repository does not exist"
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
t.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
c.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
} else if !strings.Contains(out, expected) {
t.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
}
logDone("push - untagged image")
}
func TestPushBadTag(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushBadTag(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL)
expected := "does not exist"
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
t.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
c.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
} else if !strings.Contains(out, expected) {
t.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
}
logDone("push - image with bad tag")
}
func TestPushMultipleTags(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushMultipleTags(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL)
@ -79,80 +75,80 @@ func TestPushMultipleTags(t *testing.T) {
// tag the image to upload it tot he private registry
tagCmd1 := exec.Command(dockerBinary, "tag", "busybox", repoTag1)
if out, _, err := runCommandWithOutput(tagCmd1); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoTag1)
tagCmd2 := exec.Command(dockerBinary, "tag", "busybox", repoTag2)
if out, _, err := runCommandWithOutput(tagCmd2); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoTag2)
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - multiple tags to private registry")
}
func TestPushInterrupt(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushInterrupt(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
// tag the image to upload it tot he private registry
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "tag", "busybox", repoName)); err != nil {
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoName)
pushCmd := exec.Command(dockerBinary, "push", repoName)
if err := pushCmd.Start(); err != nil {
t.Fatalf("Failed to start pushing to private registry: %v", err)
c.Fatalf("Failed to start pushing to private registry: %v", err)
}
// Interrupt push (yes, we have no idea at what point it will get killed).
time.Sleep(200 * time.Millisecond)
if err := pushCmd.Process.Kill(); err != nil {
t.Fatalf("Failed to kill push process: %v", err)
c.Fatalf("Failed to kill push process: %v", err)
}
// Try agin
pushCmd = exec.Command(dockerBinary, "push", repoName)
if err := pushCmd.Start(); err != nil {
t.Fatalf("Failed to start pushing to private registry: %v", err)
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "push", repoName)); err == nil {
str := string(out)
if !strings.Contains(str, "already in progress") {
c.Fatalf("Push should be continued on daemon side, but seems ok: %v, %s", err, out)
}
}
// now wait until all this pushes will complete
// if it will fail with timeout - this is some error, so no logic about it
// here
for exec.Command(dockerBinary, "push", repoName).Run() != nil {
}
logDone("push - interrupted")
}
func TestPushEmptyLayer(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushEmptyLayer(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
emptyTarball, err := ioutil.TempFile("", "empty_tarball")
if err != nil {
t.Fatalf("Unable to create test file: %v", err)
c.Fatalf("Unable to create test file: %v", err)
}
tw := tar.NewWriter(emptyTarball)
err = tw.Close()
if err != nil {
t.Fatalf("Error creating empty tarball: %v", err)
c.Fatalf("Error creating empty tarball: %v", err)
}
freader, err := os.Open(emptyTarball.Name())
if err != nil {
t.Fatalf("Could not open test tarball: %v", err)
c.Fatalf("Could not open test tarball: %v", err)
}
importCmd := exec.Command(dockerBinary, "import", "-", repoName)
importCmd.Stdin = freader
out, _, err := runCommandWithOutput(importCmd)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
c.Errorf("import failed with errors: %v, output: %q", err, out)
}
// Now verify we can push it
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - empty layer config to private registry")
}

View file

@ -3,16 +3,16 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestRenameStoppedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameStoppedContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "first_name", "-d", "busybox", "sh")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -20,7 +20,7 @@ func TestRenameStoppedContainer(t *testing.T) {
runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err := inspectField(cleanedContainerID, "Name")
@ -28,94 +28,87 @@ func TestRenameStoppedContainer(t *testing.T) {
runCmd = exec.Command(dockerBinary, "rename", "first_name", "new_name")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err = inspectField(cleanedContainerID, "Name")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if name != "/new_name" {
t.Fatal("Failed to rename container ", name)
c.Fatal("Failed to rename container ", name)
}
logDone("rename - stopped container")
}
func TestRenameRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameRunningContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "first_name", "-d", "busybox", "sh")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "rename", "first_name", "new_name")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err := inspectField(cleanedContainerID, "Name")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if name != "/new_name" {
t.Fatal("Failed to rename container ")
c.Fatal("Failed to rename container ")
}
logDone("rename - running container")
}
func TestRenameCheckNames(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "first_name", "-d", "busybox", "sh")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
runCmd = exec.Command(dockerBinary, "rename", "first_name", "new_name")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err := inspectField("new_name", "Name")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if name != "/new_name" {
t.Fatal("Failed to rename container ")
c.Fatal("Failed to rename container ")
}
name, err = inspectField("first_name", "Name")
if err == nil && !strings.Contains(err.Error(), "No such image or container: first_name") {
t.Fatal(err)
c.Fatal(err)
}
logDone("rename - old name released")
}
func TestRenameInvalidName(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameInvalidName(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "myname", "-d", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
runCmd = exec.Command(dockerBinary, "rename", "myname", "new:invalid")
if out, _, err := runCommandWithOutput(runCmd); err == nil || !strings.Contains(out, "Invalid container name") {
t.Fatalf("Renaming container to invalid name should have failed: %s\n%v", out, err)
c.Fatalf("Renaming container to invalid name should have failed: %s\n%v", out, err)
}
runCmd = exec.Command(dockerBinary, "ps", "-a")
if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "myname") {
t.Fatalf("Output of docker ps should have included 'myname': %s\n%v", out, err)
c.Fatalf("Output of docker ps should have included 'myname': %s\n%v", out, err)
}
logDone("rename - invalid container name")
}

View file

@ -3,61 +3,59 @@ package main
import (
"os/exec"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
func TestRestartStoppedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartStoppedContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "foobar")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "foobar\n" {
t.Errorf("container should've printed 'foobar'")
c.Errorf("container should've printed 'foobar'")
}
runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "foobar\nfoobar\n" {
t.Errorf("container should've printed 'foobar' twice")
c.Errorf("container should've printed 'foobar' twice")
}
logDone("restart - echo foobar for stopped container")
}
func TestRestartRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartRunningContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -67,41 +65,39 @@ func TestRestartRunningContainer(t *testing.T) {
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "foobar\n" {
t.Errorf("container should've printed 'foobar'")
c.Errorf("container should've printed 'foobar'")
}
runCmd = exec.Command(dockerBinary, "restart", "-t", "1", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
time.Sleep(1 * time.Second)
if out != "foobar\nfoobar\n" {
t.Errorf("container should've printed 'foobar' twice")
c.Errorf("container should've printed 'foobar' twice")
}
logDone("restart - echo foobar for running container")
}
// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
func TestRestartWithVolumes(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartWithVolumes(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/test", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -109,148 +105,139 @@ func TestRestartWithVolumes(t *testing.T) {
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out = strings.Trim(out, " \n\r"); out != "1" {
t.Errorf("expect 1 volume received %s", out)
c.Errorf("expect 1 volume received %s", out)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
volumes, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(volumes, err)
c.Fatal(volumes, err)
}
runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out = strings.Trim(out, " \n\r"); out != "1" {
t.Errorf("expect 1 volume after restart received %s", out)
c.Errorf("expect 1 volume after restart received %s", out)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
volumesAfterRestart, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(volumesAfterRestart, err)
c.Fatal(volumesAfterRestart, err)
}
if volumes != volumesAfterRestart {
volumes = strings.Trim(volumes, " \n\r")
volumesAfterRestart = strings.Trim(volumesAfterRestart, " \n\r")
t.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
c.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
}
logDone("restart - does not create a new volume on restart")
}
func TestRestartPolicyNO(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartPolicyNO(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "--restart=no", "busybox", "false")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if name != "no" {
t.Fatalf("Container restart policy name is %s, expected %s", name, "no")
c.Fatalf("Container restart policy name is %s, expected %s", name, "no")
}
logDone("restart - recording restart policy name for --restart=no")
}
func TestRestartPolicyAlways(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "--restart=always", "busybox", "false")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if name != "always" {
t.Fatalf("Container restart policy name is %s, expected %s", name, "always")
c.Fatalf("Container restart policy name is %s, expected %s", name, "always")
}
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// MaximumRetryCount=0 if the restart policy is always
if MaximumRetryCount != "0" {
t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "0")
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "0")
}
logDone("restart - recording restart policy name for --restart=always")
}
func TestRestartPolicyOnFailure(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:1", "busybox", "false")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if name != "on-failure" {
t.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
c.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
}
logDone("restart - recording restart policy name for --restart=on-failure")
}
// a good container with --restart=on-failure:3
// MaximumRetryCount!=0; RestartCount=0
func TestContainerRestartwithGoodContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerRestartwithGoodContainer(c *check.C) {
out, err := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:3", "busybox", "true").CombinedOutput()
if err != nil {
t.Fatal(string(out), err)
c.Fatal(string(out), err)
}
id := strings.TrimSpace(string(out))
if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5); err != nil {
t.Fatal(err)
c.Fatal(err)
}
count, err := inspectField(id, "RestartCount")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if count != "0" {
t.Fatalf("Container was restarted %s times, expected %d", count, 0)
c.Fatalf("Container was restarted %s times, expected %d", count, 0)
}
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if MaximumRetryCount != "3" {
t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
}
logDone("restart - for a good container with restart policy, MaximumRetryCount is not 0 and RestartCount is 0")
}

View file

@ -5,93 +5,83 @@ import (
"os"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestRmContainerWithRemovedVolume(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestRmContainerWithRemovedVolume(c *check.C) {
testRequires(c, SameHostDaemon)
cmd := exec.Command(dockerBinary, "run", "--name", "losemyvolumes", "-v", "/tmp/testing:/test", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := os.Remove("/tmp/testing"); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "rm", "-v", "losemyvolumes")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("rm - removed volume")
}
func TestRmContainerWithVolume(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmContainerWithVolume(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "foo", "-v", "/srv", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "rm", "-v", "foo")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("rm - volume")
}
func TestRmRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmRunningContainer(c *check.C) {
createRunningContainer(t, "foo")
createRunningContainer(c, "foo")
// Test cannot remove running container
cmd := exec.Command(dockerBinary, "rm", "foo")
if _, err := runCommand(cmd); err == nil {
t.Fatalf("Expected error, can't rm a running container")
c.Fatalf("Expected error, can't rm a running container")
}
logDone("rm - running container")
}
func TestRmRunningContainerCheckError409(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmRunningContainerCheckError409(c *check.C) {
createRunningContainer(t, "foo")
createRunningContainer(c, "foo")
endpoint := "/containers/foo"
status, _, err := sockRequest("DELETE", endpoint, nil)
if err == nil {
t.Fatalf("Expected error, can't rm a running container")
c.Fatalf("Expected error, can't rm a running container")
} else if status != http.StatusConflict {
t.Fatalf("Expected error to contain '409 Conflict' but found %s", err)
c.Fatalf("Expected error to contain '409 Conflict' but found %s", err)
}
logDone("rm - running container with Error 409")
}
func TestRmForceRemoveRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmForceRemoveRunningContainer(c *check.C) {
createRunningContainer(t, "foo")
createRunningContainer(c, "foo")
// Stop then remove with -s
cmd := exec.Command(dockerBinary, "rm", "-f", "foo")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("rm - running container with --force=true")
}
func TestRmContainerOrphaning(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
dockerfile1 := `FROM busybox:latest
ENTRYPOINT ["/bin/true"]`
@ -104,45 +94,43 @@ func TestRmContainerOrphaning(t *testing.T) {
img1, err := buildImage(img, dockerfile1, true)
defer deleteImages(img1)
if err != nil {
t.Fatalf("Could not build image %s: %v", img, err)
c.Fatalf("Could not build image %s: %v", img, err)
}
// run container on first image
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", img)); err != nil {
t.Fatalf("Could not run image %s: %v: %s", img, err, out)
c.Fatalf("Could not run image %s: %v: %s", img, err, out)
}
// rebuild dockerfile with a small addition at the end
if _, err := buildImage(img, dockerfile2, true); err != nil {
t.Fatalf("Could not rebuild image %s: %v", img, err)
c.Fatalf("Could not rebuild image %s: %v", img, err)
}
// try to remove the image, should error out.
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", img)); err == nil {
t.Fatalf("Expected to error out removing the image, but succeeded: %s", out)
c.Fatalf("Expected to error out removing the image, but succeeded: %s", out)
}
// check if we deleted the first image
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "images", "-q", "--no-trunc"))
if err != nil {
t.Fatalf("%v: %s", err, out)
c.Fatalf("%v: %s", err, out)
}
if !strings.Contains(out, img1) {
t.Fatalf("Orphaned container (could not find %q in docker images): %s", img1, out)
c.Fatalf("Orphaned container (could not find %q in docker images): %s", img1, out)
}
logDone("rm - container orphaning")
}
func TestRmInvalidContainer(t *testing.T) {
func (s *DockerSuite) TestRmInvalidContainer(c *check.C) {
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rm", "unknown")); err == nil {
t.Fatal("Expected error on rm unknown container, got none")
c.Fatal("Expected error on rm unknown container, got none")
} else if !strings.Contains(out, "failed to remove one or more containers") {
t.Fatalf("Expected output to contain 'failed to remove one or more containers', got %q", out)
c.Fatalf("Expected output to contain 'failed to remove one or more containers', got %q", out)
}
logDone("rm - delete unknown container")
}
func createRunningContainer(t *testing.T, name string) {
func createRunningContainer(c *check.C, name string) {
cmd := exec.Command(dockerBinary, "run", "-dt", "--name", name, "busybox", "top")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
}

View file

@ -3,17 +3,18 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestRmiWithContainerFails(t *testing.T) {
func (s *DockerSuite) TestRmiWithContainerFails(c *check.C) {
errSubstr := "is using it"
// create a container
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -22,123 +23,117 @@ func TestRmiWithContainerFails(t *testing.T) {
runCmd = exec.Command(dockerBinary, "rmi", "busybox")
out, _, err = runCommandWithOutput(runCmd)
if err == nil {
t.Fatalf("Container %q is using image, should not be able to rmi: %q", cleanedContainerID, out)
c.Fatalf("Container %q is using image, should not be able to rmi: %q", cleanedContainerID, out)
}
if !strings.Contains(out, errSubstr) {
t.Fatalf("Container %q is using image, error message should contain %q: %v", cleanedContainerID, errSubstr, out)
c.Fatalf("Container %q is using image, error message should contain %q: %v", cleanedContainerID, errSubstr, out)
}
// make sure it didn't delete the busybox name
images, _ := dockerCmd(t, "images")
images, _ := dockerCmd(c, "images")
if !strings.Contains(images, "busybox") {
t.Fatalf("The name 'busybox' should not have been removed from images: %q", images)
c.Fatalf("The name 'busybox' should not have been removed from images: %q", images)
}
deleteContainer(cleanedContainerID)
logDone("rmi - container using image while rmi, should not remove image name")
}
func TestRmiTag(t *testing.T) {
imagesBefore, _ := dockerCmd(t, "images", "-a")
dockerCmd(t, "tag", "busybox", "utest:tag1")
dockerCmd(t, "tag", "busybox", "utest/docker:tag2")
dockerCmd(t, "tag", "busybox", "utest:5000/docker:tag3")
func (s *DockerSuite) TestRmiTag(c *check.C) {
imagesBefore, _ := dockerCmd(c, "images", "-a")
dockerCmd(c, "tag", "busybox", "utest:tag1")
dockerCmd(c, "tag", "busybox", "utest/docker:tag2")
dockerCmd(c, "tag", "busybox", "utest:5000/docker:tag3")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+3 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
dockerCmd(t, "rmi", "utest/docker:tag2")
dockerCmd(c, "rmi", "utest/docker:tag2")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+2 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
dockerCmd(t, "rmi", "utest:5000/docker:tag3")
dockerCmd(c, "rmi", "utest:5000/docker:tag3")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+1 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
dockerCmd(t, "rmi", "utest:tag1")
dockerCmd(c, "rmi", "utest:tag1")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+0 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
logDone("rmi - tag,rmi - tagging the same images multiple times then removing tags")
}
func TestRmiImgIDForce(t *testing.T) {
func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container:%s, %v", out, err)
c.Fatalf("failed to create a container:%s, %v", out, err)
}
containerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "commit", containerID, "busybox-test")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to commit a new busybox-test:%s, %v", out, err)
c.Fatalf("failed to commit a new busybox-test:%s, %v", out, err)
}
imagesBefore, _ := dockerCmd(t, "images", "-a")
dockerCmd(t, "tag", "busybox-test", "utest:tag1")
dockerCmd(t, "tag", "busybox-test", "utest:tag2")
dockerCmd(t, "tag", "busybox-test", "utest/docker:tag3")
dockerCmd(t, "tag", "busybox-test", "utest:5000/docker:tag4")
imagesBefore, _ := dockerCmd(c, "images", "-a")
dockerCmd(c, "tag", "busybox-test", "utest:tag1")
dockerCmd(c, "tag", "busybox-test", "utest:tag2")
dockerCmd(c, "tag", "busybox-test", "utest/docker:tag3")
dockerCmd(c, "tag", "busybox-test", "utest:5000/docker:tag4")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+4 {
t.Fatalf("tag busybox to create 4 more images with same imageID; docker images shows: %q\n", imagesAfter)
c.Fatalf("tag busybox to create 4 more images with same imageID; docker images shows: %q\n", imagesAfter)
}
}
out, _ = dockerCmd(t, "inspect", "-f", "{{.Id}}", "busybox-test")
out, _ = dockerCmd(c, "inspect", "-f", "{{.Id}}", "busybox-test")
imgID := strings.TrimSpace(out)
dockerCmd(t, "rmi", "-f", imgID)
dockerCmd(c, "rmi", "-f", imgID)
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Contains(imagesAfter, imgID[:12]) {
t.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
c.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
}
}
logDone("rmi - imgID,rmi -f imgID delete all tagged repos of specific imgID")
}
func TestRmiTagWithExistingContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
container := "test-delete-tag"
newtag := "busybox:newtag"
bb := "busybox:latest"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "tag", bb, newtag)); err != nil {
t.Fatalf("Could not tag busybox: %v: %s", err, out)
c.Fatalf("Could not tag busybox: %v: %s", err, out)
}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", container, bb, "/bin/true")); err != nil {
t.Fatalf("Could not run busybox: %v: %s", err, out)
c.Fatalf("Could not run busybox: %v: %s", err, out)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", newtag))
if err != nil {
t.Fatalf("Could not remove tag %s: %v: %s", newtag, err, out)
c.Fatalf("Could not remove tag %s: %v: %s", newtag, err, out)
}
if d := strings.Count(out, "Untagged: "); d != 1 {
t.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
c.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
}
logDone("rmi - delete tag with existing containers")
}
func TestRmiForceWithExistingContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
image := "busybox-clone"
@ -147,64 +142,60 @@ func TestRmiForceWithExistingContainers(t *testing.T) {
MAINTAINER foo`)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatalf("Could not build %s: %s, %v", image, out, err)
c.Fatalf("Could not build %s: %s, %v", image, out, err)
}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "test-force-rmi", image, "/bin/true")); err != nil {
t.Fatalf("Could not run container: %s, %v", out, err)
c.Fatalf("Could not run container: %s, %v", out, err)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", "-f", image))
if err != nil {
t.Fatalf("Could not remove image %s: %s, %v", image, out, err)
c.Fatalf("Could not remove image %s: %s, %v", image, out, err)
}
logDone("rmi - force delete with existing containers")
}
func TestRmiWithMultipleRepositories(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) {
newRepo := "127.0.0.1:5000/busybox"
oldRepo := "busybox"
newTag := "busybox:test"
cmd := exec.Command(dockerBinary, "tag", oldRepo, newRepo)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("Could not tag busybox: %v: %s", err, out)
c.Fatalf("Could not tag busybox: %v: %s", err, out)
}
cmd = exec.Command(dockerBinary, "run", "--name", "test", oldRepo, "touch", "/home/abcd")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %s", err, out)
c.Fatalf("failed to run container: %v, output: %s", err, out)
}
cmd = exec.Command(dockerBinary, "commit", "test", newTag)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to commit container: %v, output: %s", err, out)
c.Fatalf("failed to commit container: %v, output: %s", err, out)
}
cmd = exec.Command(dockerBinary, "rmi", newTag)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to remove image: %v, output: %s", err, out)
c.Fatalf("failed to remove image: %v, output: %s", err, out)
}
if !strings.Contains(out, "Untagged: "+newTag) {
t.Fatalf("Could not remove image %s: %s, %v", newTag, out, err)
c.Fatalf("Could not remove image %s: %s, %v", newTag, out, err)
}
logDone("rmi - delete a image which its dependency tagged to multiple repositories success")
}
func TestRmiBlank(t *testing.T) {
func (s *DockerSuite) TestRmiBlank(c *check.C) {
// try to delete a blank image name
runCmd := exec.Command(dockerBinary, "rmi", "")
out, _, err := runCommandWithOutput(runCmd)
if err == nil {
t.Fatal("Should have failed to delete '' image")
c.Fatal("Should have failed to delete '' image")
}
if strings.Contains(out, "No such image") {
t.Fatalf("Wrong error message generated: %s", out)
c.Fatalf("Wrong error message generated: %s", out)
}
logDone("rmi - blank image name")
}

File diff suppressed because it is too large Load diff

View file

@ -11,22 +11,19 @@ import (
"path"
"path/filepath"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/mount"
"github.com/go-check/check"
"github.com/kr/pty"
)
// #6509
func TestRunRedirectStdout(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
checkRedirect := func(command string) {
_, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdin = tty
@ -34,35 +31,31 @@ func TestRunRedirectStdout(t *testing.T) {
cmd.Stderr = tty
ch := make(chan struct{})
if err := cmd.Start(); err != nil {
t.Fatalf("start err: %v", err)
c.Fatalf("start err: %v", err)
}
go func() {
if err := cmd.Wait(); err != nil {
t.Fatalf("wait err=%v", err)
c.Fatalf("wait err=%v", err)
}
close(ch)
}()
select {
case <-time.After(10 * time.Second):
t.Fatal("command timeout")
c.Fatal("command timeout")
case <-ch:
}
}
checkRedirect(dockerBinary + " run -i busybox cat /etc/passwd | grep -q root")
checkRedirect(dockerBinary + " run busybox cat /etc/passwd | grep -q root")
logDone("run - redirect stdout")
}
// Test recursive bind mount works by default
func TestRunWithVolumesIsRecursive(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRunWithVolumesIsRecursive(c *check.C) {
tmpDir, err := ioutil.TempDir("", "docker_recursive_mount_test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpDir)
@ -70,68 +63,62 @@ func TestRunWithVolumesIsRecursive(t *testing.T) {
// Create a temporary tmpfs mount.
tmpfsDir := filepath.Join(tmpDir, "tmpfs")
if err := os.MkdirAll(tmpfsDir, 0777); err != nil {
t.Fatalf("failed to mkdir at %s - %s", tmpfsDir, err)
c.Fatalf("failed to mkdir at %s - %s", tmpfsDir, err)
}
if err := mount.Mount("tmpfs", tmpfsDir, "tmpfs", ""); err != nil {
t.Fatalf("failed to create a tmpfs mount at %s - %s", tmpfsDir, err)
c.Fatalf("failed to create a tmpfs mount at %s - %s", tmpfsDir, err)
}
f, err := ioutil.TempFile(tmpfsDir, "touch-me")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer f.Close()
runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox:latest", "ls", "/tmp/tmpfs")
out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd)
if err != nil && exitCode != 0 {
t.Fatal(out, stderr, err)
c.Fatal(out, stderr, err)
}
if !strings.Contains(out, filepath.Base(f.Name())) {
t.Fatal("Recursive bind mount test failed. Expected file not found")
c.Fatal("Recursive bind mount test failed. Expected file not found")
}
logDone("run - volumes are bind mounted recursively")
}
func TestRunWithUlimits(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunWithUlimits(c *check.C) {
testRequires(c, NativeExecDriver)
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name=testulimits", "--ulimit", "nofile=42", "busybox", "/bin/sh", "-c", "ulimit -n"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
ul := strings.TrimSpace(out)
if ul != "42" {
t.Fatalf("expected `ulimit -n` to be 42, got %s", ul)
c.Fatalf("expected `ulimit -n` to be 42, got %s", ul)
}
logDone("run - ulimits are set")
}
func TestRunContainerWithCgroupParent(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunContainerWithCgroupParent(c *check.C) {
testRequires(c, NativeExecDriver)
cgroupParent := "test"
data, err := ioutil.ReadFile("/proc/self/cgroup")
if err != nil {
t.Fatalf("failed to read '/proc/self/cgroup - %v", err)
c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
}
selfCgroupPaths := parseCgroupPaths(string(data))
selfCpuCgroup, found := selfCgroupPaths["memory"]
if !found {
t.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths)
c.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--cgroup-parent", cgroupParent, "--rm", "busybox", "cat", "/proc/self/cgroup"))
if err != nil {
t.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
}
cgroupPaths := parseCgroupPaths(string(out))
if len(cgroupPaths) == 0 {
t.Fatalf("unexpected output - %q", string(out))
c.Fatalf("unexpected output - %q", string(out))
}
found = false
expectedCgroupPrefix := path.Join(selfCpuCgroup, cgroupParent)
@ -142,24 +129,22 @@ func TestRunContainerWithCgroupParent(t *testing.T) {
}
}
if !found {
t.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", expectedCgroupPrefix, cgroupPaths)
c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", expectedCgroupPrefix, cgroupPaths)
}
logDone("run - cgroup parent")
}
func TestRunContainerWithCgroupParentAbsPath(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunContainerWithCgroupParentAbsPath(c *check.C) {
testRequires(c, NativeExecDriver)
cgroupParent := "/cgroup-parent/test"
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--cgroup-parent", cgroupParent, "--rm", "busybox", "cat", "/proc/self/cgroup"))
if err != nil {
t.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
}
cgroupPaths := parseCgroupPaths(string(out))
if len(cgroupPaths) == 0 {
t.Fatalf("unexpected output - %q", string(out))
c.Fatalf("unexpected output - %q", string(out))
}
found := false
for _, path := range cgroupPaths {
@ -169,81 +154,75 @@ func TestRunContainerWithCgroupParentAbsPath(t *testing.T) {
}
}
if !found {
t.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", cgroupParent, cgroupPaths)
c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", cgroupParent, cgroupPaths)
}
logDone("run - cgroup parent with absolute cgroup path")
}
func TestRunDeviceDirectory(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunDeviceDirectory(c *check.C) {
testRequires(c, NativeExecDriver)
cmd := exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/snd", "busybox", "sh", "-c", "ls /dev/snd/")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "timer") {
t.Fatalf("expected output /dev/snd/timer, received %s", actual)
c.Fatalf("expected output /dev/snd/timer, received %s", actual)
}
cmd = exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/othersnd", "busybox", "sh", "-c", "ls /dev/othersnd/")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "seq") {
t.Fatalf("expected output /dev/othersnd/seq, received %s", actual)
c.Fatalf("expected output /dev/othersnd/seq, received %s", actual)
}
logDone("run - test --device directory mounts all internal devices")
}
// TestRunDetach checks attaching and detaching with the escape sequence.
func TestRunAttachDetach(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRunAttachDetach(c *check.C) {
name := "attach-detach"
cmd := exec.Command(dockerBinary, "run", "--name", name, "-it", "busybox", "cat")
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cpty.Close()
cmd.Stdin = tty
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := waitRun(name); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := cpty.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err := bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
// escape sequence
if _, err := cpty.Write([]byte{16}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
if _, err := cpty.Write([]byte{17}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
ch := make(chan struct{})
@ -254,21 +233,19 @@ func TestRunAttachDetach(t *testing.T) {
running, err := inspectField(name, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
go func() {
dockerCmd(t, "kill", name)
exec.Command(dockerBinary, "kill", name).Run()
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
t.Fatal("timed out waiting for container to exit")
c.Fatal("timed out waiting for container to exit")
}
logDone("run - attach detach")
}

View file

@ -9,15 +9,16 @@ import (
"reflect"
"sort"
"strings"
"testing"
"github.com/go-check/check"
)
// save a repo using gz compression and try to load it using stdout
func TestSaveXzAndLoadRepoStdout(t *testing.T) {
func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %v %v", out, err)
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -27,19 +28,19 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container: %v %v", out, err)
c.Fatalf("failed to commit container: %v %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %v %v", before, err)
c.Fatalf("the repo should exist before saving it: %v %v", before, err)
}
repoTarball, _, err := runCommandPipelineWithOutput(
@ -47,7 +48,7 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
exec.Command("xz", "-c"),
exec.Command("gzip", "-c"))
if err != nil {
t.Fatalf("failed to save repo: %v %v", out, err)
c.Fatalf("failed to save repo: %v %v", out, err)
}
deleteImages(repoName)
@ -55,26 +56,25 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
loadCmd.Stdin = strings.NewReader(repoTarball)
out, _, err = runCommandWithOutput(loadCmd)
if err == nil {
t.Fatalf("expected error, but succeeded with no error and output: %v", out)
c.Fatalf("expected error, but succeeded with no error and output: %v", out)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err == nil {
t.Fatalf("the repo should not exist: %v", after)
c.Fatalf("the repo should not exist: %v", after)
}
deleteImages(repoName)
logDone("load - save a repo with xz compression & load it using stdout")
}
// save a repo using xz+gz compression and try to load it using stdout
func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %v %v", out, err)
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -84,19 +84,19 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container: %v %v", out, err)
c.Fatalf("failed to commit container: %v %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %v %v", before, err)
c.Fatalf("the repo should exist before saving it: %v %v", before, err)
}
out, _, err = runCommandPipelineWithOutput(
@ -104,7 +104,7 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
exec.Command("xz", "-c"),
exec.Command("gzip", "-c"))
if err != nil {
t.Fatalf("failed to save repo: %v %v", out, err)
c.Fatalf("failed to save repo: %v %v", out, err)
}
deleteImages(repoName)
@ -113,34 +113,33 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
loadCmd.Stdin = strings.NewReader(out)
out, _, err = runCommandWithOutput(loadCmd)
if err == nil {
t.Fatalf("expected error, but succeeded with no error and output: %v", out)
c.Fatalf("expected error, but succeeded with no error and output: %v", out)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err == nil {
t.Fatalf("the repo should not exist: %v", after)
c.Fatalf("the repo should not exist: %v", after)
}
deleteContainer(cleanedContainerID)
deleteImages(repoName)
logDone("load - save a repo with xz+gz compression & load it using stdout")
}
func TestSaveSingleTag(t *testing.T) {
func (s *DockerSuite) TestSaveSingleTag(c *check.C) {
repoName := "foobar-save-single-tag-test"
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", fmt.Sprintf("%v:latest", repoName))
defer deleteImages(repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
idCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName)
out, _, err := runCommandWithOutput(idCmd)
if err != nil {
t.Fatalf("failed to get repo ID: %s, %v", out, err)
c.Fatalf("failed to get repo ID: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
@ -149,25 +148,24 @@ func TestSaveSingleTag(t *testing.T) {
exec.Command("tar", "t"),
exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID)))
if err != nil {
t.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err)
c.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err)
}
logDone("save - save a specific image:tag")
}
func TestSaveImageId(t *testing.T) {
func (s *DockerSuite) TestSaveImageId(c *check.C) {
repoName := "foobar-save-image-id-test"
tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v:latest", repoName))
defer deleteImages(repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
idLongCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName)
out, _, err := runCommandWithOutput(idLongCmd)
if err != nil {
t.Fatalf("failed to get repo ID: %s, %v", out, err)
c.Fatalf("failed to get repo ID: %s, %v", out, err)
}
cleanedLongImageID := strings.TrimSpace(out)
@ -175,7 +173,7 @@ func TestSaveImageId(t *testing.T) {
idShortCmd := exec.Command(dockerBinary, "images", "-q", repoName)
out, _, err = runCommandWithOutput(idShortCmd)
if err != nil {
t.Fatalf("failed to get repo short ID: %s, %v", out, err)
c.Fatalf("failed to get repo short ID: %s, %v", out, err)
}
cleanedShortImageID := strings.TrimSpace(out)
@ -184,19 +182,19 @@ func TestSaveImageId(t *testing.T) {
tarCmd := exec.Command("tar", "t")
tarCmd.Stdin, err = saveCmd.StdoutPipe()
if err != nil {
t.Fatalf("cannot set stdout pipe for tar: %v", err)
c.Fatalf("cannot set stdout pipe for tar: %v", err)
}
grepCmd := exec.Command("grep", cleanedLongImageID)
grepCmd.Stdin, err = tarCmd.StdoutPipe()
if err != nil {
t.Fatalf("cannot set stdout pipe for grep: %v", err)
c.Fatalf("cannot set stdout pipe for grep: %v", err)
}
if err = tarCmd.Start(); err != nil {
t.Fatalf("tar failed with error: %v", err)
c.Fatalf("tar failed with error: %v", err)
}
if err = saveCmd.Start(); err != nil {
t.Fatalf("docker save failed with error: %v", err)
c.Fatalf("docker save failed with error: %v", err)
}
defer saveCmd.Wait()
defer tarCmd.Wait()
@ -204,18 +202,17 @@ func TestSaveImageId(t *testing.T) {
out, _, err = runCommandWithOutput(grepCmd)
if err != nil {
t.Fatalf("failed to save repo with image ID: %s, %v", out, err)
c.Fatalf("failed to save repo with image ID: %s, %v", out, err)
}
logDone("save - save a image by ID")
}
// save a repo and try to load it using flags
func TestSaveAndLoadRepoFlags(t *testing.T) {
func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -225,19 +222,19 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been a container id: %s, %v", out, err)
c.Fatalf("output should've been a container id: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
deleteImages(repoName)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %s, %v", out, err)
c.Fatalf("failed to commit container: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %s, %v", before, err)
c.Fatalf("the repo should exist before saving it: %s, %v", before, err)
}
@ -245,29 +242,28 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
exec.Command(dockerBinary, "save", repoName),
exec.Command(dockerBinary, "load"))
if err != nil {
t.Fatalf("failed to save and load repo: %s, %v", out, err)
c.Fatalf("failed to save and load repo: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist after loading it: %s, %v", after, err)
c.Fatalf("the repo should exist after loading it: %s, %v", after, err)
}
if before != after {
t.Fatalf("inspect is not the same after a save / load")
c.Fatalf("inspect is not the same after a save / load")
}
logDone("save - save a repo using -o && load a repo using -i")
}
func TestSaveMultipleNames(t *testing.T) {
func (s *DockerSuite) TestSaveMultipleNames(c *check.C) {
repoName := "foobar-save-multi-name-test"
// Make one image
tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-one:latest", repoName))
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
defer deleteImages(repoName + "-one")
@ -275,7 +271,7 @@ func TestSaveMultipleNames(t *testing.T) {
tagCmd = exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName))
out, _, err := runCommandWithOutput(tagCmd)
if err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
defer deleteImages(repoName + "-two")
@ -285,13 +281,12 @@ func TestSaveMultipleNames(t *testing.T) {
exec.Command("grep", "-q", "-E", "(-one|-two)"),
)
if err != nil {
t.Fatalf("failed to save multiple repos: %s, %v", out, err)
c.Fatalf("failed to save multiple repos: %s, %v", out, err)
}
logDone("save - save by multiple names")
}
func TestSaveRepoWithMultipleImages(t *testing.T) {
func (s *DockerSuite) TestSaveRepoWithMultipleImages(c *check.C) {
makeImage := func(from string, tag string) string {
runCmd := exec.Command(dockerBinary, "run", "-d", from, "true")
@ -300,14 +295,14 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
err error
)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatalf("failed to create a container: %v %v", out, err)
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, tag)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %v %v", out, err)
c.Fatalf("failed to commit container: %v %v", out, err)
}
imageID := strings.TrimSpace(out)
return imageID
@ -331,14 +326,14 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
exec.Command("grep", "VERSION"),
exec.Command("cut", "-d", "/", "-f1"))
if err != nil {
t.Fatalf("failed to save multiple images: %s, %v", out, err)
c.Fatalf("failed to save multiple images: %s, %v", out, err)
}
actual := strings.Split(strings.TrimSpace(out), "\n")
// make the list of expected layers
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "history", "-q", "--no-trunc", "busybox:latest"))
if err != nil {
t.Fatalf("failed to get history: %s, %v", out, err)
c.Fatalf("failed to get history: %s, %v", out, err)
}
expected := append(strings.Split(strings.TrimSpace(out), "\n"), idFoo, idBar)
@ -346,21 +341,20 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
sort.Strings(actual)
sort.Strings(expected)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("achive does not contains the right layers: got %v, expected %v", actual, expected)
c.Fatalf("achive does not contains the right layers: got %v, expected %v", actual, expected)
}
logDone("save - save repository with multiple images")
}
// Issue #6722 #5892 ensure directories are included in changes
func TestSaveDirectoryPermissions(t *testing.T) {
func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
layerEntries := []string{"opt/", "opt/a/", "opt/a/b/", "opt/a/b/c"}
layerEntriesAUFS := []string{"./", ".wh..wh.aufs", ".wh..wh.orph/", ".wh..wh.plnk/", "opt/", "opt/a/", "opt/a/b/", "opt/a/b/c"}
name := "save-directory-permissions"
tmpDir, err := ioutil.TempDir("", "save-layers-with-directories")
if err != nil {
t.Errorf("failed to create temporary directory: %s", err)
c.Errorf("failed to create temporary directory: %s", err)
}
extractionDirectory := filepath.Join(tmpDir, "image-extraction-dir")
os.Mkdir(extractionDirectory, 0777)
@ -373,19 +367,19 @@ func TestSaveDirectoryPermissions(t *testing.T) {
RUN touch /opt/a/b/c && chown user:user /opt/a/b/c`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if out, _, err := runCommandPipelineWithOutput(
exec.Command(dockerBinary, "save", name),
exec.Command("tar", "-xf", "-", "-C", extractionDirectory),
); err != nil {
t.Errorf("failed to save and extract image: %s", out)
c.Errorf("failed to save and extract image: %s", out)
}
dirs, err := ioutil.ReadDir(extractionDirectory)
if err != nil {
t.Errorf("failed to get a listing of the layer directories: %s", err)
c.Errorf("failed to get a listing of the layer directories: %s", err)
}
found := false
@ -396,7 +390,7 @@ func TestSaveDirectoryPermissions(t *testing.T) {
f, err := os.Open(layerPath)
if err != nil {
t.Fatalf("failed to open %s: %s", layerPath, err)
c.Fatalf("failed to open %s: %s", layerPath, err)
}
entries, err := ListTar(f)
@ -406,7 +400,7 @@ func TestSaveDirectoryPermissions(t *testing.T) {
}
}
if err != nil {
t.Fatalf("encountered error while listing tar entries: %s", err)
c.Fatalf("encountered error while listing tar entries: %s", err)
}
if reflect.DeepEqual(entriesSansDev, layerEntries) || reflect.DeepEqual(entriesSansDev, layerEntriesAUFS) {
@ -417,8 +411,7 @@ func TestSaveDirectoryPermissions(t *testing.T) {
}
if !found {
t.Fatalf("failed to find the layer with the right content listing")
c.Fatalf("failed to find the layer with the right content listing")
}
logDone("save - ensure directories exist in exported layers")
}

View file

@ -8,17 +8,17 @@ import (
"os"
"os/exec"
"strings"
"testing"
"github.com/docker/docker/vendor/src/github.com/kr/pty"
"github.com/go-check/check"
)
// save a repo and try to load it using stdout
func TestSaveAndLoadRepoStdout(t *testing.T) {
func (s *DockerSuite) TestSaveAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -27,25 +27,25 @@ func TestSaveAndLoadRepoStdout(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been a container id: %s, %v", out, err)
c.Fatalf("output should've been a container id: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %s, %v", out, err)
c.Fatalf("failed to commit container: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %s, %v", before, err)
c.Fatalf("the repo should exist before saving it: %s, %v", before, err)
}
saveCmdTemplate := `%v save %v > /tmp/foobar-save-load-test.tar`
saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName)
saveCmd := exec.Command("bash", "-c", saveCmdFinal)
if out, _, err = runCommandWithOutput(saveCmd); err != nil {
t.Fatalf("failed to save repo: %s, %v", out, err)
c.Fatalf("failed to save repo: %s, %v", out, err)
}
deleteImages(repoName)
@ -53,17 +53,17 @@ func TestSaveAndLoadRepoStdout(t *testing.T) {
loadCmdFinal := `cat /tmp/foobar-save-load-test.tar | docker load`
loadCmd := exec.Command("bash", "-c", loadCmdFinal)
if out, _, err = runCommandWithOutput(loadCmd); err != nil {
t.Fatalf("failed to load repo: %s, %v", out, err)
c.Fatalf("failed to load repo: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist after loading it: %s %v", after, err)
c.Fatalf("the repo should exist after loading it: %s %v", after, err)
}
if before != after {
t.Fatalf("inspect is not the same after a save / load")
c.Fatalf("inspect is not the same after a save / load")
}
deleteContainer(cleanedContainerID)
@ -73,29 +73,28 @@ func TestSaveAndLoadRepoStdout(t *testing.T) {
pty, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command(dockerBinary, "save", repoName)
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
if err := cmd.Start(); err != nil {
t.Fatalf("start err: %v", err)
c.Fatalf("start err: %v", err)
}
if err := cmd.Wait(); err == nil {
t.Fatal("did not break writing to a TTY")
c.Fatal("did not break writing to a TTY")
}
buf := make([]byte, 1024)
n, err := pty.Read(buf)
if err != nil {
t.Fatal("could not read tty output")
c.Fatal("could not read tty output")
}
if !bytes.Contains(buf[:n], []byte("Cowardly refusing")) {
t.Fatal("help output is not being yielded", out)
c.Fatal("help output is not being yielded", out)
}
logDone("save - save/load a repo using stdout")
}

View file

@ -3,95 +3,93 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// search for repos named "registry" on the central registry
func TestSearchOnCentralRegistry(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestSearchOnCentralRegistry(c *check.C) {
testRequires(c, Network)
searchCmd := exec.Command(dockerBinary, "search", "busybox")
out, exitCode, err := runCommandWithOutput(searchCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search on the central registry: %s, %v", out, err)
c.Fatalf("failed to search on the central registry: %s, %v", out, err)
}
if !strings.Contains(out, "Busybox base image.") {
t.Fatal("couldn't find any repository named (or containing) 'Busybox base image.'")
c.Fatal("couldn't find any repository named (or containing) 'Busybox base image.'")
}
logDone("search - search for repositories named (or containing) 'Busybox base image.'")
}
func TestSearchStarsOptionWithWrongParameter(t *testing.T) {
func (s *DockerSuite) TestSearchStarsOptionWithWrongParameter(c *check.C) {
searchCmdStarsChars := exec.Command(dockerBinary, "search", "--stars=a", "busybox")
out, exitCode, err := runCommandWithOutput(searchCmdStarsChars)
if err == nil || exitCode == 0 {
t.Fatalf("Should not get right information: %s, %v", out, err)
c.Fatalf("Should not get right information: %s, %v", out, err)
}
if !strings.Contains(out, "invalid value") {
t.Fatal("couldn't find the invalid value warning")
c.Fatal("couldn't find the invalid value warning")
}
searchCmdStarsNegativeNumber := exec.Command(dockerBinary, "search", "-s=-1", "busybox")
out, exitCode, err = runCommandWithOutput(searchCmdStarsNegativeNumber)
if err == nil || exitCode == 0 {
t.Fatalf("Should not get right information: %s, %v", out, err)
c.Fatalf("Should not get right information: %s, %v", out, err)
}
if !strings.Contains(out, "invalid value") {
t.Fatal("couldn't find the invalid value warning")
c.Fatal("couldn't find the invalid value warning")
}
logDone("search - Verify search with wrong parameter.")
}
func TestSearchCmdOptions(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestSearchCmdOptions(c *check.C) {
testRequires(c, Network)
searchCmdhelp := exec.Command(dockerBinary, "search", "--help")
out, exitCode, err := runCommandWithOutput(searchCmdhelp)
if err != nil || exitCode != 0 {
t.Fatalf("failed to get search help information: %s, %v", out, err)
c.Fatalf("failed to get search help information: %s, %v", out, err)
}
if !strings.Contains(out, "Usage: docker search [OPTIONS] TERM") {
t.Fatalf("failed to show docker search usage: %s, %v", out, err)
c.Fatalf("failed to show docker search usage: %s, %v", out, err)
}
searchCmd := exec.Command(dockerBinary, "search", "busybox")
outSearchCmd, exitCode, err := runCommandWithOutput(searchCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search on the central registry: %s, %v", outSearchCmd, err)
c.Fatalf("failed to search on the central registry: %s, %v", outSearchCmd, err)
}
searchCmdautomated := exec.Command(dockerBinary, "search", "--automated=true", "busybox")
outSearchCmdautomated, exitCode, err := runCommandWithOutput(searchCmdautomated) //The busybox is a busybox base image, not an AUTOMATED image.
if err != nil || exitCode != 0 {
t.Fatalf("failed to search with automated=true on the central registry: %s, %v", outSearchCmdautomated, err)
c.Fatalf("failed to search with automated=true on the central registry: %s, %v", outSearchCmdautomated, err)
}
outSearchCmdautomatedSlice := strings.Split(outSearchCmdautomated, "\n")
for i := range outSearchCmdautomatedSlice {
if strings.HasPrefix(outSearchCmdautomatedSlice[i], "busybox ") {
t.Fatalf("The busybox is not an AUTOMATED image: %s, %v", out, err)
c.Fatalf("The busybox is not an AUTOMATED image: %s, %v", out, err)
}
}
searchCmdStars := exec.Command(dockerBinary, "search", "-s=2", "busybox")
outSearchCmdStars, exitCode, err := runCommandWithOutput(searchCmdStars)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search with stars=2 on the central registry: %s, %v", outSearchCmdStars, err)
c.Fatalf("failed to search with stars=2 on the central registry: %s, %v", outSearchCmdStars, err)
}
if strings.Count(outSearchCmdStars, "[OK]") > strings.Count(outSearchCmd, "[OK]") {
t.Fatalf("The quantity of images with stars should be less than that of all images: %s, %v", outSearchCmdStars, err)
c.Fatalf("The quantity of images with stars should be less than that of all images: %s, %v", outSearchCmdStars, err)
}
searchCmdOptions := exec.Command(dockerBinary, "search", "--stars=2", "--automated=true", "--no-trunc=true", "busybox")
out, exitCode, err = runCommandWithOutput(searchCmdOptions)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search with stars&automated&no-trunc options on the central registry: %s, %v", out, err)
c.Fatalf("failed to search with stars&automated&no-trunc options on the central registry: %s, %v", out, err)
}
logDone("search - have a try for search options.")
}

View file

@ -4,20 +4,20 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
// Regression test for https://github.com/docker/docker/issues/7843
func TestStartAttachReturnsOnError(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartAttachReturnsOnError(c *check.C) {
dockerCmd(t, "run", "-d", "--name", "test", "busybox")
dockerCmd(t, "wait", "test")
dockerCmd(c, "run", "-d", "--name", "test", "busybox")
dockerCmd(c, "wait", "test")
// Expect this to fail because the above container is stopped, this is what we want
if _, err := runCommand(exec.Command(dockerBinary, "run", "-d", "--name", "test2", "--link", "test:test", "busybox")); err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
ch := make(chan struct{})
@ -25,7 +25,7 @@ func TestStartAttachReturnsOnError(t *testing.T) {
// Attempt to start attached to the container that won't start
// This should return an error immediately since the container can't be started
if _, err := runCommand(exec.Command(dockerBinary, "start", "-a", "test2")); err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
close(ch)
}()
@ -33,20 +33,18 @@ func TestStartAttachReturnsOnError(t *testing.T) {
select {
case <-ch:
case <-time.After(time.Second):
t.Fatalf("Attach did not exit properly")
c.Fatalf("Attach did not exit properly")
}
logDone("start - error on start with attach exits")
}
// gh#8555: Exit code should be passed through when using start -a
func TestStartAttachCorrectExitCode(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartAttachCorrectExitCode(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "sleep 2; exit 1")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %q", err, out)
c.Fatalf("failed to run container: %v, output: %q", err, out)
}
out = strings.TrimSpace(out)
@ -54,167 +52,157 @@ func TestStartAttachCorrectExitCode(t *testing.T) {
// make sure the container has exited before trying the "start -a"
waitCmd := exec.Command(dockerBinary, "wait", out)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("Failed to wait on container: %v", err)
c.Fatalf("Failed to wait on container: %v", err)
}
startCmd := exec.Command(dockerBinary, "start", "-a", out)
startOut, exitCode, err := runCommandWithOutput(startCmd)
if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) {
t.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
c.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
}
if exitCode != 1 {
t.Fatalf("start -a did not respond with proper exit code: expected 1, got %d", exitCode)
c.Fatalf("start -a did not respond with proper exit code: expected 1, got %d", exitCode)
}
logDone("start - correct exit code returned with -a")
}
func TestStartAttachSilent(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartAttachSilent(c *check.C) {
name := "teststartattachcorrectexitcode"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "echo", "test")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %q", err, out)
c.Fatalf("failed to run container: %v, output: %q", err, out)
}
// make sure the container has exited before trying the "start -a"
waitCmd := exec.Command(dockerBinary, "wait", name)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("wait command failed with error: %v", err)
c.Fatalf("wait command failed with error: %v", err)
}
startCmd := exec.Command(dockerBinary, "start", "-a", name)
startOut, _, err := runCommandWithOutput(startCmd)
if err != nil {
t.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
c.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
}
if expected := "test\n"; startOut != expected {
t.Fatalf("start -a produced unexpected output: expected %q, got %q", expected, startOut)
c.Fatalf("start -a produced unexpected output: expected %q, got %q", expected, startOut)
}
logDone("start - don't echo container ID when attaching")
}
func TestStartRecordError(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartRecordError(c *check.C) {
// when container runs successfully, we should not have state.Error
dockerCmd(t, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
dockerCmd(c, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
stateErr, err := inspectField("test", "State.Error")
if err != nil {
t.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
c.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
}
if stateErr != "" {
t.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
}
// Expect this to fail and records error because of ports conflict
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "test2", "-p", "9999:9999", "busybox", "top"))
if err == nil {
t.Fatalf("Expected error but got none, output %q", out)
c.Fatalf("Expected error but got none, output %q", out)
}
stateErr, err = inspectField("test2", "State.Error")
if err != nil {
t.Fatalf("Failed to inspect %q state's error, got error %q", "test2", err)
c.Fatalf("Failed to inspect %q state's error, got error %q", "test2", err)
}
expected := "port is already allocated"
if stateErr == "" || !strings.Contains(stateErr, expected) {
t.Fatalf("State.Error(%q) does not include %q", stateErr, expected)
c.Fatalf("State.Error(%q) does not include %q", stateErr, expected)
}
// Expect the conflict to be resolved when we stop the initial container
dockerCmd(t, "stop", "test")
dockerCmd(t, "start", "test2")
dockerCmd(c, "stop", "test")
dockerCmd(c, "start", "test2")
stateErr, err = inspectField("test2", "State.Error")
if err != nil {
t.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
c.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
}
if stateErr != "" {
t.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
}
logDone("start - set state error when start is unsuccessful")
}
// gh#8726: a failed Start() breaks --volumes-from on subsequent Start()'s
func TestStartVolumesFromFailsCleanly(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartVolumesFromFailsCleanly(c *check.C) {
// Create the first data volume
dockerCmd(t, "run", "-d", "--name", "data_before", "-v", "/foo", "busybox")
dockerCmd(c, "run", "-d", "--name", "data_before", "-v", "/foo", "busybox")
// Expect this to fail because the data test after contaienr doesn't exist yet
if _, err := runCommand(exec.Command(dockerBinary, "run", "-d", "--name", "consumer", "--volumes-from", "data_before", "--volumes-from", "data_after", "busybox")); err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
// Create the second data volume
dockerCmd(t, "run", "-d", "--name", "data_after", "-v", "/bar", "busybox")
dockerCmd(c, "run", "-d", "--name", "data_after", "-v", "/bar", "busybox")
// Now, all the volumes should be there
dockerCmd(t, "start", "consumer")
dockerCmd(c, "start", "consumer")
// Check that we have the volumes we want
out, _ := dockerCmd(t, "inspect", "--format='{{ len .Volumes }}'", "consumer")
out, _ := dockerCmd(c, "inspect", "--format='{{ len .Volumes }}'", "consumer")
nVolumes := strings.Trim(out, " \r\n'")
if nVolumes != "2" {
t.Fatalf("Missing volumes: expected 2, got %s", nVolumes)
c.Fatalf("Missing volumes: expected 2, got %s", nVolumes)
}
logDone("start - missing containers in --volumes-from did not affect subsequent runs")
}
func TestStartPausedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartPausedContainer(c *check.C) {
defer unpauseAllContainers()
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "pause", "testing")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "start", "testing")
if out, _, err := runCommandWithOutput(runCmd); err == nil || !strings.Contains(out, "Cannot start a paused container, try unpause instead.") {
t.Fatalf("an error should have been shown that you cannot start paused container: %s\n%v", out, err)
c.Fatalf("an error should have been shown that you cannot start paused container: %s\n%v", out, err)
}
logDone("start - error should show if trying to start paused container")
}
func TestStartMultipleContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartMultipleContainers(c *check.C) {
// run a container named 'parent' and create two container link to `parent`
cmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
for _, container := range []string{"child_first", "child_second"} {
cmd = exec.Command(dockerBinary, "create", "--name", container, "--link", "parent:parent", "busybox", "top")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
}
// stop 'parent' container
cmd = exec.Command(dockerBinary, "stop", "parent")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", "parent")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if out != "false" {
t.Fatal("Container should be stopped")
c.Fatal("Container should be stopped")
}
// start all the three containers, container `child_first` start first which should be faild
@ -222,35 +210,33 @@ func TestStartMultipleContainers(t *testing.T) {
cmd = exec.Command(dockerBinary, "start", "child_first", "parent", "child_second")
out, _, err = runCommandWithOutput(cmd)
if !strings.Contains(out, "Cannot start container child_first") || err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
for container, expected := range map[string]string{"parent": "true", "child_first": "false", "child_second": "true"} {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", container)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if out != expected {
t.Fatal("Container running state wrong")
c.Fatal("Container running state wrong")
}
}
logDone("start - start multiple containers continue on one failed")
}
func TestStartAttachMultipleContainers(t *testing.T) {
func (s *DockerSuite) TestStartAttachMultipleContainers(c *check.C) {
var cmd *exec.Cmd
defer deleteAllContainers()
// run multiple containers to test
for _, container := range []string{"test1", "test2", "test3"} {
cmd = exec.Command(dockerBinary, "run", "-d", "--name", container, "busybox", "top")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
}
@ -258,7 +244,7 @@ func TestStartAttachMultipleContainers(t *testing.T) {
for _, container := range []string{"test1", "test2", "test3"} {
cmd = exec.Command(dockerBinary, "stop", container)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
}
@ -267,7 +253,7 @@ func TestStartAttachMultipleContainers(t *testing.T) {
cmd = exec.Command(dockerBinary, "start", option, "test1", "test2", "test3")
out, _, err := runCommandWithOutput(cmd)
if !strings.Contains(out, "You cannot start and attach multiple containers at once.") || err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
}
@ -276,13 +262,12 @@ func TestStartAttachMultipleContainers(t *testing.T) {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", container)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if out != expected {
t.Fatal("Container running state wrong")
c.Fatal("Container running state wrong")
}
}
logDone("start - error on start and attach multiple containers at once")
}

View file

@ -3,48 +3,46 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/docker/docker/pkg/stringutils"
"github.com/go-check/check"
)
// tagging a named image in a new unprefixed repo should work
func TestTagUnprefixedRepoByName(t *testing.T) {
func (s *DockerSuite) TestTagUnprefixedRepoByName(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", "testfoobarbaz")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
deleteImages("testfoobarbaz")
logDone("tag - busybox -> testfoobarbaz")
}
// tagging an image by ID in a new unprefixed repo should work
func TestTagUnprefixedRepoByID(t *testing.T) {
func (s *DockerSuite) TestTagUnprefixedRepoByID(c *check.C) {
getIDCmd := exec.Command(dockerBinary, "inspect", "-f", "{{.Id}}", "busybox")
out, _, err := runCommandWithOutput(getIDCmd)
if err != nil {
t.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
c.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
tagCmd := exec.Command(dockerBinary, "tag", cleanedImageID, "testfoobarbaz")
if out, _, err = runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
deleteImages("testfoobarbaz")
logDone("tag - busybox's image ID -> testfoobarbaz")
}
// ensure we don't allow the use of invalid repository names; these tag operations should fail
func TestTagInvalidUnprefixedRepo(t *testing.T) {
func (s *DockerSuite) TestTagInvalidUnprefixedRepo(c *check.C) {
invalidRepos := []string{"fo$z$", "Foo@3cc", "Foo$3", "Foo*3", "Fo^3", "Foo!3", "F)xcz(", "fo%asd"}
@ -52,14 +50,13 @@ func TestTagInvalidUnprefixedRepo(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repo)
_, _, err := runCommandWithOutput(tagCmd)
if err == nil {
t.Fatalf("tag busybox %v should have failed", repo)
c.Fatalf("tag busybox %v should have failed", repo)
}
}
logDone("tag - busybox invalid repo names --> must not work")
}
// ensure we don't allow the use of invalid tags; these tag operations should fail
func TestTagInvalidPrefixedRepo(t *testing.T) {
func (s *DockerSuite) TestTagInvalidPrefixedRepo(c *check.C) {
longTag := stringutils.GenerateRandomAlphaOnlyString(121)
invalidTags := []string{"repo:fo$z$", "repo:Foo@3cc", "repo:Foo$3", "repo:Foo*3", "repo:Fo^3", "repo:Foo!3", "repo:%goodbye", "repo:#hashtagit", "repo:F)xcz(", "repo:-foo", "repo:..", longTag}
@ -68,16 +65,15 @@ func TestTagInvalidPrefixedRepo(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repotag)
_, _, err := runCommandWithOutput(tagCmd)
if err == nil {
t.Fatalf("tag busybox %v should have failed", repotag)
c.Fatalf("tag busybox %v should have failed", repotag)
}
}
logDone("tag - busybox with invalid repo:tagnames --> must not work")
}
// ensure we allow the use of valid tags
func TestTagValidPrefixedRepo(t *testing.T) {
func (s *DockerSuite) TestTagValidPrefixedRepo(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
validRepos := []string{"fooo/bar", "fooaa/test", "foooo:t"}
@ -86,56 +82,53 @@ func TestTagValidPrefixedRepo(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", repo)
_, _, err := runCommandWithOutput(tagCmd)
if err != nil {
t.Errorf("tag busybox %v should have worked: %s", repo, err)
c.Errorf("tag busybox %v should have worked: %s", repo, err)
continue
}
deleteImages(repo)
}
logDone("tag - tag valid prefixed repo")
}
// tag an image with an existed tag name without -f option should fail
func TestTagExistedNameWithoutForce(t *testing.T) {
func (s *DockerSuite) TestTagExistedNameWithoutForce(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", "busybox:test")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
tagCmd = exec.Command(dockerBinary, "tag", "busybox:latest", "busybox:test")
out, _, err := runCommandWithOutput(tagCmd)
if err == nil || !strings.Contains(out, "Conflict: Tag test is already set to image") {
t.Fatal("tag busybox busybox:test should have failed,because busybox:test is existed")
c.Fatal("tag busybox busybox:test should have failed,because busybox:test is existed")
}
deleteImages("busybox:test")
logDone("tag - busybox with an existed tag name without -f option --> must not work")
}
// tag an image with an existed tag name with -f option should work
func TestTagExistedNameWithForce(t *testing.T) {
func (s *DockerSuite) TestTagExistedNameWithForce(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", "busybox:test")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
tagCmd = exec.Command(dockerBinary, "tag", "-f", "busybox:latest", "busybox:test")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
deleteImages("busybox:test")
logDone("tag - busybox with an existed tag name with -f option work")
}
// ensure tagging using official names works
// ensure all tags result in the same name
func TestTagOfficialNames(t *testing.T) {
func (s *DockerSuite) TestTagOfficialNames(c *check.C) {
names := []string{
"docker.io/busybox",
"index.docker.io/busybox",
@ -148,7 +141,7 @@ func TestTagOfficialNames(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "-f", "busybox:latest", name+":latest")
out, exitCode, err := runCommandWithOutput(tagCmd)
if err != nil || exitCode != 0 {
t.Errorf("tag busybox %v should have worked: %s, %s", name, err, out)
c.Errorf("tag busybox %v should have worked: %s, %s", name, err, out)
continue
}
@ -156,9 +149,9 @@ func TestTagOfficialNames(t *testing.T) {
imagesCmd := exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(imagesCmd)
if err != nil {
t.Errorf("listing images failed with errors: %v, %s", err, out)
c.Errorf("listing images failed with errors: %v, %s", err, out)
} else if strings.Contains(out, name) {
t.Errorf("images should not have listed '%s'", name)
c.Errorf("images should not have listed '%s'", name)
deleteImages(name + ":latest")
}
}
@ -167,10 +160,9 @@ func TestTagOfficialNames(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "-f", name+":latest", "fooo/bar:latest")
_, exitCode, err := runCommandWithOutput(tagCmd)
if err != nil || exitCode != 0 {
t.Errorf("tag %v fooo/bar should have worked: %s", name, err)
c.Errorf("tag %v fooo/bar should have worked: %s", name, err)
continue
}
deleteImages("fooo/bar:latest")
}
logDone("tag - tag official names")
}

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