mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #31140 from thaJeztah/1.13.2-cherry-picks
17.03 cherry picks
This commit is contained in:
commit
2a46799a87
23 changed files with 210 additions and 59 deletions
|
@ -63,6 +63,8 @@ func GetHTTPErrorStatusCode(err error) int {
|
||||||
{"unauthorized", http.StatusUnauthorized},
|
{"unauthorized", http.StatusUnauthorized},
|
||||||
{"hasn't been activated", http.StatusForbidden},
|
{"hasn't been activated", http.StatusForbidden},
|
||||||
{"this node", http.StatusServiceUnavailable},
|
{"this node", http.StatusServiceUnavailable},
|
||||||
|
{"needs to be unlocked", http.StatusServiceUnavailable},
|
||||||
|
{"certificates have expired", http.StatusServiceUnavailable},
|
||||||
} {
|
} {
|
||||||
if strings.Contains(errStr, status.keyword) {
|
if strings.Contains(errStr, status.keyword) {
|
||||||
statusCode = status.code
|
statusCode = status.code
|
||||||
|
|
|
@ -369,6 +369,11 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
version := httputils.VersionFromContext(ctx)
|
version := httputils.VersionFromContext(ctx)
|
||||||
adjustCPUShares := versions.LessThan(version, "1.19")
|
adjustCPUShares := versions.LessThan(version, "1.19")
|
||||||
|
|
||||||
|
// When using API 1.24 and under, the client is responsible for removing the container
|
||||||
|
if hostConfig != nil && versions.LessThan(version, "1.25") {
|
||||||
|
hostConfig.AutoRemove = false
|
||||||
|
}
|
||||||
|
|
||||||
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
Config: config,
|
Config: config,
|
||||||
|
|
|
@ -104,7 +104,8 @@ func MakeTarSumContext(tarStream io.Reader) (ModifiableContext, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := chrootarchive.Untar(sum, root, nil); err != nil {
|
err = chrootarchive.Untar(sum, root, nil)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,9 +74,8 @@ func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *runOptions
|
||||||
cmdPath := "run"
|
cmdPath := "run"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
flAttach *opttypes.ListOpts
|
flAttach *opttypes.ListOpts
|
||||||
ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d")
|
ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d")
|
||||||
ErrConflictRestartPolicyAndAutoRemove = fmt.Errorf("Conflicting options: --restart and --rm")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
config, hostConfig, networkingConfig, err := runconfigopts.Parse(flags, copts)
|
config, hostConfig, networkingConfig, err := runconfigopts.Parse(flags, copts)
|
||||||
|
@ -87,9 +86,6 @@ func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *runOptions
|
||||||
return cli.StatusError{StatusCode: 125}
|
return cli.StatusError{StatusCode: 125}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
|
|
||||||
return ErrConflictRestartPolicyAndAutoRemove
|
|
||||||
}
|
|
||||||
if hostConfig.OomKillDisable != nil && *hostConfig.OomKillDisable && hostConfig.Memory == 0 {
|
if hostConfig.OomKillDisable != nil && *hostConfig.OomKillDisable && hostConfig.Memory == 0 {
|
||||||
fmt.Fprintf(stderr, "WARNING: Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.\n")
|
fmt.Fprintf(stderr, "WARNING: Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.\n")
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,8 +145,10 @@ func (c *containerStatsContext) Container() string {
|
||||||
|
|
||||||
func (c *containerStatsContext) Name() string {
|
func (c *containerStatsContext) Name() string {
|
||||||
c.AddHeader(nameHeader)
|
c.AddHeader(nameHeader)
|
||||||
name := c.s.Name[1:]
|
if len(c.s.Name) > 1 {
|
||||||
return name
|
return c.s.Name[1:]
|
||||||
|
}
|
||||||
|
return "--"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerStatsContext) ID() string {
|
func (c *containerStatsContext) ID() string {
|
||||||
|
|
|
@ -69,6 +69,12 @@ func TestContainerStatsContextWrite(t *testing.T) {
|
||||||
`MEM USAGE / LIMIT
|
`MEM USAGE / LIMIT
|
||||||
20 B / 20 B
|
20 B / 20 B
|
||||||
-- / --
|
-- / --
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Context{Format: "{{.Container}} {{.ID}} {{.Name}}"},
|
||||||
|
`container1 abcdef foo
|
||||||
|
container2 --
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -83,6 +89,8 @@ container2 --
|
||||||
stats := []StatsEntry{
|
stats := []StatsEntry{
|
||||||
{
|
{
|
||||||
Container: "container1",
|
Container: "container1",
|
||||||
|
ID: "abcdef",
|
||||||
|
Name: "/foo",
|
||||||
CPUPercentage: 20,
|
CPUPercentage: 20,
|
||||||
Memory: 20,
|
Memory: 20,
|
||||||
MemoryLimit: 20,
|
MemoryLimit: 20,
|
||||||
|
|
|
@ -219,19 +219,27 @@ func convertServiceSecrets(
|
||||||
if gid == "" {
|
if gid == "" {
|
||||||
gid = "0"
|
gid = "0"
|
||||||
}
|
}
|
||||||
|
mode := secret.Mode
|
||||||
|
if mode == nil {
|
||||||
|
mode = uint32Ptr(0444)
|
||||||
|
}
|
||||||
|
|
||||||
opts = append(opts, &types.SecretRequestOption{
|
opts = append(opts, &types.SecretRequestOption{
|
||||||
Source: source,
|
Source: source,
|
||||||
Target: target,
|
Target: target,
|
||||||
UID: uid,
|
UID: uid,
|
||||||
GID: gid,
|
GID: gid,
|
||||||
Mode: os.FileMode(secret.Mode),
|
Mode: os.FileMode(*mode),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return servicecli.ParseSecrets(client, opts)
|
return servicecli.ParseSecrets(client, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func uint32Ptr(value uint32) *uint32 {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
func convertExtraHosts(extraHosts map[string]string) []string {
|
func convertExtraHosts(extraHosts map[string]string) []string {
|
||||||
hosts := []string{}
|
hosts := []string{}
|
||||||
for host, ip := range extraHosts {
|
for host, ip := range extraHosts {
|
||||||
|
|
|
@ -199,7 +199,7 @@ type ServiceSecretConfig struct {
|
||||||
Target string
|
Target string
|
||||||
UID string
|
UID string
|
||||||
GID string
|
GID string
|
||||||
Mode uint32
|
Mode *uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// UlimitsConfig the ulimit configuration
|
// UlimitsConfig the ulimit configuration
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
|
"github.com/docker/docker/api/types/versions"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,6 +26,11 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When using API 1.24 and under, the client is responsible for removing the container
|
||||||
|
if hostConfig != nil && versions.LessThan(cli.ClientVersion(), "1.25") {
|
||||||
|
hostConfig.AutoRemove = false
|
||||||
|
}
|
||||||
|
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
if containerName != "" {
|
if containerName != "" {
|
||||||
query.Set("name", containerName)
|
query.Set("name", containerName)
|
||||||
|
|
|
@ -74,3 +74,45 @@ func TestContainerCreateWithName(t *testing.T) {
|
||||||
t.Fatalf("expected `container_id`, got %s", r.ID)
|
t.Fatalf("expected `container_id`, got %s", r.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestContainerCreateAutoRemove validates that a client using API 1.24 always disables AutoRemove. When using API 1.25
|
||||||
|
// or up, AutoRemove should not be disabled.
|
||||||
|
func TestContainerCreateAutoRemove(t *testing.T) {
|
||||||
|
autoRemoveValidator := func(expectedValue bool) func(req *http.Request) (*http.Response, error) {
|
||||||
|
return func(req *http.Request) (*http.Response, error) {
|
||||||
|
var config configWrapper
|
||||||
|
|
||||||
|
if err := json.NewDecoder(req.Body).Decode(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if config.HostConfig.AutoRemove != expectedValue {
|
||||||
|
return nil, fmt.Errorf("expected AutoRemove to be %v, got %v", expectedValue, config.HostConfig.AutoRemove)
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(container.ContainerCreateCreatedBody{
|
||||||
|
ID: "container_id",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: ioutil.NopCloser(bytes.NewReader(b)),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
client: newMockClient(autoRemoveValidator(false)),
|
||||||
|
version: "1.24",
|
||||||
|
}
|
||||||
|
if _, err := client.ContainerCreate(context.Background(), nil, &container.HostConfig{AutoRemove: true}, nil, ""); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
client = &Client{
|
||||||
|
client: newMockClient(autoRemoveValidator(true)),
|
||||||
|
version: "1.25",
|
||||||
|
}
|
||||||
|
if _, err := client.ContainerCreate(context.Background(), nil, &container.HostConfig{AutoRemove: true}, nil, ""); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/loopback"
|
"github.com/docker/docker/pkg/loopback"
|
||||||
"github.com/docker/docker/pkg/mount"
|
"github.com/docker/docker/pkg/mount"
|
||||||
"github.com/docker/docker/pkg/parsers"
|
"github.com/docker/docker/pkg/parsers"
|
||||||
"github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
|
|
||||||
"github.com/opencontainers/runc/libcontainer/label"
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
)
|
)
|
||||||
|
@ -1713,9 +1713,9 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||||
// https://github.com/docker/docker/issues/4036
|
// https://github.com/docker/docker/issues/4036
|
||||||
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
||||||
if dockerversion.IAmStatic == "true" {
|
if dockerversion.IAmStatic == "true" {
|
||||||
logrus.Error("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
logrus.Error("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options")
|
||||||
} else {
|
} else {
|
||||||
logrus.Error("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
logrus.Error("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !devices.overrideUdevSyncCheck {
|
if !devices.overrideUdevSyncCheck {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/docker/docker/pkg/longpath"
|
"github.com/docker/docker/pkg/longpath"
|
||||||
"github.com/docker/docker/pkg/reexec"
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
"github.com/docker/docker/pkg/system"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
@ -265,19 +266,35 @@ func (d *Driver) Remove(id string) error {
|
||||||
// it is a transient error. Retry until it succeeds.
|
// it is a transient error. Retry until it succeeds.
|
||||||
var computeSystems []hcsshim.ContainerProperties
|
var computeSystems []hcsshim.ContainerProperties
|
||||||
retryCount := 0
|
retryCount := 0
|
||||||
|
osv := system.GetOSVersion()
|
||||||
for {
|
for {
|
||||||
// Get and terminate any template VMs that are currently using the layer
|
// Get and terminate any template VMs that are currently using the layer.
|
||||||
|
// Note: It is unfortunate that we end up in the graphdrivers Remove() call
|
||||||
|
// for both containers and images, but the logic for template VMs is only
|
||||||
|
// needed for images - specifically we are looking to see if a base layer
|
||||||
|
// is in use by a template VM as a result of having started a Hyper-V
|
||||||
|
// container at some point.
|
||||||
|
//
|
||||||
|
// We have a retry loop for ErrVmcomputeOperationInvalidState and
|
||||||
|
// ErrVmcomputeOperationAccessIsDenied as there is a race condition
|
||||||
|
// in RS1 and RS2 building during enumeration when a silo is going away
|
||||||
|
// for example under it, in HCS. AccessIsDenied added to fix 30278.
|
||||||
|
//
|
||||||
|
// TODO @jhowardmsft - For RS3, we can remove the retries. Also consider
|
||||||
|
// using platform APIs (if available) to get this more succinctly. Also
|
||||||
|
// consider enlighting the Remove() interface to have context of why
|
||||||
|
// the remove is being called - that could improve efficiency by not
|
||||||
|
// enumerating compute systems during a remove of a container as it's
|
||||||
|
// not required.
|
||||||
computeSystems, err = hcsshim.GetContainers(hcsshim.ComputeSystemQuery{})
|
computeSystems, err = hcsshim.GetContainers(hcsshim.ComputeSystemQuery{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == hcsshim.ErrVmcomputeOperationInvalidState {
|
if (osv.Build < 15139) &&
|
||||||
if retryCount >= 5 {
|
((err == hcsshim.ErrVmcomputeOperationInvalidState) || (err == hcsshim.ErrVmcomputeOperationAccessIsDenied)) {
|
||||||
// If we are unable to get the list of containers
|
if retryCount >= 500 {
|
||||||
// go ahead and attempt to delete the layer anyway
|
|
||||||
// as it will most likely work.
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
retryCount++
|
retryCount++
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(10 * time.Millisecond)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -137,7 +137,11 @@ func tailFile(f io.ReadSeeker, logWatcher *logger.LogWatcher, tail int, since ti
|
||||||
if !since.IsZero() && msg.Timestamp.Before(since) {
|
if !since.IsZero() && msg.Timestamp.Before(since) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logWatcher.Msg <- msg
|
select {
|
||||||
|
case <-logWatcher.WatchClose():
|
||||||
|
return
|
||||||
|
case logWatcher.Msg <- msg:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,9 +256,12 @@ func followLogs(f *os.File, logWatcher *logger.LogWatcher, notifyRotate chan int
|
||||||
|
|
||||||
handleDecodeErr := func(err error) error {
|
handleDecodeErr := func(err error) error {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
for err := waitRead(); err != nil; {
|
for {
|
||||||
|
err := waitRead()
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
if err == errRetry {
|
if err == errRetry {
|
||||||
// retry the waitRead
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -61,6 +61,18 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
|
||||||
Follow: follow,
|
Follow: follow,
|
||||||
}
|
}
|
||||||
logs := logReader.ReadLogs(readConfig)
|
logs := logReader.ReadLogs(readConfig)
|
||||||
|
// Close logWatcher on exit
|
||||||
|
defer func() {
|
||||||
|
logs.Close()
|
||||||
|
if cLog != container.LogDriver {
|
||||||
|
// Since the logger isn't cached in the container, which
|
||||||
|
// occurs if it is running, it must get explicitly closed
|
||||||
|
// here to avoid leaking it and any file handles it has.
|
||||||
|
if err := cLog.Close(); err != nil {
|
||||||
|
logrus.Errorf("Error closing logger: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
wf := ioutils.NewWriteFlusher(config.OutStream)
|
wf := ioutils.NewWriteFlusher(config.OutStream)
|
||||||
defer wf.Close()
|
defer wf.Close()
|
||||||
|
@ -81,19 +93,11 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
|
||||||
logrus.Errorf("Error streaming logs: %v", err)
|
logrus.Errorf("Error streaming logs: %v", err)
|
||||||
return nil
|
return nil
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
logs.Close()
|
logrus.Debugf("logs: end stream, ctx is done: %v", ctx.Err())
|
||||||
return nil
|
return nil
|
||||||
case msg, ok := <-logs.Msg:
|
case msg, ok := <-logs.Msg:
|
||||||
if !ok {
|
if !ok {
|
||||||
logrus.Debug("logs: end stream")
|
logrus.Debug("logs: end stream")
|
||||||
logs.Close()
|
|
||||||
if cLog != container.LogDriver {
|
|
||||||
// Since the logger isn't cached in the container, which occurs if it is running, it
|
|
||||||
// must get explicitly closed here to avoid leaking it and any file handles it has.
|
|
||||||
if err := cLog.Close(); err != nil {
|
|
||||||
logrus.Errorf("Error closing logger: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
logLine := msg.Line
|
logLine := msg.Line
|
||||||
|
|
|
@ -33,7 +33,9 @@ func (daemon *Daemon) ContainerStats(ctx context.Context, prefixOrName string, c
|
||||||
|
|
||||||
// If the container is either not running or restarting and requires no stream, return an empty stats.
|
// If the container is either not running or restarting and requires no stream, return an empty stats.
|
||||||
if (!container.IsRunning() || container.IsRestarting()) && !config.Stream {
|
if (!container.IsRunning() || container.IsRestarting()) && !config.Stream {
|
||||||
return json.NewEncoder(config.OutStream).Encode(&types.Stats{})
|
return json.NewEncoder(config.OutStream).Encode(&types.StatsJSON{
|
||||||
|
Name: container.Name,
|
||||||
|
ID: container.ID})
|
||||||
}
|
}
|
||||||
|
|
||||||
outStream := config.OutStream
|
outStream := config.OutStream
|
||||||
|
|
|
@ -120,7 +120,14 @@ func (s *statsCollector) run() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(errNotRunning); !ok {
|
if _, ok := err.(errNotRunning); !ok {
|
||||||
logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err)
|
logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// publish empty stats containing only name and ID if not running
|
||||||
|
pair.publisher.Publish(types.StatsJSON{
|
||||||
|
Name: pair.container.Name,
|
||||||
|
ID: pair.container.ID,
|
||||||
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// FIXME: move to containerd on Linux (not Windows)
|
// FIXME: move to containerd on Linux (not Windows)
|
||||||
|
|
|
@ -531,6 +531,10 @@ func (s *DockerSuite) TestBuildCacheAdd(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSuite) TestBuildLastModified(c *check.C) {
|
func (s *DockerSuite) TestBuildLastModified(c *check.C) {
|
||||||
|
// Temporary fix for #30890. TODO @jhowardmsft figure out what
|
||||||
|
// has changed in the master busybox image.
|
||||||
|
testRequires(c, DaemonIsLinux)
|
||||||
|
|
||||||
name := "testbuildlastmodified"
|
name := "testbuildlastmodified"
|
||||||
|
|
||||||
server, err := fakeStorage(map[string]string{
|
server, err := fakeStorage(map[string]string{
|
||||||
|
@ -3647,6 +3651,7 @@ RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(vdemeester) rename this test (and probably "merge" it with the one below TestBuildEnvUsage2)
|
||||||
func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
|
func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
|
||||||
// /docker/world/hello is not owned by the correct user
|
// /docker/world/hello is not owned by the correct user
|
||||||
testRequires(c, NotUserNamespace)
|
testRequires(c, NotUserNamespace)
|
||||||
|
@ -3685,6 +3690,7 @@ RUN [ "$ghi" = "def" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(vdemeester) rename this test (and probably "merge" it with the one above TestBuildEnvUsage)
|
||||||
func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
|
func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
|
||||||
// /docker/world/hello is not owned by the correct user
|
// /docker/world/hello is not owned by the correct user
|
||||||
testRequires(c, NotUserNamespace)
|
testRequires(c, NotUserNamespace)
|
||||||
|
@ -4811,6 +4817,7 @@ CMD cat /foo/file`,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(vdemeester) part of this should be unit test, other part should be clearer
|
||||||
func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
|
func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
|
||||||
|
|
||||||
ctx, err := fakeContext(`FROM busybox
|
ctx, err := fakeContext(`FROM busybox
|
||||||
|
|
|
@ -157,3 +157,22 @@ func (s *DockerSuite) TestStatsAllNewContainersAdded(c *check.C) {
|
||||||
// ignore, done
|
// ignore, done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestStatsFormatAll(c *check.C) {
|
||||||
|
// Windows does not support stats
|
||||||
|
testRequires(c, DaemonIsLinux)
|
||||||
|
|
||||||
|
dockerCmd(c, "run", "-d", "--name=RunningOne", "busybox", "top")
|
||||||
|
c.Assert(waitRun("RunningOne"), check.IsNil)
|
||||||
|
dockerCmd(c, "run", "-d", "--name=ExitedOne", "busybox", "top")
|
||||||
|
dockerCmd(c, "stop", "ExitedOne")
|
||||||
|
c.Assert(waitExited("ExitedOne", 5*time.Second), check.IsNil)
|
||||||
|
|
||||||
|
out, _ := dockerCmd(c, "stats", "--no-stream", "--format", "{{.Name}}")
|
||||||
|
c.Assert(out, checker.Contains, "RunningOne")
|
||||||
|
c.Assert(out, checker.Not(checker.Contains), "ExitedOne")
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "stats", "--all", "--no-stream", "--format", "{{.Name}}")
|
||||||
|
c.Assert(out, checker.Contains, "RunningOne")
|
||||||
|
c.Assert(out, checker.Contains, "ExitedOne")
|
||||||
|
}
|
||||||
|
|
|
@ -621,6 +621,10 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c
|
||||||
Runtime: copts.runtime,
|
Runtime: copts.runtime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {
|
||||||
|
return nil, nil, nil, fmt.Errorf("Conflicting options: --restart and --rm")
|
||||||
|
}
|
||||||
|
|
||||||
// only set this value if the user provided the flag, else it should default to nil
|
// only set this value if the user provided the flag, else it should default to nil
|
||||||
if flags.Changed("init") {
|
if flags.Changed("init") {
|
||||||
hostConfig.Init = &copts.init
|
hostConfig.Init = &copts.init
|
||||||
|
|
|
@ -586,6 +586,14 @@ func TestParseRestartPolicy(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseRestartPolicyAutoRemove(t *testing.T) {
|
||||||
|
expected := "Conflicting options: --restart and --rm"
|
||||||
|
_, _, _, err := parseRun([]string{"--rm", "--restart=always", "img", "cmd"})
|
||||||
|
if err == nil || err.Error() != expected {
|
||||||
|
t.Fatalf("Expected error %v, but got none", expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseHealth(t *testing.T) {
|
func TestParseHealth(t *testing.T) {
|
||||||
checkOk := func(args ...string) *container.HealthConfig {
|
checkOk := func(args ...string) *container.HealthConfig {
|
||||||
config, _, _, err := parseRun(args)
|
config, _, _, err := parseRun(args)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# the following lines are in sorted order, FYI
|
# the following lines are in sorted order, FYI
|
||||||
github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62
|
github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62
|
||||||
github.com/Microsoft/hcsshim v0.5.9
|
github.com/Microsoft/hcsshim v0.5.12
|
||||||
github.com/Microsoft/go-winio v0.3.8
|
github.com/Microsoft/go-winio v0.3.8
|
||||||
github.com/Sirupsen/logrus v0.11.0
|
github.com/Sirupsen/logrus v0.11.0
|
||||||
github.com/davecgh/go-spew 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
github.com/davecgh/go-spew 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||||
|
|
4
vendor/github.com/Microsoft/hcsshim/errors.go
generated
vendored
4
vendor/github.com/Microsoft/hcsshim/errors.go
generated
vendored
|
@ -50,6 +50,10 @@ var (
|
||||||
|
|
||||||
// ErrProcNotFound is an error encountered when the the process cannot be found
|
// ErrProcNotFound is an error encountered when the the process cannot be found
|
||||||
ErrProcNotFound = syscall.Errno(0x7f)
|
ErrProcNotFound = syscall.Errno(0x7f)
|
||||||
|
|
||||||
|
// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
|
||||||
|
// builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3.
|
||||||
|
ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessError is an error encountered in HCS during an operation on a Process object
|
// ProcessError is an error encountered in HCS during an operation on a Process object
|
||||||
|
|
50
vendor/github.com/Microsoft/hcsshim/interface.go
generated
vendored
50
vendor/github.com/Microsoft/hcsshim/interface.go
generated
vendored
|
@ -41,30 +41,32 @@ type HvRuntime struct {
|
||||||
// ContainerConfig is used as both the input of CreateContainer
|
// ContainerConfig is used as both the input of CreateContainer
|
||||||
// and to convert the parameters to JSON for passing onto the HCS
|
// and to convert the parameters to JSON for passing onto the HCS
|
||||||
type ContainerConfig struct {
|
type ContainerConfig struct {
|
||||||
SystemType string // HCS requires this to be hard-coded to "Container"
|
SystemType string // HCS requires this to be hard-coded to "Container"
|
||||||
Name string // Name of the container. We use the docker ID.
|
Name string // Name of the container. We use the docker ID.
|
||||||
Owner string // The management platform that created this container
|
Owner string // The management platform that created this container
|
||||||
IsDummy bool // Used for development purposes.
|
IsDummy bool // Used for development purposes.
|
||||||
VolumePath string `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID}
|
VolumePath string `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID}
|
||||||
IgnoreFlushesDuringBoot bool // Optimization hint for container startup in Windows
|
IgnoreFlushesDuringBoot bool // Optimization hint for container startup in Windows
|
||||||
LayerFolderPath string `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format %root%\windowsfilter\containerID
|
LayerFolderPath string `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format %root%\windowsfilter\containerID
|
||||||
Layers []Layer // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID
|
Layers []Layer // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID
|
||||||
Credentials string `json:",omitempty"` // Credentials information
|
Credentials string `json:",omitempty"` // Credentials information
|
||||||
ProcessorCount uint32 `json:",omitempty"` // Number of processors to assign to the container.
|
ProcessorCount uint32 `json:",omitempty"` // Number of processors to assign to the container.
|
||||||
ProcessorWeight uint64 `json:",omitempty"` // CPU Shares 0..10000 on Windows; where 0 will be omitted and HCS will default.
|
ProcessorWeight uint64 `json:",omitempty"` // CPU Shares 0..10000 on Windows; where 0 will be omitted and HCS will default.
|
||||||
ProcessorMaximum int64 `json:",omitempty"` // CPU maximum usage percent 1..100
|
ProcessorMaximum int64 `json:",omitempty"` // CPU maximum usage percent 1..100
|
||||||
StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS
|
StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS
|
||||||
StorageBandwidthMaximum uint64 `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second
|
StorageBandwidthMaximum uint64 `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second
|
||||||
StorageSandboxSize uint64 `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller
|
StorageSandboxSize uint64 `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller
|
||||||
MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes
|
MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes
|
||||||
HostName string // Hostname
|
HostName string // Hostname
|
||||||
MappedDirectories []MappedDir // List of mapped directories (volumes/mounts)
|
MappedDirectories []MappedDir // List of mapped directories (volumes/mounts)
|
||||||
SandboxPath string `json:",omitempty"` // Location of unmounted sandbox. Used by Hyper-V containers only. Format %root%\windowsfilter
|
SandboxPath string `json:",omitempty"` // Location of unmounted sandbox. Used by Hyper-V containers only. Format %root%\windowsfilter
|
||||||
HvPartition bool // True if it a Hyper-V Container
|
HvPartition bool // True if it a Hyper-V Container
|
||||||
EndpointList []string // List of networking endpoints to be attached to container
|
EndpointList []string // List of networking endpoints to be attached to container
|
||||||
HvRuntime *HvRuntime `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM
|
NetworkSharedContainerName string `json:",omitempty"` // Name (ID) of the container that we will share the network stack with.
|
||||||
Servicing bool // True if this container is for servicing
|
HvRuntime *HvRuntime `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM
|
||||||
AllowUnqualifiedDNSQuery bool // True to allow unqualified DNS name resolution
|
Servicing bool // True if this container is for servicing
|
||||||
|
AllowUnqualifiedDNSQuery bool // True to allow unqualified DNS name resolution
|
||||||
|
DNSSearchList string `json:",omitempty"` // Comma seperated list of DNS suffixes to use for name resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
type ComputeSystemQuery struct {
|
type ComputeSystemQuery struct {
|
||||||
|
|
Loading…
Add table
Reference in a new issue