diff --git a/api/server/httputils/errors.go b/api/server/httputils/errors.go index 59098a9df0..2f877651ea 100644 --- a/api/server/httputils/errors.go +++ b/api/server/httputils/errors.go @@ -63,6 +63,8 @@ func GetHTTPErrorStatusCode(err error) int { {"unauthorized", http.StatusUnauthorized}, {"hasn't been activated", http.StatusForbidden}, {"this node", http.StatusServiceUnavailable}, + {"needs to be unlocked", http.StatusServiceUnavailable}, + {"certificates have expired", http.StatusServiceUnavailable}, } { if strings.Contains(errStr, status.keyword) { statusCode = status.code diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go index 9c9bc0f8c3..3c389245ce 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -369,6 +369,11 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo version := httputils.VersionFromContext(ctx) 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{ Name: name, Config: config, diff --git a/builder/tarsum.go b/builder/tarsum.go index 35054dcba1..77d3142e7b 100644 --- a/builder/tarsum.go +++ b/builder/tarsum.go @@ -104,7 +104,8 @@ func MakeTarSumContext(tarStream io.Reader) (ModifiableContext, error) { return nil, err } - if err := chrootarchive.Untar(sum, root, nil); err != nil { + err = chrootarchive.Untar(sum, root, nil) + if err != nil { return nil, err } diff --git a/cli/command/container/run.go b/cli/command/container/run.go index 0fad93e688..fb3681a9f5 100644 --- a/cli/command/container/run.go +++ b/cli/command/container/run.go @@ -74,9 +74,8 @@ func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *runOptions cmdPath := "run" var ( - flAttach *opttypes.ListOpts - ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d") - ErrConflictRestartPolicyAndAutoRemove = fmt.Errorf("Conflicting options: --restart and --rm") + flAttach *opttypes.ListOpts + ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d") ) 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} } - if hostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() { - return ErrConflictRestartPolicyAndAutoRemove - } 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") } diff --git a/cli/command/formatter/stats.go b/cli/command/formatter/stats.go index 7997f996d8..30c9e30bcf 100644 --- a/cli/command/formatter/stats.go +++ b/cli/command/formatter/stats.go @@ -145,8 +145,10 @@ func (c *containerStatsContext) Container() string { func (c *containerStatsContext) Name() string { c.AddHeader(nameHeader) - name := c.s.Name[1:] - return name + if len(c.s.Name) > 1 { + return c.s.Name[1:] + } + return "--" } func (c *containerStatsContext) ID() string { diff --git a/cli/command/formatter/stats_test.go b/cli/command/formatter/stats_test.go index d5a17cc70e..f5c6cae0c3 100644 --- a/cli/command/formatter/stats_test.go +++ b/cli/command/formatter/stats_test.go @@ -69,6 +69,12 @@ func TestContainerStatsContextWrite(t *testing.T) { `MEM USAGE / LIMIT 20 B / 20 B -- / -- +`, + }, + { + Context{Format: "{{.Container}} {{.ID}} {{.Name}}"}, + `container1 abcdef foo +container2 -- `, }, { @@ -83,6 +89,8 @@ container2 -- stats := []StatsEntry{ { Container: "container1", + ID: "abcdef", + Name: "/foo", CPUPercentage: 20, Memory: 20, MemoryLimit: 20, diff --git a/cli/compose/convert/service.go b/cli/compose/convert/service.go index 4a5489562c..882050560e 100644 --- a/cli/compose/convert/service.go +++ b/cli/compose/convert/service.go @@ -219,19 +219,27 @@ func convertServiceSecrets( if gid == "" { gid = "0" } + mode := secret.Mode + if mode == nil { + mode = uint32Ptr(0444) + } opts = append(opts, &types.SecretRequestOption{ Source: source, Target: target, UID: uid, GID: gid, - Mode: os.FileMode(secret.Mode), + Mode: os.FileMode(*mode), }) } return servicecli.ParseSecrets(client, opts) } +func uint32Ptr(value uint32) *uint32 { + return &value +} + func convertExtraHosts(extraHosts map[string]string) []string { hosts := []string{} for host, ip := range extraHosts { diff --git a/cli/compose/types/types.go b/cli/compose/types/types.go index cae7b4af26..d1371d2a1c 100644 --- a/cli/compose/types/types.go +++ b/cli/compose/types/types.go @@ -199,7 +199,7 @@ type ServiceSecretConfig struct { Target string UID string GID string - Mode uint32 + Mode *uint32 } // UlimitsConfig the ulimit configuration diff --git a/client/container_create.go b/client/container_create.go index 9f627aafa6..6841b0b282 100644 --- a/client/container_create.go +++ b/client/container_create.go @@ -7,6 +7,7 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/versions" "golang.org/x/net/context" ) @@ -25,6 +26,11 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config 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{} if containerName != "" { query.Set("name", containerName) diff --git a/client/container_create_test.go b/client/container_create_test.go index 15dbd5ea01..73474cf56f 100644 --- a/client/container_create_test.go +++ b/client/container_create_test.go @@ -74,3 +74,45 @@ func TestContainerCreateWithName(t *testing.T) { 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) + } +} diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index b8e762592c..3103e19c2a 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -28,7 +28,7 @@ import ( "github.com/docker/docker/pkg/loopback" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/parsers" - "github.com/docker/go-units" + units "github.com/docker/go-units" "github.com/opencontainers/runc/libcontainer/label" ) @@ -1713,9 +1713,9 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error { // https://github.com/docker/docker/issues/4036 if supported := devicemapper.UdevSetSyncSupport(true); !supported { 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 { - 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 { diff --git a/daemon/graphdriver/windows/windows.go b/daemon/graphdriver/windows/windows.go index beac93ae75..54641cb90c 100644 --- a/daemon/graphdriver/windows/windows.go +++ b/daemon/graphdriver/windows/windows.go @@ -31,6 +31,7 @@ import ( "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/longpath" "github.com/docker/docker/pkg/reexec" + "github.com/docker/docker/pkg/system" units "github.com/docker/go-units" "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. var computeSystems []hcsshim.ContainerProperties retryCount := 0 + osv := system.GetOSVersion() 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{}) if err != nil { - if err == hcsshim.ErrVmcomputeOperationInvalidState { - if retryCount >= 5 { - // If we are unable to get the list of containers - // go ahead and attempt to delete the layer anyway - // as it will most likely work. + if (osv.Build < 15139) && + ((err == hcsshim.ErrVmcomputeOperationInvalidState) || (err == hcsshim.ErrVmcomputeOperationAccessIsDenied)) { + if retryCount >= 500 { break } retryCount++ - time.Sleep(2 * time.Second) + time.Sleep(10 * time.Millisecond) continue } return err diff --git a/daemon/logger/jsonfilelog/read.go b/daemon/logger/jsonfilelog/read.go index f2f9df1887..30d533fc1f 100644 --- a/daemon/logger/jsonfilelog/read.go +++ b/daemon/logger/jsonfilelog/read.go @@ -137,7 +137,11 @@ func tailFile(f io.ReadSeeker, logWatcher *logger.LogWatcher, tail int, since ti if !since.IsZero() && msg.Timestamp.Before(since) { 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 { if err == io.EOF { - for err := waitRead(); err != nil; { + for { + err := waitRead() + if err == nil { + break + } if err == errRetry { - // retry the waitRead continue } return err diff --git a/daemon/logs.go b/daemon/logs.go index cc34b82083..004bf20c84 100644 --- a/daemon/logs.go +++ b/daemon/logs.go @@ -61,6 +61,18 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c Follow: follow, } 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) defer wf.Close() @@ -81,19 +93,11 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c logrus.Errorf("Error streaming logs: %v", err) return nil case <-ctx.Done(): - logs.Close() + logrus.Debugf("logs: end stream, ctx is done: %v", ctx.Err()) return nil case msg, ok := <-logs.Msg: if !ok { 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 } logLine := msg.Line diff --git a/daemon/stats.go b/daemon/stats.go index 51f5962d17..1778adf92e 100644 --- a/daemon/stats.go +++ b/daemon/stats.go @@ -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 (!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 diff --git a/daemon/stats_collector.go b/daemon/stats_collector.go index dc6825e705..291933b7ac 100644 --- a/daemon/stats_collector.go +++ b/daemon/stats_collector.go @@ -120,7 +120,14 @@ func (s *statsCollector) run() { if err != nil { if _, ok := err.(errNotRunning); !ok { 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 } // FIXME: move to containerd on Linux (not Windows) diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 49c1062c25..41470f9777 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -531,6 +531,10 @@ func (s *DockerSuite) TestBuildCacheAdd(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" 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) { // /docker/world/hello is not owned by the correct user 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) { // /docker/world/hello is not owned by the correct user 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) { ctx, err := fakeContext(`FROM busybox diff --git a/integration-cli/docker_cli_stats_test.go b/integration-cli/docker_cli_stats_test.go index 5cb1a3ea02..804074d269 100644 --- a/integration-cli/docker_cli_stats_test.go +++ b/integration-cli/docker_cli_stats_test.go @@ -157,3 +157,22 @@ func (s *DockerSuite) TestStatsAllNewContainersAdded(c *check.C) { // 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") +} diff --git a/runconfig/opts/parse.go b/runconfig/opts/parse.go index 71a89277ec..3a0da7984b 100644 --- a/runconfig/opts/parse.go +++ b/runconfig/opts/parse.go @@ -621,6 +621,10 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c 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 if flags.Changed("init") { hostConfig.Init = &copts.init diff --git a/runconfig/opts/parse_test.go b/runconfig/opts/parse_test.go index a1be379ae8..98894bb4b8 100644 --- a/runconfig/opts/parse_test.go +++ b/runconfig/opts/parse_test.go @@ -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) { checkOk := func(args ...string) *container.HealthConfig { config, _, _, err := parseRun(args) diff --git a/vendor.conf b/vendor.conf index a3ab0d6817..0f0019b6ba 100644 --- a/vendor.conf +++ b/vendor.conf @@ -1,6 +1,6 @@ # the following lines are in sorted order, FYI 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/Sirupsen/logrus v0.11.0 github.com/davecgh/go-spew 6d212800a42e8ab5c146b8ace3490ee17e5225f9 diff --git a/vendor/github.com/Microsoft/hcsshim/errors.go b/vendor/github.com/Microsoft/hcsshim/errors.go index 19bb97a05b..fde148ab70 100644 --- a/vendor/github.com/Microsoft/hcsshim/errors.go +++ b/vendor/github.com/Microsoft/hcsshim/errors.go @@ -50,6 +50,10 @@ var ( // ErrProcNotFound is an error encountered when the the process cannot be found 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 diff --git a/vendor/github.com/Microsoft/hcsshim/interface.go b/vendor/github.com/Microsoft/hcsshim/interface.go index 000a18c1be..3e330f13d6 100644 --- a/vendor/github.com/Microsoft/hcsshim/interface.go +++ b/vendor/github.com/Microsoft/hcsshim/interface.go @@ -41,30 +41,32 @@ type HvRuntime struct { // ContainerConfig is used as both the input of CreateContainer // and to convert the parameters to JSON for passing onto the HCS type ContainerConfig struct { - SystemType string // HCS requires this to be hard-coded to "Container" - Name string // Name of the container. We use the docker ID. - Owner string // The management platform that created this container - 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} - 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 - 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 - 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. - ProcessorMaximum int64 `json:",omitempty"` // CPU maximum usage percent 1..100 - StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS - 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 - MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes - HostName string // Hostname - 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 - HvPartition bool // True if it a Hyper-V 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 - Servicing bool // True if this container is for servicing - AllowUnqualifiedDNSQuery bool // True to allow unqualified DNS name resolution + SystemType string // HCS requires this to be hard-coded to "Container" + Name string // Name of the container. We use the docker ID. + Owner string // The management platform that created this container + 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} + 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 + 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 + 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. + ProcessorMaximum int64 `json:",omitempty"` // CPU maximum usage percent 1..100 + StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS + 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 + MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes + HostName string // Hostname + 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 + HvPartition bool // True if it a Hyper-V Container + EndpointList []string // List of networking endpoints to be attached to container + NetworkSharedContainerName string `json:",omitempty"` // Name (ID) of the container that we will share the network stack with. + HvRuntime *HvRuntime `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM + 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 {