github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/integration-cli/docker_cli_service_create_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "path/filepath" 9 "strings" 10 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/api/types/mount" 13 "github.com/docker/docker/api/types/swarm" 14 "github.com/docker/docker/integration-cli/checker" 15 "github.com/go-check/check" 16 ) 17 18 func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *check.C) { 19 d := s.AddDaemon(c, true, true) 20 out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--mount", "type=volume,source=foo,target=/foo,volume-nocopy", "busybox", "top") 21 c.Assert(err, checker.IsNil, check.Commentf(out)) 22 id := strings.TrimSpace(out) 23 24 var tasks []swarm.Task 25 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 26 tasks = d.GetServiceTasks(c, id) 27 return len(tasks) > 0, nil 28 }, checker.Equals, true) 29 30 task := tasks[0] 31 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 32 if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { 33 task = d.GetTask(c, task.ID) 34 } 35 return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil 36 }, checker.Equals, true) 37 38 // check container mount config 39 out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .HostConfig.Mounts}}", task.Status.ContainerStatus.ContainerID) 40 c.Assert(err, checker.IsNil, check.Commentf(out)) 41 42 var mountConfig []mount.Mount 43 c.Assert(json.Unmarshal([]byte(out), &mountConfig), checker.IsNil) 44 c.Assert(mountConfig, checker.HasLen, 1) 45 46 c.Assert(mountConfig[0].Source, checker.Equals, "foo") 47 c.Assert(mountConfig[0].Target, checker.Equals, "/foo") 48 c.Assert(mountConfig[0].Type, checker.Equals, mount.TypeVolume) 49 c.Assert(mountConfig[0].VolumeOptions, checker.NotNil) 50 c.Assert(mountConfig[0].VolumeOptions.NoCopy, checker.True) 51 52 // check container mounts actual 53 out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .Mounts}}", task.Status.ContainerStatus.ContainerID) 54 c.Assert(err, checker.IsNil, check.Commentf(out)) 55 56 var mounts []types.MountPoint 57 c.Assert(json.Unmarshal([]byte(out), &mounts), checker.IsNil) 58 c.Assert(mounts, checker.HasLen, 1) 59 60 c.Assert(mounts[0].Type, checker.Equals, mount.TypeVolume) 61 c.Assert(mounts[0].Name, checker.Equals, "foo") 62 c.Assert(mounts[0].Destination, checker.Equals, "/foo") 63 c.Assert(mounts[0].RW, checker.Equals, true) 64 } 65 66 func (s *DockerSwarmSuite) TestServiceCreateWithSecretSimple(c *check.C) { 67 d := s.AddDaemon(c, true, true) 68 69 serviceName := "test-service-secret" 70 testName := "test_secret" 71 id := d.CreateSecret(c, swarm.SecretSpec{ 72 Annotations: swarm.Annotations{ 73 Name: testName, 74 }, 75 Data: []byte("TESTINGDATA"), 76 }) 77 c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id)) 78 79 out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", serviceName, "--secret", testName, "busybox", "top") 80 c.Assert(err, checker.IsNil, check.Commentf(out)) 81 82 out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName) 83 c.Assert(err, checker.IsNil) 84 85 var refs []swarm.SecretReference 86 c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil) 87 c.Assert(refs, checker.HasLen, 1) 88 89 c.Assert(refs[0].SecretName, checker.Equals, testName) 90 c.Assert(refs[0].File, checker.Not(checker.IsNil)) 91 c.Assert(refs[0].File.Name, checker.Equals, testName) 92 c.Assert(refs[0].File.UID, checker.Equals, "0") 93 c.Assert(refs[0].File.GID, checker.Equals, "0") 94 95 out, err = d.Cmd("service", "rm", serviceName) 96 c.Assert(err, checker.IsNil, check.Commentf(out)) 97 d.DeleteSecret(c, testName) 98 } 99 100 func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTargetPaths(c *check.C) { 101 d := s.AddDaemon(c, true, true) 102 103 testPaths := map[string]string{ 104 "app": "/etc/secret", 105 "test_secret": "test_secret", 106 "relative_secret": "relative/secret", 107 "escapes_in_container": "../secret", 108 } 109 110 var secretFlags []string 111 112 for testName, testTarget := range testPaths { 113 id := d.CreateSecret(c, swarm.SecretSpec{ 114 Annotations: swarm.Annotations{ 115 Name: testName, 116 }, 117 Data: []byte("TESTINGDATA " + testName + " " + testTarget), 118 }) 119 c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id)) 120 121 secretFlags = append(secretFlags, "--secret", fmt.Sprintf("source=%s,target=%s", testName, testTarget)) 122 } 123 124 serviceName := "svc" 125 serviceCmd := []string{"service", "create", "--no-resolve-image", "--name", serviceName} 126 serviceCmd = append(serviceCmd, secretFlags...) 127 serviceCmd = append(serviceCmd, "busybox", "top") 128 out, err := d.Cmd(serviceCmd...) 129 c.Assert(err, checker.IsNil, check.Commentf(out)) 130 131 out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName) 132 c.Assert(err, checker.IsNil) 133 134 var refs []swarm.SecretReference 135 c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil) 136 c.Assert(refs, checker.HasLen, len(testPaths)) 137 138 var tasks []swarm.Task 139 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 140 tasks = d.GetServiceTasks(c, serviceName) 141 return len(tasks) > 0, nil 142 }, checker.Equals, true) 143 144 task := tasks[0] 145 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 146 if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { 147 task = d.GetTask(c, task.ID) 148 } 149 return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil 150 }, checker.Equals, true) 151 152 for testName, testTarget := range testPaths { 153 path := testTarget 154 if !filepath.IsAbs(path) { 155 path = filepath.Join("/run/secrets", path) 156 } 157 out, err := d.Cmd("exec", task.Status.ContainerStatus.ContainerID, "cat", path) 158 c.Assert(err, checker.IsNil) 159 c.Assert(out, checker.Equals, "TESTINGDATA "+testName+" "+testTarget) 160 } 161 162 out, err = d.Cmd("service", "rm", serviceName) 163 c.Assert(err, checker.IsNil, check.Commentf(out)) 164 } 165 166 func (s *DockerSwarmSuite) TestServiceCreateWithSecretReferencedTwice(c *check.C) { 167 d := s.AddDaemon(c, true, true) 168 169 id := d.CreateSecret(c, swarm.SecretSpec{ 170 Annotations: swarm.Annotations{ 171 Name: "mysecret", 172 }, 173 Data: []byte("TESTINGDATA"), 174 }) 175 c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id)) 176 177 serviceName := "svc" 178 out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", serviceName, "--secret", "source=mysecret,target=target1", "--secret", "source=mysecret,target=target2", "busybox", "top") 179 c.Assert(err, checker.IsNil, check.Commentf(out)) 180 181 out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName) 182 c.Assert(err, checker.IsNil) 183 184 var refs []swarm.SecretReference 185 c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil) 186 c.Assert(refs, checker.HasLen, 2) 187 188 var tasks []swarm.Task 189 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 190 tasks = d.GetServiceTasks(c, serviceName) 191 return len(tasks) > 0, nil 192 }, checker.Equals, true) 193 194 task := tasks[0] 195 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 196 if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { 197 task = d.GetTask(c, task.ID) 198 } 199 return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil 200 }, checker.Equals, true) 201 202 for _, target := range []string{"target1", "target2"} { 203 c.Assert(err, checker.IsNil, check.Commentf(out)) 204 path := filepath.Join("/run/secrets", target) 205 out, err := d.Cmd("exec", task.Status.ContainerStatus.ContainerID, "cat", path) 206 c.Assert(err, checker.IsNil) 207 c.Assert(out, checker.Equals, "TESTINGDATA") 208 } 209 210 out, err = d.Cmd("service", "rm", serviceName) 211 c.Assert(err, checker.IsNil, check.Commentf(out)) 212 } 213 214 func (s *DockerSwarmSuite) TestServiceCreateWithConfigSimple(c *check.C) { 215 d := s.AddDaemon(c, true, true) 216 217 serviceName := "test-service-config" 218 testName := "test_config" 219 id := d.CreateConfig(c, swarm.ConfigSpec{ 220 Annotations: swarm.Annotations{ 221 Name: testName, 222 }, 223 Data: []byte("TESTINGDATA"), 224 }) 225 c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id)) 226 227 out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", serviceName, "--config", testName, "busybox", "top") 228 c.Assert(err, checker.IsNil, check.Commentf(out)) 229 230 out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Configs }}", serviceName) 231 c.Assert(err, checker.IsNil) 232 233 var refs []swarm.ConfigReference 234 c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil) 235 c.Assert(refs, checker.HasLen, 1) 236 237 c.Assert(refs[0].ConfigName, checker.Equals, testName) 238 c.Assert(refs[0].File, checker.Not(checker.IsNil)) 239 c.Assert(refs[0].File.Name, checker.Equals, testName) 240 c.Assert(refs[0].File.UID, checker.Equals, "0") 241 c.Assert(refs[0].File.GID, checker.Equals, "0") 242 243 out, err = d.Cmd("service", "rm", serviceName) 244 c.Assert(err, checker.IsNil, check.Commentf(out)) 245 d.DeleteConfig(c, testName) 246 } 247 248 func (s *DockerSwarmSuite) TestServiceCreateWithConfigSourceTargetPaths(c *check.C) { 249 d := s.AddDaemon(c, true, true) 250 251 testPaths := map[string]string{ 252 "app": "/etc/config", 253 "test_config": "test_config", 254 "relative_config": "relative/config", 255 } 256 257 var configFlags []string 258 259 for testName, testTarget := range testPaths { 260 id := d.CreateConfig(c, swarm.ConfigSpec{ 261 Annotations: swarm.Annotations{ 262 Name: testName, 263 }, 264 Data: []byte("TESTINGDATA " + testName + " " + testTarget), 265 }) 266 c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id)) 267 268 configFlags = append(configFlags, "--config", fmt.Sprintf("source=%s,target=%s", testName, testTarget)) 269 } 270 271 serviceName := "svc" 272 serviceCmd := []string{"service", "create", "--no-resolve-image", "--name", serviceName} 273 serviceCmd = append(serviceCmd, configFlags...) 274 serviceCmd = append(serviceCmd, "busybox", "top") 275 out, err := d.Cmd(serviceCmd...) 276 c.Assert(err, checker.IsNil, check.Commentf(out)) 277 278 out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Configs }}", serviceName) 279 c.Assert(err, checker.IsNil) 280 281 var refs []swarm.ConfigReference 282 c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil) 283 c.Assert(refs, checker.HasLen, len(testPaths)) 284 285 var tasks []swarm.Task 286 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 287 tasks = d.GetServiceTasks(c, serviceName) 288 return len(tasks) > 0, nil 289 }, checker.Equals, true) 290 291 task := tasks[0] 292 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 293 if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { 294 task = d.GetTask(c, task.ID) 295 } 296 return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil 297 }, checker.Equals, true) 298 299 for testName, testTarget := range testPaths { 300 path := testTarget 301 if !filepath.IsAbs(path) { 302 path = filepath.Join("/", path) 303 } 304 out, err := d.Cmd("exec", task.Status.ContainerStatus.ContainerID, "cat", path) 305 c.Assert(err, checker.IsNil) 306 c.Assert(out, checker.Equals, "TESTINGDATA "+testName+" "+testTarget) 307 } 308 309 out, err = d.Cmd("service", "rm", serviceName) 310 c.Assert(err, checker.IsNil, check.Commentf(out)) 311 } 312 313 func (s *DockerSwarmSuite) TestServiceCreateWithConfigReferencedTwice(c *check.C) { 314 d := s.AddDaemon(c, true, true) 315 316 id := d.CreateConfig(c, swarm.ConfigSpec{ 317 Annotations: swarm.Annotations{ 318 Name: "myconfig", 319 }, 320 Data: []byte("TESTINGDATA"), 321 }) 322 c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id)) 323 324 serviceName := "svc" 325 out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", serviceName, "--config", "source=myconfig,target=target1", "--config", "source=myconfig,target=target2", "busybox", "top") 326 c.Assert(err, checker.IsNil, check.Commentf(out)) 327 328 out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Configs }}", serviceName) 329 c.Assert(err, checker.IsNil) 330 331 var refs []swarm.ConfigReference 332 c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil) 333 c.Assert(refs, checker.HasLen, 2) 334 335 var tasks []swarm.Task 336 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 337 tasks = d.GetServiceTasks(c, serviceName) 338 return len(tasks) > 0, nil 339 }, checker.Equals, true) 340 341 task := tasks[0] 342 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 343 if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { 344 task = d.GetTask(c, task.ID) 345 } 346 return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil 347 }, checker.Equals, true) 348 349 for _, target := range []string{"target1", "target2"} { 350 c.Assert(err, checker.IsNil, check.Commentf(out)) 351 path := filepath.Join("/", target) 352 out, err := d.Cmd("exec", task.Status.ContainerStatus.ContainerID, "cat", path) 353 c.Assert(err, checker.IsNil) 354 c.Assert(out, checker.Equals, "TESTINGDATA") 355 } 356 357 out, err = d.Cmd("service", "rm", serviceName) 358 c.Assert(err, checker.IsNil, check.Commentf(out)) 359 } 360 361 func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *check.C) { 362 d := s.AddDaemon(c, true, true) 363 out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--mount", "type=tmpfs,target=/foo,tmpfs-size=1MB", "busybox", "sh", "-c", "mount | grep foo; tail -f /dev/null") 364 c.Assert(err, checker.IsNil, check.Commentf(out)) 365 id := strings.TrimSpace(out) 366 367 var tasks []swarm.Task 368 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 369 tasks = d.GetServiceTasks(c, id) 370 return len(tasks) > 0, nil 371 }, checker.Equals, true) 372 373 task := tasks[0] 374 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 375 if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { 376 task = d.GetTask(c, task.ID) 377 } 378 return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil 379 }, checker.Equals, true) 380 381 // check container mount config 382 out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .HostConfig.Mounts}}", task.Status.ContainerStatus.ContainerID) 383 c.Assert(err, checker.IsNil, check.Commentf(out)) 384 385 var mountConfig []mount.Mount 386 c.Assert(json.Unmarshal([]byte(out), &mountConfig), checker.IsNil) 387 c.Assert(mountConfig, checker.HasLen, 1) 388 389 c.Assert(mountConfig[0].Source, checker.Equals, "") 390 c.Assert(mountConfig[0].Target, checker.Equals, "/foo") 391 c.Assert(mountConfig[0].Type, checker.Equals, mount.TypeTmpfs) 392 c.Assert(mountConfig[0].TmpfsOptions, checker.NotNil) 393 c.Assert(mountConfig[0].TmpfsOptions.SizeBytes, checker.Equals, int64(1048576)) 394 395 // check container mounts actual 396 out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .Mounts}}", task.Status.ContainerStatus.ContainerID) 397 c.Assert(err, checker.IsNil, check.Commentf(out)) 398 399 var mounts []types.MountPoint 400 c.Assert(json.Unmarshal([]byte(out), &mounts), checker.IsNil) 401 c.Assert(mounts, checker.HasLen, 1) 402 403 c.Assert(mounts[0].Type, checker.Equals, mount.TypeTmpfs) 404 c.Assert(mounts[0].Name, checker.Equals, "") 405 c.Assert(mounts[0].Destination, checker.Equals, "/foo") 406 c.Assert(mounts[0].RW, checker.Equals, true) 407 408 out, err = s.nodeCmd(c, task.NodeID, "logs", task.Status.ContainerStatus.ContainerID) 409 c.Assert(err, checker.IsNil, check.Commentf(out)) 410 c.Assert(strings.TrimSpace(out), checker.HasPrefix, "tmpfs on /foo type tmpfs") 411 c.Assert(strings.TrimSpace(out), checker.Contains, "size=1024k") 412 } 413 414 func (s *DockerSwarmSuite) TestServiceCreateWithNetworkAlias(c *check.C) { 415 d := s.AddDaemon(c, true, true) 416 out, err := d.Cmd("network", "create", "--scope=swarm", "test_swarm_br") 417 c.Assert(err, checker.IsNil, check.Commentf(out)) 418 419 out, err = d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--network=name=test_swarm_br,alias=srv_alias", "--name=alias_tst_container", "busybox", "top") 420 c.Assert(err, checker.IsNil, check.Commentf(out)) 421 id := strings.TrimSpace(out) 422 423 var tasks []swarm.Task 424 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 425 tasks = d.GetServiceTasks(c, id) 426 return len(tasks) > 0, nil 427 }, checker.Equals, true) 428 429 task := tasks[0] 430 waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { 431 if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { 432 task = d.GetTask(c, task.ID) 433 } 434 return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil 435 }, checker.Equals, true) 436 437 // check container alias config 438 out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .NetworkSettings.Networks.test_swarm_br.Aliases}}", task.Status.ContainerStatus.ContainerID) 439 c.Assert(err, checker.IsNil, check.Commentf(out)) 440 441 // Make sure the only alias seen is the container-id 442 var aliases []string 443 c.Assert(json.Unmarshal([]byte(out), &aliases), checker.IsNil) 444 c.Assert(aliases, checker.HasLen, 1) 445 446 c.Assert(task.Status.ContainerStatus.ContainerID, checker.Contains, aliases[0]) 447 }