github.com/dougm/docker@v1.5.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  	"github.com/docker/docker/daemon/execdriver"
     9  	nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template"
    10  	"github.com/docker/libcontainer/devices"
    11  	"github.com/docker/libcontainer/security/capabilities"
    12  	"github.com/syndtr/gocapability/capability"
    13  	"io/ioutil"
    14  	"math/rand"
    15  	"os"
    16  	"path"
    17  	"strings"
    18  	"testing"
    19  	"time"
    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  	rand.Seed(time.Now().UTC().UnixNano())
    33  	var (
    34  		memMin = 33554432
    35  		memMax = 536870912
    36  		mem    = memMin + rand.Intn(memMax-memMin)
    37  		cpuMin = 100
    38  		cpuMax = 10000
    39  		cpu    = cpuMin + rand.Intn(cpuMax-cpuMin)
    40  	)
    41  
    42  	driver, err := NewDriver(root, "", false)
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	command := &execdriver.Command{
    47  		ID: "1",
    48  		Resources: &execdriver.Resources{
    49  			Memory:    int64(mem),
    50  			CpuShares: int64(cpu),
    51  		},
    52  		Network: &execdriver.Network{
    53  			Mtu:       1500,
    54  			Interface: nil,
    55  		},
    56  		AllowedDevices: make([]*devices.Device, 0),
    57  		ProcessConfig:  execdriver.ProcessConfig{},
    58  	}
    59  	p, err := driver.generateLXCConfig(command)
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	grepFile(t, p,
    64  		fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
    65  
    66  	grepFile(t, p,
    67  		fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
    68  }
    69  
    70  func TestCustomLxcConfig(t *testing.T) {
    71  	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  	defer os.RemoveAll(root)
    76  
    77  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
    78  
    79  	driver, err := NewDriver(root, "", false)
    80  	if err != nil {
    81  		t.Fatal(err)
    82  	}
    83  	processConfig := execdriver.ProcessConfig{
    84  		Privileged: false,
    85  	}
    86  	command := &execdriver.Command{
    87  		ID: "1",
    88  		LxcConfig: []string{
    89  			"lxc.utsname = docker",
    90  			"lxc.cgroup.cpuset.cpus = 0,1",
    91  		},
    92  		Network: &execdriver.Network{
    93  			Mtu:       1500,
    94  			Interface: nil,
    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, "", 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  			Interface: nil,
   227  		},
   228  		Mounts:        mounts,
   229  		ProcessConfig: processConfig,
   230  	}
   231  
   232  	p, err := driver.generateLXCConfig(command)
   233  	if err != nil {
   234  		t.Fatal(err)
   235  	}
   236  
   237  	grepFile(t, p, "lxc.utsname = docker")
   238  	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
   239  
   240  	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,ro,create=%s 0 0", tempDir, "/"+tempDir, "dir"))
   241  	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,rw,create=%s 0 0", tempFile.Name(), "/"+tempFile.Name(), "file"))
   242  }
   243  
   244  func TestCustomLxcConfigMisc(t *testing.T) {
   245  	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  	defer os.RemoveAll(root)
   250  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
   251  	driver, err := NewDriver(root, "", true)
   252  
   253  	if err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	processConfig := execdriver.ProcessConfig{
   257  		Privileged: false,
   258  	}
   259  
   260  	processConfig.Env = []string{"HOSTNAME=testhost"}
   261  	command := &execdriver.Command{
   262  		ID: "1",
   263  		LxcConfig: []string{
   264  			"lxc.cgroup.cpuset.cpus = 0,1",
   265  		},
   266  		Network: &execdriver.Network{
   267  			Mtu: 1500,
   268  			Interface: &execdriver.NetworkInterface{
   269  				Gateway:     "10.10.10.1",
   270  				IPAddress:   "10.10.10.10",
   271  				IPPrefixLen: 24,
   272  				Bridge:      "docker0",
   273  			},
   274  		},
   275  		ProcessConfig:   processConfig,
   276  		CapAdd:          []string{"net_admin", "syslog"},
   277  		CapDrop:         []string{"kill", "mknod"},
   278  		AppArmorProfile: "lxc-container-default-with-nesting",
   279  	}
   280  
   281  	p, err := driver.generateLXCConfig(command)
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	}
   285  	// network
   286  	grepFile(t, p, "lxc.network.type = veth")
   287  	grepFile(t, p, "lxc.network.link = docker0")
   288  	grepFile(t, p, "lxc.network.name = eth0")
   289  	grepFile(t, p, "lxc.network.ipv4 = 10.10.10.10/24")
   290  	grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1")
   291  	grepFile(t, p, "lxc.network.flags = up")
   292  	grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting")
   293  	// hostname
   294  	grepFile(t, p, "lxc.utsname = testhost")
   295  	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
   296  	container := nativeTemplate.New()
   297  	for _, cap := range container.Capabilities {
   298  		realCap := capabilities.GetCapability(cap)
   299  		numCap := fmt.Sprintf("%d", realCap.Value)
   300  		if cap != "MKNOD" && cap != "KILL" {
   301  			grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap))
   302  		}
   303  	}
   304  
   305  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true)
   306  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true)
   307  }
   308  
   309  func TestCustomLxcConfigMiscOverride(t *testing.T) {
   310  	root, err := ioutil.TempDir("", "TestCustomLxcConfig")
   311  	if err != nil {
   312  		t.Fatal(err)
   313  	}
   314  	defer os.RemoveAll(root)
   315  	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
   316  	driver, err := NewDriver(root, "", false)
   317  	if err != nil {
   318  		t.Fatal(err)
   319  	}
   320  	processConfig := execdriver.ProcessConfig{
   321  		Privileged: false,
   322  	}
   323  
   324  	processConfig.Env = []string{"HOSTNAME=testhost"}
   325  	command := &execdriver.Command{
   326  		ID: "1",
   327  		LxcConfig: []string{
   328  			"lxc.cgroup.cpuset.cpus = 0,1",
   329  			"lxc.network.ipv4 = 172.0.0.1",
   330  		},
   331  		Network: &execdriver.Network{
   332  			Mtu: 1500,
   333  			Interface: &execdriver.NetworkInterface{
   334  				Gateway:     "10.10.10.1",
   335  				IPAddress:   "10.10.10.10",
   336  				IPPrefixLen: 24,
   337  				Bridge:      "docker0",
   338  			},
   339  		},
   340  		ProcessConfig: processConfig,
   341  		CapAdd:        []string{"NET_ADMIN", "SYSLOG"},
   342  		CapDrop:       []string{"KILL", "MKNOD"},
   343  	}
   344  
   345  	p, err := driver.generateLXCConfig(command)
   346  	if err != nil {
   347  		t.Fatal(err)
   348  	}
   349  	// network
   350  	grepFile(t, p, "lxc.network.type = veth")
   351  	grepFile(t, p, "lxc.network.link = docker0")
   352  	grepFile(t, p, "lxc.network.name = eth0")
   353  	grepFile(t, p, "lxc.network.ipv4 = 172.0.0.1")
   354  	grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1")
   355  	grepFile(t, p, "lxc.network.flags = up")
   356  
   357  	// hostname
   358  	grepFile(t, p, "lxc.utsname = testhost")
   359  	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
   360  	container := nativeTemplate.New()
   361  	for _, cap := range container.Capabilities {
   362  		realCap := capabilities.GetCapability(cap)
   363  		numCap := fmt.Sprintf("%d", realCap.Value)
   364  		if cap != "MKNOD" && cap != "KILL" {
   365  			grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap))
   366  		}
   367  	}
   368  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true)
   369  	grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true)
   370  }