mirror of
https://github.com/clearlinux/docker.git
synced 2026-08-19 12:16:30 +00:00
Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b58a22a7e1 | |||
| 8eba018b61 | |||
| 1f9557ac66 | |||
| 1c783567c0 | |||
| f3b2b8700f | |||
| 7be79767c1 | |||
| eaa1fc41c6 | |||
| cfdb954303 | |||
| d65ac42ca8 | |||
| 0780ddc498 | |||
| ab31d9500e | |||
| bab701c143 | |||
| 6a64865991 | |||
| bece5b82a8 | |||
| 26ae6d6b36 | |||
| ef49d127e3 | |||
| 8f36ded5b1 | |||
| 2726434f72 | |||
| cffd50752c | |||
| 253f975fdb | |||
| 9685b4767f | |||
| 9b1fb0d45b | |||
| 4102537cfd | |||
| ab1f03397e | |||
| e3fabf3ea1 | |||
| c3f42b29a8 | |||
| 365a0db0f0 | |||
| ec7c368ff0 | |||
| d8b4471a59 | |||
| 4fc97e40c9 | |||
| 8c1fa7f320 | |||
| 475be776b8 | |||
| d1064bd441 | |||
| 258357857b | |||
| 3668be932e | |||
| 6f3eb994b5 | |||
| cf1b5fe601 | |||
| e23d834a01 | |||
| b1bab9e1e7 | |||
| c56b02b284 | |||
| 8b90aefd14 | |||
| 84be89a273 | |||
| b34aa69e8f | |||
| ccf5b60c6f | |||
| b054a88af1 | |||
| 7b6bca5af1 | |||
| e2870bda43 | |||
| 2afdab4454 | |||
| 7ce9f02751 | |||
| 841205ec01 | |||
| 08a43b8b3b | |||
| 30b945fac9 | |||
| 71982d8e57 | |||
| 579cf43f0f | |||
| f9026e2b7b | |||
| 1ae4eeb813 | |||
| 98c1a412b4 | |||
| 835fbee9a2 | |||
| 60b5b0d380 | |||
| ee30af5ffb | |||
| e44876bf1f | |||
| 851a533a82 | |||
| b0315375f8 | |||
| 3a713d91ce | |||
| 28c66b0491 | |||
| dee57e4c3e | |||
| 9392de9dfe | |||
| 9e3db08363 | |||
| 96a09ea77c | |||
| 89e0990224 | |||
| c37c9df18a | |||
| cb2bd8bcec | |||
| 6f1b5946b1 | |||
| f256d8ad2d | |||
| d35a1f2868 | |||
| 1052ff674c | |||
| 58b36ba242 | |||
| e1804098b9 | |||
| ebfed4d474 | |||
| ff4026fa5b | |||
| 2ec4404ba0 | |||
| a00c0d795d | |||
| 080a906aac | |||
| f255155f6b | |||
| 7345050e4d | |||
| 7aab43e8d4 | |||
| add0d25029 | |||
| 176d8c5a14 | |||
| 9216b08536 | |||
| 0f00c36d65 | |||
| 32ead68e9f | |||
| 46f7ab3585 | |||
| 196af472a6 | |||
| e4dadeed88 | |||
| 42d643af55 | |||
| 946e8cde53 | |||
| 244d9c3370 | |||
| 17b0017cd0 | |||
| 919c3c1ec8 | |||
| 84488e228a | |||
| b22f89cb77 | |||
| 37c6c53b56 | |||
| 400ac8a66c | |||
| 2b4128e904 | |||
| adb37a1b39 | |||
| 389ce0aae6 | |||
| aaa8cae345 | |||
| 29714ee836 | |||
| d60883eb10 | |||
| ddf04ad113 | |||
| 899ca94ce8 | |||
| d550fbb80e | |||
| cc653b5d61 | |||
| 7a19164c17 | |||
| 22a0b0a4f9 | |||
| 22a0ea5550 | |||
| a0398fbd19 | |||
| bc503ca8ab | |||
| b48f4bf523 | |||
| 28ad7c588f | |||
| 69949df242 | |||
| cfcddefacd | |||
| 06f0d03ced | |||
| a1d4b7dd0d | |||
| 844fb29619 | |||
| a82e3bc704 | |||
| d4d0718ebf | |||
| c6b02ad73b | |||
| 96559aaef2 | |||
| 0aee0b1f9e | |||
| 1374ebcde0 |
+1
-1
@@ -58,7 +58,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
||||
dockerfileName := cmd.String([]string{"f", "-file"}, "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
|
||||
flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit")
|
||||
flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
|
||||
flCPUShares := cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
||||
flCPUShares := cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
||||
flCPUPeriod := cmd.Int64([]string{"-cpu-period"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) period")
|
||||
flCPUQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
|
||||
flCPUSetCpus := cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
|
||||
|
||||
fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers)
|
||||
fmt.Fprintf(cli.out, "Images: %d\n", info.Images)
|
||||
fmt.Fprintf(cli.out, "Engine Version: %s\n", info.ServerVersion)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Server Version: %s\n", info.ServerVersion)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver)
|
||||
if info.DriverStatus != nil {
|
||||
for _, pair := range info.DriverStatus {
|
||||
|
||||
@@ -34,6 +34,7 @@ func (cli *DockerCli) CmdNetwork(args ...string) error {
|
||||
func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
|
||||
cmd := Cli.Subcmd("network create", []string{"NETWORK-NAME"}, "Creates a new network with a name specified by the user", false)
|
||||
flDriver := cmd.String([]string{"d", "-driver"}, "bridge", "Driver to manage the Network")
|
||||
flOpts := opts.NewMapOpts(nil, nil)
|
||||
|
||||
flIpamDriver := cmd.String([]string{"-ipam-driver"}, "default", "IP Address Management Driver")
|
||||
flIpamSubnet := opts.NewListOpts(nil)
|
||||
@@ -41,10 +42,11 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
|
||||
flIpamGateway := opts.NewListOpts(nil)
|
||||
flIpamAux := opts.NewMapOpts(nil, nil)
|
||||
|
||||
cmd.Var(&flIpamSubnet, []string{"-subnet"}, "Subnet in CIDR format that represents a network segment")
|
||||
cmd.Var(&flIpamSubnet, []string{"-subnet"}, "subnet in CIDR format that represents a network segment")
|
||||
cmd.Var(&flIpamIPRange, []string{"-ip-range"}, "allocate container ip from a sub-range")
|
||||
cmd.Var(&flIpamGateway, []string{"-gateway"}, "ipv4 or ipv6 Gateway for the master subnet")
|
||||
cmd.Var(flIpamAux, []string{"-aux-address"}, "Auxiliary ipv4 or ipv6 addresses used by network driver")
|
||||
cmd.Var(flIpamAux, []string{"-aux-address"}, "auxiliary ipv4 or ipv6 addresses used by Network driver")
|
||||
cmd.Var(flOpts, []string{"o", "-opt"}, "set driver specific options")
|
||||
|
||||
cmd.Require(flag.Exact, 1)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
@@ -62,6 +64,7 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
|
||||
Name: cmd.Arg(0),
|
||||
Driver: *flDriver,
|
||||
IPAM: network.IPAM{Driver: *flIpamDriver, Config: ipamCfg},
|
||||
Options: flOpts.GetAll(),
|
||||
CheckDuplicate: true,
|
||||
}
|
||||
obj, _, err := readBody(cli.call("POST", "/networks/create", nc, nil))
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import (
|
||||
// Common constants for daemon and client.
|
||||
const (
|
||||
// Version of Current REST API
|
||||
Version version.Version = "1.21"
|
||||
Version version.Version = "1.22"
|
||||
|
||||
// MinVersion represents Minimun REST API version supported
|
||||
MinVersion version.Version = "1.12"
|
||||
|
||||
@@ -55,9 +55,6 @@ type ArchiveOptions struct {
|
||||
// ArchiveFormValues parses form values and turns them into ArchiveOptions.
|
||||
// It fails if the archive name and path are not in the request.
|
||||
func ArchiveFormValues(r *http.Request, vars map[string]string) (ArchiveOptions, error) {
|
||||
if vars == nil {
|
||||
return ArchiveOptions{}, fmt.Errorf("Missing parameter")
|
||||
}
|
||||
if err := ParseForm(r); err != nil {
|
||||
return ArchiveOptions{}, err
|
||||
}
|
||||
|
||||
@@ -56,9 +56,6 @@ func (s *router) getContainersStats(ctx context.Context, w http.ResponseWriter,
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
stream := httputils.BoolValueOrDefault(r, "stream", true)
|
||||
var out io.Writer
|
||||
@@ -88,9 +85,6 @@ func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
// Args are validated before the stream starts because when it starts we're
|
||||
// sending HTTP 200 by writing an empty chunk of data to tell the client that
|
||||
@@ -150,18 +144,10 @@ func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r
|
||||
}
|
||||
|
||||
func (s *router) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
return s.daemon.ContainerExport(vars["name"], w)
|
||||
}
|
||||
|
||||
func (s *router) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
// If contentLength is -1, we can assumed chunked encoding
|
||||
// or more technically that the length is unknown
|
||||
// https://golang.org/src/pkg/net/http/request.go#L139
|
||||
@@ -193,9 +179,6 @@ func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter,
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
seconds, _ := strconv.Atoi(r.Form.Get("t"))
|
||||
|
||||
@@ -208,9 +191,6 @@ func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter,
|
||||
}
|
||||
|
||||
func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -247,9 +227,6 @@ func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWrite
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
timeout, _ := strconv.Atoi(r.Form.Get("t"))
|
||||
|
||||
@@ -263,9 +240,6 @@ func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWrite
|
||||
}
|
||||
|
||||
func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -280,9 +254,6 @@ func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter,
|
||||
}
|
||||
|
||||
func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -297,10 +268,6 @@ func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWrite
|
||||
}
|
||||
|
||||
func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
status, err := s.daemon.ContainerWait(vars["name"], -1*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -312,10 +279,6 @@ func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter,
|
||||
}
|
||||
|
||||
func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
changes, err := s.daemon.ContainerChanges(vars["name"])
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -325,10 +288,6 @@ func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter
|
||||
}
|
||||
|
||||
func (s *router) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -345,9 +304,6 @@ func (s *router) postContainerRename(ctx context.Context, w http.ResponseWriter,
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
name := vars["name"]
|
||||
newName := r.Form.Get("name")
|
||||
@@ -387,9 +343,6 @@ func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
name := vars["name"]
|
||||
config := &daemon.ContainerRmConfig{
|
||||
@@ -415,9 +368,6 @@ func (s *router) postContainersResize(ctx context.Context, w http.ResponseWriter
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
height, err := strconv.Atoi(r.Form.Get("h"))
|
||||
if err != nil {
|
||||
@@ -435,9 +385,6 @@ func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
containerName := vars["name"]
|
||||
|
||||
if !s.daemon.Exists(containerName) {
|
||||
@@ -477,9 +424,6 @@ func (s *router) wsContainersAttach(ctx context.Context, w http.ResponseWriter,
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
containerName := vars["name"]
|
||||
|
||||
if !s.daemon.Exists(containerName) {
|
||||
|
||||
@@ -16,10 +16,6 @@ import (
|
||||
|
||||
// postContainersCopy is deprecated in favor of getContainersArchive.
|
||||
func (s *router) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@ import (
|
||||
)
|
||||
|
||||
func (s *router) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter 'id'")
|
||||
}
|
||||
|
||||
eConfig, err := s.daemon.ContainerExecInspect(vars["id"])
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -118,10 +114,6 @@ func (s *router) postContainerExecResize(ctx context.Context, w http.ResponseWri
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
height, err := strconv.Atoi(r.Form.Get("h"))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/docker/docker/builder/dockerfile"
|
||||
"github.com/docker/docker/cliconfig"
|
||||
"github.com/docker/docker/daemon/daemonbuilder"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/graph"
|
||||
"github.com/docker/docker/graph/tags"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
@@ -63,12 +64,11 @@ func (s *router) postCommit(ctx context.Context, w http.ResponseWriter, r *http.
|
||||
Config: c,
|
||||
}
|
||||
|
||||
container, err := s.daemon.Get(cname)
|
||||
if err != nil {
|
||||
return err
|
||||
if !s.daemon.Exists(cname) {
|
||||
return derr.ErrorCodeNoSuchContainer.WithArgs(cname)
|
||||
}
|
||||
|
||||
imgID, err := dockerfile.Commit(container, s.daemon, commitCfg)
|
||||
imgID, err := dockerfile.Commit(cname, s.daemon, commitCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -156,10 +156,6 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r
|
||||
}
|
||||
|
||||
func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
metaHeaders := map[string][]string{}
|
||||
for k, v := range r.Header {
|
||||
if strings.HasPrefix(k, "X-Meta-") {
|
||||
@@ -208,9 +204,6 @@ func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *h
|
||||
}
|
||||
|
||||
func (s *router) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -243,9 +236,6 @@ func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *htt
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
name := vars["name"]
|
||||
|
||||
@@ -265,10 +255,6 @@ func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *htt
|
||||
}
|
||||
|
||||
func (s *router) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
imageInspect, err := s.daemon.LookupImage(vars["name"])
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -456,10 +442,6 @@ func (s *router) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *ht
|
||||
}
|
||||
|
||||
func (s *router) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
name := vars["name"]
|
||||
history, err := s.daemon.ImageHistory(name)
|
||||
if err != nil {
|
||||
@@ -473,10 +455,6 @@ func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *ht
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
repo := r.Form.Get("repo")
|
||||
tag := r.Form.Get("tag")
|
||||
name := vars["name"]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
@@ -11,9 +10,6 @@ import (
|
||||
// getContainersByName inspects containers configuration and serializes it as json.
|
||||
func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
displaySize := httputils.BoolValue(r, "size")
|
||||
if vars == nil {
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
var json interface{}
|
||||
var err error
|
||||
|
||||
@@ -96,7 +96,7 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr
|
||||
warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
|
||||
}
|
||||
|
||||
nw, err = n.daemon.CreateNetwork(create.Name, create.Driver, create.IPAM)
|
||||
nw, err = n.daemon.CreateNetwork(create.Name, create.Driver, create.IPAM, create.Options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -126,11 +126,7 @@ func (n *networkRouter) postNetworkConnect(ctx context.Context, w http.ResponseW
|
||||
return err
|
||||
}
|
||||
|
||||
container, err := n.daemon.Get(connect.Container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid container %s : %v", container, err)
|
||||
}
|
||||
return container.ConnectToNetwork(nw.Name())
|
||||
return n.daemon.ConnectContainerToNetwork(connect.Container, nw.Name())
|
||||
}
|
||||
|
||||
func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
@@ -152,11 +148,7 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
|
||||
return err
|
||||
}
|
||||
|
||||
container, err := n.daemon.Get(disconnect.Container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid container %s : %v", container, err)
|
||||
}
|
||||
return container.DisconnectFromNetwork(nw)
|
||||
return n.daemon.DisconnectContainerFromNetwork(disconnect.Container, nw)
|
||||
}
|
||||
|
||||
func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
@@ -182,6 +174,7 @@ func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource {
|
||||
r.ID = nw.ID()
|
||||
r.Scope = nw.Info().Scope()
|
||||
r.Driver = nw.Type()
|
||||
r.Options = nw.Info().DriverOptions()
|
||||
r.Containers = make(map[string]types.EndpointResource)
|
||||
buildIpamResources(r, nw)
|
||||
|
||||
|
||||
@@ -153,7 +153,12 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
|
||||
ctx := context.Background()
|
||||
handlerFunc := s.handleWithGlobalMiddlewares(handler)
|
||||
|
||||
if err := handlerFunc(ctx, w, r, mux.Vars(r)); err != nil {
|
||||
vars := mux.Vars(r)
|
||||
if vars == nil {
|
||||
vars = make(map[string]string)
|
||||
}
|
||||
|
||||
if err := handlerFunc(ctx, w, r, vars); err != nil {
|
||||
logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.URL.Path, utils.GetErrorMessage(err))
|
||||
httputils.WriteError(w, err)
|
||||
}
|
||||
|
||||
+6
-4
@@ -319,6 +319,7 @@ type NetworkResource struct {
|
||||
Driver string `json:"driver"`
|
||||
IPAM network.IPAM `json:"ipam"`
|
||||
Containers map[string]EndpointResource `json:"containers"`
|
||||
Options map[string]string `json:"options"`
|
||||
}
|
||||
|
||||
//EndpointResource contains network resources allocated and usd for a container in a network
|
||||
@@ -331,10 +332,11 @@ type EndpointResource struct {
|
||||
|
||||
// NetworkCreate is the expected body of the "create network" http request message
|
||||
type NetworkCreate struct {
|
||||
Name string `json:"name"`
|
||||
CheckDuplicate bool `json:"check_duplicate"`
|
||||
Driver string `json:"driver"`
|
||||
IPAM network.IPAM `json:"ipam"`
|
||||
Name string `json:"name"`
|
||||
CheckDuplicate bool `json:"check_duplicate"`
|
||||
Driver string `json:"driver"`
|
||||
IPAM network.IPAM `json:"ipam"`
|
||||
Options map[string]string `json:"options"`
|
||||
}
|
||||
|
||||
// NetworkCreateResponse is the response message sent by the server for network create call
|
||||
|
||||
@@ -256,7 +256,12 @@ func BuildFromConfig(config *runconfig.Config, changes []string) (*runconfig.Con
|
||||
|
||||
// Commit will create a new image from a container's changes
|
||||
// TODO: remove daemon, make Commit a method on *Builder ?
|
||||
func Commit(container *daemon.Container, d *daemon.Daemon, c *CommitConfig) (string, error) {
|
||||
func Commit(containerName string, d *daemon.Daemon, c *CommitConfig) (string, error) {
|
||||
container, err := d.Get(containerName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// It is not possible to commit a running container on Windows
|
||||
if runtime.GOOS == "windows" && container.IsRunning() {
|
||||
return "", fmt.Errorf("Windows does not support commit of a running container")
|
||||
|
||||
@@ -557,8 +557,9 @@ func (b *Builder) run(c *daemon.Container) error {
|
||||
go func() {
|
||||
select {
|
||||
case <-b.cancelled:
|
||||
logrus.Debugln("Build cancelled, killing container:", c.ID)
|
||||
logrus.Debugln("Build cancelled, killing and removing container:", c.ID)
|
||||
c.Kill()
|
||||
b.removeContainer(c.ID)
|
||||
case <-finished:
|
||||
}
|
||||
}()
|
||||
@@ -582,14 +583,21 @@ func (b *Builder) run(c *daemon.Container) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Builder) removeContainer(c string) error {
|
||||
rmConfig := &daemon.ContainerRmConfig{
|
||||
ForceRemove: true,
|
||||
RemoveVolume: true,
|
||||
}
|
||||
if err := b.docker.Remove(c, rmConfig); err != nil {
|
||||
fmt.Fprintf(b.Stdout, "Error removing intermediate container %s: %v\n", stringid.TruncateID(c), err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Builder) clearTmp() {
|
||||
for c := range b.tmpContainers {
|
||||
rmConfig := &daemon.ContainerRmConfig{
|
||||
ForceRemove: true,
|
||||
RemoveVolume: true,
|
||||
}
|
||||
if err := b.docker.Remove(c, rmConfig); err != nil {
|
||||
fmt.Fprintf(b.Stdout, "Error removing intermediate container %s: %v\n", stringid.TruncateID(c), err)
|
||||
if err := b.removeContainer(c); err != nil {
|
||||
return
|
||||
}
|
||||
delete(b.tmpContainers, c)
|
||||
|
||||
@@ -45,6 +45,7 @@ var dockerCommands = []Command{
|
||||
{"login", "Register or log in to a Docker registry"},
|
||||
{"logout", "Log out from a Docker registry"},
|
||||
{"logs", "Fetch the logs of a container"},
|
||||
{"network", "Manage Docker networks"},
|
||||
{"pause", "Pause all processes within a container"},
|
||||
{"port", "List port mappings or a specific mapping for the CONTAINER"},
|
||||
{"ps", "List containers"},
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM debian:jessie
|
||||
|
||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM debian:stretch
|
||||
|
||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM debian:wheezy-backports
|
||||
|
||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools/wheezy-backports build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:precise
|
||||
|
||||
RUN apt-get update && apt-get install -y bash-completion build-essential curl ca-certificates debhelper git libapparmor-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:trusty
|
||||
|
||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:vivid
|
||||
|
||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM ubuntu:wily
|
||||
|
||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM fedora:21
|
||||
RUN yum install -y @development-tools fedora-packager
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM fedora:22
|
||||
RUN yum install -y @development-tools fedora-packager
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM opensuse:13.2
|
||||
RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build
|
||||
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM oraclelinux:6
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FROM oraclelinux:7
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
ENV GO_VERSION 1.4.3
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
|
||||
@@ -461,8 +461,37 @@ _docker_attach() {
|
||||
}
|
||||
|
||||
_docker_build() {
|
||||
local options_with_args="
|
||||
--build-arg
|
||||
--cgroup-parent
|
||||
--cpuset-cpus
|
||||
--cpuset-mems
|
||||
--cpu-shares
|
||||
--cpu-period
|
||||
--cpu-quota
|
||||
--file -f
|
||||
--memory -m
|
||||
--memory-swap
|
||||
--tag -t
|
||||
--ulimit
|
||||
"
|
||||
|
||||
local boolean_options="
|
||||
--disable-content-trust=false
|
||||
--force-rm
|
||||
--help
|
||||
--no-cache
|
||||
--pull
|
||||
--quiet -q
|
||||
--rm
|
||||
"
|
||||
|
||||
local all_options="$options_with_args $boolean_options"
|
||||
|
||||
case "$prev" in
|
||||
--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--memory|-m|--memory-swap)
|
||||
--build-arg)
|
||||
COMPREPLY=( $( compgen -e -- "$cur" ) )
|
||||
__docker_nospace
|
||||
return
|
||||
;;
|
||||
--file|-f)
|
||||
@@ -473,14 +502,17 @@ _docker_build() {
|
||||
__docker_image_repos_and_tags
|
||||
return
|
||||
;;
|
||||
$(__docker_to_extglob "$options_with_args") )
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--cgroup-parent --cpuset-cpus --cpuset-mems --cpu-shares -c --cpu-period --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t --ulimit" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter="$(__docker_pos_first_nonflag '--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--file|-f|--memory|-m|--memory-swap|--tag|-t')"
|
||||
local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) )
|
||||
if [ $cword -eq $counter ]; then
|
||||
_filedir -d
|
||||
fi
|
||||
@@ -865,12 +897,18 @@ _docker_images() {
|
||||
}
|
||||
|
||||
_docker_import() {
|
||||
case "$prev" in
|
||||
--change|-c|--message|-m)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--change -c --help --message -m" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter=$(__docker_pos_first_nonflag)
|
||||
local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m')
|
||||
if [ $cword -eq $counter ]; then
|
||||
return
|
||||
fi
|
||||
@@ -906,7 +944,7 @@ _docker_inspect() {
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--format -f --type --help" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--format -f --help --size -s --type" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
case $(__docker_value_of_option --type) in
|
||||
@@ -1060,7 +1098,7 @@ _docker_network_ls() {
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--help --latest -l -n --no-trunc --quiet -q" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--help --no-trunc --quiet -q" -- "$cur" ) )
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -1272,7 +1310,7 @@ _docker_run() {
|
||||
--cpu-quota
|
||||
--cpuset-cpus
|
||||
--cpuset-mems
|
||||
--cpu-shares -c
|
||||
--cpu-shares
|
||||
--device
|
||||
--dns
|
||||
--dns-opt
|
||||
@@ -1311,7 +1349,7 @@ _docker_run() {
|
||||
--workdir -w
|
||||
"
|
||||
|
||||
local all_options="$options_with_args
|
||||
local boolean_options="
|
||||
--disable-content-trust=false
|
||||
--help
|
||||
--interactive -i
|
||||
@@ -1322,14 +1360,14 @@ _docker_run() {
|
||||
--tty -t
|
||||
"
|
||||
|
||||
local all_options="$options_with_args $boolean_options"
|
||||
|
||||
[ "$command" = "run" ] && all_options="$all_options
|
||||
--detach -d
|
||||
--rm
|
||||
--sig-proxy=false
|
||||
"
|
||||
|
||||
local options_with_args_glob=$(__docker_to_extglob "$options_with_args")
|
||||
|
||||
case "$prev" in
|
||||
--add-host)
|
||||
case "$cur" in
|
||||
@@ -1454,7 +1492,7 @@ _docker_run() {
|
||||
__docker_containers_all
|
||||
return
|
||||
;;
|
||||
$options_with_args_glob )
|
||||
$(__docker_to_extglob "$options_with_args") )
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -116,7 +116,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from cp' -l help -d 'Print u
|
||||
complete -c docker -f -n '__fish_docker_no_subcommand' -a create -d 'Create a new container'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s a -l attach -d 'Attach to STDIN, STDOUT or STDERR.'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l add-host -d 'Add a custom host-to-IP mapping (host:ip)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s c -l cpu-shares -d 'CPU shares (relative weight)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cpu-shares -d 'CPU shares (relative weight)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-add -d 'Add Linux capabilities'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-drop -d 'Drop Linux capabilities'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cidfile -d 'Write the container ID to the file'
|
||||
|
||||
+117
-112
@@ -253,6 +253,11 @@ __docker_network_subcommand() {
|
||||
_arguments -A '-*' \
|
||||
$opts_help \
|
||||
"($help -d --driver)"{-d,--driver=}"[Driver to manage the Network]:driver:(null host bridge overlay)" \
|
||||
"($help)--ipam-driver=[IP Address Management Driver]:driver:(default)" \
|
||||
"($help)*--subnet=[Subnet in CIDR format that represents a network segment]:IP/mask: " \
|
||||
"($help)*--ip-range=[Allocate container ip from a sub-range]:IP/mask: " \
|
||||
"($help)*--gateway=[ipv4 or ipv6 Gateway for the master subnet]:IP: " \
|
||||
"($help)*--aux-address[Auxiliary ipv4 or ipv6 addresses used by network driver]:key=IP: " \
|
||||
"($help -)1:Network Name: " && ret=0
|
||||
;;
|
||||
(inspect|rm)
|
||||
@@ -263,8 +268,6 @@ __docker_network_subcommand() {
|
||||
(ls)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -l --latest)"{-l,--latest}"[Show the latest network created]" \
|
||||
"($help)-n=-[Show n last created networks]:Number of networks: " \
|
||||
"($help)--no-trunc[Do not truncate the output]" \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Only display numeric IDs]" && ret=0
|
||||
;;
|
||||
@@ -330,20 +333,20 @@ __docker_volume_subcommand() {
|
||||
(create)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -d --driver)"{-d,--driver=-}"[Specify volume driver name]:Driver name: " \
|
||||
"($help)--name=-[Specify volume name]" \
|
||||
"($help -o --opt)*"{-o,--opt=-}"[Set driver specific options]:Driver option: " && ret=0
|
||||
"($help -d --driver)"{-d,--driver=}"[Specify volume driver name]:Driver name: " \
|
||||
"($help)--name=[Specify volume name]" \
|
||||
"($help -o --opt)*"{-o,--opt=}"[Set driver specific options]:Driver option: " && ret=0
|
||||
;;
|
||||
(inspect)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -f --format)"{-f,--format=-}"[Format the output using the given go template]:template: " \
|
||||
"($help -f --format)"{-f,--format=}"[Format the output using the given go template]:template: " \
|
||||
"($help -)1:volume:__docker_volumes" && ret=0
|
||||
;;
|
||||
(ls)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -f --filter)*"{-f,--filter=-}"[Provide filter values (i.e. 'dangling=true')]:filter: " \
|
||||
"($help -f --filter)*"{-f,--filter=}"[Provide filter values (i.e. 'dangling=true')]:filter: " \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Only display volume names]" && ret=0
|
||||
;;
|
||||
(rm)
|
||||
@@ -391,57 +394,57 @@ __docker_subcommand() {
|
||||
|
||||
opts_help=("(: -)--help[Print usage]")
|
||||
opts_cpumemlimit=(
|
||||
"($help -c --cpu-shares)"{-c,--cpu-shares=-}"[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)"
|
||||
"($help)--cgroup-parent=-[Parent cgroup for the container]:cgroup: "
|
||||
"($help)--cpu-period=-[Limit the CPU CFS (Completely Fair Scheduler) period]:CPU period: "
|
||||
"($help)--cpu-quota=-[Limit the CPU CFS (Completely Fair Scheduler) quota]:CPU quota: "
|
||||
"($help)--cpuset-cpus=-[CPUs in which to allow execution]:CPUs: "
|
||||
"($help)--cpuset-mems=-[MEMs in which to allow execution]:MEMs: "
|
||||
"($help -m --memory)"{-m,--memory=-}"[Memory limit]:Memory limit: "
|
||||
"($help)--memory-swap=-[Total memory limit with swap]:Memory limit: "
|
||||
"($help)*--ulimit=-[ulimit options]:ulimit: "
|
||||
"($help)--cpu-shares=[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)"
|
||||
"($help)--cgroup-parent=[Parent cgroup for the container]:cgroup: "
|
||||
"($help)--cpu-period=[Limit the CPU CFS (Completely Fair Scheduler) period]:CPU period: "
|
||||
"($help)--cpu-quota=[Limit the CPU CFS (Completely Fair Scheduler) quota]:CPU quota: "
|
||||
"($help)--cpuset-cpus=[CPUs in which to allow execution]:CPUs: "
|
||||
"($help)--cpuset-mems=[MEMs in which to allow execution]:MEMs: "
|
||||
"($help -m --memory)"{-m,--memory=}"[Memory limit]:Memory limit: "
|
||||
"($help)--memory-swap=[Total memory limit with swap]:Memory limit: "
|
||||
"($help)*--ulimit=[ulimit options]:ulimit: "
|
||||
)
|
||||
opts_create=(
|
||||
"($help -a --attach)"{-a,--attach=-}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
|
||||
"($help)*--add-host=-[Add a custom host-to-IP mapping]:host\:ip mapping: "
|
||||
"($help)--blkio-weight=-[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)"
|
||||
"($help)*--cap-add=-[Add Linux capabilities]:capability: "
|
||||
"($help)*--cap-drop=-[Drop Linux capabilities]:capability: "
|
||||
"($help)--cidfile=-[Write the container ID to the file]:CID file:_files"
|
||||
"($help)*--device=-[Add a host device to the container]:device:_files"
|
||||
"($help)*--dns=-[Set custom DNS servers]:DNS server: "
|
||||
"($help)*--dns-opt=-[Set custom DNS options]:DNS option: "
|
||||
"($help)*--dns-search=-[Set custom DNS search domains]:DNS domains: "
|
||||
"($help)*"{-e,--env=-}"[Set environment variables]:environment variable: "
|
||||
"($help)--entrypoint=-[Overwrite the default entrypoint of the image]:entry point: "
|
||||
"($help)*--env-file=-[Read environment variables from a file]:environment file:_files"
|
||||
"($help)*--expose=-[Expose a port from the container without publishing it]: "
|
||||
"($help)*--group-add=-[Add additional groups to run as]:group:_groups"
|
||||
"($help -h --hostname)"{-h,--hostname=-}"[Container host name]:hostname:_hosts"
|
||||
"($help -a --attach)"{-a,--attach=}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
|
||||
"($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: "
|
||||
"($help)--blkio-weight=[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)"
|
||||
"($help)*--cap-add=[Add Linux capabilities]:capability: "
|
||||
"($help)*--cap-drop=[Drop Linux capabilities]:capability: "
|
||||
"($help)--cidfile=[Write the container ID to the file]:CID file:_files"
|
||||
"($help)*--device=[Add a host device to the container]:device:_files"
|
||||
"($help)*--dns=[Set custom DNS servers]:DNS server: "
|
||||
"($help)*--dns-opt=[Set custom DNS options]:DNS option: "
|
||||
"($help)*--dns-search=[Set custom DNS search domains]:DNS domains: "
|
||||
"($help)*"{-e,--env=}"[Set environment variables]:environment variable: "
|
||||
"($help)--entrypoint=[Overwrite the default entrypoint of the image]:entry point: "
|
||||
"($help)*--env-file=[Read environment variables from a file]:environment file:_files"
|
||||
"($help)*--expose=[Expose a port from the container without publishing it]: "
|
||||
"($help)*--group-add=[Add additional groups to run as]:group:_groups"
|
||||
"($help -h --hostname)"{-h,--hostname=}"[Container host name]:hostname:_hosts"
|
||||
"($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]"
|
||||
"($help)--ipc=-[IPC namespace to use]:IPC namespace: "
|
||||
"($help)--ipc=[IPC namespace to use]:IPC namespace: "
|
||||
"($help)--kernel-memory[Kernel memory limit in bytes.]:Memory limit: "
|
||||
"($help)*--link=-[Add link to another container]:link:->link"
|
||||
"($help)*"{-l,--label=-}"[Set meta data on a container]:label: "
|
||||
"($help)--log-driver=-[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)"
|
||||
"($help)*--log-opt=-[Log driver specific options]:log driver options: "
|
||||
"($help)*--lxc-conf=-[Add custom lxc options]:lxc options: "
|
||||
"($help)--mac-address=-[Container MAC address]:MAC address: "
|
||||
"($help)--name=-[Container name]:name: "
|
||||
"($help)--net=-[Connect a container to a network]:network mode:(bridge none container host)"
|
||||
"($help)*--link=[Add link to another container]:link:->link"
|
||||
"($help)*"{-l,--label=}"[Set meta data on a container]:label: "
|
||||
"($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)"
|
||||
"($help)*--log-opt=[Log driver specific options]:log driver options: "
|
||||
"($help)*--lxc-conf=[Add custom lxc options]:lxc options: "
|
||||
"($help)--mac-address=[Container MAC address]:MAC address: "
|
||||
"($help)--name=[Container name]:name: "
|
||||
"($help)--net=[Connect a container to a network]:network mode:(bridge none container host)"
|
||||
"($help)--oom-kill-disable[Disable OOM Killer]"
|
||||
"($help -P --publish-all)"{-P,--publish-all}"[Publish all exposed ports]"
|
||||
"($help)*"{-p,--publish=-}"[Expose a container's port to the host]:port:_ports"
|
||||
"($help)--pid=-[PID namespace to use]:PID: "
|
||||
"($help)*"{-p,--publish=}"[Expose a container's port to the host]:port:_ports"
|
||||
"($help)--pid=[PID namespace to use]:PID: "
|
||||
"($help)--privileged[Give extended privileges to this container]"
|
||||
"($help)--read-only[Mount the container's root filesystem as read only]"
|
||||
"($help)--restart=-[Restart policy]:restart policy:(no on-failure always)"
|
||||
"($help)*--security-opt=-[Security options]:security option: "
|
||||
"($help)--restart=[Restart policy]:restart policy:(no on-failure always unless-stopped)"
|
||||
"($help)*--security-opt=[Security options]:security option: "
|
||||
"($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]"
|
||||
"($help -u --user)"{-u,--user=-}"[Username or UID]:user:_users"
|
||||
"($help -u --user)"{-u,--user=}"[Username or UID]:user:_users"
|
||||
"($help)*-v[Bind mount a volume]:volume: "
|
||||
"($help)*--volumes-from=-[Mount volumes from the specified container]:volume: "
|
||||
"($help -w --workdir)"{-w,--workdir=-}"[Working directory inside the container]:directory:_directories"
|
||||
"($help)*--volumes-from=[Mount volumes from the specified container]:volume: "
|
||||
"($help -w --workdir)"{-w,--workdir=}"[Working directory inside the container]:directory:_directories"
|
||||
)
|
||||
|
||||
case "$words[1]" in
|
||||
@@ -456,21 +459,22 @@ __docker_subcommand() {
|
||||
_arguments \
|
||||
$opts_help \
|
||||
$opts_cpumemlimit \
|
||||
"($help -f --file)"{-f,--file=-}"[Name of the Dockerfile]:Dockerfile:_files" \
|
||||
"($help)*--build-arg[Set build-time variables]:<varname>=<value>: " \
|
||||
"($help -f --file)"{-f,--file=}"[Name of the Dockerfile]:Dockerfile:_files" \
|
||||
"($help)--force-rm[Always remove intermediate containers]" \
|
||||
"($help)--no-cache[Do not use cache when building the image]" \
|
||||
"($help)--pull[Attempt to pull a newer version of the image]" \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Suppress verbose build output]" \
|
||||
"($help)--rm[Remove intermediate containers after a successful build]" \
|
||||
"($help -t --tag)"{-t,--tag=-}"[Repository, name and tag for the image]: :__docker_repositories_with_tags" \
|
||||
"($help -t --tag)"{-t,--tag=}"[Repository, name and tag for the image]: :__docker_repositories_with_tags" \
|
||||
"($help -):path or URL:_directories" && ret=0
|
||||
;;
|
||||
(commit)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -a --author)"{-a,--author=-}"[Author]:author: " \
|
||||
"($help -c --change)*"{-c,--change=-}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
|
||||
"($help -m --message)"{-m,--message=-}"[Commit message]:message: " \
|
||||
"($help -a --author)"{-a,--author=}"[Author]:author: " \
|
||||
"($help -c --change)*"{-c,--change=}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
|
||||
"($help -m --message)"{-m,--message=}"[Commit message]:message: " \
|
||||
"($help -p --pause)"{-p,--pause}"[Pause container during commit]" \
|
||||
"($help -):container:__docker_containers" \
|
||||
"($help -): :__docker_repositories_with_tags" && ret=0
|
||||
@@ -513,49 +517,49 @@ __docker_subcommand() {
|
||||
(daemon)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help)--api-cors-header=-[Set CORS headers in the remote API]:CORS headers: " \
|
||||
"($help -b --bridge)"{-b,--bridge=-}"[Attach containers to a network bridge]:bridge:_net_interfaces" \
|
||||
"($help)--bip=-[Specify network bridge IP]" \
|
||||
"($help)--api-cors-header=[Set CORS headers in the remote API]:CORS headers: " \
|
||||
"($help -b --bridge)"{-b,--bridge=}"[Attach containers to a network bridge]:bridge:_net_interfaces" \
|
||||
"($help)--bip=[Specify network bridge IP]" \
|
||||
"($help -D --debug)"{-D,--debug}"[Enable debug mode]" \
|
||||
"($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \
|
||||
"($help)--default-gateway-v6[Container default gateway IPv6 address]:IPv6 address: " \
|
||||
"($help)--cluster-store=-[URL of the distributed storage backend]:Cluster Store:->cluster-store" \
|
||||
"($help)--cluster-advertise=-[Address of the daemon instance to advertise]:Instance to advertise (host\:port): " \
|
||||
"($help)--cluster-store=[URL of the distributed storage backend]:Cluster Store:->cluster-store" \
|
||||
"($help)--cluster-advertise=[Address of the daemon instance to advertise]:Instance to advertise (host\:port): " \
|
||||
"($help)*--cluster-store-opt[Set cluster options]:Cluster options:->cluster-store-options" \
|
||||
"($help)*--dns=-[DNS server to use]:DNS: " \
|
||||
"($help)*--dns-search=-[DNS search domains to use]:DNS search: " \
|
||||
"($help)*--dns-opt=-[DNS options to use]:DNS option: " \
|
||||
"($help)*--default-ulimit=-[Set default ulimit settings for containers]:ulimit: " \
|
||||
"($help)*--dns=[DNS server to use]:DNS: " \
|
||||
"($help)*--dns-search=[DNS search domains to use]:DNS search: " \
|
||||
"($help)*--dns-opt=[DNS options to use]:DNS option: " \
|
||||
"($help)*--default-ulimit=[Set default ulimit settings for containers]:ulimit: " \
|
||||
"($help)--disable-legacy-registry[Do not contact legacy registries]" \
|
||||
"($help -e --exec-driver)"{-e,--exec-driver=-}"[Exec driver to use]:driver:(native lxc windows)" \
|
||||
"($help)*--exec-opt=-[Set exec driver options]:exec driver options: " \
|
||||
"($help)--exec-root=-[Root of the Docker execdriver]:path:_directories" \
|
||||
"($help)--fixed-cidr=-[IPv4 subnet for fixed IPs]:IPv4 subnet: " \
|
||||
"($help)--fixed-cidr-v6=-[IPv6 subnet for fixed IPs]:IPv6 subnet: " \
|
||||
"($help -G --group)"{-G,--group=-}"[Group for the unix socket]:group:_groups" \
|
||||
"($help -g --graph)"{-g,--graph=-}"[Root of the Docker runtime]:path:_directories" \
|
||||
"($help -H --host)"{-H,--host=-}"[tcp://host:port to bind/connect to]:host: " \
|
||||
"($help -e --exec-driver)"{-e,--exec-driver=}"[Exec driver to use]:driver:(native lxc windows)" \
|
||||
"($help)*--exec-opt=[Set exec driver options]:exec driver options: " \
|
||||
"($help)--exec-root=[Root of the Docker execdriver]:path:_directories" \
|
||||
"($help)--fixed-cidr=[IPv4 subnet for fixed IPs]:IPv4 subnet: " \
|
||||
"($help)--fixed-cidr-v6=[IPv6 subnet for fixed IPs]:IPv6 subnet: " \
|
||||
"($help -G --group)"{-G,--group=}"[Group for the unix socket]:group:_groups" \
|
||||
"($help -g --graph)"{-g,--graph=}"[Root of the Docker runtime]:path:_directories" \
|
||||
"($help -H --host)"{-H,--host=}"[tcp://host:port to bind/connect to]:host: " \
|
||||
"($help)--icc[Enable inter-container communication]" \
|
||||
"($help)*--insecure-registry=-[Enable insecure registry communication]:registry: " \
|
||||
"($help)--ip=-[Default IP when binding container ports]" \
|
||||
"($help)*--insecure-registry=[Enable insecure registry communication]:registry: " \
|
||||
"($help)--ip=[Default IP when binding container ports]" \
|
||||
"($help)--ip-forward[Enable net.ipv4.ip_forward]" \
|
||||
"($help)--ip-masq[Enable IP masquerading]" \
|
||||
"($help)--iptables[Enable addition of iptables rules]" \
|
||||
"($help)--ipv6[Enable IPv6 networking]" \
|
||||
"($help -l --log-level)"{-l,--log-level=-}"[Set the logging level]:level:(debug info warn error fatal)" \
|
||||
"($help)*--label=-[Set key=value labels to the daemon]:label: " \
|
||||
"($help)--log-driver=-[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)" \
|
||||
"($help)*--log-opt=-[Log driver specific options]:log driver options: " \
|
||||
"($help)--mtu=-[Set the containers network MTU]:mtu:(0 576 1420 1500 9000)" \
|
||||
"($help -p --pidfile)"{-p,--pidfile=-}"[Path to use for daemon PID file]:PID file:_files" \
|
||||
"($help)*--registry-mirror=-[Preferred Docker registry mirror]:registry mirror: " \
|
||||
"($help -s --storage-driver)"{-s,--storage-driver=-}"[Storage driver to use]:driver:(aufs devicemapper btrfs zfs overlay)" \
|
||||
"($help -l --log-level)"{-l,--log-level=}"[Set the logging level]:level:(debug info warn error fatal)" \
|
||||
"($help)*--label=[Set key=value labels to the daemon]:label: " \
|
||||
"($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)" \
|
||||
"($help)*--log-opt=[Log driver specific options]:log driver options: " \
|
||||
"($help)--mtu=[Set the containers network MTU]:mtu:(0 576 1420 1500 9000)" \
|
||||
"($help -p --pidfile)"{-p,--pidfile=}"[Path to use for daemon PID file]:PID file:_files" \
|
||||
"($help)*--registry-mirror=[Preferred Docker registry mirror]:registry mirror: " \
|
||||
"($help -s --storage-driver)"{-s,--storage-driver=}"[Storage driver to use]:driver:(aufs devicemapper btrfs zfs overlay)" \
|
||||
"($help)--selinux-enabled[Enable selinux support]" \
|
||||
"($help)*--storage-opt=-[Set storage driver options]:storage driver options: " \
|
||||
"($help)*--storage-opt=[Set storage driver options]:storage driver options: " \
|
||||
"($help)--tls[Use TLS]" \
|
||||
"($help)--tlscacert=-[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlscert=-[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlskey=-[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
|
||||
"($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlskey=[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
|
||||
"($help)--tlsverify[Use TLS and verify the remote]" \
|
||||
"($help)--userland-proxy[Use userland proxy for loopback traffic]" && ret=0
|
||||
|
||||
@@ -586,9 +590,9 @@ __docker_subcommand() {
|
||||
(events)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help)*"{-f,--filter=-}"[Filter values]:filter: " \
|
||||
"($help)--since=-[Events created since this timestamp]:timestamp: " \
|
||||
"($help)--until=-[Events created until this timestamp]:timestamp: " && ret=0
|
||||
"($help)*"{-f,--filter=}"[Filter values]:filter: " \
|
||||
"($help)--since=[Events created since this timestamp]:timestamp: " \
|
||||
"($help)--until=[Events created until this timestamp]:timestamp: " && ret=0
|
||||
;;
|
||||
(exec)
|
||||
local state
|
||||
@@ -598,7 +602,7 @@ __docker_subcommand() {
|
||||
"($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]" \
|
||||
"($help)--privileged[Give extended Linux capabilities to the command]" \
|
||||
"($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]" \
|
||||
"($help -u --user)"{-u,--user=-}"[Username or UID]:user:_users" \
|
||||
"($help -u --user)"{-u,--user=}"[Username or UID]:user:_users" \
|
||||
"($help -):containers:__docker_runningcontainers" \
|
||||
"($help -)*::command:->anycommand" && ret=0
|
||||
|
||||
@@ -613,7 +617,7 @@ __docker_subcommand() {
|
||||
(export)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -o --output)"{-o,--output=-}"[Write to a file, instead of stdout]:output file:_files" \
|
||||
"($help -o --output)"{-o,--output=}"[Write to a file, instead of stdout]:output file:_files" \
|
||||
"($help -)*:containers:__docker_containers" && ret=0
|
||||
;;
|
||||
(history)
|
||||
@@ -629,7 +633,7 @@ __docker_subcommand() {
|
||||
$opts_help \
|
||||
"($help -a --all)"{-a,--all}"[Show all images]" \
|
||||
"($help)--digest[Show digests]" \
|
||||
"($help)*"{-f,--filter=-}"[Filter values]:filter: " \
|
||||
"($help)*"{-f,--filter=}"[Filter values]:filter: " \
|
||||
"($help)--no-trunc[Do not truncate output]" \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Only show numeric IDs]" \
|
||||
"($help -): :__docker_repositories" && ret=0
|
||||
@@ -637,7 +641,8 @@ __docker_subcommand() {
|
||||
(import)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -c --change)*"{-c,--change=-}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
|
||||
"($help -c --change)*"{-c,--change=}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
|
||||
"($help -m --message)"{-m,--message=}"[Set commit message for imported image]:message: " \
|
||||
"($help -):URL:(- http:// file://)" \
|
||||
"($help -): :__docker_repositories_with_tags" && ret=0
|
||||
;;
|
||||
@@ -649,9 +654,9 @@ __docker_subcommand() {
|
||||
local state
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -f --format=-)"{-f,--format=-}"[Format the output using the given go template]:template: " \
|
||||
"($help -f --format)"{-f,--format=}"[Format the output using the given go template]:template: " \
|
||||
"($help -s --size)"{-s,--size}"[Display total file sizes if the type is container]" \
|
||||
"($help)--type=-[Return JSON for specified type]:type:(image container)" \
|
||||
"($help)--type=[Return JSON for specified type]:type:(image container)" \
|
||||
"($help -)*: :->values" && ret=0
|
||||
|
||||
case $state in
|
||||
@@ -669,20 +674,20 @@ __docker_subcommand() {
|
||||
(kill)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -s --signal)"{-s,--signal=-}"[Signal to send]:signal:_signals" \
|
||||
"($help -s --signal)"{-s,--signal=}"[Signal to send]:signal:_signals" \
|
||||
"($help -)*:containers:__docker_runningcontainers" && ret=0
|
||||
;;
|
||||
(load)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -i --input)"{-i,--input=-}"[Read from tar archive file]:archive file:_files -g "*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)"" && ret=0
|
||||
"($help -i --input)"{-i,--input=}"[Read from tar archive file]:archive file:_files -g "*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)"" && ret=0
|
||||
;;
|
||||
(login)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -e --email)"{-e,--email=-}"[Email]:email: " \
|
||||
"($help -p --password)"{-p,--password=-}"[Password]:password: " \
|
||||
"($help -u --user)"{-u,--user=-}"[Username]:username: " \
|
||||
"($help -e --email)"{-e,--email=}"[Email]:email: " \
|
||||
"($help -p --password)"{-p,--password=}"[Password]:password: " \
|
||||
"($help -u --user)"{-u,--user=}"[Username]:username: " \
|
||||
"($help -)1:server: " && ret=0
|
||||
;;
|
||||
(logout)
|
||||
@@ -694,9 +699,9 @@ __docker_subcommand() {
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -f --follow)"{-f,--follow}"[Follow log output]" \
|
||||
"($help -s --since)"{-s,--since=-}"[Show logs since this timestamp]:timestamp: " \
|
||||
"($help -s --since)"{-s,--since=}"[Show logs since this timestamp]:timestamp: " \
|
||||
"($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \
|
||||
"($help)--tail=-[Output the last K lines]:lines:(1 10 20 50 all)" \
|
||||
"($help)--tail=[Output the last K lines]:lines:(1 10 20 50 all)" \
|
||||
"($help -)*:containers:__docker_containers" && ret=0
|
||||
;;
|
||||
(network)
|
||||
@@ -731,15 +736,15 @@ __docker_subcommand() {
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -a --all)"{-a,--all}"[Show all containers]" \
|
||||
"($help)--before=-[Show only container created before...]:containers:__docker_containers" \
|
||||
"($help)*"{-f,--filter=-}"[Filter values]:filter: " \
|
||||
"($help)--before=[Show only container created before...]:containers:__docker_containers" \
|
||||
"($help)*"{-f,--filter=}"[Filter values]:filter: " \
|
||||
"($help)--format[Pretty-print containers using a Go template]:format: " \
|
||||
"($help -l --latest)"{-l,--latest}"[Show only the latest created container]" \
|
||||
"($help)-n[Show n last created containers, include non-running one]:n:(1 5 10 25 50)" \
|
||||
"($help)--no-trunc[Do not truncate output]" \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Only show numeric IDs]" \
|
||||
"($help -s --size)"{-s,--size}"[Display total file sizes]" \
|
||||
"($help)--since=-[Show only containers created since...]:containers:__docker_containers" && ret=0
|
||||
"($help)--since=[Show only containers created since...]:containers:__docker_containers" && ret=0
|
||||
;;
|
||||
(pull)
|
||||
_arguments \
|
||||
@@ -761,7 +766,7 @@ __docker_subcommand() {
|
||||
(restart|stop)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -t --time=-)"{-t,--time=-}"[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)" \
|
||||
"($help -t --time)"{-t,--time=}"[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)" \
|
||||
"($help -)*:containers:__docker_runningcontainers" && ret=0
|
||||
;;
|
||||
(rm)
|
||||
@@ -787,7 +792,7 @@ __docker_subcommand() {
|
||||
"($help -d --detach)"{-d,--detach}"[Detached mode: leave the container running in the background]" \
|
||||
"($help)--rm[Remove intermediate containers when it exits]" \
|
||||
"($help)--sig-proxy[Proxy all received signals to the process (non-TTY mode only)]" \
|
||||
"($help)--stop-signal=-[Signal to kill a container]:signal:_signals" \
|
||||
"($help)--stop-signal=[Signal to kill a container]:signal:_signals" \
|
||||
"($help -): :__docker_images" \
|
||||
"($help -):command: _command_names -e" \
|
||||
"($help -)*::arguments: _normal" && ret=0
|
||||
@@ -806,7 +811,7 @@ __docker_subcommand() {
|
||||
(save)
|
||||
_arguments \
|
||||
$opts_help \
|
||||
"($help -o --output)"{-o,--output=-}"[Write to file]:file:_files" \
|
||||
"($help -o --output)"{-o,--output=}"[Write to file]:file:_files" \
|
||||
"($help -)*: :__docker_images" && ret=0
|
||||
;;
|
||||
(search)
|
||||
@@ -814,7 +819,7 @@ __docker_subcommand() {
|
||||
$opts_help \
|
||||
"($help)--automated[Only show automated builds]" \
|
||||
"($help)--no-trunc[Do not truncate output]" \
|
||||
"($help -s --stars)"{-s,--stars=-}"[Only display with at least X stars]:stars:(0 10 100 1000)" \
|
||||
"($help -s --stars)"{-s,--stars=}"[Only display with at least X stars]:stars:(0 10 100 1000)" \
|
||||
"($help -):term: " && ret=0
|
||||
;;
|
||||
(start)
|
||||
@@ -895,12 +900,12 @@ _docker() {
|
||||
"(: -)"{-h,--help}"[Print usage]" \
|
||||
"($help)--config[Location of client config files]:path:_directories" \
|
||||
"($help -D --debug)"{-D,--debug}"[Enable debug mode]" \
|
||||
"($help -H --host)"{-H,--host=-}"[tcp://host:port to bind/connect to]:host: " \
|
||||
"($help -l --log-level)"{-l,--log-level=-}"[Set the logging level]:level:(debug info warn error fatal)" \
|
||||
"($help -H --host)"{-H,--host=}"[tcp://host:port to bind/connect to]:host: " \
|
||||
"($help -l --log-level)"{-l,--log-level=}"[Set the logging level]:level:(debug info warn error fatal)" \
|
||||
"($help)--tls[Use TLS]" \
|
||||
"($help)--tlscacert=-[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlscert=-[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlskey=-[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
|
||||
"($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlskey=[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
|
||||
"($help)--tlsverify[Use TLS and verify the remote]" \
|
||||
"($help)--userland-proxy[Use userland proxy for loopback traffic]" \
|
||||
"($help -v --version)"{-v,--version}"[Print version information and quit]" \
|
||||
|
||||
@@ -324,24 +324,20 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||
|
||||
c.ContainerPid = pid
|
||||
|
||||
oomKill := false
|
||||
oomKillNotification, err := notifyOnOOM(cgroupPaths)
|
||||
|
||||
if hooks.Start != nil {
|
||||
logrus.Debugf("Invoking startCallback")
|
||||
hooks.Start(&c.ProcessConfig, pid, oomKillNotification)
|
||||
|
||||
chOOM := make(chan struct{})
|
||||
close(chOOM)
|
||||
hooks.Start(&c.ProcessConfig, pid, chOOM)
|
||||
}
|
||||
|
||||
oomKillNotification := notifyChannelOOM(cgroupPaths)
|
||||
|
||||
<-waitLock
|
||||
exitCode := getExitCode(c)
|
||||
|
||||
if err == nil {
|
||||
_, oomKill = <-oomKillNotification
|
||||
logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr)
|
||||
} else {
|
||||
logrus.Warnf("Your kernel does not support OOM notifications: %s", err)
|
||||
}
|
||||
_, oomKill := <-oomKillNotification
|
||||
logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr)
|
||||
|
||||
// check oom error
|
||||
if oomKill {
|
||||
@@ -351,6 +347,17 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||
return execdriver.ExitStatus{ExitCode: exitCode, OOMKilled: oomKill}, waitErr
|
||||
}
|
||||
|
||||
func notifyChannelOOM(paths map[string]string) <-chan struct{} {
|
||||
oom, err := notifyOnOOM(paths)
|
||||
if err != nil {
|
||||
logrus.Warnf("Your kernel does not support OOM notifications: %s", err)
|
||||
c := make(chan struct{})
|
||||
close(c)
|
||||
return c
|
||||
}
|
||||
return oom
|
||||
}
|
||||
|
||||
// copy from libcontainer
|
||||
func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
|
||||
dir := paths["memory"]
|
||||
@@ -386,11 +393,13 @@ func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
|
||||
buf := make([]byte, 8)
|
||||
for {
|
||||
if _, err := eventfd.Read(buf); err != nil {
|
||||
logrus.Warn(err)
|
||||
return
|
||||
}
|
||||
// When a cgroup is destroyed, an event is sent to eventfd.
|
||||
// So if the control path is gone, return instead of notifying.
|
||||
if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) {
|
||||
logrus.Warn(err)
|
||||
return
|
||||
}
|
||||
ch <- struct{}{}
|
||||
@@ -424,6 +433,11 @@ func cgroupPaths(containerID string) (map[string]string, error) {
|
||||
//unsupported subystem
|
||||
continue
|
||||
}
|
||||
// if we are running dind
|
||||
dockerPathIdx := strings.LastIndex(cgroupDir, "docker")
|
||||
if dockerPathIdx != -1 {
|
||||
cgroupDir = cgroupDir[:dockerPathIdx-1]
|
||||
}
|
||||
path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerID)
|
||||
paths[subsystem] = path
|
||||
}
|
||||
|
||||
@@ -91,9 +91,9 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
|
||||
{{if .Resources}}
|
||||
{{if .Resources.Memory}}
|
||||
lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}}
|
||||
{{with $memSwap := getMemorySwap .Resources}}
|
||||
lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
|
||||
{{end}}
|
||||
{{if gt .Resources.MemorySwap 0}}
|
||||
lxc.cgroup.memory.memsw.limit_in_bytes = {{.Resources.MemorySwap}}
|
||||
{{end}}
|
||||
{{if gt .Resources.MemoryReservation 0}}
|
||||
lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.MemoryReservation}}
|
||||
@@ -209,15 +209,6 @@ func isDirectory(source string) string {
|
||||
return "file"
|
||||
}
|
||||
|
||||
func getMemorySwap(v *execdriver.Resources) int64 {
|
||||
// By default, MemorySwap is set to twice the size of RAM.
|
||||
// If you want to omit MemorySwap, set it to `-1'.
|
||||
if v.MemorySwap < 0 {
|
||||
return 0
|
||||
}
|
||||
return v.Memory * 2
|
||||
}
|
||||
|
||||
func getLabel(c map[string][]string, name string) string {
|
||||
label := c["label"]
|
||||
for _, l := range label {
|
||||
@@ -242,7 +233,6 @@ func getHostname(env []string) string {
|
||||
func init() {
|
||||
var err error
|
||||
funcMap := template.FuncMap{
|
||||
"getMemorySwap": getMemorySwap,
|
||||
"escapeFstabSpaces": escapeFstabSpaces,
|
||||
"formatMountLabel": label.FormatMountLabel,
|
||||
"isDirectory": isDirectory,
|
||||
|
||||
@@ -34,6 +34,7 @@ func TestLXCConfig(t *testing.T) {
|
||||
memMin = 33554432
|
||||
memMax = 536870912
|
||||
mem = memMin + r.Intn(memMax-memMin)
|
||||
swap = memMax
|
||||
cpuMin = 100
|
||||
cpuMax = 10000
|
||||
cpu = cpuMin + r.Intn(cpuMax-cpuMin)
|
||||
@@ -46,8 +47,9 @@ func TestLXCConfig(t *testing.T) {
|
||||
command := &execdriver.Command{
|
||||
ID: "1",
|
||||
Resources: &execdriver.Resources{
|
||||
Memory: int64(mem),
|
||||
CPUShares: int64(cpu),
|
||||
Memory: int64(mem),
|
||||
MemorySwap: int64(swap),
|
||||
CPUShares: int64(cpu),
|
||||
},
|
||||
Network: &execdriver.Network{
|
||||
Mtu: 1500,
|
||||
@@ -63,7 +65,7 @@ func TestLXCConfig(t *testing.T) {
|
||||
fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
|
||||
|
||||
grepFile(t, p,
|
||||
fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
|
||||
fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", swap))
|
||||
}
|
||||
|
||||
func TestCustomLxcConfig(t *testing.T) {
|
||||
|
||||
@@ -167,7 +167,6 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||
|
||||
oom := notifyOnOOM(cont)
|
||||
if hooks.Start != nil {
|
||||
|
||||
pid, err := p.Pid()
|
||||
if err != nil {
|
||||
p.Signal(os.Kill)
|
||||
|
||||
@@ -18,6 +18,7 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||
term execdriver.Terminal
|
||||
err error
|
||||
exitCode int32
|
||||
errno uint32
|
||||
)
|
||||
|
||||
active := d.activeContainers[c.ID]
|
||||
@@ -77,12 +78,15 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
|
||||
}
|
||||
|
||||
if exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid); err != nil {
|
||||
logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
|
||||
if exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite); err != nil {
|
||||
if errno == hcsshim.Win32PipeHasBeenEnded {
|
||||
logrus.Debugf("Exiting Run() after WaitForProcessInComputeSystem failed with recognised error 0x%X", errno)
|
||||
return hcsshim.WaitErrExecFailed, nil
|
||||
}
|
||||
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): 0x%X %s", errno, err)
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// TODO Windows - Do something with this exit code
|
||||
logrus.Debugln("Exiting Run() with ExitCode 0", c.ID)
|
||||
logrus.Debugln("Exiting Run()", c.ID)
|
||||
return int(exitCode), nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
@@ -22,7 +23,11 @@ func startStdinCopy(dst io.WriteCloser, src io.Reader) {
|
||||
go func() {
|
||||
defer dst.Close()
|
||||
bytes, err := io.Copy(dst, src)
|
||||
logrus.Debugf("Copied %d bytes from stdin err=%s", bytes, err)
|
||||
log := fmt.Sprintf("Copied %d bytes from stdin.", bytes)
|
||||
if err != nil {
|
||||
log = log + " err=" + err.Error()
|
||||
}
|
||||
logrus.Debugf(log)
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -35,7 +40,11 @@ func startStdouterrCopy(dst io.Writer, src io.ReadCloser, name string) {
|
||||
go func() {
|
||||
defer src.Close()
|
||||
bytes, err := io.Copy(dst, src)
|
||||
logrus.Debugf("Copied %d bytes from %s err=%s", bytes, name, err)
|
||||
log := fmt.Sprintf("Copied %d bytes from %s.", bytes, name)
|
||||
if err != nil {
|
||||
log = log + " err=" + err.Error()
|
||||
}
|
||||
logrus.Debugf(log)
|
||||
}()
|
||||
}
|
||||
|
||||
|
||||
@@ -220,22 +220,19 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||
}
|
||||
defer func() {
|
||||
// Stop the container
|
||||
|
||||
if terminateMode {
|
||||
logrus.Debugf("Terminating container %s", c.ID)
|
||||
if err := hcsshim.TerminateComputeSystem(c.ID); err != nil {
|
||||
// IMPORTANT: Don't fail if fails to change state. It could already
|
||||
// have been stopped through kill().
|
||||
// Otherwise, the docker daemon will hang in job wait()
|
||||
logrus.Warnf("Ignoring error from TerminateComputeSystem %s", err)
|
||||
if forceKill {
|
||||
logrus.Debugf("Forcibly terminating container %s", c.ID)
|
||||
if errno, err := hcsshim.TerminateComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
||||
logrus.Warnf("Ignoring error from TerminateComputeSystem 0x%X %s", errno, err)
|
||||
}
|
||||
} else {
|
||||
logrus.Debugf("Shutting down container %s", c.ID)
|
||||
if err := hcsshim.ShutdownComputeSystem(c.ID); err != nil {
|
||||
// IMPORTANT: Don't fail if fails to change state. It could already
|
||||
// have been stopped through kill().
|
||||
// Otherwise, the docker daemon will hang in job wait()
|
||||
logrus.Warnf("Ignoring error from ShutdownComputeSystem %s", err)
|
||||
if errno, err := hcsshim.ShutdownComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
||||
if errno != hcsshim.Win32SystemShutdownIsInProgress &&
|
||||
errno != hcsshim.Win32SpecifiedPathInvalid &&
|
||||
errno != hcsshim.Win32SystemCannotFindThePathSpecified {
|
||||
logrus.Warnf("Ignoring error from ShutdownComputeSystem 0x%X %s", errno, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -303,11 +300,20 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
|
||||
}
|
||||
|
||||
var exitCode int32
|
||||
exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid)
|
||||
var (
|
||||
exitCode int32
|
||||
errno uint32
|
||||
)
|
||||
exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite)
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
|
||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||
if errno != hcsshim.Win32PipeHasBeenEnded {
|
||||
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): %s", err)
|
||||
}
|
||||
// Do NOT return err here as the container would have
|
||||
// started, otherwise docker will deadlock. It's perfectly legitimate
|
||||
// for WaitForProcessInComputeSystem to fail in situations such
|
||||
// as the container being killed on another thread.
|
||||
return execdriver.ExitStatus{ExitCode: hcsshim.WaitErrExecFailed}, nil
|
||||
}
|
||||
|
||||
logrus.Debugf("Exiting Run() exitCode %d id=%s", exitCode, c.ID)
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
"github.com/microsoft/hcsshim"
|
||||
@@ -10,37 +13,36 @@ import (
|
||||
|
||||
// Terminate implements the exec driver Driver interface.
|
||||
func (d *Driver) Terminate(p *execdriver.Command) error {
|
||||
logrus.Debugf("WindowsExec: Terminate() id=%s", p.ID)
|
||||
return kill(p.ID, p.ContainerPid)
|
||||
return kill(p.ID, p.ContainerPid, syscall.SIGTERM)
|
||||
}
|
||||
|
||||
// Kill implements the exec driver Driver interface.
|
||||
func (d *Driver) Kill(p *execdriver.Command, sig int) error {
|
||||
logrus.Debugf("WindowsExec: Kill() id=%s sig=%d", p.ID, sig)
|
||||
return kill(p.ID, p.ContainerPid)
|
||||
return kill(p.ID, p.ContainerPid, syscall.Signal(sig))
|
||||
}
|
||||
|
||||
func kill(id string, pid int) error {
|
||||
logrus.Debugln("kill() ", id, pid)
|
||||
func kill(id string, pid int, sig syscall.Signal) error {
|
||||
logrus.Debugf("WindowsExec: kill() id=%s pid=%d sig=%d", id, pid, sig)
|
||||
var err error
|
||||
context := fmt.Sprintf("kill: sig=%d pid=%d", sig, pid)
|
||||
|
||||
// Terminate Process
|
||||
if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
|
||||
logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
|
||||
// Ignore errors
|
||||
err = nil
|
||||
}
|
||||
|
||||
if terminateMode {
|
||||
if sig == syscall.SIGKILL || forceKill {
|
||||
// Terminate the compute system
|
||||
if err = hcsshim.TerminateComputeSystem(id); err != nil {
|
||||
logrus.Errorf("Failed to terminate %s - %q", id, err)
|
||||
if errno, err := hcsshim.TerminateComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
|
||||
logrus.Errorf("Failed to terminate %s - 0x%X %q", id, errno, err)
|
||||
}
|
||||
|
||||
} else {
|
||||
// Terminate Process
|
||||
if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
|
||||
logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
|
||||
// Ignore errors
|
||||
err = nil
|
||||
}
|
||||
|
||||
// Shutdown the compute system
|
||||
if err = hcsshim.ShutdownComputeSystem(id); err != nil {
|
||||
logrus.Errorf("Failed to shutdown %s - %q", id, err)
|
||||
if errno, err := hcsshim.ShutdownComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
|
||||
logrus.Errorf("Failed to shutdown %s - 0x%X %q", id, errno, err)
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
var dummyMode bool
|
||||
|
||||
// This allows the daemon to terminate containers rather than shutdown
|
||||
var terminateMode bool
|
||||
// This allows the daemon to force kill (HCS terminate) rather than shutdown
|
||||
var forceKill bool
|
||||
|
||||
// Define name and version for windows
|
||||
var (
|
||||
@@ -62,11 +63,11 @@ func NewDriver(root, initPath string, options []string) (*Driver, error) {
|
||||
logrus.Warn("Using dummy mode in Windows exec driver. This is for development use only!")
|
||||
}
|
||||
|
||||
case "terminate":
|
||||
case "forcekill":
|
||||
switch val {
|
||||
case "1":
|
||||
terminateMode = true
|
||||
logrus.Warn("Using terminate mode in Windows exec driver. This is for testing purposes only.")
|
||||
forceKill = true
|
||||
logrus.Warn("Using force kill mode in Windows exec driver. This is for testing purposes only.")
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
+11
-1
@@ -1,6 +1,12 @@
|
||||
package daemon
|
||||
|
||||
import "syscall"
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
)
|
||||
|
||||
// ContainerKill send signal to the container
|
||||
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
||||
@@ -12,6 +18,10 @@ func (daemon *Daemon) ContainerKill(name string, sig uint64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if sig != 0 && !signal.ValidSignalForPlatform(syscall.Signal(sig)) {
|
||||
return fmt.Errorf("The %s daemon does not support signal %d", runtime.GOOS, sig)
|
||||
}
|
||||
|
||||
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
|
||||
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
||||
if err := container.Kill(); err != nil {
|
||||
|
||||
+22
-8
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api/types"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/graph"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/pkg/graphdb"
|
||||
"github.com/docker/docker/pkg/nat"
|
||||
@@ -285,6 +286,24 @@ func includeContainerInList(container *Container, ctx *listContext) iterationAct
|
||||
return includeContainer
|
||||
}
|
||||
|
||||
func getImage(s *graph.TagStore, img, imgID string) (string, error) {
|
||||
// both Image and ImageID is actually ids, nothing to guess
|
||||
if strings.HasPrefix(imgID, img) {
|
||||
return img, nil
|
||||
}
|
||||
id, err := s.GetID(img)
|
||||
if err != nil {
|
||||
if err == graph.ErrNameIsNotExist {
|
||||
return imgID, nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
if id != imgID {
|
||||
return imgID, nil
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// transformContainer generates the container type expected by the docker ps command.
|
||||
func (daemon *Daemon) transformContainer(container *Container, ctx *listContext) (*types.Container, error) {
|
||||
newC := &types.Container{
|
||||
@@ -297,16 +316,11 @@ func (daemon *Daemon) transformContainer(container *Container, ctx *listContext)
|
||||
newC.Names = []string{}
|
||||
}
|
||||
|
||||
img, err := daemon.repositories.LookupImage(container.Config.Image)
|
||||
showImg, err := getImage(daemon.repositories, container.Config.Image, container.ImageID)
|
||||
if err != nil {
|
||||
// If the image can no longer be found by its original reference,
|
||||
// it makes sense to show the ID instead of a stale reference.
|
||||
newC.Image = container.ImageID
|
||||
} else if container.ImageID == img.ID {
|
||||
newC.Image = container.Config.Image
|
||||
} else {
|
||||
newC.Image = container.ImageID
|
||||
return nil, err
|
||||
}
|
||||
newC.Image = showImg
|
||||
|
||||
if len(container.Args) > 0 {
|
||||
args := []string{}
|
||||
|
||||
+23
-1
@@ -80,7 +80,7 @@ func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
|
||||
}
|
||||
|
||||
// CreateNetwork creates a network with the given name, driver and other optional parameters
|
||||
func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM) (libnetwork.Network, error) {
|
||||
func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string) (libnetwork.Network, error) {
|
||||
c := daemon.netController
|
||||
if driver == "" {
|
||||
driver = c.Config().Daemon.DefaultDriver
|
||||
@@ -96,6 +96,7 @@ func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM) (lib
|
||||
if len(ipam.Config) > 0 {
|
||||
nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf))
|
||||
}
|
||||
nwOptions = append(nwOptions, libnetwork.NetworkOptionDriverOpts(options))
|
||||
return c.NewNetwork(driver, name, nwOptions...)
|
||||
}
|
||||
|
||||
@@ -120,3 +121,24 @@ func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnet
|
||||
}
|
||||
return ipamV4Cfg, ipamV6Cfg, nil
|
||||
}
|
||||
|
||||
// ConnectContainerToNetwork connects the given container to the given
|
||||
// network. If either cannot be found, an err is returned. If the
|
||||
// network cannot be set up, an err is returned.
|
||||
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string) error {
|
||||
container, err := daemon.Get(containerName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return container.ConnectToNetwork(networkName)
|
||||
}
|
||||
|
||||
// DisconnectContainerFromNetwork disconnects the given container from
|
||||
// the given network. If either cannot be found, an err is returned.
|
||||
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network) error {
|
||||
container, err := daemon.Get(containerName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return container.DisconnectFromNetwork(network)
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ There are two ways to install Docker Engine. You can install with the `yum` pac
|
||||
|
||||
For Fedora 22 run:
|
||||
|
||||
$ cat >/etc/yum.repos.d/docker.repo <<-EOF
|
||||
$ cat >/etc/yum.repos.d/docker.repo <<-EOF
|
||||
[dockerrepo]
|
||||
name=Docker Repository
|
||||
baseurl=https://yum.dockerproject.org/repo/main/fedora/22
|
||||
@@ -74,7 +74,7 @@ There are two ways to install Docker Engine. You can install with the `yum` pac
|
||||
|
||||
5. Start the Docker daemon.
|
||||
|
||||
$ sudo service docker start
|
||||
$ sudo systemctl start docker
|
||||
|
||||
6. Verify `docker` is installed correctly by running a test image in a container.
|
||||
|
||||
@@ -123,13 +123,13 @@ There are two ways to install Docker Engine. You can install with the `yum` pac
|
||||
|
||||
4. Start the Docker daemon.
|
||||
|
||||
$ sudo service docker start
|
||||
$ sudo systemctl start docker
|
||||
|
||||
5. Verify `docker` is installed correctly by running a test image in a container.
|
||||
|
||||
$ sudo docker run hello-world
|
||||
|
||||
## Create a docker group
|
||||
## Create a docker group
|
||||
|
||||
The `docker` daemon binds to a Unix socket instead of a TCP port. By default
|
||||
that Unix socket is owned by the user `root` and other users can access it with
|
||||
@@ -163,7 +163,7 @@ To create the `docker` group and add your user:
|
||||
|
||||
To ensure Docker starts when you boot your system, do the following:
|
||||
|
||||
$ sudo chkconfig docker on
|
||||
$ sudo systemctl enable docker
|
||||
|
||||
If you need to add an HTTP Proxy, set a different directory or partition for the
|
||||
Docker runtime files, or make other customizations, read our Systemd article to
|
||||
@@ -190,7 +190,7 @@ This configuration allows IP forwarding from the container as expected.
|
||||
|
||||
## Uninstall
|
||||
|
||||
You can uninstall the Docker software with `yum`.
|
||||
You can uninstall the Docker software with `yum`.
|
||||
|
||||
1. List the package you have installed.
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ The following short variant options are deprecated in favor of their long
|
||||
variants:
|
||||
|
||||
docker run -c (--cpu-shares)
|
||||
docker build -c (--cpu-shares)
|
||||
docker create -c (--cpu-shares)
|
||||
|
||||
### Driver Specific Log Tags
|
||||
**Deprecated In Release: v1.9**
|
||||
|
||||
@@ -23,14 +23,15 @@ client must have `root` access to interact with the daemon. If a group named
|
||||
`docker` exists on your system, `docker` applies ownership of the socket to the
|
||||
group.
|
||||
|
||||
The current version of the API is v1.21 which means calling `/info` is the same
|
||||
as calling `/v1.21/info`. To call an older version of the API use
|
||||
`/v1.20/info`.
|
||||
The current version of the API is v1.22 which means calling `/info` is the same
|
||||
as calling `/v1.22/info`. To call an older version of the API use
|
||||
`/v1.21/info`.
|
||||
|
||||
Use the table below to find the API version for a Docker version:
|
||||
|
||||
Docker version | API version | Changes
|
||||
----------------|-------------------------------------------------|-----------------------------
|
||||
1.10.x | [1.22](/reference/api/docker_remote_api_v1.22/) | [API changes](/reference/api/docker_remote_api/#v1-22-api-changes)
|
||||
1.9.x | [1.21](/reference/api/docker_remote_api_v1.21/) | [API changes](/reference/api/docker_remote_api/#v1-21-api-changes)
|
||||
1.8.x | [1.20](/reference/api/docker_remote_api_v1.20/) | [API changes](/reference/api/docker_remote_api/#v1-20-api-changes)
|
||||
1.7.x | [1.19](/reference/api/docker_remote_api_v1.19/) | [API changes](/reference/api/docker_remote_api/#v1-19-api-changes)
|
||||
@@ -89,6 +90,11 @@ Running `docker rmi` emits an **untag** event when removing an image name. The
|
||||
|
||||
This section lists each version from latest to oldest. Each listing includes a link to the full documentation set and the changes relevant in that release.
|
||||
|
||||
### v1.22 API changes
|
||||
|
||||
[Docker Remote API v1.22](docker_remote_api_v1.22.md) documentation
|
||||
|
||||
|
||||
### v1.21 API changes
|
||||
|
||||
[Docker Remote API v1.21](docker_remote_api_v1.21.md) documentation
|
||||
|
||||
@@ -1465,12 +1465,15 @@ a base64-encoded AuthConfig object.
|
||||
|
||||
Query Parameters:
|
||||
|
||||
- **fromImage** – Name of the image to pull.
|
||||
- **fromImage** – Name of the image to pull. The name may include a tag or
|
||||
digest. This parameter may only be used when pulling an image.
|
||||
- **fromSrc** – Source to import. The value may be a URL from which the image
|
||||
can be retrieved or `-` to read the image from the request body.
|
||||
- **repo** – Repository name.
|
||||
- **tag** – Tag.
|
||||
- **registry** – The registry to pull from.
|
||||
This parameter may only be used when importing an image.
|
||||
- **repo** – Repository name given to an image when it is imported.
|
||||
The repo may include a tag. This parameter may only be used when importing
|
||||
an image.
|
||||
- **tag** – Tag or digest.
|
||||
|
||||
Request Headers:
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ parent = "smn_cli"
|
||||
Build a new image from the source code at PATH
|
||||
|
||||
--build-arg=[] Set build-time variables
|
||||
-c, --cpu-shares CPU Shares (relative weight)
|
||||
--cpu-shares CPU Shares (relative weight)
|
||||
--cgroup-parent="" Optional parent cgroup for the container
|
||||
--cpu-period=0 Limit the CPU CFS (Completely Fair Scheduler) period
|
||||
--cpu-quota=0 Limit the CPU CFS (Completely Fair Scheduler) quota
|
||||
@@ -128,6 +128,8 @@ See also:
|
||||
|
||||
## Examples
|
||||
|
||||
### Build with PATH
|
||||
|
||||
$ docker build .
|
||||
Uploading context 10240 bytes
|
||||
Step 1 : FROM busybox
|
||||
@@ -168,6 +170,31 @@ The transfer of context from the local machine to the Docker daemon is what the
|
||||
If you wish to keep the intermediate containers after the build is complete,
|
||||
you must use `--rm=false`. This does not affect the build cache.
|
||||
|
||||
### Build with URL
|
||||
|
||||
$ docker build github.com/creack/docker-firefox
|
||||
|
||||
This will clone the GitHub repository and use the cloned repository as context.
|
||||
The Dockerfile at the root of the repository is used as Dockerfile. Note that
|
||||
you can specify an arbitrary Git repository by using the `git://` or `git@`
|
||||
schema.
|
||||
|
||||
### Build with -
|
||||
|
||||
$ docker build - < Dockerfile
|
||||
|
||||
This will read a Dockerfile from `STDIN` without context. Due to the lack of a
|
||||
context, no contents of any local directory will be sent to the Docker daemon.
|
||||
Since there is no context, a Dockerfile `ADD` only works if it refers to a
|
||||
remote URL.
|
||||
|
||||
$ docker build - < context.tar.gz
|
||||
|
||||
This will build an image for a compressed context read from `STDIN`. Supported
|
||||
formats are: bzip2, gzip and xz.
|
||||
|
||||
### Usage of .dockerignore
|
||||
|
||||
$ docker build .
|
||||
Uploading context 18.829 MB
|
||||
Uploading context
|
||||
@@ -193,29 +220,14 @@ directory from the context. Its effect can be seen in the changed size of the
|
||||
uploaded context. The builder reference contains detailed information on
|
||||
[creating a .dockerignore file](../builder.md#dockerignore-file)
|
||||
|
||||
### Tag image (-t)
|
||||
|
||||
$ docker build -t vieux/apache:2.0 .
|
||||
|
||||
This will build like the previous example, but it will then tag the resulting
|
||||
image. The repository name will be `vieux/apache` and the tag will be `2.0`
|
||||
|
||||
$ docker build - < Dockerfile
|
||||
|
||||
This will read a Dockerfile from `STDIN` without context. Due to the lack of a
|
||||
context, no contents of any local directory will be sent to the Docker daemon.
|
||||
Since there is no context, a Dockerfile `ADD` only works if it refers to a
|
||||
remote URL.
|
||||
|
||||
$ docker build - < context.tar.gz
|
||||
|
||||
This will build an image for a compressed context read from `STDIN`. Supported
|
||||
formats are: bzip2, gzip and xz.
|
||||
|
||||
$ docker build github.com/creack/docker-firefox
|
||||
|
||||
This will clone the GitHub repository and use the cloned repository as context.
|
||||
The Dockerfile at the root of the repository is used as Dockerfile. Note that
|
||||
you can specify an arbitrary Git repository by using the `git://` or `git@`
|
||||
schema.
|
||||
### Specify Dockerfile (-f)
|
||||
|
||||
$ docker build -f Dockerfile.debug .
|
||||
|
||||
@@ -248,14 +260,20 @@ the command line.
|
||||
> repeatable builds on remote Docker hosts. This is also the reason why
|
||||
> `ADD ../file` will not work.
|
||||
|
||||
### Optional parent cgroup (--cgroup-parent)
|
||||
|
||||
When `docker build` is run with the `--cgroup-parent` option the containers
|
||||
used in the build will be run with the [corresponding `docker run`
|
||||
flag](../run.md#specifying-custom-cgroups).
|
||||
|
||||
### Set ulimits in container (--ulimit)
|
||||
|
||||
Using the `--ulimit` option with `docker build` will cause each build step's
|
||||
container to be started using those [`--ulimit`
|
||||
flag values](../run.md#setting-ulimits-in-a-container).
|
||||
|
||||
### Set build-time variables (--build-arg)
|
||||
|
||||
You can use `ENV` instructions in a Dockerfile to define variable
|
||||
values. These values persist in the built image. However, often
|
||||
persistence is not what you want. Users want to specify variables differently
|
||||
@@ -263,7 +281,7 @@ depending on which host they build an image on.
|
||||
|
||||
A good example is `http_proxy` or source versions for pulling intermediate
|
||||
files. The `ARG` instruction lets Dockerfile authors define values that users
|
||||
can set at build-time using the `---build-arg` flag:
|
||||
can set at build-time using the `--build-arg` flag:
|
||||
|
||||
$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ To list the help on any command just execute the command, followed by the
|
||||
Run a command in a new container
|
||||
|
||||
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
|
||||
-c, --cpu-shares=0 CPU shares (relative weight)
|
||||
--cpu-shares=0 CPU shares (relative weight)
|
||||
...
|
||||
|
||||
## Option types
|
||||
|
||||
@@ -19,7 +19,7 @@ Creates a new container.
|
||||
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
|
||||
--add-host=[] Add a custom host-to-IP mapping (host:ip)
|
||||
--blkio-weight=0 Block IO weight (relative weight)
|
||||
-c, --cpu-shares=0 CPU shares (relative weight)
|
||||
--cpu-shares=0 CPU shares (relative weight)
|
||||
--cap-add=[] Add Linux capabilities
|
||||
--cap-drop=[] Drop Linux capabilities
|
||||
--cgroup-parent="" Optional parent cgroup for the container
|
||||
|
||||
@@ -205,9 +205,10 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
Example use:
|
||||
|
||||
docker daemon --storage-opt dm.thinpooldev=/dev/mapper/thin-pool
|
||||
$ docker daemon \
|
||||
--storage-opt dm.thinpooldev=/dev/mapper/thin-pool
|
||||
|
||||
* `dm.basesize`
|
||||
* `dm.basesize`
|
||||
|
||||
Specifies the size to use when creating the base device, which limits the
|
||||
size of images and containers. The default value is 100G. Note, thin devices
|
||||
@@ -227,9 +228,11 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt dm.basesize=20G
|
||||
|
||||
* `dm.loopdatasize`
|
||||
* `dm.loopdatasize`
|
||||
|
||||
>**Note**: This option configures devicemapper loopback, which should not be used in production.
|
||||
> **Note**:
|
||||
> This option configures devicemapper loopback, which should not
|
||||
> be used in production.
|
||||
|
||||
Specifies the size to use when creating the loopback file for the
|
||||
"data" device which is used for the thin pool. The default size is
|
||||
@@ -240,9 +243,11 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt dm.loopdatasize=200G
|
||||
|
||||
* `dm.loopmetadatasize`
|
||||
* `dm.loopmetadatasize`
|
||||
|
||||
>**Note**: This option configures devicemapper loopback, which should not be used in production.
|
||||
> **Note**:
|
||||
> This option configures devicemapper loopback, which should not
|
||||
> be used in production.
|
||||
|
||||
Specifies the size to use when creating the loopback file for the
|
||||
"metadata" device which is used for the thin pool. The default size
|
||||
@@ -253,7 +258,7 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt dm.loopmetadatasize=4G
|
||||
|
||||
* `dm.fs`
|
||||
* `dm.fs`
|
||||
|
||||
Specifies the filesystem type to use for the base device. The supported
|
||||
options are "ext4" and "xfs". The default is "ext4"
|
||||
@@ -262,7 +267,7 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt dm.fs=xfs
|
||||
|
||||
* `dm.mkfsarg`
|
||||
* `dm.mkfsarg`
|
||||
|
||||
Specifies extra mkfs arguments to be used when creating the base device.
|
||||
|
||||
@@ -270,7 +275,7 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt "dm.mkfsarg=-O ^has_journal"
|
||||
|
||||
* `dm.mountopt`
|
||||
* `dm.mountopt`
|
||||
|
||||
Specifies extra mount options used when mounting the thin devices.
|
||||
|
||||
@@ -278,7 +283,7 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt dm.mountopt=nodiscard
|
||||
|
||||
* `dm.datadev`
|
||||
* `dm.datadev`
|
||||
|
||||
(Deprecated, use `dm.thinpooldev`)
|
||||
|
||||
@@ -290,9 +295,11 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
Example use:
|
||||
|
||||
$ docker daemon --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1
|
||||
$ docker daemon \
|
||||
--storage-opt dm.datadev=/dev/sdb1 \
|
||||
--storage-opt dm.metadatadev=/dev/sdc1
|
||||
|
||||
* `dm.metadatadev`
|
||||
* `dm.metadatadev`
|
||||
|
||||
(Deprecated, use `dm.thinpooldev`)
|
||||
|
||||
@@ -304,13 +311,15 @@ options for `zfs` start with `zfs`.
|
||||
If setting up a new metadata pool it is required to be valid. This can be
|
||||
achieved by zeroing the first 4k to indicate empty metadata, like this:
|
||||
|
||||
$ dd if=/dev/zero of=$metadata_dev bs=4096 count=1
|
||||
$ dd if=/dev/zero of=$metadata_dev bs=4096 count=1
|
||||
|
||||
Example use:
|
||||
|
||||
$ docker daemon --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1
|
||||
$ docker daemon \
|
||||
--storage-opt dm.datadev=/dev/sdb1 \
|
||||
--storage-opt dm.metadatadev=/dev/sdc1
|
||||
|
||||
* `dm.blocksize`
|
||||
* `dm.blocksize`
|
||||
|
||||
Specifies a custom blocksize to use for the thin pool. The default
|
||||
blocksize is 64K.
|
||||
@@ -319,7 +328,7 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt dm.blocksize=512K
|
||||
|
||||
* `dm.blkdiscard`
|
||||
* `dm.blkdiscard`
|
||||
|
||||
Enables or disables the use of blkdiscard when removing devicemapper
|
||||
devices. This is enabled by default (only) if using loopback devices and is
|
||||
@@ -333,7 +342,7 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
$ docker daemon --storage-opt dm.blkdiscard=false
|
||||
|
||||
* `dm.override_udev_sync_check`
|
||||
* `dm.override_udev_sync_check`
|
||||
|
||||
Overrides the `udev` synchronization checks between `devicemapper` and `udev`.
|
||||
`udev` is the device manager for the Linux kernel.
|
||||
@@ -369,7 +378,7 @@ options for `zfs` start with `zfs`.
|
||||
> Otherwise, set this flag for migrating existing Docker daemons to
|
||||
> a daemon with a supported environment.
|
||||
|
||||
* `dm.use_deferred_removal`
|
||||
* `dm.use_deferred_removal`
|
||||
|
||||
Enables use of deferred device removal if `libdm` and the kernel driver
|
||||
support the mechanism.
|
||||
@@ -385,21 +394,25 @@ options for `zfs` start with `zfs`.
|
||||
system to schedule the device for deferred removal. It does not wait in a
|
||||
loop trying to remove a busy device.
|
||||
|
||||
Example use: `docker daemon --storage-opt dm.use_deferred_removal=true`
|
||||
Example use:
|
||||
|
||||
* `dm.use_deferred_deletion`
|
||||
$ docker daemon --storage-opt dm.use_deferred_removal=true
|
||||
|
||||
* `dm.use_deferred_deletion`
|
||||
|
||||
Enables use of deferred device deletion for thin pool devices. By default,
|
||||
thin pool device deletion is synchronous. Before a container is deleted,
|
||||
the Docker daemon removes any associated devices. If the storage driver
|
||||
can not remove a device, the container deletion fails and daemon returns.
|
||||
|
||||
`Error deleting container: Error response from daemon: Cannot destroy container`
|
||||
Error deleting container: Error response from daemon: Cannot destroy container
|
||||
|
||||
To avoid this failure, enable both deferred device deletion and deferred
|
||||
device removal on the daemon.
|
||||
|
||||
`docker daemon --storage-opt dm.use_deferred_deletion=true --storage-opt dm.use_deferred_removal=true`
|
||||
$ docker daemon \
|
||||
--storage-opt dm.use_deferred_deletion=true \
|
||||
--storage-opt dm.use_deferred_removal=true
|
||||
|
||||
With these two options enabled, if a device is busy when the driver is
|
||||
deleting a container, the driver marks the device as deleted. Later, when
|
||||
@@ -411,7 +424,7 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
Currently supported options of `zfs`:
|
||||
|
||||
* `zfs.fsname`
|
||||
* `zfs.fsname`
|
||||
|
||||
Set zfs filesystem under which docker will create its own datasets.
|
||||
By default docker will pick up the zfs filesystem where docker graph
|
||||
|
||||
@@ -22,7 +22,7 @@ For example:
|
||||
$ docker -D info
|
||||
Containers: 14
|
||||
Images: 52
|
||||
Engine Version: 1.9.0
|
||||
Server Version: 1.9.0
|
||||
Storage Driver: aufs
|
||||
Root Dir: /var/lib/docker/aufs
|
||||
Backing Filesystem: extfs
|
||||
|
||||
@@ -14,8 +14,6 @@ parent = "smn_cli"
|
||||
|
||||
Lists all the networks created by the user
|
||||
--help=false Print usage
|
||||
-l, --latest=false Show the latest network created
|
||||
-n=-1 Show n last created networks
|
||||
--no-trunc=false Do not truncate the output
|
||||
-q, --quiet=false Only display numeric IDs
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ parent = "smn_cli"
|
||||
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
|
||||
--add-host=[] Add a custom host-to-IP mapping (host:ip)
|
||||
--blkio-weight=0 Block IO weight (relative weight)
|
||||
-c, --cpu-shares=0 CPU shares (relative weight)
|
||||
--cpu-shares=0 CPU shares (relative weight)
|
||||
--cap-add=[] Add Linux capabilities
|
||||
--cap-drop=[] Drop Linux capabilities
|
||||
--cgroup-parent="" Optional parent cgroup for the container
|
||||
@@ -92,6 +92,8 @@ and linking containers.
|
||||
|
||||
## Examples
|
||||
|
||||
### Assign name and allocate psuedo-TTY (--name, -it)
|
||||
|
||||
$ docker run --name test -it debian
|
||||
root@d6c0fe130dba:/# exit 13
|
||||
$ echo $?
|
||||
@@ -106,6 +108,8 @@ In the example, the `bash` shell is quit by entering
|
||||
`exit 13`. This exit code is passed on to the caller of
|
||||
`docker run`, and is recorded in the `test` container's metadata.
|
||||
|
||||
### Capture container ID (--cidfile)
|
||||
|
||||
$ docker run --cidfile /tmp/docker_test.cid ubuntu echo "test"
|
||||
|
||||
This will create a container and print `test` to the console. The `cidfile`
|
||||
@@ -113,6 +117,8 @@ flag makes Docker attempt to create a new file and write the container ID to it.
|
||||
If the file exists already, Docker will return an error. Docker will close this
|
||||
file when `docker run` exits.
|
||||
|
||||
### Full container capabilities (--privileged)
|
||||
|
||||
$ docker run -t -i --rm ubuntu bash
|
||||
root@bc338942ef20:/# mount -t tmpfs none /mnt
|
||||
mount: permission denied
|
||||
@@ -132,11 +138,15 @@ lifts all the limitations enforced by the `device` cgroup controller. In other
|
||||
words, the container can then do almost everything that the host can do. This
|
||||
flag exists to allow special use-cases, like running Docker within Docker.
|
||||
|
||||
### Set working directory (-w)
|
||||
|
||||
$ docker run -w /path/to/dir/ -i -t ubuntu pwd
|
||||
|
||||
The `-w` lets the command being executed inside directory given, here
|
||||
`/path/to/dir/`. If the path does not exists it is created inside the container.
|
||||
|
||||
### Mount volume (-v, --read-only)
|
||||
|
||||
$ docker run -v `pwd`:`pwd` -w `pwd` -i -t ubuntu pwd
|
||||
|
||||
The `-v` flag mounts the current working directory into the container. The `-w`
|
||||
@@ -166,6 +176,8 @@ binary (such as that provided by [https://get.docker.com](
|
||||
https://get.docker.com)), you give the container the full access to create and
|
||||
manipulate the host's Docker daemon.
|
||||
|
||||
### Publish or expose port (-p, --expose)
|
||||
|
||||
$ docker run -p 127.0.0.1:80:8080 ubuntu bash
|
||||
|
||||
This binds port `8080` of the container to port `80` on `127.0.0.1` of
|
||||
@@ -179,6 +191,8 @@ publishing the port to the host system's interfaces. The [Docker User
|
||||
Guide](../../userguide/dockerlinks.md) explains in detail how to manipulate
|
||||
ports in Docker.
|
||||
|
||||
### Set environment variables (-e, --env, --env-file)
|
||||
|
||||
$ docker run -e MYVAR1 --env MYVAR2=foo --env-file ./env.list ubuntu bash
|
||||
|
||||
This sets environmental variables in the container. For illustration all three
|
||||
@@ -247,7 +261,9 @@ An example of a file passed with `--env-file`
|
||||
123qwe=bar
|
||||
org.spring.config=something
|
||||
|
||||
A label is a a `key=value` pair that applies metadata to a container. To label a container with two labels:
|
||||
### Set metadata on container (-l, --label, --label-file)
|
||||
|
||||
A label is a `key=value` pair that applies metadata to a container. To label a container with two labels:
|
||||
|
||||
$ docker run -l my-label --label com.example.foo=bar ubuntu bash
|
||||
|
||||
@@ -281,6 +297,8 @@ For additional information on working with labels, see [*Labels - custom
|
||||
metadata in Docker*](../../userguide/labels-custom-metadata.md) in the Docker User
|
||||
Guide.
|
||||
|
||||
### Add link to another container (--link)
|
||||
|
||||
$ docker run --link /redis:redis --name console ubuntu bash
|
||||
|
||||
The `--link` flag will link the container named `/redis` into the newly
|
||||
@@ -295,6 +313,8 @@ example as:
|
||||
The `--name` flag will assign the name `console` to the newly created
|
||||
container.
|
||||
|
||||
### Mount volumes from container (--volumes-from)
|
||||
|
||||
$ docker run --volumes-from 777f7dc92da7 --volumes-from ba8c0c54f0f2:ro -i -t ubuntu pwd
|
||||
|
||||
The `--volumes-from` flag mounts all the defined volumes from the referenced
|
||||
@@ -317,6 +337,8 @@ content label. Shared volume labels allow all containers to read/write content.
|
||||
The `Z` option tells Docker to label the content with a private unshared label.
|
||||
Only the current container can use a private volume.
|
||||
|
||||
### Attach to STDIN/STDOUT/STDERR (-a)
|
||||
|
||||
The `-a` flag tells `docker run` to bind to the container's `STDIN`, `STDOUT`
|
||||
or `STDERR`. This makes it possible to manipulate the output and input as
|
||||
needed.
|
||||
@@ -340,6 +362,8 @@ logs could be retrieved using `docker logs`. This is
|
||||
useful if you need to pipe a file or something else into a container and
|
||||
retrieve the container's ID once the container has finished running.
|
||||
|
||||
### Add host device to container (--device)
|
||||
|
||||
$ docker run --device=/dev/sdc:/dev/xvdc --device=/dev/sdd --device=/dev/zero:/dev/nulo -i -t ubuntu ls -l /dev/{xvdc,sdd,nulo}
|
||||
brw-rw---- 1 root disk 8, 2 Feb 9 16:05 /dev/xvdc
|
||||
brw-rw---- 1 root disk 8, 3 Feb 9 16:05 /dev/sdd
|
||||
@@ -375,38 +399,7 @@ flag:
|
||||
> that may be removed should not be added to untrusted containers with
|
||||
> `--device`.
|
||||
|
||||
**A complete example:**
|
||||
|
||||
$ docker run -d --name static static-web-files sh
|
||||
$ docker run -d --expose=8098 --name riak riakserver
|
||||
$ docker run -d -m 100m -e DEVELOPMENT=1 -e BRANCH=example-code -v $(pwd):/app/bin:ro --name app appserver
|
||||
$ docker run -d -p 1443:443 --dns=10.0.0.1 --dns-search=dev.org -v /var/log/httpd --volumes-from static --link riak --link app -h www.sven.dev.org --name web webserver
|
||||
$ docker run -t -i --rm --volumes-from web -w /var/log/httpd busybox tail -f access.log
|
||||
|
||||
This example shows five containers that might be set up to test a web
|
||||
application change:
|
||||
|
||||
1. Start a pre-prepared volume image `static-web-files` (in the background)
|
||||
that has CSS, image and static HTML in it, (with a `VOLUME` instruction in
|
||||
the Dockerfile to allow the web server to use those files);
|
||||
2. Start a pre-prepared `riakserver` image, give the container name `riak` and
|
||||
expose port `8098` to any containers that link to it;
|
||||
3. Start the `appserver` image, restricting its memory usage to 100MB, setting
|
||||
two environment variables `DEVELOPMENT` and `BRANCH` and bind-mounting the
|
||||
current directory (`$(pwd)`) in the container in read-only mode as `/app/bin`;
|
||||
4. Start the `webserver`, mapping port `443` in the container to port `1443` on
|
||||
the Docker server, setting the DNS server to `10.0.0.1` and DNS search
|
||||
domain to `dev.org`, creating a volume to put the log files into (so we can
|
||||
access it from another container), then importing the files from the volume
|
||||
exposed by the `static` container, and linking to all exposed ports from
|
||||
`riak` and `app`. Lastly, we set the hostname to `web.sven.dev.org` so its
|
||||
consistent with the pre-generated SSL certificate;
|
||||
5. Finally, we create a container that runs `tail -f access.log` using the logs
|
||||
volume from the `web` container, setting the workdir to `/var/log/httpd`. The
|
||||
`--rm` option means that when the container exits, the container's layer is
|
||||
removed.
|
||||
|
||||
## Restart policies
|
||||
### Restart policies (--restart)
|
||||
|
||||
Use Docker's `--restart` to specify a container's *restart policy*. A restart
|
||||
policy controls whether the Docker daemon restarts a container after exit.
|
||||
@@ -468,7 +461,7 @@ More detailed information on restart policies can be found in the
|
||||
[Restart Policies (--restart)](../run.md#restart-policies-restart)
|
||||
section of the Docker run reference page.
|
||||
|
||||
## Adding entries to a container hosts file
|
||||
### Add entries to container hosts file (--add-host)
|
||||
|
||||
You can add other hosts into a container's `/etc/hosts` file by using one or
|
||||
more `--add-host` flags. This example adds a static address for a host named
|
||||
@@ -499,7 +492,7 @@ For IPv6 use the `-6` flag instead of the `-4` flag. For other network
|
||||
devices, replace `eth0` with the correct device name (for example `docker0`
|
||||
for the bridge device).
|
||||
|
||||
### Setting ulimits in a container
|
||||
### Set ulimits in container (--ulimit)
|
||||
|
||||
Since setting `ulimit` settings in a container requires extra privileges not
|
||||
available in the default container, you can set these using the `--ulimit` flag.
|
||||
@@ -519,13 +512,12 @@ available in the default container, you can set these using the `--ulimit` flag.
|
||||
The values are sent to the appropriate `syscall` as they are set.
|
||||
Docker doesn't perform any byte conversion. Take this into account when setting the values.
|
||||
|
||||
#### For `nproc` usage:
|
||||
#### For `nproc` usage
|
||||
|
||||
Be careful setting `nproc` with the `ulimit` flag as `nproc` is designed by Linux to set the
|
||||
maximum number of processes available to a user, not to a container. For example, start four
|
||||
containers with `daemon` user:
|
||||
|
||||
|
||||
docker run -d -u daemon --ulimit nproc=3 busybox top
|
||||
docker run -d -u daemon --ulimit nproc=3 busybox top
|
||||
docker run -d -u daemon --ulimit nproc=3 busybox top
|
||||
@@ -535,8 +527,39 @@ The 4th container fails and reports "[8] System error: resource temporarily unav
|
||||
This fails because the caller set `nproc=3` resulting in the first three containers using up
|
||||
the three processes quota set for the `daemon` user.
|
||||
|
||||
### Stopping a container with a specific signal
|
||||
### Stop container with signal (--stop-signal)
|
||||
|
||||
The `--stop-signal` flag sets the system call signal that will be sent to the container to exit.
|
||||
This signal can be a valid unsigned number that matches a position in the kernel's syscall table, for instance 9,
|
||||
or a signal name in the format SIGNAME, for instance SIGKILL.
|
||||
|
||||
### A complete example
|
||||
|
||||
$ docker run -d --name static static-web-files sh
|
||||
$ docker run -d --expose=8098 --name riak riakserver
|
||||
$ docker run -d -m 100m -e DEVELOPMENT=1 -e BRANCH=example-code -v $(pwd):/app/bin:ro --name app appserver
|
||||
$ docker run -d -p 1443:443 --dns=10.0.0.1 --dns-search=dev.org -v /var/log/httpd --volumes-from static --link riak --link app -h www.sven.dev.org --name web webserver
|
||||
$ docker run -t -i --rm --volumes-from web -w /var/log/httpd busybox tail -f access.log
|
||||
|
||||
This example shows five containers that might be set up to test a web
|
||||
application change:
|
||||
|
||||
1. Start a pre-prepared volume image `static-web-files` (in the background)
|
||||
that has CSS, image and static HTML in it, (with a `VOLUME` instruction in
|
||||
the Dockerfile to allow the web server to use those files);
|
||||
2. Start a pre-prepared `riakserver` image, give the container name `riak` and
|
||||
expose port `8098` to any containers that link to it;
|
||||
3. Start the `appserver` image, restricting its memory usage to 100MB, setting
|
||||
two environment variables `DEVELOPMENT` and `BRANCH` and bind-mounting the
|
||||
current directory (`$(pwd)`) in the container in read-only mode as `/app/bin`;
|
||||
4. Start the `webserver`, mapping port `443` in the container to port `1443` on
|
||||
the Docker server, setting the DNS server to `10.0.0.1` and DNS search
|
||||
domain to `dev.org`, creating a volume to put the log files into (so we can
|
||||
access it from another container), then importing the files from the volume
|
||||
exposed by the `static` container, and linking to all exposed ports from
|
||||
`riak` and `app`. Lastly, we set the hostname to `web.sven.dev.org` so its
|
||||
consistent with the pre-generated SSL certificate;
|
||||
5. Finally, we create a container that runs `tail -f access.log` using the logs
|
||||
volume from the `web` container, setting the workdir to `/var/log/httpd`. The
|
||||
`--rm` option means that when the container exits, the container's layer is
|
||||
removed.
|
||||
|
||||
@@ -39,7 +39,7 @@ Then, run a container and specify values for the `labels` or `env`. For example
|
||||
|
||||
```
|
||||
docker run --label foo=bar -e fizz=buzz -d -P training/webapp python app.py
|
||||
````
|
||||
```
|
||||
|
||||
This adds additional fields to the log depending on the driver, e.g. for
|
||||
`json-file` that looks like:
|
||||
|
||||
@@ -59,11 +59,6 @@ This will create a new volume inside a container at `/webapp`.
|
||||
> You can also use the `VOLUME` instruction in a `Dockerfile` to add one or
|
||||
> more new volumes to any container created from that image.
|
||||
|
||||
Docker volumes default to mount in read-write mode, but you can also set it to be mounted read-only.
|
||||
|
||||
$ docker run -d -P --name web -v /opt/webapp:ro training/webapp python app.py
|
||||
|
||||
|
||||
### Locating a volume
|
||||
|
||||
You can locate the volume on the host by utilizing the 'docker inspect' command.
|
||||
|
||||
@@ -188,7 +188,7 @@ These labels appear as part of the `docker info` output for the daemon:
|
||||
$ docker -D info
|
||||
Containers: 12
|
||||
Images: 672
|
||||
Engine Version: 1.9.0
|
||||
Server Version: 1.9.0
|
||||
Storage Driver: aufs
|
||||
Root Dir: /var/lib/docker/aufs
|
||||
Backing Filesystem: extfs
|
||||
|
||||
+3
-1
@@ -51,8 +51,10 @@ func (s *TagStore) Images(filterArgs, filter string, all bool) ([]*types.Image,
|
||||
|
||||
if i, ok := imageFilters["dangling"]; ok {
|
||||
for _, value := range i {
|
||||
if strings.ToLower(value) == "true" {
|
||||
if v := strings.ToLower(value); v == "true" {
|
||||
filtTagged = false
|
||||
} else if v != "false" {
|
||||
return nil, fmt.Errorf("Invalid filter 'dangling=%s'", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ import (
|
||||
"github.com/docker/libtrust"
|
||||
)
|
||||
|
||||
// ErrNameIsNotExist returned when there is no image with requested name.
|
||||
var ErrNameIsNotExist = errors.New("image with specified name does not exist")
|
||||
|
||||
// TagStore manages repositories. It encompasses the Graph used for versioned
|
||||
// storage, as well as various services involved in pushing and pulling
|
||||
// repositories.
|
||||
@@ -164,6 +167,26 @@ func (store *TagStore) LookupImage(name string) (*image.Image, error) {
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// GetID returns ID for image name.
|
||||
func (store *TagStore) GetID(name string) (string, error) {
|
||||
repoName, ref := parsers.ParseRepositoryTag(name)
|
||||
if ref == "" {
|
||||
ref = tags.DefaultTag
|
||||
}
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
repoName = registry.NormalizeLocalName(repoName)
|
||||
repo, ok := store.Repositories[repoName]
|
||||
if !ok {
|
||||
return "", ErrNameIsNotExist
|
||||
}
|
||||
id, ok := repo[ref]
|
||||
if !ok {
|
||||
return "", ErrNameIsNotExist
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// ByID returns a reverse-lookup table of all the names which refer to each
|
||||
// image - e.g. {"43b5f19b10584": {"base:latest", "base:v1"}}
|
||||
func (store *TagStore) ByID() map[string][]string {
|
||||
|
||||
+62
-2
@@ -80,6 +80,16 @@ check_forked() {
|
||||
fi
|
||||
}
|
||||
|
||||
rpm_import_repository_key() {
|
||||
local key=$1; shift
|
||||
local tmpdir=$(mktemp -d)
|
||||
chmod 600 "$tmpdir"
|
||||
gpg --homedir "$tmpdir" --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"
|
||||
gpg --homedir "$tmpdir" --export --armor "$key" > "$tmpdir"/repo.key
|
||||
rpm --import "$tmpdir"/repo.key
|
||||
rm -rf "$tmpdir"
|
||||
}
|
||||
|
||||
do_install() {
|
||||
case "$(uname -m)" in
|
||||
*64)
|
||||
@@ -231,10 +241,60 @@ do_install() {
|
||||
exit 0
|
||||
;;
|
||||
|
||||
'opensuse project'|opensuse|'suse linux'|sle[sd])
|
||||
'opensuse project'|opensuse)
|
||||
echo 'Going to perform the following operations:'
|
||||
if [ "$repo" != 'main' ]; then
|
||||
echo ' * add repository obs://Virtualization:containers'
|
||||
fi
|
||||
echo ' * install Docker'
|
||||
$sh_c 'echo "Press CTRL-C to abort"; sleep 3'
|
||||
|
||||
if [ "$repo" != 'main' ]; then
|
||||
# install experimental packages from OBS://Virtualization:containers
|
||||
(
|
||||
set -x
|
||||
zypper -n ar -f obs://Virtualization:containers Virtualization:containers
|
||||
rpm_import_repository_key 55A0B34D49501BB7CA474F5AA193FBB572174FC2
|
||||
)
|
||||
fi
|
||||
(
|
||||
set -x
|
||||
$sh_c 'sleep 3; zypper -n install docker'
|
||||
zypper -n install docker
|
||||
)
|
||||
echo_docker_as_nonroot
|
||||
exit 0
|
||||
;;
|
||||
'suse linux'|sle[sd])
|
||||
echo 'Going to perform the following operations:'
|
||||
if [ "$repo" != 'main' ]; then
|
||||
echo ' * add repository obs://Virtualization:containers'
|
||||
echo ' * install experimental Docker using packages NOT supported by SUSE'
|
||||
else
|
||||
echo ' * add the "Containers" module'
|
||||
echo ' * install Docker using packages supported by SUSE'
|
||||
fi
|
||||
$sh_c 'echo "Press CTRL-C to abort"; sleep 3'
|
||||
|
||||
if [ "$repo" != 'main' ]; then
|
||||
# install experimental packages from OBS://Virtualization:containers
|
||||
echo >&2 'Warning: installing experimental packages from OBS, these packages are NOT supported by SUSE'
|
||||
(
|
||||
set -x
|
||||
zypper -n ar -f obs://Virtualization:containers/SLE_12 Virtualization:containers
|
||||
rpm_import_repository_key 55A0B34D49501BB7CA474F5AA193FBB572174FC2
|
||||
)
|
||||
else
|
||||
# Add the containers module
|
||||
# Note well-1: the SLE machine must already be registered against SUSE Customer Center
|
||||
# Note well-2: the `-r ""` is required to workaround a known issue of SUSEConnect
|
||||
(
|
||||
set -x
|
||||
SUSEConnect -p sle-module-containers/12/x86_64 -r ""
|
||||
)
|
||||
fi
|
||||
(
|
||||
set -x
|
||||
zypper -n install docker
|
||||
)
|
||||
echo_docker_as_nonroot
|
||||
exit 0
|
||||
|
||||
+15
-1
@@ -46,6 +46,20 @@ set -e
|
||||
./man/md2man-all.sh -q || true
|
||||
# TODO decide if it's worth getting go-md2man in _each_ builder environment to avoid this
|
||||
|
||||
# Convert the CHANGELOG.md file into RPM changelog format
|
||||
VERSION_REGEX="^\W\W (.*) \((.*)\)$"
|
||||
ENTRY_REGEX="^[-+*] (.*)$"
|
||||
while read -r line || [[ -n "$line" ]]; do
|
||||
if [ -z "$line" ]; then continue; fi
|
||||
if [[ "$line" =~ $VERSION_REGEX ]]; then
|
||||
echo >> contrib/builder/rpm/changelog
|
||||
echo "* `date -d ${BASH_REMATCH[2]} '+%a %b %d %Y'` ${rpmPackager} - ${BASH_REMATCH[1]}" >> contrib/builder/rpm/changelog
|
||||
fi
|
||||
if [[ "$line" =~ $ENTRY_REGEX ]]; then
|
||||
echo "- ${BASH_REMATCH[1]//\`}" >> contrib/builder/rpm/changelog
|
||||
fi
|
||||
done < CHANGELOG.md
|
||||
|
||||
# TODO add a configurable knob for _which_ rpms to build so we don't have to modify the file or build all of them every time we need to test
|
||||
for dir in contrib/builder/rpm/*/; do
|
||||
version="$(basename "$dir")"
|
||||
@@ -71,7 +85,7 @@ set -e
|
||||
RUN ln -sfv /usr/src/${rpmName}/hack/make/.build-rpm SPECS
|
||||
WORKDIR /root/rpmbuild/SPECS
|
||||
RUN tar -cz -C /usr/src -f /root/rpmbuild/SOURCES/${rpmName}.tar.gz ${rpmName}
|
||||
RUN { echo '* $rpmDate $rpmPackager $rpmVersion-$rpmRelease'; echo '* Version: $VERSION'; } >> ${rpmName}.spec && tail >&2 ${rpmName}.spec
|
||||
RUN { cat /usr/src/${rpmName}/contrib/builder/rpm/changelog; } >> ${rpmName}.spec && tail >&2 ${rpmName}.spec
|
||||
RUN rpmbuild -ba --define '_release $rpmRelease' --define '_version $rpmVersion' --define '_origversion $VERSION' ${rpmName}.spec
|
||||
EOF
|
||||
# selinux policy referencing systemd things won't work on non-systemd versions
|
||||
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# This script generates index files for the directory structure
|
||||
# of the apt and yum repos
|
||||
|
||||
: ${DOCKER_RELEASE_DIR:=$DEST}
|
||||
APTDIR=$DOCKER_RELEASE_DIR/apt
|
||||
YUMDIR=$DOCKER_RELEASE_DIR/yum
|
||||
|
||||
if [ ! -d $APTDIR ] && [ ! -d $YUMDIR ]; then
|
||||
echo >&2 'release-rpm or release-deb must be run before generate-index-listing'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create_index() {
|
||||
local directory=$1
|
||||
local original=$2
|
||||
local cleaned=${directory#$original}
|
||||
|
||||
# the index file to create
|
||||
local index_file="${directory}/index"
|
||||
|
||||
# cd into dir & touch the index file
|
||||
cd $directory
|
||||
touch $index_file
|
||||
|
||||
# print the html header
|
||||
cat <<-EOF > "$index_file"
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Index of ${cleaned}/</title></head>
|
||||
<body bgcolor="white">
|
||||
<h1>Index of ${cleaned}/</h1><hr>
|
||||
<pre><a href="../">../</a>
|
||||
EOF
|
||||
|
||||
# start of content output
|
||||
(
|
||||
# change IFS locally within subshell so the for loop saves line correctly to L var
|
||||
IFS=$'\n';
|
||||
|
||||
# pretty sweet, will mimick the normal apache output
|
||||
for L in $(find -L . -mount -depth -maxdepth 1 -type f ! -name 'index' -printf "<a href=\"%f\">%-44f@_@%Td-%Tb-%TY %Tk:%TM @%f@\n"|sort|sed 's,\([\ ]\+\)@_@,</a>\1,g');
|
||||
do
|
||||
# file
|
||||
F=$(sed -e 's,^.*@\([^@]\+\)@.*$,\1,g'<<<"$L");
|
||||
|
||||
# file with file size
|
||||
F=$(du -bh $F | cut -f1);
|
||||
|
||||
# output with correct format
|
||||
sed -e 's,\ @.*$, '"$F"',g'<<<"$L";
|
||||
done;
|
||||
) >> $index_file;
|
||||
|
||||
# now output a list of all directories in this dir (maxdepth 1) other than '.' outputting in a sorted manner exactly like apache
|
||||
find -L . -mount -depth -maxdepth 1 -type d ! -name '.' -printf "<a href=\"%f\">%-43f@_@%Td-%Tb-%TY %Tk:%TM -\n"|sort -d|sed 's,\([\ ]\+\)@_@,/</a>\1,g' >> $index_file
|
||||
|
||||
# print the footer html
|
||||
echo "</pre><hr></body></html>" >> $index_file
|
||||
|
||||
}
|
||||
|
||||
get_dirs() {
|
||||
local directory=$1
|
||||
|
||||
for d in `find ${directory} -type d`; do
|
||||
create_index $d $directory
|
||||
done
|
||||
}
|
||||
|
||||
get_dirs $APTDIR
|
||||
get_dirs $YUMDIR
|
||||
@@ -104,6 +104,8 @@ for dir in contrib/builder/deb/*/; do
|
||||
-name *~${codename#*-}*.deb > "$APTDIR/dists/$codename/$component/filelist"
|
||||
done
|
||||
|
||||
# clean the databases
|
||||
apt-ftparchive clean "$APTDIR/conf/apt-ftparchive.conf"
|
||||
|
||||
# run the apt-ftparchive commands so we can have pinning
|
||||
apt-ftparchive generate "$APTDIR/conf/apt-ftparchive.conf"
|
||||
|
||||
+6
-5
@@ -9,18 +9,19 @@ source 'hack/.vendor-helpers.sh'
|
||||
clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe
|
||||
clone git github.com/Sirupsen/logrus v0.8.2 # logrus is a common dependency among multiple deps
|
||||
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673
|
||||
clone git github.com/go-check/check 11d3bc7aa68e238947792f30573146a3231fc0f1
|
||||
clone git github.com/gorilla/context 14f550f51a
|
||||
clone git github.com/gorilla/mux e444e69cbd
|
||||
clone git github.com/kr/pty 5cf931ef8f
|
||||
clone git github.com/mattn/go-sqlite3 v1.1.0
|
||||
clone git github.com/microsoft/hcsshim 7f646aa6b26bcf90caee91e93cde4a80d0d8a83e
|
||||
clone git github.com/microsoft/hcsshim 325e531f8c49dd78580d5fd197ddb972fa4610e7
|
||||
clone git github.com/mistifyio/go-zfs v2.1.1
|
||||
clone git github.com/tchap/go-patricia v2.1.0
|
||||
clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b
|
||||
clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork dd1c5f0ffe7697f75a82bd8e4bbd6f225ec5e383
|
||||
clone git github.com/docker/libnetwork 2934f6bf585fa24c86048cc85f7506a5bb626bf5
|
||||
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
|
||||
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
|
||||
@@ -41,8 +42,8 @@ clone git github.com/boltdb/bolt v1.0
|
||||
clone git github.com/docker/distribution 20c4b7a1805a52753dfd593ee1cc35558722a0ce # docker/1.9 branch
|
||||
clone git github.com/vbatts/tar-split v0.9.10
|
||||
|
||||
clone git github.com/docker/notary ac05822d7d71ef077df3fc24f506672282a1feea
|
||||
clone git github.com/endophage/gotuf 9bcdad0308e34a49f38448b8ad436ad8860825ce
|
||||
clone git github.com/docker/notary 089d8450d8928aa1c58fd03f09cabbde9bcb4590
|
||||
clone git github.com/endophage/gotuf 876c31a61bc4aa0dae09bb8ef3946dc26dd04924
|
||||
clone git github.com/jfrazelle/go 6e461eb70cb4187b41a84e9a567d7137bdbe0f16
|
||||
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ func (s *DockerSuite) TearDownTest(c *check.C) {
|
||||
deleteAllContainers()
|
||||
deleteAllImages()
|
||||
deleteAllVolumes()
|
||||
deleteAllNetworks()
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -17,31 +17,29 @@ func (s *DockerSuite) TestBuildApiDockerfilePath(c *check.C) {
|
||||
defer tw.Close()
|
||||
|
||||
dockerfile := []byte("FROM busybox")
|
||||
if err := tw.WriteHeader(&tar.Header{
|
||||
err := tw.WriteHeader(&tar.Header{
|
||||
Name: "Dockerfile",
|
||||
Size: int64(len(dockerfile)),
|
||||
}); err != nil {
|
||||
c.Fatalf("failed to write tar file header: %v", err)
|
||||
}
|
||||
if _, err := tw.Write(dockerfile); err != nil {
|
||||
c.Fatalf("failed to write tar file content: %v", err)
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
c.Fatalf("failed to close tar archive: %v", err)
|
||||
}
|
||||
})
|
||||
//failed to write tar file header
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
_, err = tw.Write(dockerfile)
|
||||
// failed to write tar file content
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// failed to close tar archive
|
||||
c.Assert(tw.Close(), checker.IsNil)
|
||||
|
||||
res, body, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
|
||||
|
||||
out, err := readBody(body)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if !strings.Contains(string(out), "Forbidden path outside the build context") {
|
||||
c.Fatalf("Didn't complain about leaving build context: %s", out)
|
||||
}
|
||||
// Didn't complain about leaving build context
|
||||
c.Assert(string(out), checker.Contains, "Forbidden path outside the build context")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
|
||||
@@ -53,27 +51,21 @@ COPY * /tmp/
|
||||
RUN find / -name ba*
|
||||
RUN find /tmp/`,
|
||||
})
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer server.Close()
|
||||
|
||||
res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := readBody(body)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Make sure Dockerfile exists.
|
||||
// Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL
|
||||
out := string(buf)
|
||||
if !strings.Contains(out, "/tmp/Dockerfile") ||
|
||||
strings.Contains(out, "baz") {
|
||||
c.Fatalf("Incorrect output: %s", out)
|
||||
}
|
||||
c.Assert(out, checker.Contains, "/tmp/Dockerfile")
|
||||
c.Assert(out, checker.Not(checker.Contains), "baz")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildApiRemoteTarballContext(c *check.C) {
|
||||
@@ -83,29 +75,30 @@ func (s *DockerSuite) TestBuildApiRemoteTarballContext(c *check.C) {
|
||||
defer tw.Close()
|
||||
|
||||
dockerfile := []byte("FROM busybox")
|
||||
if err := tw.WriteHeader(&tar.Header{
|
||||
err := tw.WriteHeader(&tar.Header{
|
||||
Name: "Dockerfile",
|
||||
Size: int64(len(dockerfile)),
|
||||
}); err != nil {
|
||||
c.Fatalf("failed to write tar file header: %v", err)
|
||||
}
|
||||
if _, err := tw.Write(dockerfile); err != nil {
|
||||
c.Fatalf("failed to write tar file content: %v", err)
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
c.Fatalf("failed to close tar archive: %v", err)
|
||||
}
|
||||
})
|
||||
// failed to write tar file header
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
_, err = tw.Write(dockerfile)
|
||||
// failed to write tar file content
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// failed to close tar archive
|
||||
c.Assert(tw.Close(), checker.IsNil)
|
||||
|
||||
server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
|
||||
"testT.tar": buffer,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
defer server.Close()
|
||||
|
||||
res, b, err := sockRequestRaw("POST", "/build?remote="+server.URL()+"/testT.tar", nil, "application/tar")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
b.Close()
|
||||
}
|
||||
|
||||
@@ -117,51 +110,52 @@ func (s *DockerSuite) TestBuildApiRemoteTarballContextWithCustomDockerfile(c *ch
|
||||
|
||||
dockerfile := []byte(`FROM busybox
|
||||
RUN echo 'wrong'`)
|
||||
if err := tw.WriteHeader(&tar.Header{
|
||||
err := tw.WriteHeader(&tar.Header{
|
||||
Name: "Dockerfile",
|
||||
Size: int64(len(dockerfile)),
|
||||
}); err != nil {
|
||||
c.Fatalf("failed to write tar file header: %v", err)
|
||||
}
|
||||
if _, err := tw.Write(dockerfile); err != nil {
|
||||
c.Fatalf("failed to write tar file content: %v", err)
|
||||
}
|
||||
})
|
||||
// failed to write tar file header
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
_, err = tw.Write(dockerfile)
|
||||
// failed to write tar file content
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
custom := []byte(`FROM busybox
|
||||
RUN echo 'right'
|
||||
`)
|
||||
if err := tw.WriteHeader(&tar.Header{
|
||||
err = tw.WriteHeader(&tar.Header{
|
||||
Name: "custom",
|
||||
Size: int64(len(custom)),
|
||||
}); err != nil {
|
||||
c.Fatalf("failed to write tar file header: %v", err)
|
||||
}
|
||||
if _, err := tw.Write(custom); err != nil {
|
||||
c.Fatalf("failed to write tar file content: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
if err := tw.Close(); err != nil {
|
||||
c.Fatalf("failed to close tar archive: %v", err)
|
||||
}
|
||||
// failed to write tar file header
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
_, err = tw.Write(custom)
|
||||
// failed to write tar file content
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// failed to close tar archive
|
||||
c.Assert(tw.Close(), checker.IsNil)
|
||||
|
||||
server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
|
||||
"testT.tar": buffer,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
defer server.Close()
|
||||
url := "/build?dockerfile=custom&remote=" + server.URL() + "/testT.tar"
|
||||
res, body, err := sockRequestRaw("POST", url, nil, "application/tar")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
defer body.Close()
|
||||
content, err := readBody(body)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if strings.Contains(string(content), "wrong") {
|
||||
c.Fatalf("Build used the wrong dockerfile.")
|
||||
}
|
||||
// Build used the wrong dockerfile.
|
||||
c.Assert(string(content), checker.Not(checker.Contains), "wrong")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
|
||||
@@ -170,24 +164,18 @@ func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
|
||||
"dockerfile": `FROM busybox
|
||||
RUN echo from dockerfile`,
|
||||
}, false)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer git.Close()
|
||||
|
||||
res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := readBody(body)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
if !strings.Contains(out, "from dockerfile") {
|
||||
c.Fatalf("Incorrect output: %s", out)
|
||||
}
|
||||
c.Assert(out, checker.Contains, "from dockerfile")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildApiBuildGitWithF(c *check.C) {
|
||||
@@ -198,25 +186,19 @@ RUN echo from baz`,
|
||||
"Dockerfile": `FROM busybox
|
||||
RUN echo from Dockerfile`,
|
||||
}, false)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer git.Close()
|
||||
|
||||
// Make sure it tries to 'dockerfile' query param value
|
||||
res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := readBody(body)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
if !strings.Contains(out, "from baz") {
|
||||
c.Fatalf("Incorrect output: %s", out)
|
||||
}
|
||||
c.Assert(out, checker.Contains, "from baz")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) {
|
||||
@@ -227,25 +209,19 @@ RUN echo from Dockerfile`,
|
||||
"dockerfile": `FROM busybox
|
||||
RUN echo from dockerfile`,
|
||||
}, false)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer git.Close()
|
||||
|
||||
// Make sure it tries to 'dockerfile' query param value
|
||||
res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := readBody(body)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
if !strings.Contains(out, "from Dockerfile") {
|
||||
c.Fatalf("Incorrect output: %s", out)
|
||||
}
|
||||
c.Assert(out, checker.Contains, "from Dockerfile")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
|
||||
@@ -255,31 +231,27 @@ func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
|
||||
tw := tar.NewWriter(buffer)
|
||||
defer tw.Close()
|
||||
|
||||
if err := tw.WriteHeader(&tar.Header{
|
||||
err := tw.WriteHeader(&tar.Header{
|
||||
Name: "Dockerfile",
|
||||
Typeflag: tar.TypeSymlink,
|
||||
Linkname: "/etc/passwd",
|
||||
}); err != nil {
|
||||
c.Fatalf("failed to write tar file header: %v", err)
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
c.Fatalf("failed to close tar archive: %v", err)
|
||||
}
|
||||
})
|
||||
// failed to write tar file header
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// failed to close tar archive
|
||||
c.Assert(tw.Close(), checker.IsNil)
|
||||
|
||||
res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
|
||||
|
||||
out, err := readBody(body)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// The reason the error is "Cannot locate specified Dockerfile" is because
|
||||
// in the builder, the symlink is resolved within the context, therefore
|
||||
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
|
||||
// a nonexistent file.
|
||||
if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
|
||||
c.Fatalf("Didn't complain about leaving build context: %s", out)
|
||||
}
|
||||
c.Assert(string(out), checker.Contains, "Cannot locate specified Dockerfile: Dockerfile", check.Commentf("Didn't complain about leaving build context"))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -21,8 +22,8 @@ func (s *DockerSuite) TestEventsApiEmptyOutput(c *check.C) {
|
||||
|
||||
select {
|
||||
case r := <-chResp:
|
||||
c.Assert(r.err, check.IsNil)
|
||||
c.Assert(r.resp.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(r.err, checker.IsNil)
|
||||
c.Assert(r.resp.StatusCode, checker.Equals, http.StatusOK)
|
||||
case <-time.After(3 * time.Second):
|
||||
c.Fatal("timeout waiting for events api to respond, should have responded immediately")
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -19,8 +20,8 @@ func (s *DockerSuite) TestExecResizeApiHeightWidthNoInt(c *check.C) {
|
||||
|
||||
endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar"
|
||||
status, _, err := sockRequest("POST", endpoint, nil)
|
||||
c.Assert(status, check.Equals, http.StatusInternalServerError)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// Part of #14845
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -15,7 +16,7 @@ func (s *DockerSuite) TestLogsApiWithStdout(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _ := dockerCmd(c, "run", "-d", "-t", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 1; done")
|
||||
id := strings.TrimSpace(out)
|
||||
c.Assert(waitRun(id), check.IsNil)
|
||||
c.Assert(waitRun(id), checker.IsNil)
|
||||
|
||||
type logOut struct {
|
||||
out string
|
||||
@@ -41,8 +42,8 @@ func (s *DockerSuite) TestLogsApiWithStdout(c *check.C) {
|
||||
|
||||
select {
|
||||
case l := <-chLog:
|
||||
c.Assert(l.err, check.IsNil)
|
||||
c.Assert(l.res.StatusCode, check.Equals, http.StatusOK)
|
||||
c.Assert(l.err, checker.IsNil)
|
||||
c.Assert(l.res.StatusCode, checker.Equals, http.StatusOK)
|
||||
if !strings.HasSuffix(l.out, "hello") {
|
||||
c.Fatalf("expected log output to container 'hello', but it does not")
|
||||
}
|
||||
@@ -57,8 +58,8 @@ func (s *DockerSuite) TestLogsApiNoStdoutNorStderr(c *check.C) {
|
||||
dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
|
||||
|
||||
status, body, err := sockRequest("GET", fmt.Sprintf("/containers/%s/logs", name), nil)
|
||||
c.Assert(status, check.Equals, http.StatusBadRequest)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusBadRequest)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expected := "Bad parameters: you must choose at least one stream"
|
||||
if !bytes.Contains(body, []byte(expected)) {
|
||||
@@ -75,7 +76,7 @@ func (s *DockerSuite) TestLogsApiFollowEmptyOutput(c *check.C) {
|
||||
|
||||
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name), bytes.NewBuffer(nil), "")
|
||||
t1 := time.Now()
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
body.Close()
|
||||
elapsed := t1.Sub(t0).Seconds()
|
||||
if elapsed > 5.0 {
|
||||
@@ -86,6 +87,6 @@ func (s *DockerSuite) TestLogsApiFollowEmptyOutput(c *check.C) {
|
||||
func (s *DockerSuite) TestLogsAPIContainerNotFound(c *check.C) {
|
||||
name := "nonExistentContainer"
|
||||
resp, _, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name), bytes.NewBuffer(nil), "")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(resp.StatusCode, check.Equals, http.StatusNotFound)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/docker/docker/pkg/parsers/filters"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
@@ -18,7 +19,7 @@ func (s *DockerSuite) TestApiNetworkGetDefaults(c *check.C) {
|
||||
// By default docker daemon creates 3 networks. check if they are present
|
||||
defaults := []string{"bridge", "host", "none"}
|
||||
for _, nn := range defaults {
|
||||
c.Assert(isNetworkAvailable(c, nn), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, nn), checker.Equals, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,25 +31,25 @@ func (s *DockerSuite) TestApiNetworkCreateDelete(c *check.C) {
|
||||
CheckDuplicate: true,
|
||||
}
|
||||
id := createNetwork(c, config, true)
|
||||
c.Assert(isNetworkAvailable(c, name), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, name), checker.Equals, true)
|
||||
|
||||
// POST another network with same name and CheckDuplicate must fail
|
||||
createNetwork(c, config, false)
|
||||
|
||||
// delete the network and make sure it is deleted
|
||||
deleteNetwork(c, id, true)
|
||||
c.Assert(isNetworkAvailable(c, name), check.Equals, false)
|
||||
c.Assert(isNetworkAvailable(c, name), checker.Equals, false)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiNetworkFilter(c *check.C) {
|
||||
nr := getNetworkResource(c, getNetworkIDByName(c, "bridge"))
|
||||
c.Assert(nr.Name, check.Equals, "bridge")
|
||||
c.Assert(nr.Name, checker.Equals, "bridge")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
|
||||
// Inspect default bridge network
|
||||
nr := getNetworkResource(c, "bridge")
|
||||
c.Assert(nr.Name, check.Equals, "bridge")
|
||||
c.Assert(nr.Name, checker.Equals, "bridge")
|
||||
|
||||
// run a container and attach it to the default bridge network
|
||||
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
|
||||
@@ -57,15 +58,15 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
|
||||
|
||||
// inspect default bridge network again and make sure the container is connected
|
||||
nr = getNetworkResource(c, nr.ID)
|
||||
c.Assert(nr.Driver, check.Equals, "bridge")
|
||||
c.Assert(nr.Scope, check.Equals, "local")
|
||||
c.Assert(nr.IPAM.Driver, check.Equals, "default")
|
||||
c.Assert(len(nr.Containers), check.Equals, 1)
|
||||
c.Assert(nr.Containers[containerID], check.NotNil)
|
||||
c.Assert(nr.Driver, checker.Equals, "bridge")
|
||||
c.Assert(nr.Scope, checker.Equals, "local")
|
||||
c.Assert(nr.IPAM.Driver, checker.Equals, "default")
|
||||
c.Assert(len(nr.Containers), checker.Equals, 1)
|
||||
c.Assert(nr.Containers[containerID], checker.NotNil)
|
||||
|
||||
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(ip.String(), check.Equals, containerIP)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(ip.String(), checker.Equals, containerIP)
|
||||
|
||||
// IPAM configuration inspect
|
||||
ipam := network.IPAM{
|
||||
@@ -73,21 +74,25 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
|
||||
Config: []network.IPAMConfig{{Subnet: "172.28.0.0/16", IPRange: "172.28.5.0/24", Gateway: "172.28.5.254"}},
|
||||
}
|
||||
config := types.NetworkCreate{
|
||||
Name: "br0",
|
||||
Driver: "bridge",
|
||||
IPAM: ipam,
|
||||
Name: "br0",
|
||||
Driver: "bridge",
|
||||
IPAM: ipam,
|
||||
Options: map[string]string{"foo": "bar", "opts": "dopts"},
|
||||
}
|
||||
id0 := createNetwork(c, config, true)
|
||||
c.Assert(isNetworkAvailable(c, "br0"), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, true)
|
||||
|
||||
nr = getNetworkResource(c, id0)
|
||||
c.Assert(len(nr.IPAM.Config), check.Equals, 1)
|
||||
c.Assert(nr.IPAM.Config[0].Subnet, check.Equals, "172.28.0.0/16")
|
||||
c.Assert(nr.IPAM.Config[0].IPRange, check.Equals, "172.28.5.0/24")
|
||||
c.Assert(nr.IPAM.Config[0].Gateway, check.Equals, "172.28.5.254")
|
||||
c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
|
||||
c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
|
||||
c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
|
||||
c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
|
||||
c.Assert(nr.Options["foo"], checker.Equals, "bar")
|
||||
c.Assert(nr.Options["opts"], checker.Equals, "dopts")
|
||||
|
||||
// delete the network and make sure it is deleted
|
||||
deleteNetwork(c, id0, true)
|
||||
c.Assert(isNetworkAvailable(c, "br0"), check.Equals, false)
|
||||
c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, false)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
|
||||
@@ -98,9 +103,9 @@ func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
|
||||
}
|
||||
id := createNetwork(c, config, true)
|
||||
nr := getNetworkResource(c, id)
|
||||
c.Assert(nr.Name, check.Equals, name)
|
||||
c.Assert(nr.ID, check.Equals, id)
|
||||
c.Assert(len(nr.Containers), check.Equals, 0)
|
||||
c.Assert(nr.Name, checker.Equals, name)
|
||||
c.Assert(nr.ID, checker.Equals, id)
|
||||
c.Assert(len(nr.Containers), checker.Equals, 0)
|
||||
|
||||
// run a container
|
||||
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
|
||||
@@ -111,20 +116,20 @@ func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
|
||||
|
||||
// inspect the network to make sure container is connected
|
||||
nr = getNetworkResource(c, nr.ID)
|
||||
c.Assert(len(nr.Containers), check.Equals, 1)
|
||||
c.Assert(nr.Containers[containerID], check.NotNil)
|
||||
c.Assert(len(nr.Containers), checker.Equals, 1)
|
||||
c.Assert(nr.Containers[containerID], checker.NotNil)
|
||||
|
||||
// check if container IP matches network inspect
|
||||
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
containerIP := findContainerIP(c, "test")
|
||||
c.Assert(ip.String(), check.Equals, containerIP)
|
||||
c.Assert(ip.String(), checker.Equals, containerIP)
|
||||
|
||||
// disconnect container from the network
|
||||
disconnectNetwork(c, nr.ID, containerID)
|
||||
nr = getNetworkResource(c, nr.ID)
|
||||
c.Assert(nr.Name, check.Equals, name)
|
||||
c.Assert(len(nr.Containers), check.Equals, 0)
|
||||
c.Assert(nr.Name, checker.Equals, name)
|
||||
c.Assert(len(nr.Containers), checker.Equals, 0)
|
||||
|
||||
// delete the network
|
||||
deleteNetwork(c, nr.ID, true)
|
||||
@@ -142,7 +147,7 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
|
||||
IPAM: ipam0,
|
||||
}
|
||||
id0 := createNetwork(c, config0, true)
|
||||
c.Assert(isNetworkAvailable(c, "test0"), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, "test0"), checker.Equals, true)
|
||||
|
||||
ipam1 := network.IPAM{
|
||||
Driver: "default",
|
||||
@@ -155,7 +160,7 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
|
||||
IPAM: ipam1,
|
||||
}
|
||||
createNetwork(c, config1, false)
|
||||
c.Assert(isNetworkAvailable(c, "test1"), check.Equals, false)
|
||||
c.Assert(isNetworkAvailable(c, "test1"), checker.Equals, false)
|
||||
|
||||
ipam2 := network.IPAM{
|
||||
Driver: "default",
|
||||
@@ -168,20 +173,20 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
|
||||
IPAM: ipam2,
|
||||
}
|
||||
createNetwork(c, config2, true)
|
||||
c.Assert(isNetworkAvailable(c, "test2"), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, "test2"), checker.Equals, true)
|
||||
|
||||
// remove test0 and retry to create test1
|
||||
deleteNetwork(c, id0, true)
|
||||
createNetwork(c, config1, true)
|
||||
c.Assert(isNetworkAvailable(c, "test1"), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, "test1"), checker.Equals, true)
|
||||
|
||||
// for networks w/o ipam specified, docker will choose proper non-overlapping subnets
|
||||
createNetwork(c, types.NetworkCreate{Name: "test3"}, true)
|
||||
c.Assert(isNetworkAvailable(c, "test3"), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, "test3"), checker.Equals, true)
|
||||
createNetwork(c, types.NetworkCreate{Name: "test4"}, true)
|
||||
c.Assert(isNetworkAvailable(c, "test4"), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, "test4"), checker.Equals, true)
|
||||
createNetwork(c, types.NetworkCreate{Name: "test5"}, true)
|
||||
c.Assert(isNetworkAvailable(c, "test5"), check.Equals, true)
|
||||
c.Assert(isNetworkAvailable(c, "test5"), checker.Equals, true)
|
||||
|
||||
for i := 1; i < 6; i++ {
|
||||
deleteNetwork(c, fmt.Sprintf("test%d", i), true)
|
||||
@@ -190,12 +195,12 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
|
||||
|
||||
func isNetworkAvailable(c *check.C, name string) bool {
|
||||
status, body, err := sockRequest("GET", "/networks", nil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
nJSON := []types.NetworkResource{}
|
||||
err = json.Unmarshal(body, &nJSON)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
for _, n := range nJSON {
|
||||
if n.Name == name {
|
||||
@@ -212,28 +217,28 @@ func getNetworkIDByName(c *check.C, name string) string {
|
||||
)
|
||||
filterArgs["name"] = []string{name}
|
||||
filterJSON, err := filters.ToParam(filterArgs)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
v.Set("filters", filterJSON)
|
||||
|
||||
status, body, err := sockRequest("GET", "/networks?"+v.Encode(), nil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
nJSON := []types.NetworkResource{}
|
||||
err = json.Unmarshal(body, &nJSON)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(len(nJSON), check.Equals, 1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(len(nJSON), checker.Equals, 1)
|
||||
|
||||
return nJSON[0].ID
|
||||
}
|
||||
|
||||
func getNetworkResource(c *check.C, id string) *types.NetworkResource {
|
||||
_, obj, err := sockRequest("GET", "/networks/"+id, nil)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
nr := types.NetworkResource{}
|
||||
err = json.Unmarshal(obj, &nr)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
return &nr
|
||||
}
|
||||
@@ -241,16 +246,16 @@ func getNetworkResource(c *check.C, id string) *types.NetworkResource {
|
||||
func createNetwork(c *check.C, config types.NetworkCreate, shouldSucceed bool) string {
|
||||
status, resp, err := sockRequest("POST", "/networks/create", config)
|
||||
if !shouldSucceed {
|
||||
c.Assert(status, check.Not(check.Equals), http.StatusCreated)
|
||||
c.Assert(status, checker.Not(checker.Equals), http.StatusCreated)
|
||||
return ""
|
||||
}
|
||||
|
||||
c.Assert(status, check.Equals, http.StatusCreated)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusCreated)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var nr types.NetworkCreateResponse
|
||||
err = json.Unmarshal(resp, &nr)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
return nr.ID
|
||||
}
|
||||
@@ -261,8 +266,8 @@ func connectNetwork(c *check.C, nid, cid string) {
|
||||
}
|
||||
|
||||
status, _, err := sockRequest("POST", "/networks/"+nid+"/connect", config)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func disconnectNetwork(c *check.C, nid, cid string) {
|
||||
@@ -271,17 +276,17 @@ func disconnectNetwork(c *check.C, nid, cid string) {
|
||||
}
|
||||
|
||||
status, _, err := sockRequest("POST", "/networks/"+nid+"/disconnect", config)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func deleteNetwork(c *check.C, id string, shouldSucceed bool) {
|
||||
status, _, err := sockRequest("DELETE", "/networks/"+id, nil)
|
||||
if !shouldSucceed {
|
||||
c.Assert(status, check.Not(check.Equals), http.StatusOK)
|
||||
c.Assert(err, check.NotNil)
|
||||
c.Assert(status, checker.Not(checker.Equals), http.StatusOK)
|
||||
c.Assert(err, checker.NotNil)
|
||||
return
|
||||
}
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
@@ -6,20 +6,18 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/autogen/dockerversion"
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestGetVersion(c *check.C) {
|
||||
status, body, err := sockRequest("GET", "/version", nil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var v types.Version
|
||||
if err := json.Unmarshal(body, &v); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
if v.Version != dockerversion.VERSION {
|
||||
c.Fatal("Version mismatch")
|
||||
}
|
||||
c.Assert(json.Unmarshal(body, &v), checker.IsNil)
|
||||
|
||||
c.Assert(v.Version, checker.Equals, dockerversion.VERSION, check.Commentf("Version mismatch"))
|
||||
}
|
||||
|
||||
@@ -22,9 +22,8 @@ func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
|
||||
endGroup.Add(3)
|
||||
startGroup.Add(3)
|
||||
|
||||
if err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done"); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
startDone := make(chan struct{})
|
||||
endDone := make(chan struct{})
|
||||
@@ -84,7 +83,6 @@ func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
|
||||
case <-time.After(attachWait):
|
||||
c.Fatalf("Attaches did not finish properly")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
|
||||
@@ -94,13 +92,6 @@ func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
|
||||
id := strings.TrimSpace(out)
|
||||
c.Assert(waitRun(id), check.IsNil)
|
||||
|
||||
defer func() {
|
||||
cmd := exec.Command(dockerBinary, "kill", id)
|
||||
if out, _, err := runCommandWithOutput(cmd); err != nil {
|
||||
c.Fatalf("failed to kill container: %v (%v)", out, err)
|
||||
}
|
||||
}()
|
||||
|
||||
done := make(chan error)
|
||||
go func() {
|
||||
defer close(done)
|
||||
@@ -141,37 +132,21 @@ func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
|
||||
}
|
||||
defer stdin.Close()
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
defer stdout.Close()
|
||||
if err := cmd.Start(); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(cmd.Start(), check.IsNil)
|
||||
defer cmd.Process.Kill()
|
||||
|
||||
if _, err := stdin.Write([]byte("hello\n")); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
_, err = stdin.Write([]byte("hello\n"))
|
||||
c.Assert(err, check.IsNil)
|
||||
out, err = bufio.NewReader(stdout).ReadString('\n')
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
if strings.TrimSpace(out) != "hello" {
|
||||
c.Fatalf("expected 'hello', got %q", out)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, "hello")
|
||||
|
||||
if err := stdin.Close(); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(stdin.Close(), check.IsNil)
|
||||
|
||||
// Expect container to still be running after stdin is closed
|
||||
running, err := inspectField(id, "State.Running")
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
if running != "true" {
|
||||
c.Fatal("expected container to still be running")
|
||||
}
|
||||
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(running, check.Equals, "true")
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -22,9 +23,7 @@ func (s *DockerSuite) TestDiffFilenameShownInOutput(c *check.C) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
c.Errorf("couldn't find the new file in docker diff's output: %v", out)
|
||||
}
|
||||
c.Assert(found, checker.True)
|
||||
}
|
||||
|
||||
// test to ensure GH #3840 doesn't occur any more
|
||||
@@ -43,9 +42,7 @@ func (s *DockerSuite) TestDiffEnsureDockerinitFilesAreIgnored(c *check.C) {
|
||||
out, _ = dockerCmd(c, "diff", cleanCID)
|
||||
|
||||
for _, filename := range dockerinitFiles {
|
||||
if strings.Contains(out, filename) {
|
||||
c.Errorf("found file which should've been ignored %v in diff output", filename)
|
||||
}
|
||||
c.Assert(out, checker.Not(checker.Contains), filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,6 +58,7 @@ func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) {
|
||||
"C /dev": true,
|
||||
"A /dev/full": true, // busybox
|
||||
"C /dev/ptmx": true, // libcontainer
|
||||
"A /dev/mqueue": true, // lxc
|
||||
"A /dev/kmsg": true, // lxc
|
||||
"A /dev/fd": true,
|
||||
"A /dev/fuse": true,
|
||||
@@ -77,15 +75,13 @@ func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) {
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
if line != "" && !expected[line] {
|
||||
c.Errorf("%q is shown in the diff but shouldn't", line)
|
||||
}
|
||||
c.Assert(line == "" || expected[line], checker.True)
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/docker/docker/pull/14381#discussion_r33859347
|
||||
func (s *DockerSuite) TestDiffEmptyArgClientError(c *check.C) {
|
||||
out, _, err := dockerCmdWithError("diff", "")
|
||||
c.Assert(err, check.NotNil)
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, "Container name cannot be empty")
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(strings.TrimSpace(out), checker.Equals, "Container name cannot be empty")
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ func (s *DockerSuite) TestEventsRedirectStdout(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, NativeExecDriver)
|
||||
testRequires(c, oomControl)
|
||||
|
||||
errChan := make(chan error)
|
||||
@@ -103,6 +104,7 @@ func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestEventsOOMDisableTrue(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, NativeExecDriver)
|
||||
testRequires(c, oomControl)
|
||||
|
||||
errChan := make(chan error)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
"github.com/kr/pty"
|
||||
)
|
||||
@@ -21,9 +22,7 @@ func (s *DockerSuite) TestExecInteractiveStdinClose(c *check.C) {
|
||||
|
||||
cmd := exec.Command(dockerBinary, "exec", "-i", contID, "echo", "-n", "hello")
|
||||
p, err := pty.Start(cmd)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
b := bytes.NewBuffer(nil)
|
||||
go io.Copy(b, p)
|
||||
@@ -33,12 +32,9 @@ func (s *DockerSuite) TestExecInteractiveStdinClose(c *check.C) {
|
||||
|
||||
select {
|
||||
case err := <-ch:
|
||||
if err != nil {
|
||||
c.Errorf("cmd finished with error %v", err)
|
||||
}
|
||||
if output := b.String(); strings.TrimSpace(output) != "hello" {
|
||||
c.Fatalf("Unexpected output %s", output)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
output := b.String()
|
||||
c.Assert(strings.TrimSpace(output), checker.Equals, "hello")
|
||||
case <-time.After(1 * time.Second):
|
||||
c.Fatal("timed out running docker exec")
|
||||
}
|
||||
@@ -50,11 +46,11 @@ func (s *DockerSuite) TestExecTTY(c *check.C) {
|
||||
|
||||
cmd := exec.Command(dockerBinary, "exec", "-it", "test", "sh")
|
||||
p, err := pty.Start(cmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer p.Close()
|
||||
|
||||
_, err = p.Write([]byte("cat /foo && exit\n"))
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
chErr := make(chan error)
|
||||
go func() {
|
||||
@@ -62,13 +58,13 @@ func (s *DockerSuite) TestExecTTY(c *check.C) {
|
||||
}()
|
||||
select {
|
||||
case err := <-chErr:
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
case <-time.After(3 * time.Second):
|
||||
c.Fatal("timeout waiting for exec to exit")
|
||||
}
|
||||
|
||||
buf := make([]byte, 256)
|
||||
read, err := p.Read(buf)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(bytes.Contains(buf, []byte("hello")), check.Equals, true, check.Commentf(string(buf[:read])))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(bytes.Contains(buf, []byte("hello")), checker.Equals, true, check.Commentf(string(buf[:read])))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
@@ -197,3 +198,9 @@ func (s *DockerSuite) TestImagesEnsureDanglingImageOnlyListedOnce(c *check.C) {
|
||||
c.Fatalf("expected 1 dangling image, got %d: %s", a, out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestImagesWithIncorrectFilter(c *check.C) {
|
||||
out, _, err := dockerCmdWithError("images", "-f", "dangling=invalid")
|
||||
c.Assert(err, check.NotNil)
|
||||
c.Assert(out, checker.Contains, "Invalid filter")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -12,34 +13,22 @@ func (s *DockerSuite) TestInspectNamedMountPoint(c *check.C) {
|
||||
dockerCmd(c, "run", "-d", "--name", "test", "-v", "data:/data", "busybox", "cat")
|
||||
|
||||
vol, err := inspectFieldJSON("test", "Mounts")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var mp []types.MountPoint
|
||||
err = unmarshalJSON([]byte(vol), &mp)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if len(mp) != 1 {
|
||||
c.Fatalf("Expected 1 mount point, was %v\n", len(mp))
|
||||
}
|
||||
c.Assert(mp, checker.HasLen, 1, check.Commentf("Expected 1 mount point"))
|
||||
|
||||
m := mp[0]
|
||||
if m.Name != "data" {
|
||||
c.Fatalf("Expected name data, was %s\n", m.Name)
|
||||
}
|
||||
c.Assert(m.Name, checker.Equals, "data", check.Commentf("Expected name data"))
|
||||
|
||||
if m.Driver != "local" {
|
||||
c.Fatalf("Expected driver local, was %s\n", m.Driver)
|
||||
}
|
||||
c.Assert(m.Driver, checker.Equals, "local", check.Commentf("Expected driver local"))
|
||||
|
||||
if m.Source == "" {
|
||||
c.Fatalf("Expected source to not be empty")
|
||||
}
|
||||
c.Assert(m.Source, checker.Not(checker.Equals), "", check.Commentf("Expected source to not be empty"))
|
||||
|
||||
if m.RW != true {
|
||||
c.Fatalf("Expected rw to be true")
|
||||
}
|
||||
c.Assert(m.RW, checker.Equals, true)
|
||||
|
||||
if m.Destination != "/data" {
|
||||
c.Fatalf("Expected destination /data, was %s\n", m.Destination)
|
||||
}
|
||||
c.Assert(m.Destination, checker.Equals, "/data", check.Commentf("Expected destination /data"))
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/docker/docker/pkg/timeutils"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
@@ -19,13 +20,13 @@ func (s *DockerSuite) TestLogsContainerSmallerThanPage(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testLen := 32767
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
out, _ = dockerCmd(c, "logs", cleanedContainerID)
|
||||
if len(out) != testLen+1 {
|
||||
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
|
||||
}
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", id)
|
||||
|
||||
c.Assert(out, checker.HasLen, testLen+1)
|
||||
}
|
||||
|
||||
// Regression test: When going over the PageSize, it used to panic (gh#4851)
|
||||
@@ -34,14 +35,12 @@ func (s *DockerSuite) TestLogsContainerBiggerThanPage(c *check.C) {
|
||||
testLen := 32768
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", cleanedContainerID)
|
||||
out, _ = dockerCmd(c, "logs", id)
|
||||
|
||||
if len(out) != testLen+1 {
|
||||
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
|
||||
}
|
||||
c.Assert(out, checker.HasLen, testLen+1)
|
||||
}
|
||||
|
||||
// Regression test: When going much over the PageSize, it used to block (gh#4851)
|
||||
@@ -50,14 +49,12 @@ func (s *DockerSuite) TestLogsContainerMuchBiggerThanPage(c *check.C) {
|
||||
testLen := 33000
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", cleanedContainerID)
|
||||
out, _ = dockerCmd(c, "logs", id)
|
||||
|
||||
if len(out) != testLen+1 {
|
||||
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
|
||||
}
|
||||
c.Assert(out, checker.HasLen, testLen+1)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
|
||||
@@ -65,28 +62,23 @@ func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
|
||||
testLen := 100
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "-t", cleanedContainerID)
|
||||
out, _ = dockerCmd(c, "logs", "-t", id)
|
||||
|
||||
lines := strings.Split(out, "\n")
|
||||
|
||||
if len(lines) != testLen+1 {
|
||||
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
|
||||
}
|
||||
c.Assert(lines, checker.HasLen, testLen+1)
|
||||
|
||||
ts := regexp.MustCompile(`^.* `)
|
||||
|
||||
for _, l := range lines {
|
||||
if l != "" {
|
||||
_, err := time.Parse(timeutils.RFC3339NanoFixed+" ", ts.FindString(l))
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to parse timestamp from %v: %v", l, err)
|
||||
}
|
||||
if l[29] != 'Z' { // ensure we have padded 0's
|
||||
c.Fatalf("Timestamp isn't padded properly: %s", l)
|
||||
}
|
||||
c.Assert(err, checker.IsNil, check.Commentf("Failed to parse timestamp from %v", l))
|
||||
// ensure we have padded 0's
|
||||
c.Assert(l[29], checker.Equals, uint8('Z'))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,19 +88,16 @@ func (s *DockerSuite) TestLogsSeparateStderr(c *check.C) {
|
||||
msg := "stderr_log"
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", cleanedContainerID)
|
||||
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", id)
|
||||
|
||||
if stdout != "" {
|
||||
c.Fatalf("Expected empty stdout stream, got %v", stdout)
|
||||
}
|
||||
c.Assert(stdout, checker.Equals, "")
|
||||
|
||||
stderr = strings.TrimSpace(stderr)
|
||||
if stderr != msg {
|
||||
c.Fatalf("Expected %v in stderr stream, got %v", msg, stderr)
|
||||
}
|
||||
|
||||
c.Assert(stderr, checker.Equals, msg)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
|
||||
@@ -116,18 +105,14 @@ func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
|
||||
msg := "stderr_log"
|
||||
out, _ := dockerCmd(c, "run", "-d", "-t", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", cleanedContainerID)
|
||||
if stderr != "" {
|
||||
c.Fatalf("Expected empty stderr stream, got %v", stderr)
|
||||
}
|
||||
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", id)
|
||||
c.Assert(stderr, checker.Equals, "")
|
||||
|
||||
stdout = strings.TrimSpace(stdout)
|
||||
if stdout != msg {
|
||||
c.Fatalf("Expected %v in stdout stream, got %v", msg, stdout)
|
||||
}
|
||||
c.Assert(stdout, checker.Equals, msg)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLogsTail(c *check.C) {
|
||||
@@ -135,43 +120,37 @@ func (s *DockerSuite) TestLogsTail(c *check.C) {
|
||||
testLen := 100
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "5", cleanedContainerID)
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "5", id)
|
||||
|
||||
lines := strings.Split(out, "\n")
|
||||
|
||||
if len(lines) != 6 {
|
||||
c.Fatalf("Expected log %d lines, received %d\n", 6, len(lines))
|
||||
}
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "all", cleanedContainerID)
|
||||
c.Assert(lines, checker.HasLen, 6)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "all", id)
|
||||
|
||||
lines = strings.Split(out, "\n")
|
||||
|
||||
if len(lines) != testLen+1 {
|
||||
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
|
||||
}
|
||||
out, _, _ = dockerCmdWithStdoutStderr(c, "logs", "--tail", "random", cleanedContainerID)
|
||||
c.Assert(lines, checker.HasLen, testLen+1)
|
||||
|
||||
out, _, _ = dockerCmdWithStdoutStderr(c, "logs", "--tail", "random", id)
|
||||
|
||||
lines = strings.Split(out, "\n")
|
||||
|
||||
if len(lines) != testLen+1 {
|
||||
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
|
||||
}
|
||||
c.Assert(lines, checker.HasLen, testLen+1)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
logsCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
|
||||
if err := logsCmd.Start(); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
logsCmd := exec.Command(dockerBinary, "logs", "-f", id)
|
||||
c.Assert(logsCmd.Start(), checker.IsNil)
|
||||
|
||||
errChan := make(chan error)
|
||||
go func() {
|
||||
@@ -181,7 +160,7 @@ func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
|
||||
|
||||
select {
|
||||
case err := <-errChan:
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
case <-time.After(1 * time.Second):
|
||||
c.Fatal("Following logs is hanged")
|
||||
}
|
||||
@@ -194,16 +173,14 @@ func (s *DockerSuite) TestLogsSince(c *check.C) {
|
||||
|
||||
log2Line := strings.Split(strings.Split(out, "\n")[1], " ")
|
||||
t, err := strconv.ParseInt(log2Line[0], 10, 64) // the timestamp log2 is written
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
since := t + 1 // add 1s so log1 & log2 doesn't show up
|
||||
out, _ = dockerCmd(c, "logs", "-t", fmt.Sprintf("--since=%v", since), name)
|
||||
|
||||
// Skip 2 seconds
|
||||
unexpected := []string{"log1", "log2"}
|
||||
for _, v := range unexpected {
|
||||
if strings.Contains(out, v) {
|
||||
c.Fatalf("unexpected log message returned=%v, since=%v\nout=%v", v, since, out)
|
||||
}
|
||||
c.Assert(out, checker.Not(checker.Contains), v, check.Commentf("unexpected log message returned, since=%v", since))
|
||||
}
|
||||
// Test with default value specified and parameter omitted
|
||||
expected := []string{"log1", "log2", "log3"}
|
||||
@@ -212,13 +189,9 @@ func (s *DockerSuite) TestLogsSince(c *check.C) {
|
||||
exec.Command(dockerBinary, "logs", "-t", "--since=0", name),
|
||||
} {
|
||||
out, _, err = runCommandWithOutput(cmd)
|
||||
if err != nil {
|
||||
c.Fatalf("failed to log container: %s, %v", out, err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil, check.Commentf("failed to log container: %s", out))
|
||||
for _, v := range expected {
|
||||
if !strings.Contains(out, v) {
|
||||
c.Fatalf("'%v' does not contain=%v\nout=%s", cmd.Args, v, out)
|
||||
}
|
||||
c.Assert(out, checker.Contains, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,23 +199,17 @@ func (s *DockerSuite) TestLogsSince(c *check.C) {
|
||||
func (s *DockerSuite) TestLogsSinceFutureFollow(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", `for i in $(seq 1 5); do date +%s; sleep 1; done`)
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
id := strings.TrimSpace(out)
|
||||
|
||||
now := daemonTime(c).Unix()
|
||||
since := now + 2
|
||||
out, _ = dockerCmd(c, "logs", "-f", fmt.Sprintf("--since=%v", since), cleanedContainerID)
|
||||
out, _ = dockerCmd(c, "logs", "-f", fmt.Sprintf("--since=%v", since), id)
|
||||
lines := strings.Split(strings.TrimSpace(out), "\n")
|
||||
if len(lines) == 0 {
|
||||
c.Fatal("got no log lines")
|
||||
}
|
||||
c.Assert(lines, checker.Not(checker.HasLen), 0)
|
||||
for _, v := range lines {
|
||||
ts, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
c.Fatalf("cannot parse timestamp output from log: '%v'\nout=%s", v, out)
|
||||
}
|
||||
if ts < since {
|
||||
c.Fatalf("earlier log found. since=%v logdate=%v", since, ts)
|
||||
}
|
||||
c.Assert(err, checker.IsNil, check.Commentf("cannot parse timestamp output from log: '%v'\nout=%s", v, out))
|
||||
c.Assert(ts >= since, checker.Equals, true, check.Commentf("earlier log found. since=%v logdate=%v", since, ts))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,33 +218,31 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", `usleep 200000;yes X | head -c 200000`)
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
id := strings.TrimSpace(out)
|
||||
|
||||
stopSlowRead := make(chan bool)
|
||||
|
||||
go func() {
|
||||
exec.Command(dockerBinary, "wait", cleanedContainerID).Run()
|
||||
exec.Command(dockerBinary, "wait", id).Run()
|
||||
stopSlowRead <- true
|
||||
}()
|
||||
|
||||
logCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
|
||||
logCmd := exec.Command(dockerBinary, "logs", "-f", id)
|
||||
stdout, err := logCmd.StdoutPipe()
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(logCmd.Start(), check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(logCmd.Start(), checker.IsNil)
|
||||
|
||||
// First read slowly
|
||||
bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// After the container has finished we can continue reading fast
|
||||
bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
actual := bytes1 + bytes2
|
||||
expected := 200000
|
||||
if actual != expected {
|
||||
c.Fatalf("Invalid bytes read: %d, expected %d", actual, expected)
|
||||
}
|
||||
c.Assert(actual, checker.Equals, expected)
|
||||
|
||||
}
|
||||
|
||||
@@ -285,7 +250,7 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 2; done")
|
||||
id := strings.TrimSpace(out)
|
||||
c.Assert(waitRun(id), check.IsNil)
|
||||
c.Assert(waitRun(id), checker.IsNil)
|
||||
|
||||
type info struct {
|
||||
NGoroutines int
|
||||
@@ -293,9 +258,9 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
|
||||
getNGoroutines := func() int {
|
||||
var i info
|
||||
status, b, err := sockRequest("GET", "/info", nil)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, 200)
|
||||
c.Assert(json.Unmarshal(b, &i), check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, 200)
|
||||
c.Assert(json.Unmarshal(b, &i), checker.IsNil)
|
||||
return i.NGoroutines
|
||||
}
|
||||
|
||||
@@ -304,7 +269,7 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
|
||||
cmd := exec.Command(dockerBinary, "logs", "-f", id)
|
||||
r, w := io.Pipe()
|
||||
cmd.Stdout = w
|
||||
c.Assert(cmd.Start(), check.IsNil)
|
||||
c.Assert(cmd.Start(), checker.IsNil)
|
||||
|
||||
// Make sure pipe is written to
|
||||
chErr := make(chan error)
|
||||
@@ -313,17 +278,17 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
|
||||
_, err := r.Read(b)
|
||||
chErr <- err
|
||||
}()
|
||||
c.Assert(<-chErr, check.IsNil)
|
||||
c.Assert(cmd.Process.Kill(), check.IsNil)
|
||||
c.Assert(<-chErr, checker.IsNil)
|
||||
c.Assert(cmd.Process.Kill(), checker.IsNil)
|
||||
|
||||
// NGoroutines is not updated right away, so we need to wait before failing
|
||||
t := time.After(30 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-t:
|
||||
if n := getNGoroutines(); n > nroutines {
|
||||
c.Fatalf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n)
|
||||
}
|
||||
n := getNGoroutines()
|
||||
c.Assert(n <= nroutines, checker.Equals, true, check.Commentf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n))
|
||||
|
||||
default:
|
||||
if n := getNGoroutines(); n <= nroutines {
|
||||
return
|
||||
@@ -337,7 +302,7 @@ func (s *DockerSuite) TestLogsFollowGoroutinesNoOutput(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 2; done")
|
||||
id := strings.TrimSpace(out)
|
||||
c.Assert(waitRun(id), check.IsNil)
|
||||
c.Assert(waitRun(id), checker.IsNil)
|
||||
|
||||
type info struct {
|
||||
NGoroutines int
|
||||
@@ -345,27 +310,27 @@ func (s *DockerSuite) TestLogsFollowGoroutinesNoOutput(c *check.C) {
|
||||
getNGoroutines := func() int {
|
||||
var i info
|
||||
status, b, err := sockRequest("GET", "/info", nil)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, 200)
|
||||
c.Assert(json.Unmarshal(b, &i), check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, 200)
|
||||
c.Assert(json.Unmarshal(b, &i), checker.IsNil)
|
||||
return i.NGoroutines
|
||||
}
|
||||
|
||||
nroutines := getNGoroutines()
|
||||
|
||||
cmd := exec.Command(dockerBinary, "logs", "-f", id)
|
||||
c.Assert(cmd.Start(), check.IsNil)
|
||||
c.Assert(cmd.Start(), checker.IsNil)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
c.Assert(cmd.Process.Kill(), check.IsNil)
|
||||
c.Assert(cmd.Process.Kill(), checker.IsNil)
|
||||
|
||||
// NGoroutines is not updated right away, so we need to wait before failing
|
||||
t := time.After(30 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-t:
|
||||
if n := getNGoroutines(); n > nroutines {
|
||||
c.Fatalf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n)
|
||||
}
|
||||
n := getNGoroutines()
|
||||
c.Assert(n <= nroutines, checker.Equals, true, check.Commentf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n))
|
||||
|
||||
default:
|
||||
if n := getNGoroutines(); n <= nroutines {
|
||||
return
|
||||
@@ -379,5 +344,5 @@ func (s *DockerSuite) TestLogsCLIContainerNotFound(c *check.C) {
|
||||
name := "testlogsnocontainer"
|
||||
out, _, _ := dockerCmdWithError("logs", name)
|
||||
message := fmt.Sprintf(".*no such id: %s.*\n", name)
|
||||
c.Assert(out, check.Matches, message)
|
||||
c.Assert(out, checker.Matches, message)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -17,9 +18,7 @@ func startServerContainer(c *check.C, msg string, port int) string {
|
||||
"busybox",
|
||||
"sh", "-c", fmt.Sprintf("echo %q | nc -lp %d", msg, port),
|
||||
}
|
||||
if err := waitForContainer(name, cmd...); err != nil {
|
||||
c.Fatalf("Failed to launch server container: %v", err)
|
||||
}
|
||||
c.Assert(waitForContainer(name, cmd...), check.IsNil)
|
||||
return name
|
||||
}
|
||||
|
||||
@@ -30,14 +29,11 @@ func getExternalAddress(c *check.C) net.IP {
|
||||
}
|
||||
|
||||
ifaceAddrs, err := iface.Addrs()
|
||||
if err != nil || len(ifaceAddrs) == 0 {
|
||||
c.Fatalf("Error retrieving addresses for eth0: %v (%d addresses)", err, len(ifaceAddrs))
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(ifaceAddrs, checker.Not(checker.HasLen), 0)
|
||||
|
||||
ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String())
|
||||
if err != nil {
|
||||
c.Fatalf("Error retrieving the up for eth0: %s", err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
return ifaceIP
|
||||
}
|
||||
@@ -60,18 +56,14 @@ func (s *DockerSuite) TestNetworkNat(c *check.C) {
|
||||
startServerContainer(c, msg, 8080)
|
||||
endpoint := getExternalAddress(c)
|
||||
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", endpoint.String(), 8080))
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to connect to container (%v)", err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
data, err := ioutil.ReadAll(conn)
|
||||
conn.Close()
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
final := strings.TrimRight(string(data), "\n")
|
||||
if final != msg {
|
||||
c.Fatalf("Expected message %q but received %q", msg, final)
|
||||
}
|
||||
c.Assert(final, checker.Equals, msg)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
|
||||
@@ -82,18 +74,14 @@ func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
|
||||
)
|
||||
startServerContainer(c, msg, 8081)
|
||||
conn, err := net.Dial("tcp", "localhost:8081")
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to connect to container (%v)", err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
data, err := ioutil.ReadAll(conn)
|
||||
conn.Close()
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
final := strings.TrimRight(string(data), "\n")
|
||||
if final != msg {
|
||||
c.Fatalf("Expected message %q but received %q", msg, final)
|
||||
}
|
||||
c.Assert(final, checker.Equals, msg)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestNetworkLoopbackNat(c *check.C) {
|
||||
@@ -105,7 +93,5 @@ func (s *DockerSuite) TestNetworkLoopbackNat(c *check.C) {
|
||||
out, _ := dockerCmd(c, "run", "-t", "--net=container:server", "busybox",
|
||||
"sh", "-c", fmt.Sprintf("stty raw && nc -w 5 %s 8080", endpoint.String()))
|
||||
final := strings.TrimRight(string(out), "\n")
|
||||
if final != msg {
|
||||
c.Fatalf("Expected message %q but received %q", msg, final)
|
||||
}
|
||||
c.Assert(final, checker.Equals, msg)
|
||||
}
|
||||
|
||||
@@ -13,12 +13,17 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
remoteapi "github.com/docker/libnetwork/drivers/remote/api"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
const dummyNetworkDriver = "dummy-network-driver"
|
||||
|
||||
var remoteDriverNetworkRequest remoteapi.CreateNetworkRequest
|
||||
|
||||
func init() {
|
||||
check.Suite(&DockerNetworkSuite{
|
||||
ds: &DockerSuite{},
|
||||
@@ -43,9 +48,7 @@ func (s *DockerNetworkSuite) TearDownTest(c *check.C) {
|
||||
func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
|
||||
mux := http.NewServeMux()
|
||||
s.server = httptest.NewServer(mux)
|
||||
if s.server == nil {
|
||||
c.Fatal("Failed to start a HTTP Server")
|
||||
}
|
||||
c.Assert(s.server, check.NotNil, check.Commentf("Failed to start a HTTP Server"))
|
||||
|
||||
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
|
||||
@@ -58,6 +61,11 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
|
||||
})
|
||||
|
||||
mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
|
||||
err := json.NewDecoder(r.Body).Decode(&remoteDriverNetworkRequest)
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
|
||||
fmt.Fprintf(w, "null")
|
||||
})
|
||||
@@ -67,14 +75,12 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
|
||||
fmt.Fprintf(w, "null")
|
||||
})
|
||||
|
||||
if err := os.MkdirAll("/etc/docker/plugins", 0755); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
err := os.MkdirAll("/etc/docker/plugins", 0755)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", dummyNetworkDriver)
|
||||
if err := ioutil.WriteFile(fileName, []byte(s.server.URL), 0644); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fileName, []byte(s.server.URL), 0644)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *DockerNetworkSuite) TearDownSuite(c *check.C) {
|
||||
@@ -84,9 +90,8 @@ func (s *DockerNetworkSuite) TearDownSuite(c *check.C) {
|
||||
|
||||
s.server.Close()
|
||||
|
||||
if err := os.RemoveAll("/etc/docker/plugins"); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
err := os.RemoveAll("/etc/docker/plugins")
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func assertNwIsAvailable(c *check.C, name string) {
|
||||
@@ -135,13 +140,18 @@ func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) {
|
||||
assertNwNotAvailable(c, "test")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDockerNetworkDeleteNotExists(c *check.C) {
|
||||
out, _, err := dockerCmdWithError("network", "rm", "test")
|
||||
c.Assert(err, checker.NotNil, check.Commentf("%v", out))
|
||||
}
|
||||
|
||||
func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
|
||||
dockerCmd(c, "network", "create", "test")
|
||||
assertNwIsAvailable(c, "test")
|
||||
nr := getNwResource(c, "test")
|
||||
|
||||
c.Assert(nr.Name, check.Equals, "test")
|
||||
c.Assert(len(nr.Containers), check.Equals, 0)
|
||||
c.Assert(nr.Name, checker.Equals, "test")
|
||||
c.Assert(len(nr.Containers), checker.Equals, 0)
|
||||
|
||||
// run a container
|
||||
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
|
||||
@@ -153,20 +163,20 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
|
||||
|
||||
// inspect the network to make sure container is connected
|
||||
nr = getNetworkResource(c, nr.ID)
|
||||
c.Assert(len(nr.Containers), check.Equals, 1)
|
||||
c.Assert(len(nr.Containers), checker.Equals, 1)
|
||||
c.Assert(nr.Containers[containerID], check.NotNil)
|
||||
|
||||
// check if container IP matches network inspect
|
||||
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
|
||||
c.Assert(err, check.IsNil)
|
||||
containerIP := findContainerIP(c, "test")
|
||||
c.Assert(ip.String(), check.Equals, containerIP)
|
||||
c.Assert(ip.String(), checker.Equals, containerIP)
|
||||
|
||||
// disconnect container from the network
|
||||
dockerCmd(c, "network", "disconnect", "test", containerID)
|
||||
nr = getNwResource(c, "test")
|
||||
c.Assert(nr.Name, check.Equals, "test")
|
||||
c.Assert(len(nr.Containers), check.Equals, 0)
|
||||
c.Assert(nr.Name, checker.Equals, "test")
|
||||
c.Assert(len(nr.Containers), checker.Equals, 0)
|
||||
|
||||
// check if network connect fails for inactive containers
|
||||
dockerCmd(c, "stop", containerID)
|
||||
@@ -223,13 +233,13 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspect(c *check.C) {
|
||||
assertNwIsAvailable(c, "br0")
|
||||
|
||||
nr := getNetworkResource(c, "br0")
|
||||
c.Assert(nr.Driver, check.Equals, "bridge")
|
||||
c.Assert(nr.Scope, check.Equals, "local")
|
||||
c.Assert(nr.IPAM.Driver, check.Equals, "default")
|
||||
c.Assert(len(nr.IPAM.Config), check.Equals, 1)
|
||||
c.Assert(nr.IPAM.Config[0].Subnet, check.Equals, "172.28.0.0/16")
|
||||
c.Assert(nr.IPAM.Config[0].IPRange, check.Equals, "172.28.5.0/24")
|
||||
c.Assert(nr.IPAM.Config[0].Gateway, check.Equals, "172.28.5.254")
|
||||
c.Assert(nr.Driver, checker.Equals, "bridge")
|
||||
c.Assert(nr.Scope, checker.Equals, "local")
|
||||
c.Assert(nr.IPAM.Driver, checker.Equals, "default")
|
||||
c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
|
||||
c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
|
||||
c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
|
||||
c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
|
||||
dockerCmd(c, "network", "rm", "br0")
|
||||
}
|
||||
|
||||
@@ -255,3 +265,16 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpamInvalidCombinations(c *check.C
|
||||
c.Assert(err, check.NotNil)
|
||||
dockerCmd(c, "network", "rm", "test0")
|
||||
}
|
||||
|
||||
func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) {
|
||||
dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "-o", "opt1=drv1", "-o", "opt2=drv2", "testopt")
|
||||
assertNwIsAvailable(c, "testopt")
|
||||
gopts := remoteDriverNetworkRequest.Options[netlabel.GenericData]
|
||||
c.Assert(gopts, checker.NotNil)
|
||||
opts, ok := gopts.(map[string]interface{})
|
||||
c.Assert(ok, checker.Equals, true)
|
||||
c.Assert(opts["opt1"], checker.Equals, "drv1")
|
||||
c.Assert(opts["opt2"], checker.Equals, "drv2")
|
||||
dockerCmd(c, "network", "rm", "testopt")
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -16,30 +17,20 @@ func (s *DockerSuite) TestPause(c *check.C) {
|
||||
|
||||
dockerCmd(c, "pause", name)
|
||||
pausedContainers, err := getSliceOfPausedContainers()
|
||||
if err != nil {
|
||||
c.Fatalf("error thrown while checking if containers were paused: %v", err)
|
||||
}
|
||||
if len(pausedContainers) != 1 {
|
||||
c.Fatalf("there should be one paused container and not %d", len(pausedContainers))
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(len(pausedContainers), checker.Equals, 1)
|
||||
|
||||
dockerCmd(c, "unpause", name)
|
||||
|
||||
out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
|
||||
events := strings.Split(out, "\n")
|
||||
if len(events) <= 1 {
|
||||
c.Fatalf("Missing expected event")
|
||||
}
|
||||
c.Assert(len(events) > 1, checker.Equals, true)
|
||||
|
||||
pauseEvent := strings.Fields(events[len(events)-3])
|
||||
unpauseEvent := strings.Fields(events[len(events)-2])
|
||||
|
||||
if pauseEvent[len(pauseEvent)-1] != "pause" {
|
||||
c.Fatalf("event should be pause, not %#v", pauseEvent)
|
||||
}
|
||||
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
|
||||
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
|
||||
}
|
||||
c.Assert(pauseEvent[len(pauseEvent)-1], checker.Equals, "pause")
|
||||
c.Assert(unpauseEvent[len(unpauseEvent)-1], checker.Equals, "unpause")
|
||||
|
||||
}
|
||||
|
||||
@@ -56,20 +47,14 @@ func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) {
|
||||
}
|
||||
dockerCmd(c, append([]string{"pause"}, containers...)...)
|
||||
pausedContainers, err := getSliceOfPausedContainers()
|
||||
if err != nil {
|
||||
c.Fatalf("error thrown while checking if containers were paused: %v", err)
|
||||
}
|
||||
if len(pausedContainers) != len(containers) {
|
||||
c.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(len(pausedContainers), checker.Equals, len(containers))
|
||||
|
||||
dockerCmd(c, append([]string{"unpause"}, containers...)...)
|
||||
|
||||
out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
|
||||
events := strings.Split(out, "\n")
|
||||
if len(events) <= len(containers)*3-2 {
|
||||
c.Fatalf("Missing expected event")
|
||||
}
|
||||
c.Assert(len(events) > len(containers)*3-2, checker.Equals, true)
|
||||
|
||||
pauseEvents := make([][]string, len(containers))
|
||||
unpauseEvents := make([][]string, len(containers))
|
||||
@@ -79,14 +64,10 @@ func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) {
|
||||
}
|
||||
|
||||
for _, pauseEvent := range pauseEvents {
|
||||
if pauseEvent[len(pauseEvent)-1] != "pause" {
|
||||
c.Fatalf("event should be pause, not %#v", pauseEvent)
|
||||
}
|
||||
c.Assert(pauseEvent[len(pauseEvent)-1], checker.Equals, "pause")
|
||||
}
|
||||
for _, unpauseEvent := range unpauseEvents {
|
||||
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
|
||||
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
|
||||
}
|
||||
c.Assert(unpauseEvent[len(unpauseEvent)-1], checker.Equals, "unpause")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -18,15 +19,16 @@ func (s *DockerSuite) TestPortList(c *check.C) {
|
||||
|
||||
out, _ = dockerCmd(c, "port", firstID, "80")
|
||||
|
||||
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
|
||||
c.Error("Port list is not correct")
|
||||
}
|
||||
err := assertPortList(c, out, []string{"0.0.0.0:9876"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out, _ = dockerCmd(c, "port", firstID)
|
||||
|
||||
if !assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"}) {
|
||||
c.Error("Port list is not correct")
|
||||
}
|
||||
err = assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
dockerCmd(c, "rm", "-f", firstID)
|
||||
|
||||
// three port
|
||||
@@ -39,18 +41,19 @@ func (s *DockerSuite) TestPortList(c *check.C) {
|
||||
|
||||
out, _ = dockerCmd(c, "port", ID, "80")
|
||||
|
||||
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
|
||||
c.Error("Port list is not correct")
|
||||
}
|
||||
err = assertPortList(c, out, []string{"0.0.0.0:9876"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out, _ = dockerCmd(c, "port", ID)
|
||||
|
||||
if !assertPortList(c, out, []string{
|
||||
err = assertPortList(c, out, []string{
|
||||
"80/tcp -> 0.0.0.0:9876",
|
||||
"81/tcp -> 0.0.0.0:9877",
|
||||
"82/tcp -> 0.0.0.0:9878"}) {
|
||||
c.Error("Port list is not correct")
|
||||
}
|
||||
"82/tcp -> 0.0.0.0:9878"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
dockerCmd(c, "rm", "-f", ID)
|
||||
|
||||
// more and one port mapped to the same container port
|
||||
@@ -64,19 +67,19 @@ func (s *DockerSuite) TestPortList(c *check.C) {
|
||||
|
||||
out, _ = dockerCmd(c, "port", ID, "80")
|
||||
|
||||
if !assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) {
|
||||
c.Error("Port list is not correct")
|
||||
}
|
||||
err = assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out, _ = dockerCmd(c, "port", ID)
|
||||
|
||||
if !assertPortList(c, out, []string{
|
||||
err = assertPortList(c, out, []string{
|
||||
"80/tcp -> 0.0.0.0:9876",
|
||||
"80/tcp -> 0.0.0.0:9999",
|
||||
"81/tcp -> 0.0.0.0:9877",
|
||||
"82/tcp -> 0.0.0.0:9878"}) {
|
||||
c.Error("Port list is not correct\n", out)
|
||||
}
|
||||
"82/tcp -> 0.0.0.0:9878"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
dockerCmd(c, "rm", "-f", ID)
|
||||
|
||||
testRange := func() {
|
||||
@@ -90,19 +93,17 @@ func (s *DockerSuite) TestPortList(c *check.C) {
|
||||
|
||||
out, _ = dockerCmd(c, "port", IDs[i])
|
||||
|
||||
if !assertPortList(c, out, []string{
|
||||
fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090+i)}) {
|
||||
c.Error("Port list is not correct\n", out)
|
||||
}
|
||||
err = assertPortList(c, out, []string{fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090+i)})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// test port range exhaustion
|
||||
out, _, err := dockerCmdWithError("run", "-d",
|
||||
out, _, err = dockerCmdWithError("run", "-d",
|
||||
"-p", "9090-9092:80",
|
||||
"busybox", "top")
|
||||
if err == nil {
|
||||
c.Errorf("Exhausted port range did not return an error. Out: %s", out)
|
||||
}
|
||||
// Exhausted port range did not return an error
|
||||
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
dockerCmd(c, "rm", "-f", IDs[i])
|
||||
@@ -114,12 +115,11 @@ func (s *DockerSuite) TestPortList(c *check.C) {
|
||||
|
||||
// test invalid port ranges
|
||||
for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} {
|
||||
out, _, err := dockerCmdWithError("run", "-d",
|
||||
out, _, err = dockerCmdWithError("run", "-d",
|
||||
"-p", invalidRange,
|
||||
"busybox", "top")
|
||||
if err == nil {
|
||||
c.Errorf("Port range should have returned an error. Out: %s", out)
|
||||
}
|
||||
// Port range should have returned an error
|
||||
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
|
||||
}
|
||||
|
||||
// test host range:container range spec.
|
||||
@@ -130,13 +130,13 @@ func (s *DockerSuite) TestPortList(c *check.C) {
|
||||
|
||||
out, _ = dockerCmd(c, "port", ID)
|
||||
|
||||
if !assertPortList(c, out, []string{
|
||||
err = assertPortList(c, out, []string{
|
||||
"80/tcp -> 0.0.0.0:9800",
|
||||
"81/tcp -> 0.0.0.0:9801",
|
||||
"82/tcp -> 0.0.0.0:9802",
|
||||
"83/tcp -> 0.0.0.0:9803"}) {
|
||||
c.Error("Port list is not correct\n", out)
|
||||
}
|
||||
"83/tcp -> 0.0.0.0:9803"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
dockerCmd(c, "rm", "-f", ID)
|
||||
|
||||
// test mixing protocols in same port range
|
||||
@@ -148,32 +148,29 @@ func (s *DockerSuite) TestPortList(c *check.C) {
|
||||
|
||||
out, _ = dockerCmd(c, "port", ID)
|
||||
|
||||
if !assertPortList(c, out, []string{
|
||||
err = assertPortList(c, out, []string{
|
||||
"80/tcp -> 0.0.0.0:8000",
|
||||
"80/udp -> 0.0.0.0:8000"}) {
|
||||
c.Error("Port list is not correct\n", out)
|
||||
}
|
||||
"80/udp -> 0.0.0.0:8000"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
dockerCmd(c, "rm", "-f", ID)
|
||||
}
|
||||
|
||||
func assertPortList(c *check.C, out string, expected []string) bool {
|
||||
//lines := strings.Split(out, "\n")
|
||||
func assertPortList(c *check.C, out string, expected []string) error {
|
||||
lines := strings.Split(strings.Trim(out, "\n "), "\n")
|
||||
if len(lines) != len(expected) {
|
||||
c.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
|
||||
return false
|
||||
return fmt.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
|
||||
}
|
||||
sort.Strings(lines)
|
||||
sort.Strings(expected)
|
||||
|
||||
for i := 0; i < len(expected); i++ {
|
||||
if lines[i] != expected[i] {
|
||||
c.Error("|" + lines[i] + "!=" + expected[i] + "|")
|
||||
return false
|
||||
return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|")
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
func stopRemoveContainer(id string, c *check.C) {
|
||||
@@ -193,9 +190,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
|
||||
unpPort1 := fmt.Sprintf("%d/tcp", port1)
|
||||
unpPort2 := fmt.Sprintf("%d/tcp", port2)
|
||||
out, _ := dockerCmd(c, "ps", "-n=1")
|
||||
if !strings.Contains(out, unpPort1) || !strings.Contains(out, unpPort2) {
|
||||
c.Errorf("Missing unpublished ports(s) (%s, %s) in docker ps output: %s", unpPort1, unpPort2, out)
|
||||
}
|
||||
// Missing unpublished ports in docker ps output
|
||||
c.Assert(out, checker.Contains, unpPort1)
|
||||
// Missing unpublished ports in docker ps output
|
||||
c.Assert(out, checker.Contains, unpPort2)
|
||||
|
||||
// Run the container forcing to publish the exposed ports
|
||||
dockerCmd(c, "run", "-d", "-P", expose1, expose2, "busybox", "sleep", "5")
|
||||
@@ -204,10 +202,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
|
||||
expBndRegx1 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort1)
|
||||
expBndRegx2 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort2)
|
||||
out, _ = dockerCmd(c, "ps", "-n=1")
|
||||
if !expBndRegx1.MatchString(out) || !expBndRegx2.MatchString(out) {
|
||||
c.Errorf("Cannot find expected port binding ports(s) (0.0.0.0:xxxxx->%s, 0.0.0.0:xxxxx->%s) in docker ps output:\n%s",
|
||||
unpPort1, unpPort2, out)
|
||||
}
|
||||
// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort1) in docker ps output
|
||||
c.Assert(expBndRegx1.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort1: %s", out, unpPort1))
|
||||
// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort2) in docker ps output
|
||||
c.Assert(expBndRegx2.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort2: %s", out, unpPort2))
|
||||
|
||||
// Run the container specifying explicit port bindings for the exposed ports
|
||||
offset := 10000
|
||||
@@ -220,9 +218,11 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
|
||||
expBnd1 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port1, unpPort1)
|
||||
expBnd2 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port2, unpPort2)
|
||||
out, _ = dockerCmd(c, "ps", "-n=1")
|
||||
if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) {
|
||||
c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out)
|
||||
}
|
||||
// Cannot find expected port binding (expBnd1) in docker ps output
|
||||
c.Assert(out, checker.Contains, expBnd1)
|
||||
// Cannot find expected port binding (expBnd2) in docker ps output
|
||||
c.Assert(out, checker.Contains, expBnd2)
|
||||
|
||||
// Remove container now otherwise it will interfeer with next test
|
||||
stopRemoveContainer(id, c)
|
||||
|
||||
@@ -232,9 +232,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
|
||||
|
||||
// Check docker ps o/p for last created container reports the specified port mappings
|
||||
out, _ = dockerCmd(c, "ps", "-n=1")
|
||||
if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) {
|
||||
c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out)
|
||||
}
|
||||
// Cannot find expected port binding (expBnd1) in docker ps output
|
||||
c.Assert(out, checker.Contains, expBnd1)
|
||||
// Cannot find expected port binding (expBnd2) in docker ps output
|
||||
c.Assert(out, checker.Contains, expBnd2)
|
||||
// Remove container now otherwise it will interfeer with next test
|
||||
stopRemoveContainer(id, c)
|
||||
|
||||
@@ -243,9 +244,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
|
||||
|
||||
// Check docker ps o/p for last created container reports the specified unpublished port and port mapping
|
||||
out, _ = dockerCmd(c, "ps", "-n=1")
|
||||
if !strings.Contains(out, unpPort1) || !strings.Contains(out, expBnd2) {
|
||||
c.Errorf("Missing unpublished ports or port binding (%s, %s) in docker ps output: %s", unpPort1, expBnd2, out)
|
||||
}
|
||||
// Missing unpublished exposed ports (unpPort1) in docker ps output
|
||||
c.Assert(out, checker.Contains, unpPort1)
|
||||
// Missing port binding (expBnd2) in docker ps output
|
||||
c.Assert(out, checker.Contains, expBnd2)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPortHostBinding(c *check.C) {
|
||||
@@ -256,19 +258,18 @@ func (s *DockerSuite) TestPortHostBinding(c *check.C) {
|
||||
|
||||
out, _ = dockerCmd(c, "port", firstID, "80")
|
||||
|
||||
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
|
||||
c.Error("Port list is not correct")
|
||||
}
|
||||
err := assertPortList(c, out, []string{"0.0.0.0:9876"})
|
||||
// Port list is not correct
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
dockerCmd(c, "run", "--net=host", "busybox",
|
||||
"nc", "localhost", "9876")
|
||||
|
||||
dockerCmd(c, "rm", "-f", firstID)
|
||||
|
||||
if _, _, err := dockerCmdWithError("run", "--net=host", "busybox",
|
||||
"nc", "localhost", "9876"); err == nil {
|
||||
c.Error("Port is still bound after the Container is removed")
|
||||
}
|
||||
out, _, err = dockerCmdWithError("run", "--net=host", "busybox", "nc", "localhost", "9876")
|
||||
// Port is still bound after the Container is removed
|
||||
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
|
||||
@@ -280,18 +281,15 @@ func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
|
||||
out, _ = dockerCmd(c, "port", firstID, "80")
|
||||
|
||||
_, exposedPort, err := net.SplitHostPort(out)
|
||||
|
||||
if err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
c.Assert(err, checker.IsNil, check.Commentf("out: %s", out))
|
||||
|
||||
dockerCmd(c, "run", "--net=host", "busybox",
|
||||
"nc", "localhost", strings.TrimSpace(exposedPort))
|
||||
|
||||
dockerCmd(c, "rm", "-f", firstID)
|
||||
|
||||
if _, _, err = dockerCmdWithError("run", "--net=host", "busybox",
|
||||
"nc", "localhost", strings.TrimSpace(exposedPort)); err == nil {
|
||||
c.Error("Port is still bound after the Container is removed")
|
||||
}
|
||||
out, _, err = dockerCmdWithError("run", "--net=host", "busybox",
|
||||
"nc", "localhost", strings.TrimSpace(exposedPort))
|
||||
// Port is still bound after the Container is removed
|
||||
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -15,16 +16,12 @@ func (s *DockerSuite) TestRestartStoppedContainer(c *check.C) {
|
||||
dockerCmd(c, "wait", cleanedContainerID)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", cleanedContainerID)
|
||||
if out != "foobar\n" {
|
||||
c.Errorf("container should've printed 'foobar'")
|
||||
}
|
||||
c.Assert(out, checker.Equals, "foobar\n")
|
||||
|
||||
dockerCmd(c, "restart", cleanedContainerID)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", cleanedContainerID)
|
||||
if out != "foobar\nfoobar\n" {
|
||||
c.Errorf("container should've printed 'foobar' twice, got %v", out)
|
||||
}
|
||||
c.Assert(out, checker.Equals, "foobar\nfoobar\n")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRestartRunningContainer(c *check.C) {
|
||||
@@ -33,22 +30,18 @@ func (s *DockerSuite) TestRestartRunningContainer(c *check.C) {
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
|
||||
c.Assert(waitRun(cleanedContainerID), check.IsNil)
|
||||
c.Assert(waitRun(cleanedContainerID), checker.IsNil)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", cleanedContainerID)
|
||||
if out != "foobar\n" {
|
||||
c.Errorf("container should've printed 'foobar'")
|
||||
}
|
||||
c.Assert(out, checker.Equals, "foobar\n")
|
||||
|
||||
dockerCmd(c, "restart", "-t", "1", cleanedContainerID)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", cleanedContainerID)
|
||||
|
||||
c.Assert(waitRun(cleanedContainerID), check.IsNil)
|
||||
c.Assert(waitRun(cleanedContainerID), checker.IsNil)
|
||||
|
||||
if out != "foobar\nfoobar\n" {
|
||||
c.Errorf("container should've printed 'foobar' twice")
|
||||
}
|
||||
c.Assert(out, checker.Equals, "foobar\nfoobar\n")
|
||||
}
|
||||
|
||||
// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
|
||||
@@ -58,27 +51,21 @@ func (s *DockerSuite) TestRestartWithVolumes(c *check.C) {
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
out, _ = dockerCmd(c, "inspect", "--format", "{{ len .Mounts }}", cleanedContainerID)
|
||||
|
||||
if out = strings.Trim(out, " \n\r"); out != "1" {
|
||||
c.Errorf("expect 1 volume received %s", out)
|
||||
}
|
||||
out = strings.Trim(out, " \n\r")
|
||||
c.Assert(out, checker.Equals, "1")
|
||||
|
||||
source, err := inspectMountSourceField(cleanedContainerID, "/test")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
dockerCmd(c, "restart", cleanedContainerID)
|
||||
|
||||
out, _ = dockerCmd(c, "inspect", "--format", "{{ len .Mounts }}", cleanedContainerID)
|
||||
if out = strings.Trim(out, " \n\r"); out != "1" {
|
||||
c.Errorf("expect 1 volume after restart received %s", out)
|
||||
}
|
||||
out = strings.Trim(out, " \n\r")
|
||||
c.Assert(out, checker.Equals, "1")
|
||||
|
||||
sourceAfterRestart, err := inspectMountSourceField(cleanedContainerID, "/test")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
if source != sourceAfterRestart {
|
||||
c.Errorf("expected volume path: %s Actual path: %s", source, sourceAfterRestart)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(source, checker.Equals, sourceAfterRestart)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRestartPolicyNO(c *check.C) {
|
||||
@@ -87,10 +74,8 @@ func (s *DockerSuite) TestRestartPolicyNO(c *check.C) {
|
||||
|
||||
id := strings.TrimSpace(string(out))
|
||||
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
|
||||
c.Assert(err, check.IsNil)
|
||||
if name != "no" {
|
||||
c.Fatalf("Container restart policy name is %s, expected %s", name, "no")
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(name, checker.Equals, "no")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) {
|
||||
@@ -99,18 +84,14 @@ func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) {
|
||||
|
||||
id := strings.TrimSpace(string(out))
|
||||
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
|
||||
c.Assert(err, check.IsNil)
|
||||
if name != "always" {
|
||||
c.Fatalf("Container restart policy name is %s, expected %s", name, "always")
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(name, checker.Equals, "always")
|
||||
|
||||
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// MaximumRetryCount=0 if the restart policy is always
|
||||
if MaximumRetryCount != "0" {
|
||||
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "0")
|
||||
}
|
||||
c.Assert(MaximumRetryCount, checker.Equals, "0")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) {
|
||||
@@ -119,10 +100,8 @@ func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) {
|
||||
|
||||
id := strings.TrimSpace(string(out))
|
||||
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
|
||||
c.Assert(err, check.IsNil)
|
||||
if name != "on-failure" {
|
||||
c.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(name, checker.Equals, "on-failure")
|
||||
|
||||
}
|
||||
|
||||
@@ -133,18 +112,15 @@ func (s *DockerSuite) TestContainerRestartwithGoodContainer(c *check.C) {
|
||||
out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "true")
|
||||
|
||||
id := strings.TrimSpace(string(out))
|
||||
if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5*time.Second); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5*time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
count, err := inspectField(id, "RestartCount")
|
||||
c.Assert(err, check.IsNil)
|
||||
if count != "0" {
|
||||
c.Fatalf("Container was restarted %s times, expected %d", count, 0)
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(count, checker.Equals, "0")
|
||||
|
||||
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
|
||||
c.Assert(err, check.IsNil)
|
||||
if MaximumRetryCount != "3" {
|
||||
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
|
||||
}
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(MaximumRetryCount, checker.Equals, "3")
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -13,9 +14,8 @@ func (s *DockerSuite) TestRmContainerWithRemovedVolume(c *check.C) {
|
||||
|
||||
dockerCmd(c, "run", "--name", "losemyvolumes", "-v", "/tmp/testing:/test", "busybox", "true")
|
||||
|
||||
if err := os.Remove("/tmp/testing"); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
err := os.Remove("/tmp/testing")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
dockerCmd(c, "rm", "-v", "losemyvolumes")
|
||||
}
|
||||
@@ -31,9 +31,8 @@ func (s *DockerSuite) TestRmRunningContainer(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
createRunningContainer(c, "foo")
|
||||
|
||||
if _, _, err := dockerCmdWithError("rm", "foo"); err == nil {
|
||||
c.Fatalf("Expected error, can't rm a running container")
|
||||
}
|
||||
_, _, err := dockerCmdWithError("rm", "foo")
|
||||
c.Assert(err, checker.NotNil, check.Commentf("Expected error, can't rm a running container"))
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmForceRemoveRunningContainer(c *check.C) {
|
||||
@@ -55,31 +54,20 @@ func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
|
||||
|
||||
// build first dockerfile
|
||||
img1, err := buildImage(img, dockerfile1, true)
|
||||
if err != nil {
|
||||
c.Fatalf("Could not build image %s: %v", img, err)
|
||||
}
|
||||
c.Assert(err, check.IsNil, check.Commentf("Could not build image %s", img))
|
||||
// run container on first image
|
||||
if out, _, err := dockerCmdWithError("run", img); err != nil {
|
||||
c.Fatalf("Could not run image %s: %v: %s", img, err, out)
|
||||
}
|
||||
|
||||
dockerCmd(c, "run", img)
|
||||
// rebuild dockerfile with a small addition at the end
|
||||
if _, err := buildImage(img, dockerfile2, true); err != nil {
|
||||
c.Fatalf("Could not rebuild image %s: %v", img, err)
|
||||
}
|
||||
_, err = buildImage(img, dockerfile2, true)
|
||||
c.Assert(err, check.IsNil, check.Commentf("Could not rebuild image %s", img))
|
||||
// try to remove the image, should error out.
|
||||
if out, _, err := dockerCmdWithError("rmi", img); err == nil {
|
||||
c.Fatalf("Expected to error out removing the image, but succeeded: %s", out)
|
||||
}
|
||||
out, _, err := dockerCmdWithError("rmi", img)
|
||||
c.Assert(err, check.NotNil, check.Commentf("Expected to error out removing the image, but succeeded: %s", out))
|
||||
|
||||
// check if we deleted the first image
|
||||
out, _, err := dockerCmdWithError("images", "-q", "--no-trunc")
|
||||
if err != nil {
|
||||
c.Fatalf("%v: %s", err, out)
|
||||
}
|
||||
if !strings.Contains(out, img1) {
|
||||
c.Fatalf("Orphaned container (could not find %q in docker images): %s", img1, out)
|
||||
}
|
||||
out, _ = dockerCmd(c, "images", "-q", "--no-trunc")
|
||||
c.Assert(out, checker.Contains, img1, check.Commentf("Orphaned container (could not find %q in docker images): %s", img1, out))
|
||||
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmInvalidContainer(c *check.C) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -13,27 +14,21 @@ func (s *DockerSuite) TestRmiWithContainerFails(c *check.C) {
|
||||
errSubstr := "is using it"
|
||||
|
||||
// create a container
|
||||
out, _, err := dockerCmdWithError("run", "-d", "busybox", "true")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to create a container: %s, %v", out, err)
|
||||
}
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
|
||||
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
|
||||
// try to delete the image
|
||||
out, _, err = dockerCmdWithError("rmi", "busybox")
|
||||
if err == nil {
|
||||
c.Fatalf("Container %q is using image, should not be able to rmi: %q", cleanedContainerID, out)
|
||||
}
|
||||
if !strings.Contains(out, errSubstr) {
|
||||
c.Fatalf("Container %q is using image, error message should contain %q: %v", cleanedContainerID, errSubstr, out)
|
||||
}
|
||||
out, _, err := dockerCmdWithError("rmi", "busybox")
|
||||
// Container is using image, should not be able to rmi
|
||||
c.Assert(err, checker.NotNil)
|
||||
// Container is using image, error message should contain errSubstr
|
||||
c.Assert(out, checker.Contains, errSubstr, check.Commentf("Container: %q", cleanedContainerID))
|
||||
|
||||
// make sure it didn't delete the busybox name
|
||||
images, _ := dockerCmd(c, "images")
|
||||
if !strings.Contains(images, "busybox") {
|
||||
c.Fatalf("The name 'busybox' should not have been removed from images: %q", images)
|
||||
}
|
||||
// The name 'busybox' should not have been removed from images
|
||||
c.Assert(images, checker.Contains, "busybox")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiTag(c *check.C) {
|
||||
@@ -44,97 +39,71 @@ func (s *DockerSuite) TestRmiTag(c *check.C) {
|
||||
dockerCmd(c, "tag", "busybox", "utest:5000/docker:tag3")
|
||||
{
|
||||
imagesAfter, _ := dockerCmd(c, "images", "-a")
|
||||
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+3 {
|
||||
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
|
||||
}
|
||||
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+3, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
|
||||
}
|
||||
dockerCmd(c, "rmi", "utest/docker:tag2")
|
||||
{
|
||||
imagesAfter, _ := dockerCmd(c, "images", "-a")
|
||||
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+2 {
|
||||
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
|
||||
}
|
||||
|
||||
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+2, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
|
||||
}
|
||||
dockerCmd(c, "rmi", "utest:5000/docker:tag3")
|
||||
{
|
||||
imagesAfter, _ := dockerCmd(c, "images", "-a")
|
||||
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+1 {
|
||||
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
|
||||
}
|
||||
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+1, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
|
||||
|
||||
}
|
||||
dockerCmd(c, "rmi", "utest:tag1")
|
||||
{
|
||||
imagesAfter, _ := dockerCmd(c, "images", "-a")
|
||||
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+0 {
|
||||
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
|
||||
}
|
||||
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n"), check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiImgIDMultipleTag(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _, err := dockerCmdWithError("run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-one'")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to create a container:%s, %v", out, err)
|
||||
}
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-one'")
|
||||
|
||||
containerID := strings.TrimSpace(out)
|
||||
out, _, err = dockerCmdWithError("commit", containerID, "busybox-one")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to commit a new busybox-one:%s, %v", out, err)
|
||||
}
|
||||
dockerCmd(c, "commit", containerID, "busybox-one")
|
||||
|
||||
imagesBefore, _ := dockerCmd(c, "images", "-a")
|
||||
dockerCmd(c, "tag", "busybox-one", "busybox-one:tag1")
|
||||
dockerCmd(c, "tag", "busybox-one", "busybox-one:tag2")
|
||||
|
||||
imagesAfter, _ := dockerCmd(c, "images", "-a")
|
||||
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+2 {
|
||||
c.Fatalf("tag busybox to create 2 more images with same imageID; docker images shows: %q\n", imagesAfter)
|
||||
}
|
||||
// tag busybox to create 2 more images with same imageID
|
||||
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+2, check.Commentf("docker images shows: %q\n", imagesAfter))
|
||||
|
||||
imgID, err := inspectField("busybox-one:tag1", "Id")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// run a container with the image
|
||||
out, _, err = dockerCmdWithError("run", "-d", "busybox-one", "top")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to create a container:%s, %v", out, err)
|
||||
}
|
||||
out, _ = dockerCmd(c, "run", "-d", "busybox-one", "top")
|
||||
|
||||
containerID = strings.TrimSpace(out)
|
||||
|
||||
// first checkout without force it fails
|
||||
out, _, err = dockerCmdWithError("rmi", imgID)
|
||||
expected := fmt.Sprintf("conflict: unable to delete %s (cannot be forced) - image is being used by running container %s", imgID[:12], containerID[:12])
|
||||
if err == nil || !strings.Contains(out, expected) {
|
||||
c.Fatalf("rmi tagged in multiple repos should have failed without force: %s, %v, expected: %s", out, err, expected)
|
||||
}
|
||||
// rmi tagged in multiple repos should have failed without force
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(out, checker.Contains, expected)
|
||||
|
||||
dockerCmd(c, "stop", containerID)
|
||||
dockerCmd(c, "rmi", "-f", imgID)
|
||||
|
||||
imagesAfter, _ = dockerCmd(c, "images", "-a")
|
||||
if strings.Contains(imagesAfter, imgID[:12]) {
|
||||
c.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
|
||||
}
|
||||
// rmi -f failed, image still exists
|
||||
c.Assert(imagesAfter, checker.Not(checker.Contains), imgID[:12], check.Commentf("ImageID:%q; ImagesAfter: %q", imgID, imagesAfter))
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _, err := dockerCmdWithError("run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to create a container:%s, %v", out, err)
|
||||
}
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'")
|
||||
|
||||
containerID := strings.TrimSpace(out)
|
||||
out, _, err = dockerCmdWithError("commit", containerID, "busybox-test")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to commit a new busybox-test:%s, %v", out, err)
|
||||
}
|
||||
dockerCmd(c, "commit", containerID, "busybox-test")
|
||||
|
||||
imagesBefore, _ := dockerCmd(c, "images", "-a")
|
||||
dockerCmd(c, "tag", "busybox-test", "utest:tag1")
|
||||
@@ -143,25 +112,23 @@ func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
|
||||
dockerCmd(c, "tag", "busybox-test", "utest:5000/docker:tag4")
|
||||
{
|
||||
imagesAfter, _ := dockerCmd(c, "images", "-a")
|
||||
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+4 {
|
||||
c.Fatalf("tag busybox to create 4 more images with same imageID; docker images shows: %q\n", imagesAfter)
|
||||
}
|
||||
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+4, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
|
||||
}
|
||||
imgID, err := inspectField("busybox-test", "Id")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// first checkout without force it fails
|
||||
out, _, err = dockerCmdWithError("rmi", imgID)
|
||||
if err == nil || !strings.Contains(out, "(must be forced) - image is referenced in one or more repositories") {
|
||||
c.Fatalf("rmi tagged in multiple repos should have failed without force:%s, %v", out, err)
|
||||
}
|
||||
// rmi tagged in multiple repos should have failed without force
|
||||
c.Assert(err, checker.NotNil)
|
||||
// rmi tagged in multiple repos should have failed without force
|
||||
c.Assert(out, checker.Contains, "(must be forced) - image is referenced in one or more repositories", check.Commentf("out: %s; err: %v;", out, err))
|
||||
|
||||
dockerCmd(c, "rmi", "-f", imgID)
|
||||
{
|
||||
imagesAfter, _ := dockerCmd(c, "images", "-a")
|
||||
if strings.Contains(imagesAfter, imgID[:12]) {
|
||||
c.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
|
||||
}
|
||||
// rmi failed, image still exists
|
||||
c.Assert(imagesAfter, checker.Not(checker.Contains), imgID[:12])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,17 +137,16 @@ func (s *DockerSuite) TestRmiImageIDForceWithRunningContainersAndMultipleTags(c
|
||||
testRequires(c, DaemonIsLinux)
|
||||
dockerfile := "FROM busybox\nRUN echo test 14116\n"
|
||||
imgID, err := buildImage("test-14116", dockerfile, false)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
newTag := "newtag"
|
||||
dockerCmd(c, "tag", imgID, newTag)
|
||||
dockerCmd(c, "run", "-d", imgID, "top")
|
||||
|
||||
out, _, err := dockerCmdWithError("rmi", "-f", imgID)
|
||||
if err == nil || !strings.Contains(out, "(cannot be forced) - image is being used by running container") {
|
||||
c.Log(out)
|
||||
c.Fatalf("rmi -f should not delete image with running containers")
|
||||
}
|
||||
// rmi -f should not delete image with running containers
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(out, checker.Contains, "(cannot be forced) - image is being used by running container")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
|
||||
@@ -188,19 +154,12 @@ func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
|
||||
container := "test-delete-tag"
|
||||
newtag := "busybox:newtag"
|
||||
bb := "busybox:latest"
|
||||
if out, _, err := dockerCmdWithError("tag", bb, newtag); err != nil {
|
||||
c.Fatalf("Could not tag busybox: %v: %s", err, out)
|
||||
}
|
||||
if out, _, err := dockerCmdWithError("run", "--name", container, bb, "/bin/true"); err != nil {
|
||||
c.Fatalf("Could not run busybox: %v: %s", err, out)
|
||||
}
|
||||
out, _, err := dockerCmdWithError("rmi", newtag)
|
||||
if err != nil {
|
||||
c.Fatalf("Could not remove tag %s: %v: %s", newtag, err, out)
|
||||
}
|
||||
if d := strings.Count(out, "Untagged: "); d != 1 {
|
||||
c.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
|
||||
}
|
||||
dockerCmd(c, "tag", bb, newtag)
|
||||
|
||||
dockerCmd(c, "run", "--name", container, bb, "/bin/true")
|
||||
|
||||
out, _ := dockerCmd(c, "rmi", newtag)
|
||||
c.Assert(strings.Count(out, "Untagged: "), checker.Equals, 1)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
|
||||
@@ -211,17 +170,12 @@ func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
|
||||
cmd.Stdin = strings.NewReader(`FROM busybox
|
||||
MAINTAINER foo`)
|
||||
|
||||
if out, _, err := runCommandWithOutput(cmd); err != nil {
|
||||
c.Fatalf("Could not build %s: %s, %v", image, out, err)
|
||||
}
|
||||
out, _, err := runCommandWithOutput(cmd)
|
||||
c.Assert(err, checker.IsNil, check.Commentf("Could not build %s: %s", image, out))
|
||||
|
||||
if out, _, err := dockerCmdWithError("run", "--name", "test-force-rmi", image, "/bin/true"); err != nil {
|
||||
c.Fatalf("Could not run container: %s, %v", out, err)
|
||||
}
|
||||
dockerCmd(c, "run", "--name", "test-force-rmi", image, "/bin/true")
|
||||
|
||||
if out, _, err := dockerCmdWithError("rmi", "-f", image); err != nil {
|
||||
c.Fatalf("Could not remove image %s: %s, %v", image, out, err)
|
||||
}
|
||||
dockerCmd(c, "rmi", "-f", image)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) {
|
||||
@@ -229,51 +183,32 @@ func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) {
|
||||
newRepo := "127.0.0.1:5000/busybox"
|
||||
oldRepo := "busybox"
|
||||
newTag := "busybox:test"
|
||||
out, _, err := dockerCmdWithError("tag", oldRepo, newRepo)
|
||||
if err != nil {
|
||||
c.Fatalf("Could not tag busybox: %v: %s", err, out)
|
||||
}
|
||||
dockerCmd(c, "tag", oldRepo, newRepo)
|
||||
|
||||
out, _, err = dockerCmdWithError("run", "--name", "test", oldRepo, "touch", "/home/abcd")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to run container: %v, output: %s", err, out)
|
||||
}
|
||||
dockerCmd(c, "run", "--name", "test", oldRepo, "touch", "/home/abcd")
|
||||
|
||||
out, _, err = dockerCmdWithError("commit", "test", newTag)
|
||||
if err != nil {
|
||||
c.Fatalf("failed to commit container: %v, output: %s", err, out)
|
||||
}
|
||||
dockerCmd(c, "commit", "test", newTag)
|
||||
|
||||
out, _, err = dockerCmdWithError("rmi", newTag)
|
||||
if err != nil {
|
||||
c.Fatalf("failed to remove image: %v, output: %s", err, out)
|
||||
}
|
||||
if !strings.Contains(out, "Untagged: "+newTag) {
|
||||
c.Fatalf("Could not remove image %s: %s, %v", newTag, out, err)
|
||||
}
|
||||
out, _ := dockerCmd(c, "rmi", newTag)
|
||||
c.Assert(out, checker.Contains, "Untagged: "+newTag)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiBlank(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// try to delete a blank image name
|
||||
out, _, err := dockerCmdWithError("rmi", "")
|
||||
if err == nil {
|
||||
c.Fatal("Should have failed to delete '' image")
|
||||
}
|
||||
if strings.Contains(out, "no such id") {
|
||||
c.Fatalf("Wrong error message generated: %s", out)
|
||||
}
|
||||
if !strings.Contains(out, "image name cannot be blank") {
|
||||
c.Fatalf("Expected error message not generated: %s", out)
|
||||
}
|
||||
// Should have failed to delete '' image
|
||||
c.Assert(err, checker.NotNil)
|
||||
// Wrong error message generated
|
||||
c.Assert(out, checker.Not(checker.Contains), "no such id", check.Commentf("out: %s", out))
|
||||
// Expected error message not generated
|
||||
c.Assert(out, checker.Contains, "image name cannot be blank", check.Commentf("out: %s", out))
|
||||
|
||||
out, _, err = dockerCmdWithError("rmi", " ")
|
||||
if err == nil {
|
||||
c.Fatal("Should have failed to delete '' image")
|
||||
}
|
||||
if !strings.Contains(out, "no such id") {
|
||||
c.Fatalf("Expected error message not generated: %s", out)
|
||||
}
|
||||
// Should have failed to delete '' image
|
||||
c.Assert(err, checker.NotNil)
|
||||
// Expected error message not generated
|
||||
c.Assert(out, checker.Contains, "no such id", check.Commentf("out: %s", out))
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
|
||||
@@ -284,7 +219,7 @@ func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
|
||||
for i, name := range imageNames {
|
||||
dockerfile := fmt.Sprintf("FROM busybox\nMAINTAINER %s\nRUN echo %s\n", name, name)
|
||||
id, err := buildImage(name, dockerfile, false)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
imageIds[i] = id
|
||||
}
|
||||
|
||||
@@ -297,10 +232,9 @@ func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
|
||||
|
||||
// Try to remove the image of the running container and see if it fails as expected.
|
||||
out, _, err := dockerCmdWithError("rmi", "-f", imageIds[0])
|
||||
if err == nil || !strings.Contains(out, "image is being used by running container") {
|
||||
c.Log(out)
|
||||
c.Fatal("The image of the running container should not be removed.")
|
||||
}
|
||||
// The image of the running container should not be removed.
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(out, checker.Contains, "image is being used by running container", check.Commentf("out: %s", out))
|
||||
}
|
||||
|
||||
// #13422
|
||||
@@ -315,7 +249,7 @@ RUN echo 1 #layer1
|
||||
RUN echo 2 #layer2
|
||||
`
|
||||
_, err := buildImage(image, dockerfile, false)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out, _ := dockerCmd(c, "history", "-q", image)
|
||||
ids := strings.Split(out, "\n")
|
||||
@@ -329,10 +263,8 @@ RUN echo 2 #layer2
|
||||
|
||||
// See if the "tmp2" can be untagged.
|
||||
out, _ = dockerCmd(c, "rmi", newTag)
|
||||
if d := strings.Count(out, "Untagged: "); d != 1 {
|
||||
c.Log(out)
|
||||
c.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
|
||||
}
|
||||
// Expected 1 untagged entry
|
||||
c.Assert(strings.Count(out, "Untagged: "), checker.Equals, 1, check.Commentf("out: %s", out))
|
||||
|
||||
// Now let's add the tag again and create a container based on it.
|
||||
dockerCmd(c, "tag", idToTag, newTag)
|
||||
@@ -342,15 +274,13 @@ RUN echo 2 #layer2
|
||||
// At this point we have 2 containers, one based on layer2 and another based on layer0.
|
||||
// Try to untag "tmp2" without the -f flag.
|
||||
out, _, err = dockerCmdWithError("rmi", newTag)
|
||||
if err == nil || !strings.Contains(out, cid[:12]) || !strings.Contains(out, "(must force)") {
|
||||
c.Log(out)
|
||||
c.Fatalf("%q should not be untagged without the -f flag", newTag)
|
||||
}
|
||||
// should not be untagged without the -f flag
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(out, checker.Contains, cid[:12])
|
||||
c.Assert(out, checker.Contains, "(must force)")
|
||||
|
||||
// Add the -f flag and test again.
|
||||
out, _ = dockerCmd(c, "rmi", "-f", newTag)
|
||||
if !strings.Contains(out, fmt.Sprintf("Untagged: %s:latest", newTag)) {
|
||||
c.Log(out)
|
||||
c.Fatalf("%q should be allowed to untag with the -f flag", newTag)
|
||||
}
|
||||
// should be allowed to untag with the -f flag
|
||||
c.Assert(out, checker.Contains, fmt.Sprintf("Untagged: %s:latest", newTag))
|
||||
}
|
||||
|
||||
@@ -1197,7 +1197,7 @@ func (s *DockerSuite) TestRunNonRootUserResolvName(c *check.C) {
|
||||
// uses the host's /etc/resolv.conf and does not have any dns options provided.
|
||||
func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) {
|
||||
// Not applicable on Windows as testing unix specific functionality
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NativeExecDriver)
|
||||
|
||||
tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\n")
|
||||
tmpLocalhostResolvConf := []byte("nameserver 127.0.0.1")
|
||||
@@ -3425,13 +3425,10 @@ func (s *DockerSuite) TestContainersInUserDefinedNetwork(c *check.C) {
|
||||
dockerCmd(c, "run", "-d", "--net=testnetwork", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
dockerCmd(c, "run", "-t", "--net=testnetwork", "--name=second", "busybox", "ping", "-c", "1", "first")
|
||||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "stop", "second")
|
||||
dockerCmd(c, "network", "rm", "testnetwork")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace, NativeExecDriver)
|
||||
// Create 2 networks using bridge driver
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
|
||||
@@ -3447,14 +3444,10 @@ func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
|
||||
dockerCmd(c, "network", "connect", "testnetwork2", "second")
|
||||
// Check connectivity between containers
|
||||
dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2")
|
||||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "stop", "second")
|
||||
dockerCmd(c, "network", "rm", "testnetwork1")
|
||||
dockerCmd(c, "network", "rm", "testnetwork2")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace, NativeExecDriver)
|
||||
// Create 2 networks using bridge driver
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
|
||||
@@ -3478,11 +3471,6 @@ func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
|
||||
// ping must fail again
|
||||
_, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second")
|
||||
c.Assert(err, check.NotNil)
|
||||
|
||||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "stop", "second")
|
||||
dockerCmd(c, "network", "rm", "testnetwork1")
|
||||
dockerCmd(c, "network", "rm", "testnetwork2")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
|
||||
@@ -3501,17 +3489,14 @@ func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
|
||||
dockerCmd(c, "stop", "first")
|
||||
_, _, err = dockerCmdWithError("network", "rm", "testnetwork1")
|
||||
c.Assert(err, check.NotNil)
|
||||
|
||||
dockerCmd(c, "stop", "second")
|
||||
// Network delete must succeed after all the connected containers are inactive
|
||||
dockerCmd(c, "network", "rm", "testnetwork1")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace, NativeExecDriver)
|
||||
// Create 2 networks using bridge driver
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
|
||||
|
||||
// Run and connect containers to testnetwork1
|
||||
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
@@ -3536,11 +3521,6 @@ func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
|
||||
dockerCmd(c, "start", "second")
|
||||
dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1")
|
||||
dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2")
|
||||
|
||||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "stop", "second")
|
||||
dockerCmd(c, "network", "rm", "testnetwork1")
|
||||
dockerCmd(c, "network", "rm", "testnetwork2")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
|
||||
@@ -3555,8 +3535,6 @@ func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
|
||||
// Connecting to the user defined network must fail
|
||||
_, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "first")
|
||||
c.Assert(err, check.NotNil)
|
||||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "network", "rm", "testnetwork1")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
|
||||
@@ -3574,10 +3552,6 @@ func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
|
||||
out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "second")
|
||||
c.Assert(err, check.NotNil)
|
||||
c.Assert(out, checker.Contains, runconfig.ErrConflictSharedNetwork.Error())
|
||||
|
||||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "stop", "second")
|
||||
dockerCmd(c, "network", "rm", "testnetwork1")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) {
|
||||
@@ -3600,10 +3574,6 @@ func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) {
|
||||
// Connect second container to none network. it must fail as well
|
||||
_, _, err = dockerCmdWithError("network", "connect", "none", "second")
|
||||
c.Assert(err, check.NotNil)
|
||||
|
||||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "stop", "second")
|
||||
dockerCmd(c, "network", "rm", "testnetwork1")
|
||||
}
|
||||
|
||||
// #11957 - stdin with no tty does not exit if stdin is not closed even though container exited
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"github.com/docker/docker/pkg/units"
|
||||
"github.com/go-check/check"
|
||||
"github.com/kr/pty"
|
||||
)
|
||||
@@ -272,9 +273,10 @@ func (s *DockerSuite) TestRunWithBlkioWeight(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunWithBlkioInvalidWeight(c *check.C) {
|
||||
testRequires(c, blkioWeight)
|
||||
if _, _, err := dockerCmdWithError("run", "--blkio-weight", "5", "busybox", "true"); err == nil {
|
||||
c.Fatalf("run with invalid blkio-weight should failed")
|
||||
}
|
||||
out, _, err := dockerCmdWithError("run", "--blkio-weight", "5", "busybox", "true")
|
||||
c.Assert(err, check.NotNil, check.Commentf(out))
|
||||
expected := "Range of blkio weight is from 10 to 1000"
|
||||
c.Assert(out, checker.Contains, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunOOMExitCode(c *check.C) {
|
||||
@@ -419,7 +421,7 @@ func (s *DockerSuite) TestRunInvalidCpusetMemsFlagValue(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) {
|
||||
testRequires(c, cpuShare)
|
||||
testRequires(c, cpuShare, NativeExecDriver)
|
||||
out, _, err := dockerCmdWithError("run", "--cpu-shares", "1", "busybox", "echo", "test")
|
||||
c.Assert(err, check.NotNil, check.Commentf(out))
|
||||
expected := "The minimum allowed cpu-shares is 2"
|
||||
@@ -435,3 +437,22 @@ func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) {
|
||||
expected = "The maximum allowed cpu-shares is"
|
||||
c.Assert(out, checker.Contains, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunWithCorrectMemorySwapOnLXC(c *check.C) {
|
||||
testRequires(c, memoryLimitSupport)
|
||||
testRequires(c, swapMemorySupport)
|
||||
testRequires(c, SameHostDaemon)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "-d", "-m", "16m", "--memory-swap", "64m", "busybox", "top")
|
||||
if _, err := os.Stat("/sys/fs/cgroup/memory/lxc"); err != nil {
|
||||
c.Skip("Excecution driver must be LXC for this test")
|
||||
}
|
||||
id := strings.TrimSpace(out)
|
||||
memorySwap, err := ioutil.ReadFile(fmt.Sprintf("/sys/fs/cgroup/memory/lxc/%s/memory.memsw.limit_in_bytes", id))
|
||||
c.Assert(err, check.IsNil)
|
||||
cgSwap, err := strconv.ParseInt(strings.TrimSpace(string(memorySwap)), 10, 64)
|
||||
c.Assert(err, check.IsNil)
|
||||
swap, err := units.RAMInBytes("64m")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(cgSwap, check.Equals, swap)
|
||||
}
|
||||
|
||||
@@ -37,9 +37,7 @@ func makefile(contents string) (string, func(), error) {
|
||||
// attempt to contact any v1 registry endpoints.
|
||||
func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
reg, err := newTestRegistry(c)
|
||||
if err != nil {
|
||||
c.Fatal(err.Error())
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(404)
|
||||
@@ -52,14 +50,10 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
repoName := fmt.Sprintf("%s/busybox", reg.hostport)
|
||||
|
||||
err = s.d.Start("--insecure-registry", reg.hostport, "--disable-legacy-registry=true")
|
||||
if err != nil {
|
||||
c.Fatalf("Error starting daemon: %s", err.Error())
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport))
|
||||
if err != nil {
|
||||
c.Fatalf("Unable to create test dockerfile")
|
||||
}
|
||||
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
|
||||
defer cleanup()
|
||||
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
@@ -76,9 +70,7 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
// login, push, pull, build & run
|
||||
func (s *DockerRegistrySuite) TestV1(c *check.C) {
|
||||
reg, err := newTestRegistry(c)
|
||||
if err != nil {
|
||||
c.Fatal(err.Error())
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
v2Pings := 0
|
||||
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -107,42 +99,29 @@ func (s *DockerRegistrySuite) TestV1(c *check.C) {
|
||||
})
|
||||
|
||||
err = s.d.Start("--insecure-registry", reg.hostport, "--disable-legacy-registry=false")
|
||||
if err != nil {
|
||||
c.Fatalf("Error starting daemon: %s", err.Error())
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport))
|
||||
if err != nil {
|
||||
c.Fatalf("Unable to create test dockerfile")
|
||||
}
|
||||
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
|
||||
defer cleanup()
|
||||
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
if v1Repo == 0 {
|
||||
c.Errorf("Expected v1 repository access after build")
|
||||
}
|
||||
c.Assert(v1Repo, check.Not(check.Equals), 0, check.Commentf("Expected v1 repository access after build"))
|
||||
|
||||
repoName := fmt.Sprintf("%s/busybox", reg.hostport)
|
||||
s.d.Cmd("run", repoName)
|
||||
if v1Repo == 1 {
|
||||
c.Errorf("Expected v1 repository access after run")
|
||||
}
|
||||
c.Assert(v1Repo, check.Not(check.Equals), 1, check.Commentf("Expected v1 repository access after run"))
|
||||
|
||||
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.hostport)
|
||||
if v1Logins == 0 {
|
||||
c.Errorf("Expected v1 login attempt")
|
||||
}
|
||||
c.Assert(v1Logins, check.Not(check.Equals), 0, check.Commentf("Expected v1 login attempt"))
|
||||
|
||||
s.d.Cmd("tag", "busybox", repoName)
|
||||
s.d.Cmd("push", repoName)
|
||||
|
||||
if v1Repo != 2 || v1Pings != 1 {
|
||||
c.Error("Not all endpoints contacted after push", v1Repo, v1Pings)
|
||||
}
|
||||
c.Assert(v1Repo, check.Equals, 2)
|
||||
c.Assert(v1Pings, check.Equals, 1)
|
||||
|
||||
s.d.Cmd("pull", repoName)
|
||||
if v1Repo != 3 {
|
||||
c.Errorf("Expected v1 repository access after pull")
|
||||
}
|
||||
c.Assert(v1Repo, check.Equals, 3, check.Commentf("Expected v1 repository access after pull"))
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -21,9 +22,7 @@ func (s *DockerSuite) TestVersionEnsureSucceeds(c *check.C) {
|
||||
}
|
||||
|
||||
for k, v := range stringsToCheck {
|
||||
if strings.Count(out, k) != v {
|
||||
c.Errorf("%v expected %d instances found %d", k, v, strings.Count(out, k))
|
||||
}
|
||||
c.Assert(strings.Count(out, k), checker.Equals, v, check.Commentf("The count of %v in %s does not match excepted", k, out))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +43,7 @@ func testVersionPlatform(c *check.C, platform string) {
|
||||
expected := "OS/Arch: " + platform
|
||||
|
||||
split := strings.Split(out, "\n")
|
||||
if len(split) < 14 { // To avoid invalid indexing in loop below
|
||||
c.Errorf("got %d lines from version", len(split))
|
||||
}
|
||||
c.Assert(len(split) >= 14, checker.Equals, true, check.Commentf("got %d lines from version", len(split)))
|
||||
|
||||
// Verify the second 'OS/Arch' matches the platform. Experimental has
|
||||
// more lines of output than 'regular'
|
||||
@@ -57,7 +54,5 @@ func testVersionPlatform(c *check.C, platform string) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !bFound {
|
||||
c.Errorf("Could not find server '%s' in '%s'", expected, out)
|
||||
}
|
||||
c.Assert(bFound, checker.Equals, true, check.Commentf("Could not find server '%s' in '%s'", expected, out))
|
||||
}
|
||||
|
||||
@@ -57,21 +57,15 @@ type Daemon struct {
|
||||
// The daemon will not automatically start.
|
||||
func NewDaemon(c *check.C) *Daemon {
|
||||
dest := os.Getenv("DEST")
|
||||
if dest == "" {
|
||||
c.Fatal("Please set the DEST environment variable")
|
||||
}
|
||||
c.Assert(dest, check.Not(check.Equals), "", check.Commentf("Please set the DEST environment variable"))
|
||||
|
||||
id := fmt.Sprintf("d%d", time.Now().UnixNano()%100000000)
|
||||
dir := filepath.Join(dest, id)
|
||||
daemonFolder, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
c.Fatalf("Could not make %q an absolute path: %v", dir, err)
|
||||
}
|
||||
c.Assert(err, check.IsNil, check.Commentf("Could not make %q an absolute path", dir))
|
||||
daemonRoot := filepath.Join(daemonFolder, "root")
|
||||
|
||||
if err := os.MkdirAll(daemonRoot, 0755); err != nil {
|
||||
c.Fatalf("Could not create daemon root %q: %v", dir, err)
|
||||
}
|
||||
c.Assert(os.MkdirAll(daemonRoot, 0755), check.IsNil, check.Commentf("Could not create daemon root %q", dir))
|
||||
|
||||
userlandProxy := true
|
||||
if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" {
|
||||
@@ -96,9 +90,7 @@ func NewDaemon(c *check.C) *Daemon {
|
||||
// You can specify additional daemon flags.
|
||||
func (d *Daemon) Start(arg ...string) error {
|
||||
dockerBinary, err := exec.LookPath(dockerBinary)
|
||||
if err != nil {
|
||||
d.c.Fatalf("[%s] could not find docker binary in $PATH: %v", d.id, err)
|
||||
}
|
||||
d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not find docker binary in $PATH", d.id))
|
||||
|
||||
args := append(d.GlobalFlags,
|
||||
d.Command,
|
||||
@@ -136,9 +128,7 @@ func (d *Daemon) Start(arg ...string) error {
|
||||
d.cmd = exec.Command(dockerBinary, args...)
|
||||
|
||||
d.logFile, err = os.OpenFile(filepath.Join(d.folder, "docker.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
d.c.Fatalf("[%s] Could not create %s/docker.log: %v", d.id, d.folder, err)
|
||||
}
|
||||
d.c.Assert(err, check.IsNil, check.Commentf("[%s] Could not create %s/docker.log", d.id, d.folder))
|
||||
|
||||
d.cmd.Stdout = d.logFile
|
||||
d.cmd.Stderr = d.logFile
|
||||
@@ -187,9 +177,7 @@ func (d *Daemon) Start(arg ...string) error {
|
||||
defer client.Close()
|
||||
|
||||
req, err := http.NewRequest("GET", "/_ping", nil)
|
||||
if err != nil {
|
||||
d.c.Fatalf("[%s] could not create new request: %v", d.id, err)
|
||||
}
|
||||
d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not create new request", d.id))
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
@@ -506,6 +494,42 @@ func deleteAllContainers() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteAllNetworks() error {
|
||||
networks, err := getAllNetworks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var errors []string
|
||||
for _, n := range networks {
|
||||
if n.Name != "bridge" {
|
||||
status, b, err := sockRequest("DELETE", "/networks/"+n.Name, nil)
|
||||
if err != nil {
|
||||
errors = append(errors, err.Error())
|
||||
continue
|
||||
}
|
||||
if status != http.StatusNoContent {
|
||||
errors = append(errors, fmt.Sprintf("error deleting network %s: %s", n.Name, string(b)))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(errors) > 0 {
|
||||
return fmt.Errorf(strings.Join(errors, "\n"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAllNetworks() ([]types.NetworkResource, error) {
|
||||
var networks []types.NetworkResource
|
||||
_, b, err := sockRequest("GET", "/networks", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(b, &networks); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return networks, nil
|
||||
}
|
||||
|
||||
func deleteAllVolumes() error {
|
||||
volumes, err := getAllVolumes()
|
||||
if err != nil {
|
||||
@@ -718,13 +742,7 @@ func dockerCmdInDirWithTimeout(timeout time.Duration, path string, args ...strin
|
||||
}
|
||||
|
||||
func findContainerIP(c *check.C, id string, vargs ...string) string {
|
||||
args := append(vargs, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
|
||||
cmd := exec.Command(dockerBinary, args...)
|
||||
out, _, err := runCommandWithOutput(cmd)
|
||||
if err != nil {
|
||||
c.Fatal(err, out)
|
||||
}
|
||||
|
||||
out, _ := dockerCmd(c, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
|
||||
return strings.Trim(out, " \r\n'")
|
||||
}
|
||||
|
||||
@@ -1276,30 +1294,23 @@ func newFakeGit(name string, files map[string]string, enforceLocalServer bool) (
|
||||
// Write `content` to the file at path `dst`, creating it if necessary,
|
||||
// as well as any missing directories.
|
||||
// The file is truncated if it already exists.
|
||||
// Call c.Fatal() at the first error.
|
||||
// Fail the test when error occures.
|
||||
func writeFile(dst, content string, c *check.C) {
|
||||
// Create subdirectories if necessary
|
||||
if err := os.MkdirAll(path.Dir(dst), 0700); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(os.MkdirAll(path.Dir(dst), 0700), check.IsNil)
|
||||
f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
defer f.Close()
|
||||
// Write content (truncate if it exists)
|
||||
if _, err := io.Copy(f, strings.NewReader(content)); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
_, err = io.Copy(f, strings.NewReader(content))
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
||||
// Return the contents of file at path `src`.
|
||||
// Call c.Fatal() at the first error (including if the file doesn't exist)
|
||||
// Fail the test when error occures.
|
||||
func readFile(src string, c *check.C) (content string) {
|
||||
data, err := ioutil.ReadFile(src)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
return string(data)
|
||||
}
|
||||
@@ -1351,30 +1362,25 @@ func daemonTime(c *check.C) time.Time {
|
||||
}
|
||||
|
||||
status, body, err := sockRequest("GET", "/info", nil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
|
||||
type infoJSON struct {
|
||||
SystemTime string
|
||||
}
|
||||
var info infoJSON
|
||||
if err = json.Unmarshal(body, &info); err != nil {
|
||||
c.Fatalf("unable to unmarshal /info response: %v", err)
|
||||
}
|
||||
err = json.Unmarshal(body, &info)
|
||||
c.Assert(err, check.IsNil, check.Commentf("unable to unmarshal GET /info response"))
|
||||
|
||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil, check.Commentf("invalid time format in GET /info response"))
|
||||
return dt
|
||||
}
|
||||
|
||||
func setupRegistry(c *check.C) *testRegistryV2 {
|
||||
testRequires(c, RegistryHosting)
|
||||
reg, err := newTestRegistryV2(c)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Wait for registry to be ready to serve requests.
|
||||
for i := 0; i != 5; i++ {
|
||||
@@ -1384,18 +1390,14 @@ func setupRegistry(c *check.C) *testRegistryV2 {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Fatal("Timeout waiting for test registry to become available")
|
||||
}
|
||||
c.Assert(err, check.IsNil, check.Commentf("Timeout waiting for test registry to become available"))
|
||||
return reg
|
||||
}
|
||||
|
||||
func setupNotary(c *check.C) *testNotary {
|
||||
testRequires(c, NotaryHosting)
|
||||
ts, err := newTestNotary(c)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ docker-build - Build a new image from the source code at PATH
|
||||
# SYNOPSIS
|
||||
**docker build**
|
||||
[**--build-arg**[=*[]*]]
|
||||
[**-c**|**--cpu-shares**[=*0*]]
|
||||
[**--cpu-shares**[=*0*]]
|
||||
[**--cgroup-parent**[=*CGROUP-PARENT*]]
|
||||
[**--help**]
|
||||
[**-f**|**--file**[=*PATH/Dockerfile*]]
|
||||
@@ -90,7 +90,7 @@ set as the **URL**, the repository is cloned locally and then sent as the contex
|
||||
**--memory-swap**=*MEMORY-SWAP*
|
||||
Total memory (memory + swap), '-1' to disable swap.
|
||||
|
||||
**-c**, **--cpu-shares**=*0*
|
||||
**--cpu-shares**=*0*
|
||||
CPU shares (relative weight).
|
||||
|
||||
By default, all containers get the same proportion of CPU cycles.
|
||||
|
||||
@@ -9,7 +9,7 @@ docker-create - Create a new container
|
||||
[**-a**|**--attach**[=*[]*]]
|
||||
[**--add-host**[=*[]*]]
|
||||
[**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
|
||||
[**-c**|**--cpu-shares**[=*0*]]
|
||||
[**--cpu-shares**[=*0*]]
|
||||
[**--cap-add**[=*[]*]]
|
||||
[**--cap-drop**[=*[]*]]
|
||||
[**--cgroup-parent**[=*CGROUP-PATH*]]
|
||||
@@ -83,7 +83,7 @@ The initial status of the container created with **docker create** is 'created'.
|
||||
**--blkio-weight**=0
|
||||
Block IO weight (relative weight) accepts a weight value between 10 and 1000.
|
||||
|
||||
**-c**, **--cpu-shares**=0
|
||||
**--cpu-shares**=0
|
||||
CPU shares (relative weight)
|
||||
|
||||
**--cap-add**=[]
|
||||
|
||||
@@ -33,7 +33,7 @@ Here is a sample output:
|
||||
# docker info
|
||||
Containers: 14
|
||||
Images: 52
|
||||
Engine Version: 1.9.0
|
||||
Server Version: 1.9.0
|
||||
Storage Driver: aufs
|
||||
Root Dir: /var/lib/docker/aufs
|
||||
Dirs: 80
|
||||
|
||||
+11
-7
@@ -9,7 +9,7 @@ docker-run - Run a command in a new container
|
||||
[**-a**|**--attach**[=*[]*]]
|
||||
[**--add-host**[=*[]*]]
|
||||
[**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
|
||||
[**-c**|**--cpu-shares**[=*0*]]
|
||||
[**--cpu-shares**[=*0*]]
|
||||
[**--cap-add**[=*[]*]]
|
||||
[**--cap-drop**[=*[]*]]
|
||||
[**--cgroup-parent**[=*CGROUP-PATH*]]
|
||||
@@ -100,14 +100,14 @@ option can be set multiple times.
|
||||
**--blkio-weight**=0
|
||||
Block IO weight (relative weight) accepts a weight value between 10 and 1000.
|
||||
|
||||
**-c**, **--cpu-shares**=0
|
||||
**--cpu-shares**=0
|
||||
CPU shares (relative weight)
|
||||
|
||||
By default, all containers get the same proportion of CPU cycles. This proportion
|
||||
can be modified by changing the container's CPU share weighting relative
|
||||
to the weighting of all other running containers.
|
||||
|
||||
To modify the proportion from the default of 1024, use the **-c** or **--cpu-shares**
|
||||
To modify the proportion from the default of 1024, use the **--cpu-shares**
|
||||
flag to set the weighting to 2 or higher.
|
||||
|
||||
The proportion will only apply when CPU-intensive processes are running.
|
||||
@@ -353,10 +353,14 @@ ports and the exposed ports, use `docker port`.
|
||||
|
||||
**-p**, **--publish**=[]
|
||||
Publish a container's port, or range of ports, to the host.
|
||||
format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
|
||||
Both hostPort and containerPort can be specified as a range of ports.
|
||||
When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range. (e.g., `-p 1234-1236:1234-1236/tcp`)
|
||||
(use 'docker port' to see the actual mapping)
|
||||
|
||||
Format: `ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort`
|
||||
Both hostPort and containerPort can be specified as a range of ports.
|
||||
When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range.
|
||||
(e.g., `docker run -p 1234-1236:1222-1224 --name thisWorks -t busybox`
|
||||
but not `docker run -p 1230-1236:1230-1240 --name RangeContainerPortsBiggerThanRangeHostPorts -t busybox`)
|
||||
With ip: `docker run -p 127.0.0.1:$HOSTPORT:$CONTAINERPORT --name CONTAINER -t someimage`
|
||||
Use `docker port` to see the actual mapping: `docker port CONTAINER $CONTAINERPORT`
|
||||
|
||||
**--pid**=host
|
||||
Set the PID mode for the container
|
||||
|
||||
+28
-48
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/fileutils"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/pools"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
@@ -116,10 +117,10 @@ func DetectCompression(source []byte) Compression {
|
||||
return Uncompressed
|
||||
}
|
||||
|
||||
func xzDecompress(archive io.Reader) (io.ReadCloser, error) {
|
||||
func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) {
|
||||
args := []string{"xz", "-d", "-c", "-q"}
|
||||
|
||||
return CmdStream(exec.Command(args[0], args[1:]...), archive)
|
||||
return cmdStream(exec.Command(args[0], args[1:]...), archive)
|
||||
}
|
||||
|
||||
// DecompressStream decompress the archive and returns a ReaderCloser with the decompressed archive.
|
||||
@@ -148,12 +149,15 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
|
||||
readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader)
|
||||
return readBufWrapper, nil
|
||||
case Xz:
|
||||
xzReader, err := xzDecompress(buf)
|
||||
xzReader, chdone, err := xzDecompress(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
readBufWrapper := p.NewReadCloserWrapper(buf, xzReader)
|
||||
return readBufWrapper, nil
|
||||
return ioutils.NewReadCloserWrapper(readBufWrapper, func() error {
|
||||
<-chdone
|
||||
return readBufWrapper.Close()
|
||||
}), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
|
||||
}
|
||||
@@ -245,14 +249,14 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
||||
}
|
||||
hdr.Name = name
|
||||
|
||||
nlink, inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
|
||||
inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if it's a regular file and has more than 1 link,
|
||||
// if it's not a directory and has more than 1 link,
|
||||
// it's hardlinked, so set the type flag accordingly
|
||||
if fi.Mode().IsRegular() && nlink > 1 {
|
||||
if !fi.IsDir() && hasHardlinks(fi) {
|
||||
// a link should have a name that it links too
|
||||
// and that linked name should be first in the tar archive
|
||||
if oldpath, ok := ta.SeenFiles[inode]; ok {
|
||||
@@ -925,57 +929,33 @@ func CopyFileWithTar(src, dst string) (err error) {
|
||||
return defaultArchiver.CopyFileWithTar(src, dst)
|
||||
}
|
||||
|
||||
// CmdStream executes a command, and returns its stdout as a stream.
|
||||
// cmdStream executes a command, and returns its stdout as a stream.
|
||||
// If the command fails to run or doesn't complete successfully, an error
|
||||
// will be returned, including anything written on stderr.
|
||||
func CmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, error) {
|
||||
if input != nil {
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Write stdin if any
|
||||
go func() {
|
||||
io.Copy(stdin, input)
|
||||
stdin.Close()
|
||||
}()
|
||||
}
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) {
|
||||
chdone := make(chan struct{})
|
||||
cmd.Stdin = input
|
||||
pipeR, pipeW := io.Pipe()
|
||||
errChan := make(chan []byte)
|
||||
// Collect stderr, we will use it in case of an error
|
||||
go func() {
|
||||
errText, e := ioutil.ReadAll(stderr)
|
||||
if e != nil {
|
||||
errText = []byte("(...couldn't fetch stderr: " + e.Error() + ")")
|
||||
}
|
||||
errChan <- errText
|
||||
}()
|
||||
cmd.Stdout = pipeW
|
||||
var errBuf bytes.Buffer
|
||||
cmd.Stderr = &errBuf
|
||||
|
||||
// Run the command and return the pipe
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Copy stdout to the returned pipe
|
||||
go func() {
|
||||
_, err := io.Copy(pipeW, stdout)
|
||||
if err != nil {
|
||||
pipeW.CloseWithError(err)
|
||||
}
|
||||
errText := <-errChan
|
||||
if err := cmd.Wait(); err != nil {
|
||||
pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errText))
|
||||
pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String()))
|
||||
} else {
|
||||
pipeW.Close()
|
||||
}
|
||||
close(chdone)
|
||||
}()
|
||||
// Run the command and return the pipe
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pipeR, nil
|
||||
|
||||
return pipeR, chdone, nil
|
||||
}
|
||||
|
||||
// NewTempArchive reads the content of src into a temporary file, and returns the contents
|
||||
|
||||
@@ -160,7 +160,7 @@ func TestExtensionXz(t *testing.T) {
|
||||
|
||||
func TestCmdStreamLargeStderr(t *testing.T) {
|
||||
cmd := exec.Command("/bin/sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello")
|
||||
out, err := CmdStream(cmd, nil)
|
||||
out, _, err := cmdStream(cmd, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start command: %s", err)
|
||||
}
|
||||
@@ -181,7 +181,7 @@ func TestCmdStreamLargeStderr(t *testing.T) {
|
||||
|
||||
func TestCmdStreamBad(t *testing.T) {
|
||||
badCmd := exec.Command("/bin/sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1")
|
||||
out, err := CmdStream(badCmd, nil)
|
||||
out, _, err := cmdStream(badCmd, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start command: %s", err)
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func TestCmdStreamBad(t *testing.T) {
|
||||
|
||||
func TestCmdStreamGood(t *testing.T) {
|
||||
cmd := exec.Command("/bin/sh", "-c", "echo hello; exit 0")
|
||||
out, err := CmdStream(cmd, nil)
|
||||
out, _, err := cmdStream(cmd, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func chmodTarEntry(perm os.FileMode) os.FileMode {
|
||||
return perm // noop for unix as golang APIs provide perm bits correctly
|
||||
}
|
||||
|
||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
|
||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (inode uint64, err error) {
|
||||
s, ok := stat.(*syscall.Stat_t)
|
||||
|
||||
if !ok {
|
||||
@@ -48,7 +48,6 @@ func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, st
|
||||
return
|
||||
}
|
||||
|
||||
nlink = uint32(s.Nlink)
|
||||
inode = uint64(s.Ino)
|
||||
|
||||
// Currently go does not fill in the major/minors
|
||||
|
||||
@@ -49,7 +49,7 @@ func chmodTarEntry(perm os.FileMode) os.FileMode {
|
||||
return perm
|
||||
}
|
||||
|
||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
|
||||
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (inode uint64, err error) {
|
||||
// do nothing. no notion of Rdev, Inode, Nlink in stat on Windows
|
||||
return
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user