github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/driver/java_test.go (about) 1 package driver 2 3 import ( 4 "os" 5 "os/exec" 6 "path/filepath" 7 "runtime" 8 "strings" 9 "syscall" 10 "testing" 11 "time" 12 13 "github.com/hashicorp/nomad/client/config" 14 "github.com/hashicorp/nomad/nomad/structs" 15 "github.com/hashicorp/nomad/testutil" 16 17 ctestutils "github.com/hashicorp/nomad/client/testutil" 18 ) 19 20 var ( 21 osJavaDriverSupport = map[string]bool{ 22 "linux": true, 23 } 24 ) 25 26 // javaLocated checks whether java is installed so we can run java stuff. 27 func javaLocated() bool { 28 _, err := exec.Command("java", "-version").CombinedOutput() 29 return err == nil 30 } 31 32 // The fingerprinter test should always pass, even if Java is not installed. 33 func TestJavaDriver_Fingerprint(t *testing.T) { 34 if !testutil.IsTravis() { 35 t.Parallel() 36 } 37 ctestutils.JavaCompatible(t) 38 task := &structs.Task{ 39 Name: "foo", 40 Driver: "java", 41 Resources: structs.DefaultResources(), 42 } 43 ctx := testDriverContexts(t, task) 44 defer ctx.AllocDir.Destroy() 45 d := NewJavaDriver(ctx.DriverCtx) 46 node := &structs.Node{ 47 Attributes: map[string]string{ 48 "unique.cgroup.mountpoint": "/sys/fs/cgroups", 49 }, 50 } 51 apply, err := d.Fingerprint(&config.Config{}, node) 52 if err != nil { 53 t.Fatalf("err: %v", err) 54 } 55 if apply != javaLocated() { 56 t.Fatalf("Fingerprinter should detect Java when it is installed") 57 } 58 if node.Attributes["driver.java"] != "1" { 59 if v, ok := osJavaDriverSupport[runtime.GOOS]; v && ok { 60 t.Fatalf("missing java driver") 61 } else { 62 t.Skipf("missing java driver, no OS support") 63 } 64 } 65 for _, key := range []string{"driver.java.version", "driver.java.runtime", "driver.java.vm"} { 66 if node.Attributes[key] == "" { 67 t.Fatalf("missing driver key (%s)", key) 68 } 69 } 70 } 71 72 func TestJavaDriver_StartOpen_Wait(t *testing.T) { 73 if !testutil.IsTravis() { 74 t.Parallel() 75 } 76 if !javaLocated() { 77 t.Skip("Java not found; skipping") 78 } 79 80 ctestutils.JavaCompatible(t) 81 task := &structs.Task{ 82 Name: "demo-app", 83 Driver: "java", 84 Config: map[string]interface{}{ 85 "jar_path": "demoapp.jar", 86 "jvm_options": []string{"-Xmx64m", "-Xms32m"}, 87 }, 88 LogConfig: &structs.LogConfig{ 89 MaxFiles: 10, 90 MaxFileSizeMB: 10, 91 }, 92 Resources: basicResources, 93 } 94 95 ctx := testDriverContexts(t, task) 96 defer ctx.AllocDir.Destroy() 97 d := NewJavaDriver(ctx.DriverCtx) 98 99 // Copy the test jar into the task's directory 100 dst := ctx.ExecCtx.TaskDir.Dir 101 copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t) 102 103 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 104 t.Fatalf("prestart err: %v", err) 105 } 106 resp, err := d.Start(ctx.ExecCtx, task) 107 if err != nil { 108 t.Fatalf("err: %v", err) 109 } 110 111 // Attempt to open 112 handle2, err := d.Open(ctx.ExecCtx, resp.Handle.ID()) 113 if err != nil { 114 t.Fatalf("err: %v", err) 115 } 116 if handle2 == nil { 117 t.Fatalf("missing handle") 118 } 119 120 time.Sleep(2 * time.Second) 121 122 // There is a race condition between the handle waiting and killing. One 123 // will return an error. 124 resp.Handle.Kill() 125 handle2.Kill() 126 } 127 128 func TestJavaDriver_Start_Wait(t *testing.T) { 129 if !testutil.IsTravis() { 130 t.Parallel() 131 } 132 if !javaLocated() { 133 t.Skip("Java not found; skipping") 134 } 135 136 ctestutils.JavaCompatible(t) 137 task := &structs.Task{ 138 Name: "demo-app", 139 Driver: "java", 140 Config: map[string]interface{}{ 141 "jar_path": "demoapp.jar", 142 "args": []string{"1"}, 143 }, 144 LogConfig: &structs.LogConfig{ 145 MaxFiles: 10, 146 MaxFileSizeMB: 10, 147 }, 148 Resources: basicResources, 149 } 150 151 ctx := testDriverContexts(t, task) 152 defer ctx.AllocDir.Destroy() 153 d := NewJavaDriver(ctx.DriverCtx) 154 155 // Copy the test jar into the task's directory 156 dst := ctx.ExecCtx.TaskDir.Dir 157 copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t) 158 159 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 160 t.Fatalf("prestart err: %v", err) 161 } 162 resp, err := d.Start(ctx.ExecCtx, task) 163 if err != nil { 164 t.Fatalf("err: %v", err) 165 } 166 167 // Task should terminate after 1 seconds 168 select { 169 case res := <-resp.Handle.WaitCh(): 170 if !res.Successful() { 171 t.Fatalf("err: %v", res.String()) 172 } 173 case <-time.After(5 * time.Second): 174 t.Fatalf("timeout") 175 } 176 177 // Get the stdout of the process and assrt that it's not empty 178 stdout := filepath.Join(ctx.ExecCtx.TaskDir.LogDir, "demo-app.stdout.0") 179 fInfo, err := os.Stat(stdout) 180 if err != nil { 181 t.Fatalf("failed to get stdout of process: %v", err) 182 } 183 if fInfo.Size() == 0 { 184 t.Fatalf("stdout of process is empty") 185 } 186 187 // need to kill long lived process 188 err = resp.Handle.Kill() 189 if err != nil { 190 t.Fatalf("Error: %s", err) 191 } 192 } 193 194 func TestJavaDriver_Start_Kill_Wait(t *testing.T) { 195 if !testutil.IsTravis() { 196 t.Parallel() 197 } 198 if !javaLocated() { 199 t.Skip("Java not found; skipping") 200 } 201 202 ctestutils.JavaCompatible(t) 203 task := &structs.Task{ 204 Name: "demo-app", 205 Driver: "java", 206 Config: map[string]interface{}{ 207 "jar_path": "demoapp.jar", 208 }, 209 LogConfig: &structs.LogConfig{ 210 MaxFiles: 10, 211 MaxFileSizeMB: 10, 212 }, 213 Resources: basicResources, 214 } 215 216 ctx := testDriverContexts(t, task) 217 defer ctx.AllocDir.Destroy() 218 d := NewJavaDriver(ctx.DriverCtx) 219 220 // Copy the test jar into the task's directory 221 dst := ctx.ExecCtx.TaskDir.Dir 222 copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t) 223 224 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 225 t.Fatalf("prestart err: %v", err) 226 } 227 resp, err := d.Start(ctx.ExecCtx, task) 228 if err != nil { 229 t.Fatalf("err: %v", err) 230 } 231 232 go func() { 233 time.Sleep(100 * time.Millisecond) 234 err := resp.Handle.Kill() 235 if err != nil { 236 t.Fatalf("err: %v", err) 237 } 238 }() 239 240 // Task should terminate quickly 241 select { 242 case res := <-resp.Handle.WaitCh(): 243 if res.Successful() { 244 t.Fatal("should err") 245 } 246 case <-time.After(time.Duration(testutil.TestMultiplier()*10) * time.Second): 247 t.Fatalf("timeout") 248 249 // Need to kill long lived process 250 if err = resp.Handle.Kill(); err != nil { 251 t.Fatalf("Error: %s", err) 252 } 253 } 254 } 255 256 func TestJavaDriver_Signal(t *testing.T) { 257 if !testutil.IsTravis() { 258 t.Parallel() 259 } 260 if !javaLocated() { 261 t.Skip("Java not found; skipping") 262 } 263 264 ctestutils.JavaCompatible(t) 265 task := &structs.Task{ 266 Name: "demo-app", 267 Driver: "java", 268 Config: map[string]interface{}{ 269 "jar_path": "demoapp.jar", 270 }, 271 LogConfig: &structs.LogConfig{ 272 MaxFiles: 10, 273 MaxFileSizeMB: 10, 274 }, 275 Resources: basicResources, 276 } 277 278 ctx := testDriverContexts(t, task) 279 defer ctx.AllocDir.Destroy() 280 d := NewJavaDriver(ctx.DriverCtx) 281 282 // Copy the test jar into the task's directory 283 dst := ctx.ExecCtx.TaskDir.Dir 284 copyFile("./test-resources/java/demoapp.jar", filepath.Join(dst, "demoapp.jar"), t) 285 286 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 287 t.Fatalf("prestart err: %v", err) 288 } 289 resp, err := d.Start(ctx.ExecCtx, task) 290 if err != nil { 291 t.Fatalf("err: %v", err) 292 } 293 294 go func() { 295 time.Sleep(100 * time.Millisecond) 296 err := resp.Handle.Signal(syscall.SIGHUP) 297 if err != nil { 298 t.Fatalf("err: %v", err) 299 } 300 }() 301 302 // Task should terminate quickly 303 select { 304 case res := <-resp.Handle.WaitCh(): 305 if res.Successful() { 306 t.Fatal("should err") 307 } 308 case <-time.After(time.Duration(testutil.TestMultiplier()*10) * time.Second): 309 t.Fatalf("timeout") 310 311 // Need to kill long lived process 312 if err = resp.Handle.Kill(); err != nil { 313 t.Fatalf("Error: %s", err) 314 } 315 } 316 } 317 318 func TestJavaDriver_User(t *testing.T) { 319 if !testutil.IsTravis() { 320 t.Parallel() 321 } 322 if !javaLocated() { 323 t.Skip("Java not found; skipping") 324 } 325 if runtime.GOOS != "linux" { 326 t.Skip("Linux only test") 327 } 328 329 ctestutils.JavaCompatible(t) 330 task := &structs.Task{ 331 Name: "demo-app", 332 Driver: "java", 333 User: "alice", 334 Config: map[string]interface{}{ 335 "jar_path": "demoapp.jar", 336 }, 337 LogConfig: &structs.LogConfig{ 338 MaxFiles: 10, 339 MaxFileSizeMB: 10, 340 }, 341 Resources: basicResources, 342 } 343 344 ctx := testDriverContexts(t, task) 345 defer ctx.AllocDir.Destroy() 346 d := NewJavaDriver(ctx.DriverCtx) 347 348 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 349 t.Fatalf("prestart err: %v", err) 350 } 351 resp, err := d.Start(ctx.ExecCtx, task) 352 if err == nil { 353 resp.Handle.Kill() 354 t.Fatalf("Should've failed") 355 } 356 msg := "user alice" 357 if !strings.Contains(err.Error(), msg) { 358 t.Fatalf("Expecting '%v' in '%v'", msg, err) 359 } 360 } 361 362 func TestJavaDriver_Start_Wait_Class(t *testing.T) { 363 if !testutil.IsTravis() { 364 t.Parallel() 365 } 366 if !javaLocated() { 367 t.Skip("Java not found; skipping") 368 } 369 370 ctestutils.JavaCompatible(t) 371 task := &structs.Task{ 372 Name: "demo-app", 373 Driver: "java", 374 Config: map[string]interface{}{ 375 "class_path": "${NOMAD_TASK_DIR}", 376 "class": "Hello", 377 "args": []string{"1"}, 378 }, 379 LogConfig: &structs.LogConfig{ 380 MaxFiles: 10, 381 MaxFileSizeMB: 10, 382 }, 383 Resources: basicResources, 384 } 385 386 ctx := testDriverContexts(t, task) 387 defer ctx.AllocDir.Destroy() 388 d := NewJavaDriver(ctx.DriverCtx) 389 390 // Copy the test jar into the task's directory 391 dst := ctx.ExecCtx.TaskDir.LocalDir 392 copyFile("./test-resources/java/Hello.class", filepath.Join(dst, "Hello.class"), t) 393 394 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 395 t.Fatalf("prestart err: %v", err) 396 } 397 resp, err := d.Start(ctx.ExecCtx, task) 398 if err != nil { 399 t.Fatalf("err: %v", err) 400 } 401 402 // Task should terminate after 1 seconds 403 select { 404 case res := <-resp.Handle.WaitCh(): 405 if !res.Successful() { 406 t.Fatalf("err: %v", res.String()) 407 } 408 case <-time.After(5 * time.Second): 409 t.Fatalf("timeout") 410 } 411 412 // Get the stdout of the process and assrt that it's not empty 413 stdout := filepath.Join(ctx.ExecCtx.TaskDir.LogDir, "demo-app.stdout.0") 414 fInfo, err := os.Stat(stdout) 415 if err != nil { 416 t.Fatalf("failed to get stdout of process: %v", err) 417 } 418 if fInfo.Size() == 0 { 419 t.Fatalf("stdout of process is empty") 420 } 421 422 // need to kill long lived process 423 if err := resp.Handle.Kill(); err != nil { 424 t.Fatalf("Error: %s", err) 425 } 426 }