github.com/psychoss/docker@v1.9.0/daemon/execdriver/lxc/lxc_template_unit_test.go (about) 1 // +build linux 2 3 package lxc 4 5 import ( 6 "bufio" 7 "fmt" 8 "io/ioutil" 9 "math/rand" 10 "os" 11 "path" 12 "strings" 13 "testing" 14 "time" 15 16 "github.com/docker/docker/daemon/execdriver" 17 nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" 18 "github.com/opencontainers/runc/libcontainer/configs" 19 "github.com/syndtr/gocapability/capability" 20 ) 21 22 func TestLXCConfig(t *testing.T) { 23 root, err := ioutil.TempDir("", "TestLXCConfig") 24 if err != nil { 25 t.Fatal(err) 26 } 27 defer os.RemoveAll(root) 28 29 os.MkdirAll(path.Join(root, "containers", "1"), 0777) 30 31 // Memory is allocated randomly for testing 32 r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) 33 var ( 34 memMin = 33554432 35 memMax = 536870912 36 mem = memMin + r.Intn(memMax-memMin) 37 swap = memMax 38 cpuMin = 100 39 cpuMax = 10000 40 cpu = cpuMin + r.Intn(cpuMax-cpuMin) 41 ) 42 43 driver, err := NewDriver(root, root, "", false) 44 if err != nil { 45 t.Fatal(err) 46 } 47 command := &execdriver.Command{ 48 ID: "1", 49 Resources: &execdriver.Resources{ 50 Memory: int64(mem), 51 MemorySwap: int64(swap), 52 CPUShares: int64(cpu), 53 }, 54 Network: &execdriver.Network{ 55 Mtu: 1500, 56 }, 57 AllowedDevices: make([]*configs.Device, 0), 58 ProcessConfig: execdriver.ProcessConfig{}, 59 } 60 p, err := driver.generateLXCConfig(command) 61 if err != nil { 62 t.Fatal(err) 63 } 64 grepFile(t, p, 65 fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem)) 66 67 grepFile(t, p, 68 fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", swap)) 69 } 70 71 func TestCustomLxcConfig(t *testing.T) { 72 root, err := ioutil.TempDir("", "TestCustomLxcConfig") 73 if err != nil { 74 t.Fatal(err) 75 } 76 defer os.RemoveAll(root) 77 78 os.MkdirAll(path.Join(root, "containers", "1"), 0777) 79 80 driver, err := NewDriver(root, root, "", false) 81 if err != nil { 82 t.Fatal(err) 83 } 84 processConfig := execdriver.ProcessConfig{ 85 Privileged: false, 86 } 87 command := &execdriver.Command{ 88 ID: "1", 89 LxcConfig: []string{ 90 "lxc.utsname = docker", 91 "lxc.cgroup.cpuset.cpus = 0,1", 92 }, 93 Network: &execdriver.Network{ 94 Mtu: 1500, 95 }, 96 ProcessConfig: processConfig, 97 } 98 99 p, err := driver.generateLXCConfig(command) 100 if err != nil { 101 t.Fatal(err) 102 } 103 104 grepFile(t, p, "lxc.utsname = docker") 105 grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") 106 } 107 108 func grepFile(t *testing.T, path string, pattern string) { 109 grepFileWithReverse(t, path, pattern, false) 110 } 111 112 func grepFileWithReverse(t *testing.T, path string, pattern string, inverseGrep bool) { 113 f, err := os.Open(path) 114 if err != nil { 115 t.Fatal(err) 116 } 117 defer f.Close() 118 r := bufio.NewReader(f) 119 var ( 120 line string 121 ) 122 err = nil 123 for err == nil { 124 line, err = r.ReadString('\n') 125 if strings.Contains(line, pattern) == true { 126 if inverseGrep { 127 t.Fatalf("grepFile: pattern \"%s\" found in \"%s\"", pattern, path) 128 } 129 return 130 } 131 } 132 if inverseGrep { 133 return 134 } 135 t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path) 136 } 137 138 func TestEscapeFstabSpaces(t *testing.T) { 139 var testInputs = map[string]string{ 140 " ": "\\040", 141 "": "", 142 "/double space": "/double\\040\\040space", 143 "/some long test string": "/some\\040long\\040test\\040string", 144 "/var/lib/docker": "/var/lib/docker", 145 " leading": "\\040leading", 146 "trailing ": "trailing\\040", 147 } 148 for in, exp := range testInputs { 149 if out := escapeFstabSpaces(in); exp != out { 150 t.Logf("Expected %s got %s", exp, out) 151 t.Fail() 152 } 153 } 154 } 155 156 func TestIsDirectory(t *testing.T) { 157 tempDir, err := ioutil.TempDir("", "TestIsDir") 158 if err != nil { 159 t.Fatal(err) 160 } 161 defer os.RemoveAll(tempDir) 162 163 tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile") 164 if err != nil { 165 t.Fatal(err) 166 } 167 168 if isDirectory(tempDir) != "dir" { 169 t.Logf("Could not identify %s as a directory", tempDir) 170 t.Fail() 171 } 172 173 if isDirectory(tempFile.Name()) != "file" { 174 t.Logf("Could not identify %s as a file", tempFile.Name()) 175 t.Fail() 176 } 177 } 178 179 func TestCustomLxcConfigMounts(t *testing.T) { 180 root, err := ioutil.TempDir("", "TestCustomLxcConfig") 181 if err != nil { 182 t.Fatal(err) 183 } 184 defer os.RemoveAll(root) 185 tempDir, err := ioutil.TempDir("", "TestIsDir") 186 if err != nil { 187 t.Fatal(err) 188 } 189 defer os.RemoveAll(tempDir) 190 191 tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile") 192 if err != nil { 193 t.Fatal(err) 194 } 195 os.MkdirAll(path.Join(root, "containers", "1"), 0777) 196 197 driver, err := NewDriver(root, root, "", false) 198 if err != nil { 199 t.Fatal(err) 200 } 201 processConfig := execdriver.ProcessConfig{ 202 Privileged: false, 203 } 204 mounts := []execdriver.Mount{ 205 { 206 Source: tempDir, 207 Destination: tempDir, 208 Writable: false, 209 Private: true, 210 }, 211 { 212 Source: tempFile.Name(), 213 Destination: tempFile.Name(), 214 Writable: true, 215 Private: true, 216 }, 217 } 218 command := &execdriver.Command{ 219 ID: "1", 220 LxcConfig: []string{ 221 "lxc.utsname = docker", 222 "lxc.cgroup.cpuset.cpus = 0,1", 223 }, 224 Network: &execdriver.Network{ 225 Mtu: 1500, 226 }, 227 Mounts: mounts, 228 ProcessConfig: processConfig, 229 } 230 231 p, err := driver.generateLXCConfig(command) 232 if err != nil { 233 t.Fatal(err) 234 } 235 236 grepFile(t, p, "lxc.utsname = docker") 237 grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") 238 239 grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,ro,create=%s 0 0", tempDir, "/"+tempDir, "dir")) 240 grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,rw,create=%s 0 0", tempFile.Name(), "/"+tempFile.Name(), "file")) 241 } 242 243 func TestCustomLxcConfigMisc(t *testing.T) { 244 root, err := ioutil.TempDir("", "TestCustomLxcConfig") 245 if err != nil { 246 t.Fatal(err) 247 } 248 defer os.RemoveAll(root) 249 os.MkdirAll(path.Join(root, "containers", "1"), 0777) 250 driver, err := NewDriver(root, root, "", true) 251 252 if err != nil { 253 t.Fatal(err) 254 } 255 processConfig := execdriver.ProcessConfig{ 256 Privileged: false, 257 } 258 259 processConfig.Env = []string{"HOSTNAME=testhost"} 260 command := &execdriver.Command{ 261 ID: "1", 262 LxcConfig: []string{ 263 "lxc.cgroup.cpuset.cpus = 0,1", 264 }, 265 Network: &execdriver.Network{ 266 Mtu: 1500, 267 }, 268 ProcessConfig: processConfig, 269 CapAdd: []string{"net_admin", "syslog"}, 270 CapDrop: []string{"kill", "mknod"}, 271 AppArmorProfile: "lxc-container-default-with-nesting", 272 } 273 274 p, err := driver.generateLXCConfig(command) 275 if err != nil { 276 t.Fatal(err) 277 } 278 grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting") 279 // hostname 280 grepFile(t, p, "lxc.utsname = testhost") 281 grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") 282 container := nativeTemplate.New() 283 for _, cap := range container.Capabilities { 284 realCap := execdriver.GetCapability(cap) 285 numCap := fmt.Sprintf("%d", realCap.Value) 286 if cap != "MKNOD" && cap != "KILL" { 287 grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) 288 } 289 } 290 291 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) 292 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) 293 } 294 295 func TestCustomLxcConfigMiscOverride(t *testing.T) { 296 root, err := ioutil.TempDir("", "TestCustomLxcConfig") 297 if err != nil { 298 t.Fatal(err) 299 } 300 defer os.RemoveAll(root) 301 os.MkdirAll(path.Join(root, "containers", "1"), 0777) 302 driver, err := NewDriver(root, root, "", false) 303 if err != nil { 304 t.Fatal(err) 305 } 306 processConfig := execdriver.ProcessConfig{ 307 Privileged: false, 308 } 309 310 processConfig.Env = []string{"HOSTNAME=testhost"} 311 command := &execdriver.Command{ 312 ID: "1", 313 LxcConfig: []string{ 314 "lxc.cgroup.cpuset.cpus = 0,1", 315 "lxc.network.ipv4 = 172.0.0.1", 316 }, 317 Network: &execdriver.Network{ 318 Mtu: 1500, 319 }, 320 ProcessConfig: processConfig, 321 CapAdd: []string{"NET_ADMIN", "SYSLOG"}, 322 CapDrop: []string{"KILL", "MKNOD"}, 323 } 324 325 p, err := driver.generateLXCConfig(command) 326 if err != nil { 327 t.Fatal(err) 328 } 329 330 // hostname 331 grepFile(t, p, "lxc.utsname = testhost") 332 grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") 333 container := nativeTemplate.New() 334 for _, cap := range container.Capabilities { 335 realCap := execdriver.GetCapability(cap) 336 numCap := fmt.Sprintf("%d", realCap.Value) 337 if cap != "MKNOD" && cap != "KILL" { 338 grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) 339 } 340 } 341 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) 342 grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) 343 }