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:
commit
b88b2fa72e
130 changed files with 8735 additions and 5203 deletions
|
@ -179,7 +179,7 @@ Under the hood, Docker is built on the following components:
|
|||
Contributing to Docker
|
||||
======================
|
||||
|
||||
[](https://godoc.org/github.com/docker/docker)
|
||||
[](https://godoc.org/github.com/docker/docker)
|
||||
[](https://jenkins.dockerproject.com/job/Docker%20Master/)
|
||||
|
||||
Want to hack on Docker? Awesome! We have [instructions to help you get
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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"))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
111
graph/service.go
111
graph/service.go
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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=
|
||||
|
|
19
hack/make.sh
19
hack/make.sh
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }')
|
||||
|
|
|
@ -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) )
|
||||
|
|
|
@ -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) )
|
||||
|
|
|
@ -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) )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
34
integration-cli/check_test.go
Normal file
34
integration-cli/check_test.go
Normal 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{})
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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×tamps=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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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 ':'")
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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.")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue