github.com/jmitchell/nomad@v0.1.3-0.20151007230021-7ab84c2862d8/client/driver/docker_test.go (about) 1 package driver 2 3 import ( 4 "os/exec" 5 "testing" 6 "time" 7 8 "github.com/hashicorp/nomad/client/config" 9 "github.com/hashicorp/nomad/nomad/structs" 10 ) 11 12 // dockerLocated looks to see whether docker is available on this system before 13 // we try to run tests. We'll keep it simple and just check for the CLI. 14 func dockerLocated() bool { 15 _, err := exec.Command("docker", "-v").CombinedOutput() 16 return err == nil 17 } 18 19 func TestDockerDriver_Handle(t *testing.T) { 20 h := &dockerHandle{ 21 imageID: "imageid", 22 containerID: "containerid", 23 doneCh: make(chan struct{}), 24 waitCh: make(chan error, 1), 25 } 26 27 actual := h.ID() 28 expected := `DOCKER:{"ImageID":"imageid","ContainerID":"containerid"}` 29 if actual != expected { 30 t.Errorf("Expected `%s`, found `%s`", expected, actual) 31 } 32 } 33 34 // The fingerprinter test should always pass, even if Docker is not installed. 35 func TestDockerDriver_Fingerprint(t *testing.T) { 36 d := NewDockerDriver(testDriverContext("")) 37 node := &structs.Node{ 38 Attributes: make(map[string]string), 39 } 40 apply, err := d.Fingerprint(&config.Config{}, node) 41 if err != nil { 42 t.Fatalf("err: %v", err) 43 } 44 if apply != dockerLocated() { 45 t.Fatalf("Fingerprinter should detect Docker when it is installed") 46 } 47 if node.Attributes["driver.docker"] == "" { 48 t.Log("Docker not found. The remainder of the docker tests will be skipped.") 49 } 50 t.Logf("Found docker version %s", node.Attributes["driver.docker.version"]) 51 } 52 53 func TestDockerDriver_StartOpen_Wait(t *testing.T) { 54 if !dockerLocated() { 55 t.SkipNow() 56 } 57 58 task := &structs.Task{ 59 Name: "python-demo", 60 Config: map[string]string{ 61 "image": "redis", 62 }, 63 Resources: basicResources, 64 } 65 66 driverCtx := testDriverContext(task.Name) 67 ctx := testDriverExecContext(task, driverCtx) 68 defer ctx.AllocDir.Destroy() 69 d := NewDockerDriver(driverCtx) 70 71 handle, err := d.Start(ctx, task) 72 if err != nil { 73 t.Fatalf("err: %v", err) 74 } 75 if handle == nil { 76 t.Fatalf("missing handle") 77 } 78 defer handle.Kill() 79 80 // Attempt to open 81 handle2, err := d.Open(ctx, handle.ID()) 82 if err != nil { 83 t.Fatalf("err: %v", err) 84 } 85 if handle2 == nil { 86 t.Fatalf("missing handle") 87 } 88 } 89 90 func TestDockerDriver_Start_Wait(t *testing.T) { 91 if !dockerLocated() { 92 t.SkipNow() 93 } 94 95 task := &structs.Task{ 96 Name: "python-demo", 97 Config: map[string]string{ 98 "image": "redis", 99 "command": "redis-server -v", 100 }, 101 Resources: &structs.Resources{ 102 MemoryMB: 256, 103 CPU: 512, 104 }, 105 } 106 107 driverCtx := testDriverContext(task.Name) 108 ctx := testDriverExecContext(task, driverCtx) 109 defer ctx.AllocDir.Destroy() 110 d := NewDockerDriver(driverCtx) 111 112 handle, err := d.Start(ctx, task) 113 if err != nil { 114 t.Fatalf("err: %v", err) 115 } 116 if handle == nil { 117 t.Fatalf("missing handle") 118 } 119 defer handle.Kill() 120 121 // Update should be a no-op 122 err = handle.Update(task) 123 if err != nil { 124 t.Fatalf("err: %v", err) 125 } 126 127 select { 128 case err := <-handle.WaitCh(): 129 if err != nil { 130 t.Fatalf("err: %v", err) 131 } 132 case <-time.After(5 * time.Second): 133 t.Fatalf("timeout") 134 } 135 } 136 137 func TestDockerDriver_Start_Kill_Wait(t *testing.T) { 138 if !dockerLocated() { 139 t.SkipNow() 140 } 141 142 task := &structs.Task{ 143 Name: "python-demo", 144 Config: map[string]string{ 145 "image": "redis", 146 "command": "sleep 10", 147 }, 148 Resources: basicResources, 149 } 150 151 driverCtx := testDriverContext(task.Name) 152 ctx := testDriverExecContext(task, driverCtx) 153 defer ctx.AllocDir.Destroy() 154 d := NewDockerDriver(driverCtx) 155 156 handle, err := d.Start(ctx, task) 157 if err != nil { 158 t.Fatalf("err: %v", err) 159 } 160 if handle == nil { 161 t.Fatalf("missing handle") 162 } 163 defer handle.Kill() 164 165 go func() { 166 time.Sleep(100 * time.Millisecond) 167 err := handle.Kill() 168 if err != nil { 169 t.Fatalf("err: %v", err) 170 } 171 }() 172 173 select { 174 case err := <-handle.WaitCh(): 175 if err == nil { 176 t.Fatalf("should err: %v", err) 177 } 178 case <-time.After(10 * time.Second): 179 t.Fatalf("timeout") 180 } 181 } 182 183 func taskTemplate() *structs.Task { 184 return &structs.Task{ 185 Config: map[string]string{ 186 "image": "redis", 187 }, 188 Resources: &structs.Resources{ 189 MemoryMB: 256, 190 CPU: 512, 191 Networks: []*structs.NetworkResource{ 192 &structs.NetworkResource{ 193 IP: "127.0.0.1", 194 ReservedPorts: []int{11110}, 195 DynamicPorts: []string{"REDIS"}, 196 }, 197 }, 198 }, 199 } 200 } 201 202 func TestDocker_StartN(t *testing.T) { 203 if !dockerLocated() { 204 t.SkipNow() 205 } 206 207 task1 := taskTemplate() 208 task1.Resources.Networks[0].ReservedPorts[0] = 11111 209 210 task2 := taskTemplate() 211 task2.Resources.Networks[0].ReservedPorts[0] = 22222 212 213 task3 := taskTemplate() 214 task3.Resources.Networks[0].ReservedPorts[0] = 33333 215 216 taskList := []*structs.Task{task1, task2, task3} 217 218 handles := make([]DriverHandle, len(taskList)) 219 220 t.Logf("==> Starting %d tasks", len(taskList)) 221 222 // Let's spin up a bunch of things 223 var err error 224 for idx, task := range taskList { 225 driverCtx := testDriverContext(task.Name) 226 ctx := testDriverExecContext(task, driverCtx) 227 defer ctx.AllocDir.Destroy() 228 d := NewDockerDriver(driverCtx) 229 230 handles[idx], err = d.Start(ctx, task) 231 if err != nil { 232 t.Errorf("Failed starting task #%d: %s", idx+1, err) 233 } 234 } 235 236 t.Log("==> All tasks are started. Terminating...") 237 238 for idx, handle := range handles { 239 err := handle.Kill() 240 if err != nil { 241 t.Errorf("Failed stopping task #%d: %s", idx+1, err) 242 } 243 } 244 245 t.Log("==> Test complete!") 246 } 247 248 func TestDocker_StartNVersions(t *testing.T) { 249 if !dockerLocated() { 250 t.SkipNow() 251 } 252 253 task1 := taskTemplate() 254 task1.Config["image"] = "redis" 255 task1.Resources.Networks[0].ReservedPorts[0] = 11111 256 257 task2 := taskTemplate() 258 task2.Config["image"] = "redis:latest" 259 task2.Resources.Networks[0].ReservedPorts[0] = 22222 260 261 task3 := taskTemplate() 262 task3.Config["image"] = "redis:3.0" 263 task3.Resources.Networks[0].ReservedPorts[0] = 33333 264 265 taskList := []*structs.Task{task1, task2, task3} 266 267 handles := make([]DriverHandle, len(taskList)) 268 269 t.Logf("==> Starting %d tasks", len(taskList)) 270 271 // Let's spin up a bunch of things 272 var err error 273 for idx, task := range taskList { 274 driverCtx := testDriverContext(task.Name) 275 ctx := testDriverExecContext(task, driverCtx) 276 defer ctx.AllocDir.Destroy() 277 d := NewDockerDriver(driverCtx) 278 279 handles[idx], err = d.Start(ctx, task) 280 if err != nil { 281 t.Errorf("Failed starting task #%d: %s", idx+1, err) 282 } 283 } 284 285 t.Log("==> All tasks are started. Terminating...") 286 287 for idx, handle := range handles { 288 err := handle.Kill() 289 if err != nil { 290 t.Errorf("Failed stopping task #%d: %s", idx+1, err) 291 } 292 } 293 294 t.Log("==> Test complete!") 295 } 296 297 func TestDockerHostNet(t *testing.T) { 298 if !dockerLocated() { 299 t.SkipNow() 300 } 301 302 task := &structs.Task{ 303 Config: map[string]string{ 304 "image": "redis", 305 "network_mode": "host", 306 }, 307 Resources: &structs.Resources{ 308 MemoryMB: 256, 309 CPU: 512, 310 }, 311 } 312 driverCtx := testDriverContext(task.Name) 313 ctx := testDriverExecContext(task, driverCtx) 314 defer ctx.AllocDir.Destroy() 315 d := NewDockerDriver(driverCtx) 316 317 handle, err := d.Start(ctx, task) 318 if err != nil { 319 t.Fatalf("err: %v", err) 320 } 321 if handle == nil { 322 t.Fatalf("missing handle") 323 } 324 defer handle.Kill() 325 }