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 }