diff --git a/apparmor/gen.go b/apparmor/gen.go index a3192e23..653bf34d 100644 --- a/apparmor/gen.go +++ b/apparmor/gen.go @@ -1,3 +1,5 @@ +// +build linux + package apparmor import ( diff --git a/apparmor/setup.go b/apparmor/setup.go index 8ed54374..2df21268 100644 --- a/apparmor/setup.go +++ b/apparmor/setup.go @@ -1,3 +1,5 @@ +// +build linux + package apparmor import ( diff --git a/cgroups/cgroups.go b/cgroups/cgroups.go index df7bfb3c..ec9c39da 100644 --- a/cgroups/cgroups.go +++ b/cgroups/cgroups.go @@ -1,3 +1,5 @@ +// +build linux + package cgroups import ( diff --git a/cgroups/cgroups_test.go b/cgroups/cgroups_test.go index e8c52938..597834a0 100644 --- a/cgroups/cgroups_test.go +++ b/cgroups/cgroups_test.go @@ -1,3 +1,5 @@ +// +build linux + package cgroups import ( diff --git a/cgroups/cgroups_unsupported.go b/cgroups/cgroups_unsupported.go new file mode 100644 index 00000000..278d507e --- /dev/null +++ b/cgroups/cgroups_unsupported.go @@ -0,0 +1,3 @@ +// +build !linux + +package cgroups diff --git a/cgroups/fs/apply_raw.go b/cgroups/fs/apply_raw.go index 99c78457..2507b190 100644 --- a/cgroups/fs/apply_raw.go +++ b/cgroups/fs/apply_raw.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/blkio.go b/cgroups/fs/blkio.go index 06f0a3b2..eadee1ba 100644 --- a/cgroups/fs/blkio.go +++ b/cgroups/fs/blkio.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/blkio_test.go b/cgroups/fs/blkio_test.go index 9d0915da..2ed40bf0 100644 --- a/cgroups/fs/blkio_test.go +++ b/cgroups/fs/blkio_test.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/cpu.go b/cgroups/fs/cpu.go index c9d4ad1a..963eb680 100644 --- a/cgroups/fs/cpu.go +++ b/cgroups/fs/cpu.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/cpu_test.go b/cgroups/fs/cpu_test.go index bcf4ac4e..20e43792 100644 --- a/cgroups/fs/cpu_test.go +++ b/cgroups/fs/cpu_test.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/cpuacct.go b/cgroups/fs/cpuacct.go index decee850..1c324cbb 100644 --- a/cgroups/fs/cpuacct.go +++ b/cgroups/fs/cpuacct.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/cpuset.go b/cgroups/fs/cpuset.go index 6ad42a58..a84506fd 100644 --- a/cgroups/fs/cpuset.go +++ b/cgroups/fs/cpuset.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/cpuset_test.go b/cgroups/fs/cpuset_test.go index 7449cdca..44b2f943 100644 --- a/cgroups/fs/cpuset_test.go +++ b/cgroups/fs/cpuset_test.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/devices.go b/cgroups/fs/devices.go index 09ce92ef..32387d87 100644 --- a/cgroups/fs/devices.go +++ b/cgroups/fs/devices.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/devices_test.go b/cgroups/fs/devices_test.go index f950c1b9..cd786bae 100644 --- a/cgroups/fs/devices_test.go +++ b/cgroups/fs/devices_test.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/freezer.go b/cgroups/fs/freezer.go index 1110e5ff..112ee04c 100644 --- a/cgroups/fs/freezer.go +++ b/cgroups/fs/freezer.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/fs_unsupported.go b/cgroups/fs/fs_unsupported.go new file mode 100644 index 00000000..3ef9e031 --- /dev/null +++ b/cgroups/fs/fs_unsupported.go @@ -0,0 +1,3 @@ +// +build !linux + +package fs diff --git a/cgroups/fs/hugetlb.go b/cgroups/fs/hugetlb.go index 8defdd1b..277e87fe 100644 --- a/cgroups/fs/hugetlb.go +++ b/cgroups/fs/hugetlb.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/memory.go b/cgroups/fs/memory.go index 2dcef0f4..e03dd7c1 100644 --- a/cgroups/fs/memory.go +++ b/cgroups/fs/memory.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/memory_test.go b/cgroups/fs/memory_test.go index 60edc67a..d6e99a7a 100644 --- a/cgroups/fs/memory_test.go +++ b/cgroups/fs/memory_test.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/perf_event.go b/cgroups/fs/perf_event.go index ca65f734..2b349270 100644 --- a/cgroups/fs/perf_event.go +++ b/cgroups/fs/perf_event.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/stats_util_test.go b/cgroups/fs/stats_util_test.go index 48e2f3ae..55e1e48c 100644 --- a/cgroups/fs/stats_util_test.go +++ b/cgroups/fs/stats_util_test.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/util_test.go b/cgroups/fs/util_test.go index 37bf5157..0344c8ed 100644 --- a/cgroups/fs/util_test.go +++ b/cgroups/fs/util_test.go @@ -1,3 +1,5 @@ +// +build linux + /* Utility for testing cgroup operations. diff --git a/cgroups/fs/utils.go b/cgroups/fs/utils.go index c2f75c8e..3a6eec79 100644 --- a/cgroups/fs/utils.go +++ b/cgroups/fs/utils.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/fs/utils_test.go b/cgroups/fs/utils_test.go index 8b19a84b..99cdc18e 100644 --- a/cgroups/fs/utils_test.go +++ b/cgroups/fs/utils_test.go @@ -1,3 +1,5 @@ +// +build linux + package fs import ( diff --git a/cgroups/stats.go b/cgroups/stats.go index 25c8f199..6d81a12e 100644 --- a/cgroups/stats.go +++ b/cgroups/stats.go @@ -1,3 +1,5 @@ +// +build linux + package cgroups type ThrottlingData struct { diff --git a/cgroups/utils.go b/cgroups/utils.go index c6c400c7..54868839 100644 --- a/cgroups/utils.go +++ b/cgroups/utils.go @@ -1,3 +1,5 @@ +// +build linux + package cgroups import ( diff --git a/configs/cgroup.go b/configs/cgroup.go index 8a161fcf..ea69a867 100644 --- a/configs/cgroup.go +++ b/configs/cgroup.go @@ -8,6 +8,9 @@ const ( Thawed FreezerState = "THAWED" ) +// TODO Windows: This can be factored out in the future as Cgroups are not +// supported on the Windows platform. + type Cgroup struct { Name string `json:"name"` diff --git a/configs/config.go b/configs/config.go index 2c311a0c..293af0a9 100644 --- a/configs/config.go +++ b/configs/config.go @@ -1,7 +1,5 @@ package configs -import "fmt" - type Rlimit struct { Type int `json:"type"` Hard uint64 `json:"hard"` @@ -15,6 +13,9 @@ type IDMap struct { Size int `json:"size"` } +// TODO Windows. Many of these fields should be factored out into those parts +// which are common across platforms, and those which are platform specific. + // Config defines configuration options for executing a process inside a contained environment. type Config struct { // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs @@ -104,49 +105,3 @@ type Config struct { // sysctl -w my.property.name value in Linux. SystemProperties map[string]string `json:"system_properties"` } - -// Gets the root uid for the process on host which could be non-zero -// when user namespaces are enabled. -func (c Config) HostUID() (int, error) { - if c.Namespaces.Contains(NEWUSER) { - if c.UidMappings == nil { - return -1, fmt.Errorf("User namespaces enabled, but no user mappings found.") - } - id, found := c.hostIDFromMapping(0, c.UidMappings) - if !found { - return -1, fmt.Errorf("User namespaces enabled, but no root user mapping found.") - } - return id, nil - } - // Return default root uid 0 - return 0, nil -} - -// Gets the root uid for the process on host which could be non-zero -// when user namespaces are enabled. -func (c Config) HostGID() (int, error) { - if c.Namespaces.Contains(NEWUSER) { - if c.GidMappings == nil { - return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.") - } - id, found := c.hostIDFromMapping(0, c.GidMappings) - if !found { - return -1, fmt.Errorf("User namespaces enabled, but no root user mapping found.") - } - return id, nil - } - // Return default root uid 0 - return 0, nil -} - -// Utility function that gets a host ID for a container ID from user namespace map -// if that ID is present in the map. -func (c Config) hostIDFromMapping(containerID int, uMap []IDMap) (int, bool) { - for _, m := range uMap { - if (containerID >= m.ContainerID) && (containerID <= (m.ContainerID + m.Size - 1)) { - hostID := m.HostID + (containerID - m.ContainerID) - return hostID, true - } - } - return -1, false -} diff --git a/configs/config_linux.go b/configs/config_linux.go new file mode 100644 index 00000000..97544b2a --- /dev/null +++ b/configs/config_linux.go @@ -0,0 +1,49 @@ +package configs + +import "fmt" + +// Gets the root uid for the process on host which could be non-zero +// when user namespaces are enabled. +func (c Config) HostUID() (int, error) { + if c.Namespaces.Contains(NEWUSER) { + if c.UidMappings == nil { + return -1, fmt.Errorf("User namespaces enabled, but no user mappings found.") + } + id, found := c.hostIDFromMapping(0, c.UidMappings) + if !found { + return -1, fmt.Errorf("User namespaces enabled, but no root user mapping found.") + } + return id, nil + } + // Return default root uid 0 + return 0, nil +} + +// Gets the root uid for the process on host which could be non-zero +// when user namespaces are enabled. +func (c Config) HostGID() (int, error) { + if c.Namespaces.Contains(NEWUSER) { + if c.GidMappings == nil { + return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.") + } + id, found := c.hostIDFromMapping(0, c.GidMappings) + if !found { + return -1, fmt.Errorf("User namespaces enabled, but no root user mapping found.") + } + return id, nil + } + // Return default root uid 0 + return 0, nil +} + +// Utility function that gets a host ID for a container ID from user namespace map +// if that ID is present in the map. +func (c Config) hostIDFromMapping(containerID int, uMap []IDMap) (int, bool) { + for _, m := range uMap { + if (containerID >= m.ContainerID) && (containerID <= (m.ContainerID + m.Size - 1)) { + hostID := m.HostID + (containerID - m.ContainerID) + return hostID, true + } + } + return -1, false +} diff --git a/configs/device.go b/configs/device.go index abff2669..a52a024a 100644 --- a/configs/device.go +++ b/configs/device.go @@ -9,6 +9,8 @@ const ( Wildcard = -1 ) +// TODO Windows: This can be factored out in the future + type Device struct { // Device type, block, char, etc. Type rune `json:"type"` diff --git a/configs/device_defaults.go b/configs/device_defaults.go index 70fa4af0..b0966b97 100644 --- a/configs/device_defaults.go +++ b/configs/device_defaults.go @@ -1,3 +1,5 @@ +// +build linux + package configs var ( diff --git a/configs/namespaces.go b/configs/namespaces.go index 2c2a9fd2..a3329a31 100644 --- a/configs/namespaces.go +++ b/configs/namespaces.go @@ -1,91 +1,5 @@ package configs -import "fmt" - type NamespaceType string -const ( - NEWNET NamespaceType = "NEWNET" - NEWPID NamespaceType = "NEWPID" - NEWNS NamespaceType = "NEWNS" - NEWUTS NamespaceType = "NEWUTS" - NEWIPC NamespaceType = "NEWIPC" - NEWUSER NamespaceType = "NEWUSER" -) - -func NamespaceTypes() []NamespaceType { - return []NamespaceType{ - NEWNET, - NEWPID, - NEWNS, - NEWUTS, - NEWIPC, - NEWUSER, - } -} - -// Namespace defines configuration for each namespace. It specifies an -// alternate path that is able to be joined via setns. -type Namespace struct { - Type NamespaceType `json:"type"` - Path string `json:"path"` -} - -func (n *Namespace) GetPath(pid int) string { - if n.Path != "" { - return n.Path - } - return fmt.Sprintf("/proc/%d/ns/%s", pid, n.file()) -} - -func (n *Namespace) file() string { - file := "" - switch n.Type { - case NEWNET: - file = "net" - case NEWNS: - file = "mnt" - case NEWPID: - file = "pid" - case NEWIPC: - file = "ipc" - case NEWUSER: - file = "user" - case NEWUTS: - file = "uts" - } - return file -} - type Namespaces []Namespace - -func (n *Namespaces) Remove(t NamespaceType) bool { - i := n.index(t) - if i == -1 { - return false - } - *n = append((*n)[:i], (*n)[i+1:]...) - return true -} - -func (n *Namespaces) Add(t NamespaceType, path string) { - i := n.index(t) - if i == -1 { - *n = append(*n, Namespace{Type: t, Path: path}) - return - } - (*n)[i].Path = path -} - -func (n *Namespaces) index(t NamespaceType) int { - for i, ns := range *n { - if ns.Type == t { - return i - } - } - return -1 -} - -func (n *Namespaces) Contains(t NamespaceType) bool { - return n.index(t) != -1 -} diff --git a/configs/namespaces_linux.go b/configs/namespaces_linux.go new file mode 100644 index 00000000..c937b49f --- /dev/null +++ b/configs/namespaces_linux.go @@ -0,0 +1,89 @@ +// +build linux + +package configs + +import "fmt" + +const ( + NEWNET NamespaceType = "NEWNET" + NEWPID NamespaceType = "NEWPID" + NEWNS NamespaceType = "NEWNS" + NEWUTS NamespaceType = "NEWUTS" + NEWIPC NamespaceType = "NEWIPC" + NEWUSER NamespaceType = "NEWUSER" +) + +func NamespaceTypes() []NamespaceType { + return []NamespaceType{ + NEWNET, + NEWPID, + NEWNS, + NEWUTS, + NEWIPC, + NEWUSER, + } +} + +// Namespace defines configuration for each namespace. It specifies an +// alternate path that is able to be joined via setns. +type Namespace struct { + Type NamespaceType `json:"type"` + Path string `json:"path"` +} + +func (n *Namespace) GetPath(pid int) string { + if n.Path != "" { + return n.Path + } + return fmt.Sprintf("/proc/%d/ns/%s", pid, n.file()) +} + +func (n *Namespace) file() string { + file := "" + switch n.Type { + case NEWNET: + file = "net" + case NEWNS: + file = "mnt" + case NEWPID: + file = "pid" + case NEWIPC: + file = "ipc" + case NEWUSER: + file = "user" + case NEWUTS: + file = "uts" + } + return file +} + +func (n *Namespaces) Remove(t NamespaceType) bool { + i := n.index(t) + if i == -1 { + return false + } + *n = append((*n)[:i], (*n)[i+1:]...) + return true +} + +func (n *Namespaces) Add(t NamespaceType, path string) { + i := n.index(t) + if i == -1 { + *n = append(*n, Namespace{Type: t, Path: path}) + return + } + (*n)[i].Path = path +} + +func (n *Namespaces) index(t NamespaceType) int { + for i, ns := range *n { + if ns.Type == t { + return i + } + } + return -1 +} + +func (n *Namespaces) Contains(t NamespaceType) bool { + return n.index(t) != -1 +} diff --git a/configs/namespaces_syscall_unsupported.go b/configs/namespaces_syscall_unsupported.go index 1bd26bd6..1644588d 100644 --- a/configs/namespaces_syscall_unsupported.go +++ b/configs/namespaces_syscall_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux +// +build !linux,!windows package configs diff --git a/configs/namespaces_windows.go b/configs/namespaces_windows.go new file mode 100644 index 00000000..f8fe47a8 --- /dev/null +++ b/configs/namespaces_windows.go @@ -0,0 +1,6 @@ +package configs + +// Namespace defines configuration for each namespace. It specifies an +// alternate path that is able to be joined via setns. +type Namespace struct { +} diff --git a/console_linux.go b/console_linux.go index a3a0551c..5eaf0316 100644 --- a/console_linux.go +++ b/console_linux.go @@ -1,5 +1,3 @@ -// +build linux - package libcontainer import ( diff --git a/console_windows.go b/console_windows.go new file mode 100644 index 00000000..80c7463b --- /dev/null +++ b/console_windows.go @@ -0,0 +1,30 @@ +package libcontainer + +// newConsole returns an initalized console that can be used within a container +func newConsole(uid, gid int) (Console, error) { + return &windowsConsole{}, nil +} + +// windowsConsole is a Windows psuedo TTY for use within a container. +type windowsConsole struct { +} + +func (c *windowsConsole) Fd() uintptr { + return 0 +} + +func (c *windowsConsole) Path() string { + return "" +} + +func (c *windowsConsole) Read(b []byte) (int, error) { + return 0, nil +} + +func (c *windowsConsole) Write(b []byte) (int, error) { + return 0, nil +} + +func (c *windowsConsole) Close() error { + return nil +} diff --git a/devices/devices.go b/devices/devices_linux.go similarity index 100% rename from devices/devices.go rename to devices/devices_linux.go diff --git a/devices/devices_windows.go b/devices/devices_windows.go new file mode 100644 index 00000000..bd477f8c --- /dev/null +++ b/devices/devices_windows.go @@ -0,0 +1,16 @@ +package devices + +import ( + "github.com/docker/libcontainer/configs" +) + +// TODO Windows. This can be factored out further - Devices are not supported +// by Windows Containers. + +func DeviceFromPath(path, permissions string) (*configs.Device, error) { + return nil, nil +} + +func HostDevices() ([]*configs.Device, error) { + return nil, nil +} diff --git a/devices/number.go b/devices/number.go index 9e8feb83..e9c3e516 100644 --- a/devices/number.go +++ b/devices/number.go @@ -1,3 +1,5 @@ +// +build linux + package devices /* diff --git a/stats.go b/stats.go index ba72a6fd..303e4b94 100644 --- a/stats.go +++ b/stats.go @@ -1,12 +1,5 @@ package libcontainer -import "github.com/docker/libcontainer/cgroups" - -type Stats struct { - Interfaces []*NetworkInterface - CgroupStats *cgroups.Stats -} - type NetworkInterface struct { // Name is the name of the network interface. Name string diff --git a/stats_linux.go b/stats_linux.go new file mode 100644 index 00000000..8ce96978 --- /dev/null +++ b/stats_linux.go @@ -0,0 +1,8 @@ +package libcontainer + +import "github.com/docker/libcontainer/cgroups" + +type Stats struct { + Interfaces []*NetworkInterface + CgroupStats *cgroups.Stats +} diff --git a/stats_windows.go b/stats_windows.go new file mode 100644 index 00000000..f8d1d689 --- /dev/null +++ b/stats_windows.go @@ -0,0 +1,5 @@ +package libcontainer + +type Stats struct { + Interfaces []*NetworkInterface +} diff --git a/system/sysconfig.go b/system/sysconfig.go index 5efddefa..b8434f10 100644 --- a/system/sysconfig.go +++ b/system/sysconfig.go @@ -1,4 +1,4 @@ -// +build cgo +// +build cgo,linux package system diff --git a/system/sysconfig_notcgo.go b/system/sysconfig_notcgo.go index 663db82b..d93b5d5f 100644 --- a/system/sysconfig_notcgo.go +++ b/system/sysconfig_notcgo.go @@ -1,8 +1,15 @@ -// +build !cgo +// +build !cgo windows package system func GetClockTicks() int { // TODO figure out a better alternative for platforms where we're missing cgo + // + // TODO Windows. This could be implemented using Win32 QueryPerformanceFrequency(). + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx + // + // An example of its usage can be found here. + // https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx + return 100 }