container/container_windows.go
4f0d95fa
 package container // import "github.com/docker/docker/container"
6bb0d181
 
 import (
ff3ea4c9
 	"fmt"
67912303
 	"os"
 	"path/filepath"
 
cfc404a3
 	"github.com/docker/docker/api/types"
91e197d6
 	containertypes "github.com/docker/docker/api/types/container"
c0217180
 	swarmtypes "github.com/docker/docker/api/types/swarm"
bd4e8aa6
 	"github.com/docker/docker/pkg/system"
6bb0d181
 )
 
67d282a5
 const (
bd4e8aa6
 	containerSecretMountPath         = `C:\ProgramData\Docker\secrets`
 	containerInternalSecretMountPath = `C:\ProgramData\Docker\internal\secrets`
e0d533b1
 	containerInternalConfigsDirPath  = `C:\ProgramData\Docker\internal\configs`
ed74ee12
 
 	// DefaultStopTimeout is the timeout (in seconds) for the shutdown call on a container
 	DefaultStopTimeout = 30
67d282a5
 )
 
7120976d
 // UnmountIpcMount unmounts Ipc related mounts.
6bb0d181
 // This is a NOOP on windows.
77bc327e
 func (container *Container) UnmountIpcMount() error {
7120976d
 	return nil
6bb0d181
 }
 
 // IpcMounts returns the list of Ipc related mounts.
94d70d83
 func (container *Container) IpcMounts() []Mount {
6bb0d181
 	return nil
 }
 
bd4e8aa6
 // CreateSecretSymlinks creates symlinks to files in the secret mount.
 func (container *Container) CreateSecretSymlinks() error {
 	for _, r := range container.SecretReferences {
 		if r.File == nil {
 			continue
 		}
 		resolvedPath, _, err := container.ResolvePath(getSecretTargetPath(r))
 		if err != nil {
 			return err
 		}
ed10ac6e
 		if err := system.MkdirAll(filepath.Dir(resolvedPath), 0, ""); err != nil {
bd4e8aa6
 			return err
 		}
 		if err := os.Symlink(filepath.Join(containerInternalSecretMountPath, r.SecretID), resolvedPath); err != nil {
 			return err
 		}
 	}
 
72c1d7f4
 	return nil
 }
 
bd4e8aa6
 // SecretMounts returns the mount for the secret path.
 // All secrets are stored in a single mount on Windows. Target symlinks are
 // created for each secret, pointing to the files in this mount.
eaa51928
 func (container *Container) SecretMounts() ([]Mount, error) {
bd4e8aa6
 	var mounts []Mount
 	if len(container.SecretReferences) > 0 {
eaa51928
 		src, err := container.SecretMountPath()
 		if err != nil {
 			return nil, err
 		}
bd4e8aa6
 		mounts = append(mounts, Mount{
eaa51928
 			Source:      src,
bd4e8aa6
 			Destination: containerInternalSecretMountPath,
 			Writable:    false,
 		})
 	}
 
eaa51928
 	return mounts, nil
bd4e8aa6
 }
 
72c1d7f4
 // UnmountSecrets unmounts the fs for secrets
 func (container *Container) UnmountSecrets() error {
eaa51928
 	p, err := container.SecretMountPath()
 	if err != nil {
 		return err
 	}
 	return os.RemoveAll(p)
72c1d7f4
 }
 
e0d533b1
 // CreateConfigSymlinks creates symlinks to files in the config mount.
 func (container *Container) CreateConfigSymlinks() error {
 	for _, configRef := range container.ConfigReferences {
 		if configRef.File == nil {
 			continue
 		}
 		resolvedPath, _, err := container.ResolvePath(configRef.File.Name)
 		if err != nil {
 			return err
 		}
ed10ac6e
 		if err := system.MkdirAll(filepath.Dir(resolvedPath), 0, ""); err != nil {
e0d533b1
 			return err
 		}
 		if err := os.Symlink(filepath.Join(containerInternalConfigsDirPath, configRef.ConfigID), resolvedPath); err != nil {
 			return err
 		}
 	}
 
 	return nil
 }
 
 // ConfigMounts returns the mount for configs.
c0217180
 // TODO: Right now Windows doesn't really have a "secure" storage for secrets,
 // however some configs may contain secrets. Once secure storage is worked out,
 // configs and secret handling should be merged.
 func (container *Container) ConfigMounts() []Mount {
e0d533b1
 	var mounts []Mount
 	if len(container.ConfigReferences) > 0 {
 		mounts = append(mounts, Mount{
c0217180
 			Source:      container.ConfigsDirPath(),
e0d533b1
 			Destination: containerInternalConfigsDirPath,
 			Writable:    false,
 		})
 	}
 
c0217180
 	return mounts
e0d533b1
 }
 
9a2d0bc3
 // DetachAndUnmount unmounts all volumes.
 // On Windows it only delegates to `UnmountVolumes` since there is nothing to
 // force unmount.
 func (container *Container) DetachAndUnmount(volumeEventLog func(name, action string, attributes map[string]string)) error {
 	return container.UnmountVolumes(volumeEventLog)
6bb0d181
 }
 
 // TmpfsMounts returns the list of tmpfs mounts
18768fdc
 func (container *Container) TmpfsMounts() ([]Mount, error) {
756f6cef
 	var mounts []Mount
18768fdc
 	return mounts, nil
6bb0d181
 }
 
eed4c7b7
 // UpdateContainer updates configuration of a container. Callers must hold a Lock on the Container.
5849a553
 func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
ff3ea4c9
 	resources := hostConfig.Resources
e5070663
 	if resources.CPUShares != 0 ||
 		resources.Memory != 0 ||
 		resources.NanoCPUs != 0 ||
 		resources.CgroupParent != "" ||
 		resources.BlkioWeight != 0 ||
 		len(resources.BlkioWeightDevice) != 0 ||
 		len(resources.BlkioDeviceReadBps) != 0 ||
 		len(resources.BlkioDeviceWriteBps) != 0 ||
 		len(resources.BlkioDeviceReadIOps) != 0 ||
 		len(resources.BlkioDeviceWriteIOps) != 0 ||
 		resources.CPUPeriod != 0 ||
 		resources.CPUQuota != 0 ||
 		resources.CPURealtimePeriod != 0 ||
 		resources.CPURealtimeRuntime != 0 ||
 		resources.CpusetCpus != "" ||
 		resources.CpusetMems != "" ||
 		len(resources.Devices) != 0 ||
 		len(resources.DeviceCgroupRules) != 0 ||
 		resources.KernelMemory != 0 ||
 		resources.MemoryReservation != 0 ||
 		resources.MemorySwap != 0 ||
 		resources.MemorySwappiness != nil ||
 		resources.OomKillDisable != nil ||
74eb258f
 		(resources.PidsLimit != nil && *resources.PidsLimit != 0) ||
e5070663
 		len(resources.Ulimits) != 0 ||
 		resources.CPUCount != 0 ||
 		resources.CPUPercent != 0 ||
 		resources.IOMaximumIOps != 0 ||
 		resources.IOMaximumBandwidth != 0 {
 		return fmt.Errorf("resource updating isn't supported on Windows")
ff3ea4c9
 	}
 	// update HostConfig of container
 	if hostConfig.RestartPolicy.Name != "" {
4754c64a
 		if container.HostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
 			return fmt.Errorf("Restart policy cannot be updated because AutoRemove is enabled for the container")
 		}
ff3ea4c9
 		container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
 	}
8799c4fc
 	return nil
 }
 
e8026d8a
 // BuildHostnameFile writes the container's hostname file.
 func (container *Container) BuildHostnameFile() error {
 	return nil
 }
 
cfc404a3
 // GetMountPoints gives a platform specific transformation to types.MountPoint. Callers must hold a Container lock.
 func (container *Container) GetMountPoints() []types.MountPoint {
 	mountPoints := make([]types.MountPoint, 0, len(container.MountPoints))
 	for _, m := range container.MountPoints {
 		mountPoints = append(mountPoints, types.MountPoint{
 			Type:        m.Type,
 			Name:        m.Name,
 			Source:      m.Path(),
 			Destination: m.Destination,
 			Driver:      m.Driver,
 			RW:          m.RW,
 		})
 	}
 	return mountPoints
 }
c0217180
 
 func (container *Container) ConfigsDirPath() string {
 	return filepath.Join(container.Root, "configs")
 }
 
 // ConfigFilePath returns the path to the on-disk location of a config.
 func (container *Container) ConfigFilePath(configRef swarmtypes.ConfigReference) string {
 	return filepath.Join(container.ConfigsDirPath(), configRef.ConfigID)
 }