Browse code

Update libcontainer to 5210a236b92a8022a673108f347 Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@docker.com> (github: crosbymichael)

Michael Crosby authored on 2014/06/25 03:30:36
Showing 37 changed files
... ...
@@ -61,4 +61,4 @@ mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar
61 61
 
62 62
 clone git github.com/godbus/dbus v1
63 63
 clone git github.com/coreos/go-systemd v2
64
-clone git github.com/docker/libcontainer v1.0.1
64
+clone git github.com/docker/libcontainer 5210a236b92a8022a673108f3471fed0a046bd05
... ...
@@ -1,5 +1,9 @@
1 1
 ## libcontainer - reference implementation for containers
2 2
 
3
+### Note on API changes:
4
+
5
+Please bear with us while we work on making the libcontainer API stable and something that we can support long term.  We are currently discussing the API with the community, therefore, if you currently depend on libcontainer please pin your dependency at a specific tag or commit id.  Please join the discussion and help shape the API.
6
+
3 7
 #### Background
4 8
 
5 9
 libcontainer specifies configuration options for what a container is.  It provides a native Go implementation 
... ...
@@ -13,7 +17,7 @@ a `container.json` file is placed with the runtime configuration for how the pro
13 13
 should be contained and run.  Environment, networking, and different capabilities for the 
14 14
 process are specified in this file.  The configuration is used for each process executed inside the container.
15 15
 
16
-See the `container.json` file for what the configuration should look like.
16
+See the `sample_configs` folder for examples of what the container configuration should look like.
17 17
 
18 18
 Using this configuration and the current directory holding the rootfs for a process, one can use libcontainer to exec the container. Running the life of the namespace, a `pid` file 
19 19
 is written to the current directory with the pid of the namespaced process to the external world.  A client can use this pid to wait, kill, or perform other operation with the container.  If a user tries to run a new process inside an existing container with a live namespace, the namespace will be joined by the new process.
... ...
@@ -57,12 +57,13 @@ func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
57 57
 
58 58
 	d, err := getCgroupData(c, 0)
59 59
 	if err != nil {
60
-		return nil, err
60
+		return nil, fmt.Errorf("getting CgroupData %s", err)
61 61
 	}
62 62
 
63
-	for _, sys := range subsystems {
64
-		if err := sys.GetStats(d, stats); err != nil {
65
-			return nil, err
63
+	for sysName, sys := range subsystems {
64
+		// Don't fail if a cgroup hierarchy was not found.
65
+		if err := sys.GetStats(d, stats); err != nil && err != cgroups.ErrNotFound {
66
+			return nil, fmt.Errorf("getting stats for system %q %s", sysName, err)
66 67
 		}
67 68
 	}
68 69
 
... ...
@@ -2,24 +2,21 @@ package libcontainer
2 2
 
3 3
 import (
4 4
 	"github.com/docker/libcontainer/cgroups"
5
-	"github.com/docker/libcontainer/devices"
5
+	"github.com/docker/libcontainer/mount"
6
+	"github.com/docker/libcontainer/network"
6 7
 )
7 8
 
8
-// Context is a generic key value pair that allows arbatrary data to be sent
9
-type Context map[string]string
9
+type MountConfig mount.MountConfig
10 10
 
11
-// Container defines configuration options for executing a process inside a contained environment
12
-type Container struct {
13
-	// Hostname optionally sets the container's hostname if provided
14
-	Hostname string `json:"hostname,omitempty"`
11
+type Network network.Network
15 12
 
16
-	// ReadonlyFs will remount the container's rootfs as readonly where only externally mounted
17
-	// bind mounts are writtable
18
-	ReadonlyFs bool `json:"readonly_fs,omitempty"`
13
+// Config defines configuration options for executing a process inside a contained environment.
14
+type Config struct {
15
+	// Mount specific options.
16
+	MountConfig *MountConfig `json:"mount_config,omitempty"`
19 17
 
20
-	// NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs
21
-	// This is a common option when the container is running in ramdisk
22
-	NoPivotRoot bool `json:"no_pivot_root,omitempty"`
18
+	// Hostname optionally sets the container's hostname if provided
19
+	Hostname string `json:"hostname,omitempty"`
23 20
 
24 21
 	// User will set the uid and gid of the executing process running inside the container
25 22
 	User string `json:"user,omitempty"`
... ...
@@ -58,37 +55,8 @@ type Container struct {
58 58
 	// on the container's creation
59 59
 	// This is commonly used to specify apparmor profiles, selinux labels, and different restrictions
60 60
 	// placed on the container's processes
61
-	Context Context `json:"context,omitempty"`
62
-
63
-	// Mounts specify additional source and destination paths that will be mounted inside the container's
64
-	// rootfs and mount namespace if specified
65
-	Mounts Mounts `json:"mounts,omitempty"`
66
-
67
-	// The device nodes that should be automatically created within the container upon container start.  Note, make sure that the node is marked as allowed in the cgroup as well!
68
-	DeviceNodes []*devices.Device `json:"device_nodes,omitempty"`
69
-}
70
-
71
-// Network defines configuration for a container's networking stack
72
-//
73
-// The network configuration can be omited from a container causing the
74
-// container to be setup with the host's networking stack
75
-type Network struct {
76
-	// Type sets the networks type, commonly veth and loopback
77
-	Type string `json:"type,omitempty"`
78
-
79
-	// Context is a generic key value format for setting additional options that are specific to
80
-	// the network type
81
-	Context Context `json:"context,omitempty"`
82
-
83
-	// Address contains the IP and mask to set on the network interface
84
-	Address string `json:"address,omitempty"`
85
-
86
-	// Gateway sets the gateway address that is used as the default for the interface
87
-	Gateway string `json:"gateway,omitempty"`
88
-
89
-	// Mtu sets the mtu value for the interface and will be mirrored on both the host and
90
-	// container's interfaces if a pair is created, specifically in the case of type veth
91
-	Mtu int `json:"mtu,omitempty"`
61
+	// TODO(vishh): Avoid overloading this field with params for different subsystems. Strongtype this.
62
+	Context map[string]string `json:"context,omitempty"`
92 63
 }
93 64
 
94 65
 // Routes can be specified to create entries in the route table as the container is started
95 66
deleted file mode 100644
... ...
@@ -1,213 +0,0 @@
1
-{
2
-    "capabilities": [
3
-        "CHOWN",
4
-        "DAC_OVERRIDE",
5
-        "FOWNER",
6
-        "MKNOD",
7
-        "NET_RAW",
8
-        "SETGID",
9
-        "SETUID",
10
-        "SETFCAP",
11
-        "SETPCAP",
12
-        "NET_BIND_SERVICE",
13
-        "SYS_CHROOT",
14
-        "KILL"
15
-    ],
16
-    "cgroups": {
17
-        "allowed_devices": [
18
-            {
19
-                "cgroup_permissions": "m",
20
-                "major_number": -1,
21
-                "minor_number": -1,
22
-                "type": 99
23
-            },
24
-            {
25
-                "cgroup_permissions": "m",
26
-                "major_number": -1,
27
-                "minor_number": -1,
28
-                "type": 98
29
-            },
30
-            {
31
-                "cgroup_permissions": "rwm",
32
-                "major_number": 5,
33
-                "minor_number": 1,
34
-                "path": "/dev/console",
35
-                "type": 99
36
-            },
37
-            {
38
-                "cgroup_permissions": "rwm",
39
-                "major_number": 4,
40
-                "path": "/dev/tty0",
41
-                "type": 99
42
-            },
43
-            {
44
-                "cgroup_permissions": "rwm",
45
-                "major_number": 4,
46
-                "minor_number": 1,
47
-                "path": "/dev/tty1",
48
-                "type": 99
49
-            },
50
-            {
51
-                "cgroup_permissions": "rwm",
52
-                "major_number": 136,
53
-                "minor_number": -1,
54
-                "type": 99
55
-            },
56
-            {
57
-                "cgroup_permissions": "rwm",
58
-                "major_number": 5,
59
-                "minor_number": 2,
60
-                "type": 99
61
-            },
62
-            {
63
-                "cgroup_permissions": "rwm",
64
-                "major_number": 10,
65
-                "minor_number": 200,
66
-                "type": 99
67
-            },
68
-            {
69
-                "cgroup_permissions": "rwm",
70
-                "file_mode": 438,
71
-                "major_number": 1,
72
-                "minor_number": 3,
73
-                "path": "/dev/null",
74
-                "type": 99
75
-            },
76
-            {
77
-                "cgroup_permissions": "rwm",
78
-                "file_mode": 438,
79
-                "major_number": 1,
80
-                "minor_number": 5,
81
-                "path": "/dev/zero",
82
-                "type": 99
83
-            },
84
-            {
85
-                "cgroup_permissions": "rwm",
86
-                "file_mode": 438,
87
-                "major_number": 1,
88
-                "minor_number": 7,
89
-                "path": "/dev/full",
90
-                "type": 99
91
-            },
92
-            {
93
-                "cgroup_permissions": "rwm",
94
-                "file_mode": 438,
95
-                "major_number": 5,
96
-                "path": "/dev/tty",
97
-                "type": 99
98
-            },
99
-            {
100
-                "cgroup_permissions": "rwm",
101
-                "file_mode": 438,
102
-                "major_number": 1,
103
-                "minor_number": 9,
104
-                "path": "/dev/urandom",
105
-                "type": 99
106
-            },
107
-            {
108
-                "cgroup_permissions": "rwm",
109
-                "file_mode": 438,
110
-                "major_number": 1,
111
-                "minor_number": 8,
112
-                "path": "/dev/random",
113
-                "type": 99
114
-            }
115
-        ],
116
-        "name": "docker-koye",
117
-        "parent": "docker"
118
-    },
119
-    "context": {
120
-        "mount_label": "",
121
-        "process_label": "",
122
-        "restrictions": "true"
123
-    },
124
-    "device_nodes": [
125
-        {
126
-            "cgroup_permissions": "rwm",
127
-            "major_number": 10,
128
-            "minor_number": 229,
129
-            "path": "/dev/fuse",
130
-            "type": 99
131
-        },
132
-        {
133
-            "cgroup_permissions": "rwm",
134
-            "file_mode": 438,
135
-            "major_number": 1,
136
-            "minor_number": 3,
137
-            "path": "/dev/null",
138
-            "type": 99
139
-        },
140
-        {
141
-            "cgroup_permissions": "rwm",
142
-            "file_mode": 438,
143
-            "major_number": 1,
144
-            "minor_number": 5,
145
-            "path": "/dev/zero",
146
-            "type": 99
147
-        },
148
-        {
149
-            "cgroup_permissions": "rwm",
150
-            "file_mode": 438,
151
-            "major_number": 1,
152
-            "minor_number": 7,
153
-            "path": "/dev/full",
154
-            "type": 99
155
-        },
156
-        {
157
-            "cgroup_permissions": "rwm",
158
-            "file_mode": 438,
159
-            "major_number": 5,
160
-            "path": "/dev/tty",
161
-            "type": 99
162
-        },
163
-        {
164
-            "cgroup_permissions": "rwm",
165
-            "file_mode": 438,
166
-            "major_number": 1,
167
-            "minor_number": 9,
168
-            "path": "/dev/urandom",
169
-            "type": 99
170
-        },
171
-        {
172
-            "cgroup_permissions": "rwm",
173
-            "file_mode": 438,
174
-            "major_number": 1,
175
-            "minor_number": 8,
176
-            "path": "/dev/random",
177
-            "type": 99
178
-        }
179
-    ],
180
-    "environment": [
181
-        "HOME=/",
182
-        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
183
-        "HOSTNAME=2d388ea3bd92",
184
-        "TERM=xterm"
185
-    ],
186
-    "hostname": "koye",
187
-    "namespaces": {
188
-        "NEWIPC": true,
189
-        "NEWNET": true,
190
-        "NEWNS": true,
191
-        "NEWPID": true,
192
-        "NEWUTS": true
193
-    },
194
-    "networks": [
195
-        {
196
-            "address": "127.0.0.1/0",
197
-            "gateway": "localhost",
198
-            "mtu": 1500,
199
-            "type": "loopback"
200
-        },
201
-        {
202
-            "address": "172.17.0.101/16",
203
-            "context": {
204
-                "bridge": "docker0",
205
-                "prefix": "veth"
206
-            },
207
-            "gateway": "172.17.42.1",
208
-            "mtu": 1500,
209
-            "type": "veth"
210
-        }
211
-    ],
212
-    "tty": true
213
-}
... ...
@@ -4,6 +4,8 @@ import (
4 4
 	"encoding/json"
5 5
 	"os"
6 6
 	"testing"
7
+
8
+	"github.com/docker/libcontainer/devices"
7 9
 )
8 10
 
9 11
 // Checks whether the expected capability is specified in the capabilities.
... ...
@@ -16,14 +18,28 @@ func contains(expected string, values []string) bool {
16 16
 	return false
17 17
 }
18 18
 
19
-func TestContainerJsonFormat(t *testing.T) {
20
-	f, err := os.Open("container.json")
19
+func containsDevice(expected *devices.Device, values []*devices.Device) bool {
20
+	for _, d := range values {
21
+		if d.Path == expected.Path &&
22
+			d.CgroupPermissions == expected.CgroupPermissions &&
23
+			d.FileMode == expected.FileMode &&
24
+			d.MajorNumber == expected.MajorNumber &&
25
+			d.MinorNumber == expected.MinorNumber &&
26
+			d.Type == expected.Type {
27
+			return true
28
+		}
29
+	}
30
+	return false
31
+}
32
+
33
+func TestConfigJsonFormat(t *testing.T) {
34
+	f, err := os.Open("sample_configs/attach_to_bridge.json")
21 35
 	if err != nil {
22 36
 		t.Fatal("Unable to open container.json")
23 37
 	}
24 38
 	defer f.Close()
25 39
 
26
-	var container *Container
40
+	var container *Config
27 41
 	if err := json.NewDecoder(f).Decode(&container); err != nil {
28 42
 		t.Fatalf("failed to decode container config: %s", err)
29 43
 	}
... ...
@@ -61,4 +77,42 @@ func TestContainerJsonFormat(t *testing.T) {
61 61
 		t.Log("capabilities mask should contain SYS_CHROOT")
62 62
 		t.Fail()
63 63
 	}
64
+
65
+	for _, n := range container.Networks {
66
+		if n.Type == "veth" {
67
+			if n.Bridge != "docker0" {
68
+				t.Logf("veth bridge should be docker0 but received %q", n.Bridge)
69
+				t.Fail()
70
+			}
71
+
72
+			if n.Address != "172.17.0.101/16" {
73
+				t.Logf("veth address should be 172.17.0.101/61 but received %q", n.Address)
74
+				t.Fail()
75
+			}
76
+
77
+			if n.VethPrefix != "veth" {
78
+				t.Logf("veth prefix should be veth but received %q", n.VethPrefix)
79
+				t.Fail()
80
+			}
81
+
82
+			if n.Gateway != "172.17.42.1" {
83
+				t.Logf("veth gateway should be 172.17.42.1 but received %q", n.Gateway)
84
+				t.Fail()
85
+			}
86
+
87
+			if n.Mtu != 1500 {
88
+				t.Logf("veth mtu should be 1500 but received %d", n.Mtu)
89
+				t.Fail()
90
+			}
91
+
92
+			break
93
+		}
94
+	}
95
+
96
+	for _, d := range devices.DefaultSimpleDevices {
97
+		if !containsDevice(d, container.MountConfig.DeviceNodes) {
98
+			t.Logf("expected defice configuration for %s", d.Path)
99
+			t.Fail()
100
+		}
101
+	}
64 102
 }
... ...
@@ -8,7 +8,6 @@ import (
8 8
 	"path/filepath"
9 9
 	"syscall"
10 10
 
11
-	"github.com/docker/libcontainer"
12 11
 	"github.com/docker/libcontainer/label"
13 12
 	"github.com/docker/libcontainer/mount/nodes"
14 13
 	"github.com/dotcloud/docker/pkg/symlink"
... ...
@@ -28,12 +27,12 @@ type mount struct {
28 28
 
29 29
 // InitializeMountNamespace setups up the devices, mount points, and filesystems for use inside a
30 30
 // new mount namepsace
31
-func InitializeMountNamespace(rootfs, console string, container *libcontainer.Container) error {
31
+func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig) error {
32 32
 	var (
33 33
 		err  error
34 34
 		flag = syscall.MS_PRIVATE
35 35
 	)
36
-	if container.NoPivotRoot {
36
+	if mountConfig.NoPivotRoot {
37 37
 		flag = syscall.MS_SLAVE
38 38
 	}
39 39
 	if err := system.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil {
... ...
@@ -42,16 +41,16 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
42 42
 	if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil {
43 43
 		return fmt.Errorf("mouting %s as bind %s", rootfs, err)
44 44
 	}
45
-	if err := mountSystem(rootfs, container); err != nil {
45
+	if err := mountSystem(rootfs, mountConfig); err != nil {
46 46
 		return fmt.Errorf("mount system %s", err)
47 47
 	}
48
-	if err := setupBindmounts(rootfs, container.Mounts); err != nil {
48
+	if err := setupBindmounts(rootfs, mountConfig.Mounts); err != nil {
49 49
 		return fmt.Errorf("bind mounts %s", err)
50 50
 	}
51
-	if err := nodes.CreateDeviceNodes(rootfs, container.DeviceNodes); err != nil {
51
+	if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil {
52 52
 		return fmt.Errorf("create device nodes %s", err)
53 53
 	}
54
-	if err := SetupPtmx(rootfs, console, container.Context["mount_label"]); err != nil {
54
+	if err := SetupPtmx(rootfs, console, mountConfig.MountLabel); err != nil {
55 55
 		return err
56 56
 	}
57 57
 	if err := setupDevSymlinks(rootfs); err != nil {
... ...
@@ -61,7 +60,7 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
61 61
 		return fmt.Errorf("chdir into %s %s", rootfs, err)
62 62
 	}
63 63
 
64
-	if container.NoPivotRoot {
64
+	if mountConfig.NoPivotRoot {
65 65
 		err = MsMoveRoot(rootfs)
66 66
 	} else {
67 67
 		err = PivotRoot(rootfs)
... ...
@@ -70,7 +69,7 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
70 70
 		return err
71 71
 	}
72 72
 
73
-	if container.ReadonlyFs {
73
+	if mountConfig.ReadonlyFs {
74 74
 		if err := SetReadonly(); err != nil {
75 75
 			return fmt.Errorf("set readonly %s", err)
76 76
 		}
... ...
@@ -83,8 +82,8 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
83 83
 
84 84
 // mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts
85 85
 // inside the mount namespace
86
-func mountSystem(rootfs string, container *libcontainer.Container) error {
87
-	for _, m := range newSystemMounts(rootfs, container.Context["mount_label"], container.Mounts) {
86
+func mountSystem(rootfs string, mountConfig *MountConfig) error {
87
+	for _, m := range newSystemMounts(rootfs, mountConfig.MountLabel, mountConfig.Mounts) {
88 88
 		if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) {
89 89
 			return fmt.Errorf("mkdirall %s %s", m.path, err)
90 90
 		}
... ...
@@ -145,7 +144,7 @@ func setupDevSymlinks(rootfs string) error {
145 145
 	return nil
146 146
 }
147 147
 
148
-func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error {
148
+func setupBindmounts(rootfs string, bindMounts Mounts) error {
149 149
 	for _, m := range bindMounts.OfType("bind") {
150 150
 		var (
151 151
 			flags = syscall.MS_BIND | syscall.MS_REC
... ...
@@ -188,7 +187,7 @@ func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error {
188 188
 
189 189
 // TODO: this is crappy right now and should be cleaned up with a better way of handling system and
190 190
 // standard bind mounts allowing them to be more dynamic
191
-func newSystemMounts(rootfs, mountLabel string, mounts libcontainer.Mounts) []mount {
191
+func newSystemMounts(rootfs, mountLabel string, mounts Mounts) []mount {
192 192
 	systemMounts := []mount{
193 193
 		{source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags},
194 194
 		{source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: defaultMountFlags},
... ...
@@ -3,10 +3,11 @@
3 3
 package nodes
4 4
 
5 5
 import (
6
-	"github.com/docker/libcontainer"
6
+	"errors"
7
+
7 8
 	"github.com/docker/libcontainer/devices"
8 9
 )
9 10
 
10 11
 func CreateDeviceNodes(rootfs string, nodesToCreate []*devices.Device) error {
11
-	return libcontainer.ErrUnsupported
12
+	return errors.New("Unsupported method")
12 13
 }
13 14
new file mode 100644
... ...
@@ -0,0 +1,47 @@
0
+package mount
1
+
2
+import (
3
+	"errors"
4
+	"github.com/docker/libcontainer/devices"
5
+)
6
+
7
+type MountConfig struct {
8
+	// NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs
9
+	// This is a common option when the container is running in ramdisk
10
+	NoPivotRoot bool `json:"no_pivot_root,omitempty"`
11
+
12
+	// ReadonlyFs will remount the container's rootfs as readonly where only externally mounted
13
+	// bind mounts are writtable
14
+	ReadonlyFs bool `json:"readonly_fs,omitempty"`
15
+
16
+	// Mounts specify additional source and destination paths that will be mounted inside the container's
17
+	// rootfs and mount namespace if specified
18
+	Mounts Mounts `json:"mounts,omitempty"`
19
+
20
+	// The device nodes that should be automatically created within the container upon container start.  Note, make sure that the node is marked as allowed in the cgroup as well!
21
+	DeviceNodes []*devices.Device `json:"device_nodes,omitempty"`
22
+
23
+	MountLabel string `json:"mount_label,omitempty"`
24
+}
25
+
26
+type Mount struct {
27
+	Type        string `json:"type,omitempty"`
28
+	Source      string `json:"source,omitempty"`      // Source path, in the host namespace
29
+	Destination string `json:"destination,omitempty"` // Destination path, in the container
30
+	Writable    bool   `json:"writable,omitempty"`
31
+	Private     bool   `json:"private,omitempty"`
32
+}
33
+
34
+type Mounts []Mount
35
+
36
+var ErrUnsupported = errors.New("Unsupported method")
37
+
38
+func (s Mounts) OfType(t string) Mounts {
39
+	out := Mounts{}
40
+	for _, m := range s {
41
+		if m.Type == t {
42
+			out = append(out, m)
43
+		}
44
+	}
45
+	return out
46
+}
... ...
@@ -7,4 +7,4 @@ import (
7 7
 	"github.com/docker/libcontainer"
8 8
 )
9 9
 
10
-type CreateCommand func(container *libcontainer.Container, console, rootfs, dataPath, init string, childPipe *os.File, args []string) *exec.Cmd
10
+type CreateCommand func(container *libcontainer.Config, console, rootfs, dataPath, init string, childPipe *os.File, args []string) *exec.Cmd
... ...
@@ -15,9 +15,11 @@ import (
15 15
 	"github.com/dotcloud/docker/pkg/system"
16 16
 )
17 17
 
18
+// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work.
19
+// Move this to libcontainer package.
18 20
 // Exec performes setup outside of a namespace so that a container can be
19 21
 // executed.  Exec is a high level function for working with container namespaces.
20
-func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
22
+func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
21 23
 	var (
22 24
 		master  *os.File
23 25
 		console string
... ...
@@ -103,7 +105,7 @@ func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath str
103 103
 // root: the path to the container json file and information
104 104
 // pipe: sync pipe to syncronize the parent and child processes
105 105
 // args: the arguemnts to pass to the container to run as the user's program
106
-func DefaultCreateCommand(container *libcontainer.Container, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
106
+func DefaultCreateCommand(container *libcontainer.Config, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
107 107
 	// get our binary name from arg0 so we can always reexec ourself
108 108
 	env := []string{
109 109
 		"console=" + console,
... ...
@@ -135,7 +137,7 @@ func DefaultCreateCommand(container *libcontainer.Container, console, rootfs, da
135 135
 
136 136
 // SetupCgroups applies the cgroup restrictions to the process running in the contaienr based
137 137
 // on the container's configuration
138
-func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveCgroup, error) {
138
+func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) {
139 139
 	if container.Cgroups != nil {
140 140
 		c := container.Cgroups
141 141
 		if systemd.UseSystemd() {
... ...
@@ -148,14 +150,14 @@ func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveC
148 148
 
149 149
 // InitializeNetworking creates the container's network stack outside of the namespace and moves
150 150
 // interfaces into the container's net namespaces if necessary
151
-func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *SyncPipe) error {
152
-	context := libcontainer.Context{}
151
+func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *SyncPipe) error {
152
+	context := map[string]string{}
153 153
 	for _, config := range container.Networks {
154 154
 		strategy, err := network.GetStrategy(config.Type)
155 155
 		if err != nil {
156 156
 			return err
157 157
 		}
158
-		if err := strategy.Create(config, nspid, context); err != nil {
158
+		if err := strategy.Create((*network.Network)(config), nspid, context); err != nil {
159 159
 			return err
160 160
 		}
161 161
 	}
... ...
@@ -167,7 +169,7 @@ func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *Sy
167 167
 func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
168 168
 	for key, enabled := range namespaces {
169 169
 		if enabled {
170
-			if ns := libcontainer.GetNamespace(key); ns != nil {
170
+			if ns := GetNamespace(key); ns != nil {
171 171
 				flag |= ns.Value
172 172
 			}
173 173
 		}
... ...
@@ -13,7 +13,7 @@ import (
13 13
 )
14 14
 
15 15
 // ExecIn uses an existing pid and joins the pid's namespaces with the new command.
16
-func ExecIn(container *libcontainer.Container, nspid int, args []string) error {
16
+func ExecIn(container *libcontainer.Config, nspid int, args []string) error {
17 17
 	// TODO(vmarmol): If this gets too long, send it over a pipe to the child.
18 18
 	// Marshall the container into JSON since it won't be available in the namespace.
19 19
 	containerJson, err := json.Marshal(container)
... ...
@@ -31,7 +31,7 @@ func ExecIn(container *libcontainer.Container, nspid int, args []string) error {
31 31
 }
32 32
 
33 33
 // NsEnter is run after entering the namespace.
34
-func NsEnter(container *libcontainer.Container, nspid int, args []string) error {
34
+func NsEnter(container *libcontainer.Config, nspid int, args []string) error {
35 35
 	// clear the current processes env and replace it with the environment
36 36
 	// defined on the container
37 37
 	if err := LoadContainerEnvironment(container); err != nil {
... ...
@@ -23,9 +23,11 @@ import (
23 23
 	"github.com/dotcloud/docker/pkg/user"
24 24
 )
25 25
 
26
+// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work.
27
+// Move this to libcontainer package.
26 28
 // Init is the init process that first runs inside a new namespace to setup mounts, users, networking,
27 29
 // and other options required for the new container.
28
-func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
30
+func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
29 31
 	rootfs, err := utils.ResolveRootfs(uncleanRootfs)
30 32
 	if err != nil {
31 33
 		return err
... ...
@@ -67,7 +69,9 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string,
67 67
 
68 68
 	label.Init()
69 69
 
70
-	if err := mount.InitializeMountNamespace(rootfs, consolePath, container); err != nil {
70
+	if err := mount.InitializeMountNamespace(rootfs,
71
+		consolePath,
72
+		(*mount.MountConfig)(container.MountConfig)); err != nil {
71 73
 		return fmt.Errorf("setup mount namespace %s", err)
72 74
 	}
73 75
 	if container.Hostname != "" {
... ...
@@ -157,14 +161,14 @@ func SetupUser(u string) error {
157 157
 // setupVethNetwork uses the Network config if it is not nil to initialize
158 158
 // the new veth interface inside the container for use by changing the name to eth0
159 159
 // setting the MTU and IP address along with the default gateway
160
-func setupNetwork(container *libcontainer.Container, context libcontainer.Context) error {
160
+func setupNetwork(container *libcontainer.Config, context map[string]string) error {
161 161
 	for _, config := range container.Networks {
162 162
 		strategy, err := network.GetStrategy(config.Type)
163 163
 		if err != nil {
164 164
 			return err
165 165
 		}
166 166
 
167
-		err1 := strategy.Initialize(config, context)
167
+		err1 := strategy.Initialize((*network.Network)(config), context)
168 168
 		if err1 != nil {
169 169
 			return err1
170 170
 		}
... ...
@@ -172,7 +176,7 @@ func setupNetwork(container *libcontainer.Container, context libcontainer.Contex
172 172
 	return nil
173 173
 }
174 174
 
175
-func setupRoute(container *libcontainer.Container) error {
175
+func setupRoute(container *libcontainer.Config) error {
176 176
 	for _, config := range container.Routes {
177 177
 		if err := netlink.AddRoute(config.Destination, config.Source, config.Gateway, config.InterfaceName); err != nil {
178 178
 			return err
... ...
@@ -184,7 +188,7 @@ func setupRoute(container *libcontainer.Container) error {
184 184
 // FinalizeNamespace drops the caps, sets the correct user
185 185
 // and working dir, and closes any leaky file descriptors
186 186
 // before execing the command inside the namespace
187
-func FinalizeNamespace(container *libcontainer.Container) error {
187
+func FinalizeNamespace(container *libcontainer.Config) error {
188 188
 	// Ensure that all non-standard fds we may have accidentally
189 189
 	// inherited are marked close-on-exec so they stay out of the
190 190
 	// container
... ...
@@ -193,7 +197,7 @@ func FinalizeNamespace(container *libcontainer.Container) error {
193 193
 	}
194 194
 
195 195
 	// drop capabilities in bounding set before changing user
196
-	if err := capabilities.DropBoundingSet(container); err != nil {
196
+	if err := capabilities.DropBoundingSet(container.Capabilities); err != nil {
197 197
 		return fmt.Errorf("drop bounding set %s", err)
198 198
 	}
199 199
 
... ...
@@ -211,7 +215,7 @@ func FinalizeNamespace(container *libcontainer.Container) error {
211 211
 	}
212 212
 
213 213
 	// drop all other capabilities
214
-	if err := capabilities.DropCapabilities(container); err != nil {
214
+	if err := capabilities.DropCapabilities(container.Capabilities); err != nil {
215 215
 		return fmt.Errorf("drop capabilities %s", err)
216 216
 	}
217 217
 
... ...
@@ -224,7 +228,7 @@ func FinalizeNamespace(container *libcontainer.Container) error {
224 224
 	return nil
225 225
 }
226 226
 
227
-func LoadContainerEnvironment(container *libcontainer.Container) error {
227
+func LoadContainerEnvironment(container *libcontainer.Config) error {
228 228
 	os.Clearenv()
229 229
 	for _, pair := range container.Env {
230 230
 		p := strings.SplitN(pair, "=", 2)
... ...
@@ -5,8 +5,6 @@ import (
5 5
 	"fmt"
6 6
 	"io/ioutil"
7 7
 	"os"
8
-
9
-	"github.com/docker/libcontainer"
10 8
 )
11 9
 
12 10
 // SyncPipe allows communication to and from the child processes
... ...
@@ -45,7 +43,7 @@ func (s *SyncPipe) Parent() *os.File {
45 45
 	return s.parent
46 46
 }
47 47
 
48
-func (s *SyncPipe) SendToChild(context libcontainer.Context) error {
48
+func (s *SyncPipe) SendToChild(context map[string]string) error {
49 49
 	data, err := json.Marshal(context)
50 50
 	if err != nil {
51 51
 		return err
... ...
@@ -54,12 +52,12 @@ func (s *SyncPipe) SendToChild(context libcontainer.Context) error {
54 54
 	return nil
55 55
 }
56 56
 
57
-func (s *SyncPipe) ReadFromParent() (libcontainer.Context, error) {
57
+func (s *SyncPipe) ReadFromParent() (map[string]string, error) {
58 58
 	data, err := ioutil.ReadAll(s.child)
59 59
 	if err != nil {
60 60
 		return nil, fmt.Errorf("error reading from sync pipe %s", err)
61 61
 	}
62
-	var context libcontainer.Context
62
+	var context map[string]string
63 63
 	if len(data) > 0 {
64 64
 		if err := json.Unmarshal(data, &context); err != nil {
65 65
 			return nil, err
66 66
new file mode 100644
... ...
@@ -0,0 +1,50 @@
0
+package namespaces
1
+
2
+import "errors"
3
+
4
+type (
5
+	Namespace struct {
6
+		Key   string `json:"key,omitempty"`
7
+		Value int    `json:"value,omitempty"`
8
+		File  string `json:"file,omitempty"`
9
+	}
10
+	Namespaces []*Namespace
11
+)
12
+
13
+// namespaceList is used to convert the libcontainer types
14
+// into the names of the files located in /proc/<pid>/ns/* for
15
+// each namespace
16
+var (
17
+	namespaceList      = Namespaces{}
18
+	ErrUnkownNamespace = errors.New("Unknown namespace")
19
+	ErrUnsupported     = errors.New("Unsupported method")
20
+)
21
+
22
+func (ns *Namespace) String() string {
23
+	return ns.Key
24
+}
25
+
26
+func GetNamespace(key string) *Namespace {
27
+	for _, ns := range namespaceList {
28
+		if ns.Key == key {
29
+			cpy := *ns
30
+			return &cpy
31
+		}
32
+	}
33
+	return nil
34
+}
35
+
36
+// Contains returns true if the specified Namespace is
37
+// in the slice
38
+func (n Namespaces) Contains(ns string) bool {
39
+	return n.Get(ns) != nil
40
+}
41
+
42
+func (n Namespaces) Get(ns string) *Namespace {
43
+	for _, nsp := range n {
44
+		if nsp != nil && nsp.Key == ns {
45
+			return nsp
46
+		}
47
+	}
48
+	return nil
49
+}
0 50
new file mode 100644
... ...
@@ -0,0 +1,16 @@
0
+package namespaces
1
+
2
+import (
3
+	"syscall"
4
+)
5
+
6
+func init() {
7
+	namespaceList = Namespaces{
8
+		{Key: "NEWNS", Value: syscall.CLONE_NEWNS, File: "mnt"},
9
+		{Key: "NEWUTS", Value: syscall.CLONE_NEWUTS, File: "uts"},
10
+		{Key: "NEWIPC", Value: syscall.CLONE_NEWIPC, File: "ipc"},
11
+		{Key: "NEWUSER", Value: syscall.CLONE_NEWUSER, File: "user"},
12
+		{Key: "NEWPID", Value: syscall.CLONE_NEWPID, File: "pid"},
13
+		{Key: "NEWNET", Value: syscall.CLONE_NEWNET, File: "net"},
14
+	}
15
+}
0 16
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+package namespaces
1
+
2
+import (
3
+	"testing"
4
+)
5
+
6
+func TestNamespacesContains(t *testing.T) {
7
+	ns := Namespaces{
8
+		GetNamespace("NEWPID"),
9
+		GetNamespace("NEWNS"),
10
+		GetNamespace("NEWUTS"),
11
+	}
12
+
13
+	if ns.Contains("NEWNET") {
14
+		t.Fatal("namespaces should not contain NEWNET")
15
+	}
16
+
17
+	if !ns.Contains("NEWPID") {
18
+		t.Fatal("namespaces should contain NEWPID but does not")
19
+	}
20
+
21
+	withNil := Namespaces{
22
+		GetNamespace("UNDEFINED"), // this element will be nil
23
+		GetNamespace("NEWPID"),
24
+	}
25
+
26
+	if !withNil.Contains("NEWPID") {
27
+		t.Fatal("namespaces should contain NEWPID but does not")
28
+	}
29
+}
... ...
@@ -7,20 +7,20 @@ import (
7 7
 	"github.com/docker/libcontainer/cgroups"
8 8
 )
9 9
 
10
-func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
11
-	return -1, libcontainer.ErrUnsupported
10
+func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
11
+	return -1, ErrUnsupported
12 12
 }
13 13
 
14
-func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
15
-	return libcontainer.ErrUnsupported
14
+func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
15
+	return ErrUnsupported
16 16
 }
17 17
 
18
-func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *SyncPipe) error {
19
-	return libcontainer.ErrUnsupported
18
+func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *SyncPipe) error {
19
+	return ErrUnsupported
20 20
 }
21 21
 
22
-func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveCgroup, error) {
23
-	return nil, libcontainer.ErrUnsupported
22
+func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) {
23
+	return nil, ErrUnsupported
24 24
 }
25 25
 
26 26
 func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
... ...
@@ -1,19 +1,20 @@
1
+// +build linux
2
+
1 3
 package network
2 4
 
3 5
 import (
4 6
 	"fmt"
5
-	"github.com/docker/libcontainer"
6 7
 )
7 8
 
8 9
 // Loopback is a network strategy that provides a basic loopback device
9 10
 type Loopback struct {
10 11
 }
11 12
 
12
-func (l *Loopback) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error {
13
+func (l *Loopback) Create(n *Network, nspid int, context map[string]string) error {
13 14
 	return nil
14 15
 }
15 16
 
16
-func (l *Loopback) Initialize(config *libcontainer.Network, context libcontainer.Context) error {
17
+func (l *Loopback) Initialize(config *Network, context map[string]string) error {
17 18
 	if err := SetMtu("lo", config.Mtu); err != nil {
18 19
 		return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err)
19 20
 	}
... ...
@@ -1,3 +1,5 @@
1
+// +build linux
2
+
1 3
 package network
2 4
 
3 5
 import (
... ...
@@ -5,7 +7,6 @@ import (
5 5
 	"os"
6 6
 	"syscall"
7 7
 
8
-	"github.com/docker/libcontainer"
9 8
 	"github.com/dotcloud/docker/pkg/system"
10 9
 )
11 10
 
... ...
@@ -13,12 +14,12 @@ import (
13 13
 type NetNS struct {
14 14
 }
15 15
 
16
-func (v *NetNS) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error {
17
-	context["nspath"] = n.Context["nspath"]
16
+func (v *NetNS) Create(n *Network, nspid int, context map[string]string) error {
17
+	context["nspath"] = n.NsPath
18 18
 	return nil
19 19
 }
20 20
 
21
-func (v *NetNS) Initialize(config *libcontainer.Network, context libcontainer.Context) error {
21
+func (v *NetNS) Initialize(config *Network, context map[string]string) error {
22 22
 	nspath, exists := context["nspath"]
23 23
 	if !exists {
24 24
 		return fmt.Errorf("nspath does not exist in network context")
... ...
@@ -1,8 +1,11 @@
1
+// +build linux
2
+
1 3
 package network
2 4
 
3 5
 import (
4
-	"github.com/docker/libcontainer/netlink"
5 6
 	"net"
7
+
8
+	"github.com/docker/libcontainer/netlink"
6 9
 )
7 10
 
8 11
 func InterfaceUp(name string) error {
... ...
@@ -1,9 +1,9 @@
1
+// +build linux
2
+
1 3
 package network
2 4
 
3 5
 import (
4 6
 	"errors"
5
-
6
-	"github.com/docker/libcontainer"
7 7
 )
8 8
 
9 9
 var (
... ...
@@ -19,8 +19,8 @@ var strategies = map[string]NetworkStrategy{
19 19
 // NetworkStrategy represents a specific network configuration for
20 20
 // a container's networking stack
21 21
 type NetworkStrategy interface {
22
-	Create(*libcontainer.Network, int, libcontainer.Context) error
23
-	Initialize(*libcontainer.Network, libcontainer.Context) error
22
+	Create(*Network, int, map[string]string) error
23
+	Initialize(*Network, map[string]string) error
24 24
 }
25 25
 
26 26
 // GetStrategy returns the specific network strategy for the
27 27
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+package network
1
+
2
+// Network defines configuration for a container's networking stack
3
+//
4
+// The network configuration can be omited from a container causing the
5
+// container to be setup with the host's networking stack
6
+type Network struct {
7
+	// Type sets the networks type, commonly veth and loopback
8
+	Type string `json:"type,omitempty"`
9
+
10
+	// Path to network namespace
11
+	NsPath string `json:"ns_path,omitempty"`
12
+
13
+	// The bridge to use.
14
+	Bridge string `json:"bridge,omitempty"`
15
+
16
+	// Prefix for the veth interfaces.
17
+	VethPrefix string `json:"veth_prefix,omitempty"`
18
+
19
+	// Address contains the IP and mask to set on the network interface
20
+	Address string `json:"address,omitempty"`
21
+
22
+	// Gateway sets the gateway address that is used as the default for the interface
23
+	Gateway string `json:"gateway,omitempty"`
24
+
25
+	// Mtu sets the mtu value for the interface and will be mirrored on both the host and
26
+	// container's interfaces if a pair is created, specifically in the case of type veth
27
+	Mtu int `json:"mtu,omitempty"`
28
+}
... ...
@@ -1,8 +1,10 @@
1
+// +build linux
2
+
1 3
 package network
2 4
 
3 5
 import (
4 6
 	"fmt"
5
-	"github.com/docker/libcontainer"
7
+
6 8
 	"github.com/docker/libcontainer/utils"
7 9
 )
8 10
 
... ...
@@ -14,17 +16,16 @@ type Veth struct {
14 14
 
15 15
 const defaultDevice = "eth0"
16 16
 
17
-func (v *Veth) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error {
17
+func (v *Veth) Create(n *Network, nspid int, context map[string]string) error {
18 18
 	var (
19
-		bridge string
20
-		prefix string
21
-		exists bool
19
+		bridge = n.Bridge
20
+		prefix = n.VethPrefix
22 21
 	)
23
-	if bridge, exists = n.Context["bridge"]; !exists {
24
-		return fmt.Errorf("bridge does not exist in network context")
22
+	if bridge == "" {
23
+		return fmt.Errorf("bridge is not specified")
25 24
 	}
26
-	if prefix, exists = n.Context["prefix"]; !exists {
27
-		return fmt.Errorf("veth prefix does not exist in network context")
25
+	if prefix == "" {
26
+		return fmt.Errorf("veth prefix is not specified")
28 27
 	}
29 28
 	name1, name2, err := createVethPair(prefix)
30 29
 	if err != nil {
... ...
@@ -47,7 +48,7 @@ func (v *Veth) Create(n *libcontainer.Network, nspid int, context libcontainer.C
47 47
 	return nil
48 48
 }
49 49
 
50
-func (v *Veth) Initialize(config *libcontainer.Network, context libcontainer.Context) error {
50
+func (v *Veth) Initialize(config *Network, context map[string]string) error {
51 51
 	var (
52 52
 		vethChild string
53 53
 		exists    bool
... ...
@@ -48,7 +48,7 @@ func execAction(context *cli.Context) {
48 48
 // error.
49 49
 //
50 50
 // Signals sent to the current process will be forwarded to container.
51
-func startContainer(container *libcontainer.Container, term namespaces.Terminal, dataPath string, args []string) (int, error) {
51
+func startContainer(container *libcontainer.Config, term namespaces.Terminal, dataPath string, args []string) (int, error) {
52 52
 	var (
53 53
 		cmd  *exec.Cmd
54 54
 		sigc = make(chan os.Signal, 10)
... ...
@@ -56,7 +56,7 @@ func startContainer(container *libcontainer.Container, term namespaces.Terminal,
56 56
 
57 57
 	signal.Notify(sigc)
58 58
 
59
-	createCommand := func(container *libcontainer.Container, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
59
+	createCommand := func(container *libcontainer.Config, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
60 60
 		cmd = namespaces.DefaultCreateCommand(container, console, rootfs, dataPath, init, pipe, args)
61 61
 		if logPath != "" {
62 62
 			cmd.Env = append(cmd.Env, fmt.Sprintf("log=%s", logPath))
... ...
@@ -30,7 +30,7 @@ func specAction(context *cli.Context) {
30 30
 }
31 31
 
32 32
 // returns the container spec in json format.
33
-func getContainerSpec(container *libcontainer.Container) (string, error) {
33
+func getContainerSpec(container *libcontainer.Config) (string, error) {
34 34
 	spec, err := json.MarshalIndent(container, "", "\t")
35 35
 	if err != nil {
36 36
 		return "", err
... ...
@@ -31,7 +31,7 @@ func statsAction(context *cli.Context) {
31 31
 }
32 32
 
33 33
 // returns the container stats in json format.
34
-func getContainerStats(container *libcontainer.Container) (string, error) {
34
+func getContainerStats(container *libcontainer.Config) (string, error) {
35 35
 	stats, err := fs.GetStats(container.Cgroups)
36 36
 	if err != nil {
37 37
 		return "", err
... ...
@@ -11,14 +11,14 @@ import (
11 11
 	"github.com/docker/libcontainer"
12 12
 )
13 13
 
14
-func loadContainer() (*libcontainer.Container, error) {
14
+func loadContainer() (*libcontainer.Config, error) {
15 15
 	f, err := os.Open(filepath.Join(dataPath, "container.json"))
16 16
 	if err != nil {
17 17
 		return nil, err
18 18
 	}
19 19
 	defer f.Close()
20 20
 
21
-	var container *libcontainer.Container
21
+	var container *libcontainer.Config
22 22
 	if err := json.NewDecoder(f).Decode(&container); err != nil {
23 23
 		return nil, err
24 24
 	}
... ...
@@ -51,8 +51,8 @@ func openLog(name string) error {
51 51
 	return nil
52 52
 }
53 53
 
54
-func loadContainerFromJson(rawData string) (*libcontainer.Container, error) {
55
-	var container *libcontainer.Container
54
+func loadContainerFromJson(rawData string) (*libcontainer.Config, error) {
55
+	var container *libcontainer.Config
56 56
 
57 57
 	if err := json.Unmarshal([]byte(rawData), &container); err != nil {
58 58
 		return nil, err
59 59
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+These configuration files can be used with `nsinit` to quickly develop, test,
1
+and experiment with features of libcontainer.
2
+
3
+When consuming these configuration files, copy them into your rootfs and rename
4
+the file to `container.json` for use with `nsinit`.
0 5
new file mode 100644
... ...
@@ -0,0 +1,206 @@
0
+{
1
+    "capabilities": [
2
+        "CHOWN",
3
+        "DAC_OVERRIDE",
4
+        "FOWNER",
5
+        "MKNOD",
6
+        "NET_RAW",
7
+        "SETGID",
8
+        "SETUID",
9
+        "SETFCAP",
10
+        "SETPCAP",
11
+        "NET_BIND_SERVICE",
12
+        "SYS_CHROOT",
13
+        "KILL"
14
+    ],
15
+    "cgroups": {
16
+        "allowed_devices": [
17
+            {
18
+                "cgroup_permissions": "m",
19
+                "major_number": -1,
20
+                "minor_number": -1,
21
+                "type": 99
22
+            },
23
+            {
24
+                "cgroup_permissions": "m",
25
+                "major_number": -1,
26
+                "minor_number": -1,
27
+                "type": 98
28
+            },
29
+            {
30
+                "cgroup_permissions": "rwm",
31
+                "major_number": 5,
32
+                "minor_number": 1,
33
+                "path": "/dev/console",
34
+                "type": 99
35
+            },
36
+            {
37
+                "cgroup_permissions": "rwm",
38
+                "major_number": 4,
39
+                "path": "/dev/tty0",
40
+                "type": 99
41
+            },
42
+            {
43
+                "cgroup_permissions": "rwm",
44
+                "major_number": 4,
45
+                "minor_number": 1,
46
+                "path": "/dev/tty1",
47
+                "type": 99
48
+            },
49
+            {
50
+                "cgroup_permissions": "rwm",
51
+                "major_number": 136,
52
+                "minor_number": -1,
53
+                "type": 99
54
+            },
55
+            {
56
+                "cgroup_permissions": "rwm",
57
+                "major_number": 5,
58
+                "minor_number": 2,
59
+                "type": 99
60
+            },
61
+            {
62
+                "cgroup_permissions": "rwm",
63
+                "major_number": 10,
64
+                "minor_number": 200,
65
+                "type": 99
66
+            },
67
+            {
68
+                "cgroup_permissions": "rwm",
69
+                "file_mode": 438,
70
+                "major_number": 1,
71
+                "minor_number": 3,
72
+                "path": "/dev/null",
73
+                "type": 99
74
+            },
75
+            {
76
+                "cgroup_permissions": "rwm",
77
+                "file_mode": 438,
78
+                "major_number": 1,
79
+                "minor_number": 5,
80
+                "path": "/dev/zero",
81
+                "type": 99
82
+            },
83
+            {
84
+                "cgroup_permissions": "rwm",
85
+                "file_mode": 438,
86
+                "major_number": 1,
87
+                "minor_number": 7,
88
+                "path": "/dev/full",
89
+                "type": 99
90
+            },
91
+            {
92
+                "cgroup_permissions": "rwm",
93
+                "file_mode": 438,
94
+                "major_number": 5,
95
+                "path": "/dev/tty",
96
+                "type": 99
97
+            },
98
+            {
99
+                "cgroup_permissions": "rwm",
100
+                "file_mode": 438,
101
+                "major_number": 1,
102
+                "minor_number": 9,
103
+                "path": "/dev/urandom",
104
+                "type": 99
105
+            },
106
+            {
107
+                "cgroup_permissions": "rwm",
108
+                "file_mode": 438,
109
+                "major_number": 1,
110
+                "minor_number": 8,
111
+                "path": "/dev/random",
112
+                "type": 99
113
+            }
114
+        ],
115
+        "name": "docker-koye",
116
+        "parent": "docker"
117
+    },
118
+    "context": {
119
+        "mount_label": "",
120
+        "process_label": "",
121
+        "restrictions": "true"
122
+    },
123
+    "mount_config": {
124
+        "device_nodes": [
125
+            {
126
+                "cgroup_permissions": "rwm",
127
+                "file_mode": 438,
128
+                "major_number": 1,
129
+                "minor_number": 3,
130
+                "path": "/dev/null",
131
+                "type": 99
132
+            },
133
+            {
134
+                "cgroup_permissions": "rwm",
135
+                "file_mode": 438,
136
+                "major_number": 1,
137
+                "minor_number": 5,
138
+                "path": "/dev/zero",
139
+                "type": 99
140
+            },
141
+            {
142
+                "cgroup_permissions": "rwm",
143
+                "file_mode": 438,
144
+                "major_number": 1,
145
+                "minor_number": 7,
146
+                "path": "/dev/full",
147
+                "type": 99
148
+            },
149
+            {
150
+                "cgroup_permissions": "rwm",
151
+                "file_mode": 438,
152
+                "major_number": 5,
153
+                "path": "/dev/tty",
154
+                "type": 99
155
+            },
156
+            {
157
+                "cgroup_permissions": "rwm",
158
+                "file_mode": 438,
159
+                "major_number": 1,
160
+                "minor_number": 9,
161
+                "path": "/dev/urandom",
162
+                "type": 99
163
+            },
164
+            {
165
+                "cgroup_permissions": "rwm",
166
+                "file_mode": 438,
167
+                "major_number": 1,
168
+                "minor_number": 8,
169
+                "path": "/dev/random",
170
+                "type": 99
171
+            }
172
+        ]
173
+    },
174
+    "environment": [
175
+        "HOME=/",
176
+        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
177
+        "HOSTNAME=koye",
178
+        "TERM=xterm"
179
+    ],
180
+    "hostname": "koye",
181
+    "namespaces": {
182
+        "NEWIPC": true,
183
+        "NEWNET": true,
184
+        "NEWNS": true,
185
+        "NEWPID": true,
186
+        "NEWUTS": true
187
+    },
188
+    "networks": [
189
+        {
190
+            "address": "127.0.0.1/0",
191
+            "gateway": "localhost",
192
+            "mtu": 1500,
193
+            "type": "loopback"
194
+        },
195
+        {
196
+            "address": "172.17.0.101/16",
197
+            "bridge": "docker0",
198
+            "veth_prefix": "veth",
199
+            "gateway": "172.17.42.1",
200
+            "mtu": 1500,
201
+            "type": "veth"
202
+        }
203
+    ],
204
+    "tty": true
205
+}
0 206
new file mode 100644
... ...
@@ -0,0 +1,199 @@
0
+{
1
+    "capabilities": [
2
+        "CHOWN",
3
+        "DAC_OVERRIDE",
4
+        "FOWNER",
5
+        "MKNOD",
6
+        "NET_RAW",
7
+        "SETGID",
8
+        "SETUID",
9
+        "SETFCAP",
10
+        "SETPCAP",
11
+        "NET_BIND_SERVICE",
12
+        "SYS_CHROOT",
13
+        "KILL"
14
+    ],
15
+    "cgroups": {
16
+        "allowed_devices": [
17
+            {
18
+                "cgroup_permissions": "m",
19
+                "major_number": -1,
20
+                "minor_number": -1,
21
+                "type": 99
22
+            },
23
+            {
24
+                "cgroup_permissions": "m",
25
+                "major_number": -1,
26
+                "minor_number": -1,
27
+                "type": 98
28
+            },
29
+            {
30
+                "cgroup_permissions": "rwm",
31
+                "major_number": 5,
32
+                "minor_number": 1,
33
+                "path": "/dev/console",
34
+                "type": 99
35
+            },
36
+            {
37
+                "cgroup_permissions": "rwm",
38
+                "major_number": 4,
39
+                "path": "/dev/tty0",
40
+                "type": 99
41
+            },
42
+            {
43
+                "cgroup_permissions": "rwm",
44
+                "major_number": 4,
45
+                "minor_number": 1,
46
+                "path": "/dev/tty1",
47
+                "type": 99
48
+            },
49
+            {
50
+                "cgroup_permissions": "rwm",
51
+                "major_number": 136,
52
+                "minor_number": -1,
53
+                "type": 99
54
+            },
55
+            {
56
+                "cgroup_permissions": "rwm",
57
+                "major_number": 5,
58
+                "minor_number": 2,
59
+                "type": 99
60
+            },
61
+            {
62
+                "cgroup_permissions": "rwm",
63
+                "major_number": 10,
64
+                "minor_number": 200,
65
+                "type": 99
66
+            },
67
+            {
68
+                "cgroup_permissions": "rwm",
69
+                "file_mode": 438,
70
+                "major_number": 1,
71
+                "minor_number": 3,
72
+                "path": "/dev/null",
73
+                "type": 99
74
+            },
75
+            {
76
+                "cgroup_permissions": "rwm",
77
+                "file_mode": 438,
78
+                "major_number": 1,
79
+                "minor_number": 5,
80
+                "path": "/dev/zero",
81
+                "type": 99
82
+            },
83
+            {
84
+                "cgroup_permissions": "rwm",
85
+                "file_mode": 438,
86
+                "major_number": 1,
87
+                "minor_number": 7,
88
+                "path": "/dev/full",
89
+                "type": 99
90
+            },
91
+            {
92
+                "cgroup_permissions": "rwm",
93
+                "file_mode": 438,
94
+                "major_number": 5,
95
+                "path": "/dev/tty",
96
+                "type": 99
97
+            },
98
+            {
99
+                "cgroup_permissions": "rwm",
100
+                "file_mode": 438,
101
+                "major_number": 1,
102
+                "minor_number": 9,
103
+                "path": "/dev/urandom",
104
+                "type": 99
105
+            },
106
+            {
107
+                "cgroup_permissions": "rwm",
108
+                "file_mode": 438,
109
+                "major_number": 1,
110
+                "minor_number": 8,
111
+                "path": "/dev/random",
112
+                "type": 99
113
+            }
114
+        ],
115
+        "name": "docker-koye",
116
+        "parent": "docker"
117
+    },
118
+    "context": {
119
+        "mount_label": "",
120
+        "process_label": "",
121
+        "restrictions": "true"
122
+    },
123
+    "mount_config": {
124
+        "device_nodes": [
125
+            {
126
+                "cgroup_permissions": "rwm",
127
+                "file_mode": 438,
128
+                "major_number": 1,
129
+                "minor_number": 3,
130
+                "path": "/dev/null",
131
+                "type": 99
132
+            },
133
+            {
134
+                "cgroup_permissions": "rwm",
135
+                "file_mode": 438,
136
+                "major_number": 1,
137
+                "minor_number": 5,
138
+                "path": "/dev/zero",
139
+                "type": 99
140
+            },
141
+            {
142
+                "cgroup_permissions": "rwm",
143
+                "file_mode": 438,
144
+                "major_number": 1,
145
+                "minor_number": 7,
146
+                "path": "/dev/full",
147
+                "type": 99
148
+            },
149
+            {
150
+                "cgroup_permissions": "rwm",
151
+                "file_mode": 438,
152
+                "major_number": 5,
153
+                "path": "/dev/tty",
154
+                "type": 99
155
+            },
156
+            {
157
+                "cgroup_permissions": "rwm",
158
+                "file_mode": 438,
159
+                "major_number": 1,
160
+                "minor_number": 9,
161
+                "path": "/dev/urandom",
162
+                "type": 99
163
+            },
164
+            {
165
+                "cgroup_permissions": "rwm",
166
+                "file_mode": 438,
167
+                "major_number": 1,
168
+                "minor_number": 8,
169
+                "path": "/dev/random",
170
+                "type": 99
171
+            }
172
+        ]
173
+    },
174
+    "environment": [
175
+        "HOME=/",
176
+        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
177
+        "HOSTNAME=koye",
178
+        "TERM=xterm"
179
+    ],
180
+    "hostname": "koye",
181
+    "namespaces": {
182
+        "NEWIPC": true,
183
+        "NEWNET": true,
184
+        "NEWNS": true,
185
+        "NEWPID": true,
186
+        "NEWUTS": true
187
+    },
188
+    "networks": [
189
+        {
190
+            "address": "127.0.0.1/0",
191
+            "gateway": "localhost",
192
+            "mtu": 1500,
193
+            "type": "loopback"
194
+        }
195
+    ],
196
+    "tty": true,
197
+    "user": "daemon"
198
+}
... ...
@@ -3,7 +3,6 @@ package capabilities
3 3
 import (
4 4
 	"os"
5 5
 
6
-	"github.com/docker/libcontainer"
7 6
 	"github.com/syndtr/gocapability/capability"
8 7
 )
9 8
 
... ...
@@ -11,13 +10,13 @@ const allCapabilityTypes = capability.CAPS | capability.BOUNDS
11 11
 
12 12
 // DropBoundingSet drops the capability bounding set to those specified in the
13 13
 // container configuration.
14
-func DropBoundingSet(container *libcontainer.Container) error {
14
+func DropBoundingSet(capabilities []string) error {
15 15
 	c, err := capability.NewPid(os.Getpid())
16 16
 	if err != nil {
17 17
 		return err
18 18
 	}
19 19
 
20
-	keep := getEnabledCapabilities(container)
20
+	keep := getEnabledCapabilities(capabilities)
21 21
 	c.Clear(capability.BOUNDS)
22 22
 	c.Set(capability.BOUNDS, keep...)
23 23
 
... ...
@@ -29,13 +28,13 @@ func DropBoundingSet(container *libcontainer.Container) error {
29 29
 }
30 30
 
31 31
 // DropCapabilities drops all capabilities for the current process expect those specified in the container configuration.
32
-func DropCapabilities(container *libcontainer.Container) error {
32
+func DropCapabilities(capList []string) error {
33 33
 	c, err := capability.NewPid(os.Getpid())
34 34
 	if err != nil {
35 35
 		return err
36 36
 	}
37 37
 
38
-	keep := getEnabledCapabilities(container)
38
+	keep := getEnabledCapabilities(capList)
39 39
 	c.Clear(allCapabilityTypes)
40 40
 	c.Set(allCapabilityTypes, keep...)
41 41
 
... ...
@@ -46,10 +45,10 @@ func DropCapabilities(container *libcontainer.Container) error {
46 46
 }
47 47
 
48 48
 // getEnabledCapabilities returns the capabilities that should not be dropped by the container.
49
-func getEnabledCapabilities(container *libcontainer.Container) []capability.Cap {
49
+func getEnabledCapabilities(capList []string) []capability.Cap {
50 50
 	keep := []capability.Cap{}
51
-	for _, capability := range container.Capabilities {
52
-		if c := libcontainer.GetCapability(capability); c != nil {
51
+	for _, capability := range capList {
52
+		if c := GetCapability(capability); c != nil {
53 53
 			keep = append(keep, c.Value)
54 54
 		}
55 55
 	}
56 56
new file mode 100644
... ...
@@ -0,0 +1,90 @@
0
+package capabilities
1
+
2
+import "github.com/syndtr/gocapability/capability"
3
+
4
+type (
5
+	CapabilityMapping struct {
6
+		Key   string         `json:"key,omitempty"`
7
+		Value capability.Cap `json:"value,omitempty"`
8
+	}
9
+	Capabilities []*CapabilityMapping
10
+)
11
+
12
+func (c *CapabilityMapping) String() string {
13
+	return c.Key
14
+}
15
+
16
+func GetCapability(key string) *CapabilityMapping {
17
+	for _, capp := range capabilityList {
18
+		if capp.Key == key {
19
+			cpy := *capp
20
+			return &cpy
21
+		}
22
+	}
23
+	return nil
24
+}
25
+
26
+func GetAllCapabilities() []string {
27
+	output := make([]string, len(capabilityList))
28
+	for i, capability := range capabilityList {
29
+		output[i] = capability.String()
30
+	}
31
+	return output
32
+}
33
+
34
+// Contains returns true if the specified Capability is
35
+// in the slice
36
+func (c Capabilities) contains(capp string) bool {
37
+	return c.get(capp) != nil
38
+}
39
+
40
+func (c Capabilities) get(capp string) *CapabilityMapping {
41
+	for _, cap := range c {
42
+		if cap.Key == capp {
43
+			return cap
44
+		}
45
+	}
46
+	return nil
47
+}
48
+
49
+var capabilityList = Capabilities{
50
+	{Key: "SETPCAP", Value: capability.CAP_SETPCAP},
51
+	{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE},
52
+	{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO},
53
+	{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT},
54
+	{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN},
55
+	{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE},
56
+	{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE},
57
+	{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME},
58
+	{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG},
59
+	{Key: "MKNOD", Value: capability.CAP_MKNOD},
60
+	{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE},
61
+	{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL},
62
+	{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE},
63
+	{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN},
64
+	{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN},
65
+	{Key: "SYSLOG", Value: capability.CAP_SYSLOG},
66
+	{Key: "SETUID", Value: capability.CAP_SETUID},
67
+	{Key: "SETGID", Value: capability.CAP_SETGID},
68
+	{Key: "CHOWN", Value: capability.CAP_CHOWN},
69
+	{Key: "NET_RAW", Value: capability.CAP_NET_RAW},
70
+	{Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE},
71
+	{Key: "FOWNER", Value: capability.CAP_FOWNER},
72
+	{Key: "DAC_READ_SEARCH", Value: capability.CAP_DAC_READ_SEARCH},
73
+	{Key: "FSETID", Value: capability.CAP_FSETID},
74
+	{Key: "KILL", Value: capability.CAP_KILL},
75
+	{Key: "SETGID", Value: capability.CAP_SETGID},
76
+	{Key: "SETUID", Value: capability.CAP_SETUID},
77
+	{Key: "LINUX_IMMUTABLE", Value: capability.CAP_LINUX_IMMUTABLE},
78
+	{Key: "NET_BIND_SERVICE", Value: capability.CAP_NET_BIND_SERVICE},
79
+	{Key: "NET_BROADCAST", Value: capability.CAP_NET_BROADCAST},
80
+	{Key: "IPC_LOCK", Value: capability.CAP_IPC_LOCK},
81
+	{Key: "IPC_OWNER", Value: capability.CAP_IPC_OWNER},
82
+	{Key: "SYS_CHROOT", Value: capability.CAP_SYS_CHROOT},
83
+	{Key: "SYS_PTRACE", Value: capability.CAP_SYS_PTRACE},
84
+	{Key: "SYS_BOOT", Value: capability.CAP_SYS_BOOT},
85
+	{Key: "LEASE", Value: capability.CAP_LEASE},
86
+	{Key: "SETFCAP", Value: capability.CAP_SETFCAP},
87
+	{Key: "WAKE_ALARM", Value: capability.CAP_WAKE_ALARM},
88
+	{Key: "BLOCK_SUSPEND", Value: capability.CAP_BLOCK_SUSPEND},
89
+}
0 90
new file mode 100644
... ...
@@ -0,0 +1,19 @@
0
+package capabilities
1
+
2
+import (
3
+	"testing"
4
+)
5
+
6
+func TestCapabilitiesContains(t *testing.T) {
7
+	caps := Capabilities{
8
+		GetCapability("MKNOD"),
9
+		GetCapability("SETPCAP"),
10
+	}
11
+
12
+	if caps.contains("SYS_ADMIN") {
13
+		t.Fatal("capabilities should not contain SYS_ADMIN")
14
+	}
15
+	if !caps.contains("MKNOD") {
16
+		t.Fatal("capabilities should contain MKNOD but does not")
17
+	}
18
+}
0 19
deleted file mode 100644
... ...
@@ -1,165 +0,0 @@
1
-package libcontainer
2
-
3
-import (
4
-	"errors"
5
-
6
-	"github.com/syndtr/gocapability/capability"
7
-)
8
-
9
-var (
10
-	ErrUnkownNamespace  = errors.New("Unknown namespace")
11
-	ErrUnkownCapability = errors.New("Unknown capability")
12
-	ErrUnsupported      = errors.New("Unsupported method")
13
-)
14
-
15
-type Mounts []Mount
16
-
17
-func (s Mounts) OfType(t string) Mounts {
18
-	out := Mounts{}
19
-	for _, m := range s {
20
-		if m.Type == t {
21
-			out = append(out, m)
22
-		}
23
-	}
24
-	return out
25
-}
26
-
27
-type Mount struct {
28
-	Type        string `json:"type,omitempty"`
29
-	Source      string `json:"source,omitempty"`      // Source path, in the host namespace
30
-	Destination string `json:"destination,omitempty"` // Destination path, in the container
31
-	Writable    bool   `json:"writable,omitempty"`
32
-	Private     bool   `json:"private,omitempty"`
33
-}
34
-
35
-// namespaceList is used to convert the libcontainer types
36
-// into the names of the files located in /proc/<pid>/ns/* for
37
-// each namespace
38
-var (
39
-	namespaceList = Namespaces{}
40
-
41
-	capabilityList = Capabilities{
42
-		{Key: "SETPCAP", Value: capability.CAP_SETPCAP},
43
-		{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE},
44
-		{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO},
45
-		{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT},
46
-		{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN},
47
-		{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE},
48
-		{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE},
49
-		{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME},
50
-		{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG},
51
-		{Key: "MKNOD", Value: capability.CAP_MKNOD},
52
-		{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE},
53
-		{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL},
54
-		{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE},
55
-		{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN},
56
-		{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN},
57
-		{Key: "SYSLOG", Value: capability.CAP_SYSLOG},
58
-		{Key: "SETUID", Value: capability.CAP_SETUID},
59
-		{Key: "SETGID", Value: capability.CAP_SETGID},
60
-		{Key: "CHOWN", Value: capability.CAP_CHOWN},
61
-		{Key: "NET_RAW", Value: capability.CAP_NET_RAW},
62
-		{Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE},
63
-		{Key: "FOWNER", Value: capability.CAP_FOWNER},
64
-		{Key: "DAC_READ_SEARCH", Value: capability.CAP_DAC_READ_SEARCH},
65
-		{Key: "FSETID", Value: capability.CAP_FSETID},
66
-		{Key: "KILL", Value: capability.CAP_KILL},
67
-		{Key: "SETGID", Value: capability.CAP_SETGID},
68
-		{Key: "SETUID", Value: capability.CAP_SETUID},
69
-		{Key: "LINUX_IMMUTABLE", Value: capability.CAP_LINUX_IMMUTABLE},
70
-		{Key: "NET_BIND_SERVICE", Value: capability.CAP_NET_BIND_SERVICE},
71
-		{Key: "NET_BROADCAST", Value: capability.CAP_NET_BROADCAST},
72
-		{Key: "IPC_LOCK", Value: capability.CAP_IPC_LOCK},
73
-		{Key: "IPC_OWNER", Value: capability.CAP_IPC_OWNER},
74
-		{Key: "SYS_CHROOT", Value: capability.CAP_SYS_CHROOT},
75
-		{Key: "SYS_PTRACE", Value: capability.CAP_SYS_PTRACE},
76
-		{Key: "SYS_BOOT", Value: capability.CAP_SYS_BOOT},
77
-		{Key: "LEASE", Value: capability.CAP_LEASE},
78
-		{Key: "SETFCAP", Value: capability.CAP_SETFCAP},
79
-		{Key: "WAKE_ALARM", Value: capability.CAP_WAKE_ALARM},
80
-		{Key: "BLOCK_SUSPEND", Value: capability.CAP_BLOCK_SUSPEND},
81
-	}
82
-)
83
-
84
-type (
85
-	Namespace struct {
86
-		Key   string `json:"key,omitempty"`
87
-		Value int    `json:"value,omitempty"`
88
-		File  string `json:"file,omitempty"`
89
-	}
90
-	Namespaces []*Namespace
91
-)
92
-
93
-func (ns *Namespace) String() string {
94
-	return ns.Key
95
-}
96
-
97
-func GetNamespace(key string) *Namespace {
98
-	for _, ns := range namespaceList {
99
-		if ns.Key == key {
100
-			cpy := *ns
101
-			return &cpy
102
-		}
103
-	}
104
-	return nil
105
-}
106
-
107
-// Contains returns true if the specified Namespace is
108
-// in the slice
109
-func (n Namespaces) Contains(ns string) bool {
110
-	return n.Get(ns) != nil
111
-}
112
-
113
-func (n Namespaces) Get(ns string) *Namespace {
114
-	for _, nsp := range n {
115
-		if nsp != nil && nsp.Key == ns {
116
-			return nsp
117
-		}
118
-	}
119
-	return nil
120
-}
121
-
122
-type (
123
-	Capability struct {
124
-		Key   string         `json:"key,omitempty"`
125
-		Value capability.Cap `json:"value,omitempty"`
126
-	}
127
-	Capabilities []*Capability
128
-)
129
-
130
-func (c *Capability) String() string {
131
-	return c.Key
132
-}
133
-
134
-func GetCapability(key string) *Capability {
135
-	for _, capp := range capabilityList {
136
-		if capp.Key == key {
137
-			cpy := *capp
138
-			return &cpy
139
-		}
140
-	}
141
-	return nil
142
-}
143
-
144
-func GetAllCapabilities() []string {
145
-	output := make([]string, len(capabilityList))
146
-	for i, capability := range capabilityList {
147
-		output[i] = capability.String()
148
-	}
149
-	return output
150
-}
151
-
152
-// Contains returns true if the specified Capability is
153
-// in the slice
154
-func (c Capabilities) Contains(capp string) bool {
155
-	return c.Get(capp) != nil
156
-}
157
-
158
-func (c Capabilities) Get(capp string) *Capability {
159
-	for _, cap := range c {
160
-		if cap.Key == capp {
161
-			return cap
162
-		}
163
-	}
164
-	return nil
165
-}
166 1
deleted file mode 100644
... ...
@@ -1,16 +0,0 @@
1
-package libcontainer
2
-
3
-import (
4
-	"syscall"
5
-)
6
-
7
-func init() {
8
-	namespaceList = Namespaces{
9
-		{Key: "NEWNS", Value: syscall.CLONE_NEWNS, File: "mnt"},
10
-		{Key: "NEWUTS", Value: syscall.CLONE_NEWUTS, File: "uts"},
11
-		{Key: "NEWIPC", Value: syscall.CLONE_NEWIPC, File: "ipc"},
12
-		{Key: "NEWUSER", Value: syscall.CLONE_NEWUSER, File: "user"},
13
-		{Key: "NEWPID", Value: syscall.CLONE_NEWPID, File: "pid"},
14
-		{Key: "NEWNET", Value: syscall.CLONE_NEWNET, File: "net"},
15
-	}
16
-}
17 1
deleted file mode 100644
... ...
@@ -1,44 +0,0 @@
1
-package libcontainer
2
-
3
-import (
4
-	"testing"
5
-)
6
-
7
-func TestNamespacesContains(t *testing.T) {
8
-	ns := Namespaces{
9
-		GetNamespace("NEWPID"),
10
-		GetNamespace("NEWNS"),
11
-		GetNamespace("NEWUTS"),
12
-	}
13
-
14
-	if ns.Contains("NEWNET") {
15
-		t.Fatal("namespaces should not contain NEWNET")
16
-	}
17
-
18
-	if !ns.Contains("NEWPID") {
19
-		t.Fatal("namespaces should contain NEWPID but does not")
20
-	}
21
-
22
-	withNil := Namespaces{
23
-		GetNamespace("UNDEFINED"), // this element will be nil
24
-		GetNamespace("NEWPID"),
25
-	}
26
-
27
-	if !withNil.Contains("NEWPID") {
28
-		t.Fatal("namespaces should contain NEWPID but does not")
29
-	}
30
-}
31
-
32
-func TestCapabilitiesContains(t *testing.T) {
33
-	caps := Capabilities{
34
-		GetCapability("MKNOD"),
35
-		GetCapability("SETPCAP"),
36
-	}
37
-
38
-	if caps.Contains("SYS_ADMIN") {
39
-		t.Fatal("capabilities should not contain SYS_ADMIN")
40
-	}
41
-	if !caps.Contains("MKNOD") {
42
-		t.Fatal("capabilities should contain MKNOD but does not")
43
-	}
44
-}