github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/daemon/daemon_unix_test.go (about)

     1  // +build !windows,!solaris
     2  
     3  package daemon
     4  
     5  import (
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	containertypes "github.com/docker/docker/api/types/container"
    12  	"github.com/docker/docker/container"
    13  	"github.com/docker/docker/daemon/config"
    14  	"github.com/docker/docker/pkg/idtools"
    15  	"github.com/docker/docker/volume"
    16  	"github.com/docker/docker/volume/drivers"
    17  	"github.com/docker/docker/volume/local"
    18  	"github.com/docker/docker/volume/store"
    19  )
    20  
    21  // Unix test as uses settings which are not available on Windows
    22  func TestAdjustCPUShares(t *testing.T) {
    23  	tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-")
    24  	if err != nil {
    25  		t.Fatal(err)
    26  	}
    27  	defer os.RemoveAll(tmp)
    28  	daemon := &Daemon{
    29  		repository: tmp,
    30  		root:       tmp,
    31  	}
    32  
    33  	hostConfig := &containertypes.HostConfig{
    34  		Resources: containertypes.Resources{CPUShares: linuxMinCPUShares - 1},
    35  	}
    36  	daemon.adaptContainerSettings(hostConfig, true)
    37  	if hostConfig.CPUShares != linuxMinCPUShares {
    38  		t.Errorf("Expected CPUShares to be %d", linuxMinCPUShares)
    39  	}
    40  
    41  	hostConfig.CPUShares = linuxMaxCPUShares + 1
    42  	daemon.adaptContainerSettings(hostConfig, true)
    43  	if hostConfig.CPUShares != linuxMaxCPUShares {
    44  		t.Errorf("Expected CPUShares to be %d", linuxMaxCPUShares)
    45  	}
    46  
    47  	hostConfig.CPUShares = 0
    48  	daemon.adaptContainerSettings(hostConfig, true)
    49  	if hostConfig.CPUShares != 0 {
    50  		t.Error("Expected CPUShares to be unchanged")
    51  	}
    52  
    53  	hostConfig.CPUShares = 1024
    54  	daemon.adaptContainerSettings(hostConfig, true)
    55  	if hostConfig.CPUShares != 1024 {
    56  		t.Error("Expected CPUShares to be unchanged")
    57  	}
    58  }
    59  
    60  // Unix test as uses settings which are not available on Windows
    61  func TestAdjustCPUSharesNoAdjustment(t *testing.T) {
    62  	tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-")
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	defer os.RemoveAll(tmp)
    67  	daemon := &Daemon{
    68  		repository: tmp,
    69  		root:       tmp,
    70  	}
    71  
    72  	hostConfig := &containertypes.HostConfig{
    73  		Resources: containertypes.Resources{CPUShares: linuxMinCPUShares - 1},
    74  	}
    75  	daemon.adaptContainerSettings(hostConfig, false)
    76  	if hostConfig.CPUShares != linuxMinCPUShares-1 {
    77  		t.Errorf("Expected CPUShares to be %d", linuxMinCPUShares-1)
    78  	}
    79  
    80  	hostConfig.CPUShares = linuxMaxCPUShares + 1
    81  	daemon.adaptContainerSettings(hostConfig, false)
    82  	if hostConfig.CPUShares != linuxMaxCPUShares+1 {
    83  		t.Errorf("Expected CPUShares to be %d", linuxMaxCPUShares+1)
    84  	}
    85  
    86  	hostConfig.CPUShares = 0
    87  	daemon.adaptContainerSettings(hostConfig, false)
    88  	if hostConfig.CPUShares != 0 {
    89  		t.Error("Expected CPUShares to be unchanged")
    90  	}
    91  
    92  	hostConfig.CPUShares = 1024
    93  	daemon.adaptContainerSettings(hostConfig, false)
    94  	if hostConfig.CPUShares != 1024 {
    95  		t.Error("Expected CPUShares to be unchanged")
    96  	}
    97  }
    98  
    99  // Unix test as uses settings which are not available on Windows
   100  func TestParseSecurityOptWithDeprecatedColon(t *testing.T) {
   101  	container := &container.Container{}
   102  	config := &containertypes.HostConfig{}
   103  
   104  	// test apparmor
   105  	config.SecurityOpt = []string{"apparmor=test_profile"}
   106  	if err := parseSecurityOpt(container, config); err != nil {
   107  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   108  	}
   109  	if container.AppArmorProfile != "test_profile" {
   110  		t.Fatalf("Unexpected AppArmorProfile, expected: \"test_profile\", got %q", container.AppArmorProfile)
   111  	}
   112  
   113  	// test seccomp
   114  	sp := "/path/to/seccomp_test.json"
   115  	config.SecurityOpt = []string{"seccomp=" + sp}
   116  	if err := parseSecurityOpt(container, config); err != nil {
   117  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   118  	}
   119  	if container.SeccompProfile != sp {
   120  		t.Fatalf("Unexpected AppArmorProfile, expected: %q, got %q", sp, container.SeccompProfile)
   121  	}
   122  
   123  	// test valid label
   124  	config.SecurityOpt = []string{"label=user:USER"}
   125  	if err := parseSecurityOpt(container, config); err != nil {
   126  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   127  	}
   128  
   129  	// test invalid label
   130  	config.SecurityOpt = []string{"label"}
   131  	if err := parseSecurityOpt(container, config); err == nil {
   132  		t.Fatal("Expected parseSecurityOpt error, got nil")
   133  	}
   134  
   135  	// test invalid opt
   136  	config.SecurityOpt = []string{"test"}
   137  	if err := parseSecurityOpt(container, config); err == nil {
   138  		t.Fatal("Expected parseSecurityOpt error, got nil")
   139  	}
   140  }
   141  
   142  func TestParseSecurityOpt(t *testing.T) {
   143  	container := &container.Container{}
   144  	config := &containertypes.HostConfig{}
   145  
   146  	// test apparmor
   147  	config.SecurityOpt = []string{"apparmor=test_profile"}
   148  	if err := parseSecurityOpt(container, config); err != nil {
   149  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   150  	}
   151  	if container.AppArmorProfile != "test_profile" {
   152  		t.Fatalf("Unexpected AppArmorProfile, expected: \"test_profile\", got %q", container.AppArmorProfile)
   153  	}
   154  
   155  	// test seccomp
   156  	sp := "/path/to/seccomp_test.json"
   157  	config.SecurityOpt = []string{"seccomp=" + sp}
   158  	if err := parseSecurityOpt(container, config); err != nil {
   159  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   160  	}
   161  	if container.SeccompProfile != sp {
   162  		t.Fatalf("Unexpected SeccompProfile, expected: %q, got %q", sp, container.SeccompProfile)
   163  	}
   164  
   165  	// test valid label
   166  	config.SecurityOpt = []string{"label=user:USER"}
   167  	if err := parseSecurityOpt(container, config); err != nil {
   168  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   169  	}
   170  
   171  	// test invalid label
   172  	config.SecurityOpt = []string{"label"}
   173  	if err := parseSecurityOpt(container, config); err == nil {
   174  		t.Fatal("Expected parseSecurityOpt error, got nil")
   175  	}
   176  
   177  	// test invalid opt
   178  	config.SecurityOpt = []string{"test"}
   179  	if err := parseSecurityOpt(container, config); err == nil {
   180  		t.Fatal("Expected parseSecurityOpt error, got nil")
   181  	}
   182  }
   183  
   184  func TestParseNNPSecurityOptions(t *testing.T) {
   185  	daemon := &Daemon{
   186  		configStore: &config.Config{NoNewPrivileges: true},
   187  	}
   188  	container := &container.Container{}
   189  	config := &containertypes.HostConfig{}
   190  
   191  	// test NNP when "daemon:true" and "no-new-privileges=false""
   192  	config.SecurityOpt = []string{"no-new-privileges=false"}
   193  
   194  	if err := daemon.parseSecurityOpt(container, config); err != nil {
   195  		t.Fatalf("Unexpected daemon.parseSecurityOpt error: %v", err)
   196  	}
   197  	if container.NoNewPrivileges {
   198  		t.Fatalf("container.NoNewPrivileges should be FALSE: %v", container.NoNewPrivileges)
   199  	}
   200  
   201  	// test NNP when "daemon:false" and "no-new-privileges=true""
   202  	daemon.configStore.NoNewPrivileges = false
   203  	config.SecurityOpt = []string{"no-new-privileges=true"}
   204  
   205  	if err := daemon.parseSecurityOpt(container, config); err != nil {
   206  		t.Fatalf("Unexpected daemon.parseSecurityOpt error: %v", err)
   207  	}
   208  	if !container.NoNewPrivileges {
   209  		t.Fatalf("container.NoNewPrivileges should be TRUE: %v", container.NoNewPrivileges)
   210  	}
   211  }
   212  
   213  func TestNetworkOptions(t *testing.T) {
   214  	daemon := &Daemon{}
   215  	dconfigCorrect := &config.Config{
   216  		CommonConfig: config.CommonConfig{
   217  			ClusterStore:     "consul://localhost:8500",
   218  			ClusterAdvertise: "192.168.0.1:8000",
   219  		},
   220  	}
   221  
   222  	if _, err := daemon.networkOptions(dconfigCorrect, nil, nil); err != nil {
   223  		t.Fatalf("Expect networkOptions success, got error: %v", err)
   224  	}
   225  
   226  	dconfigWrong := &config.Config{
   227  		CommonConfig: config.CommonConfig{
   228  			ClusterStore: "consul://localhost:8500://test://bbb",
   229  		},
   230  	}
   231  
   232  	if _, err := daemon.networkOptions(dconfigWrong, nil, nil); err == nil {
   233  		t.Fatal("Expected networkOptions error, got nil")
   234  	}
   235  }
   236  
   237  func TestMigratePre17Volumes(t *testing.T) {
   238  	rootDir, err := ioutil.TempDir("", "test-daemon-volumes")
   239  	if err != nil {
   240  		t.Fatal(err)
   241  	}
   242  	defer os.RemoveAll(rootDir)
   243  
   244  	volumeRoot := filepath.Join(rootDir, "volumes")
   245  	err = os.MkdirAll(volumeRoot, 0755)
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  
   250  	containerRoot := filepath.Join(rootDir, "containers")
   251  	cid := "1234"
   252  	err = os.MkdirAll(filepath.Join(containerRoot, cid), 0755)
   253  
   254  	vid := "5678"
   255  	vfsPath := filepath.Join(rootDir, "vfs", "dir", vid)
   256  	err = os.MkdirAll(vfsPath, 0755)
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  
   261  	config := []byte(`
   262  		{
   263  			"ID": "` + cid + `",
   264  			"Volumes": {
   265  				"/foo": "` + vfsPath + `",
   266  				"/bar": "/foo",
   267  				"/quux": "/quux"
   268  			},
   269  			"VolumesRW": {
   270  				"/foo": true,
   271  				"/bar": true,
   272  				"/quux": false
   273  			}
   274  		}
   275  	`)
   276  
   277  	volStore, err := store.New(volumeRoot)
   278  	if err != nil {
   279  		t.Fatal(err)
   280  	}
   281  	drv, err := local.New(volumeRoot, idtools.IDPair{UID: 0, GID: 0})
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	}
   285  	volumedrivers.Register(drv, volume.DefaultDriverName)
   286  
   287  	daemon := &Daemon{root: rootDir, repository: containerRoot, volumes: volStore}
   288  	err = ioutil.WriteFile(filepath.Join(containerRoot, cid, "config.v2.json"), config, 600)
   289  	if err != nil {
   290  		t.Fatal(err)
   291  	}
   292  	c, err := daemon.load(cid)
   293  	if err != nil {
   294  		t.Fatal(err)
   295  	}
   296  	if err := daemon.verifyVolumesInfo(c); err != nil {
   297  		t.Fatal(err)
   298  	}
   299  
   300  	expected := map[string]volume.MountPoint{
   301  		"/foo":  {Destination: "/foo", RW: true, Name: vid},
   302  		"/bar":  {Source: "/foo", Destination: "/bar", RW: true},
   303  		"/quux": {Source: "/quux", Destination: "/quux", RW: false},
   304  	}
   305  	for id, mp := range c.MountPoints {
   306  		x, exists := expected[id]
   307  		if !exists {
   308  			t.Fatal("volume not migrated")
   309  		}
   310  		if mp.Source != x.Source || mp.Destination != x.Destination || mp.RW != x.RW || mp.Name != x.Name {
   311  			t.Fatalf("got unexpected mountpoint, expected: %+v, got: %+v", x, mp)
   312  		}
   313  	}
   314  }