github.com/huiliang/nomad@v0.2.1-0.20151124023127-7a8b664699ff/client/driver/raw_exec_test.go (about) 1 package driver 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "path/filepath" 7 "reflect" 8 "runtime" 9 "testing" 10 "time" 11 12 "github.com/hashicorp/nomad/client/config" 13 "github.com/hashicorp/nomad/client/driver/environment" 14 "github.com/hashicorp/nomad/nomad/structs" 15 ) 16 17 func TestRawExecDriver_Fingerprint(t *testing.T) { 18 d := NewRawExecDriver(testDriverContext("")) 19 node := &structs.Node{ 20 Attributes: make(map[string]string), 21 } 22 23 // Disable raw exec. 24 cfg := &config.Config{Options: map[string]string{rawExecConfigOption: "false"}} 25 26 apply, err := d.Fingerprint(cfg, node) 27 if err != nil { 28 t.Fatalf("err: %v", err) 29 } 30 if apply { 31 t.Fatalf("should not apply") 32 } 33 if node.Attributes["driver.raw_exec"] != "" { 34 t.Fatalf("driver incorrectly enabled") 35 } 36 37 // Enable raw exec. 38 cfg.Options[rawExecConfigOption] = "true" 39 apply, err = d.Fingerprint(cfg, node) 40 if err != nil { 41 t.Fatalf("err: %v", err) 42 } 43 if !apply { 44 t.Fatalf("should apply") 45 } 46 if node.Attributes["driver.raw_exec"] != "1" { 47 t.Fatalf("driver not enabled") 48 } 49 } 50 51 func TestRawExecDriver_StartOpen_Wait(t *testing.T) { 52 task := &structs.Task{ 53 Name: "sleep", 54 Config: map[string]interface{}{ 55 "command": "/bin/sleep", 56 "args": []string{"1"}, 57 }, 58 Resources: basicResources, 59 } 60 driverCtx := testDriverContext(task.Name) 61 ctx := testDriverExecContext(task, driverCtx) 62 defer ctx.AllocDir.Destroy() 63 64 d := NewRawExecDriver(driverCtx) 65 handle, err := d.Start(ctx, task) 66 if err != nil { 67 t.Fatalf("err: %v", err) 68 } 69 if handle == nil { 70 t.Fatalf("missing handle") 71 } 72 73 // Attempt to open 74 handle2, err := d.Open(ctx, handle.ID()) 75 if err != nil { 76 t.Fatalf("err: %v", err) 77 } 78 if handle2 == nil { 79 t.Fatalf("missing handle") 80 } 81 82 // Task should terminate quickly 83 select { 84 case <-handle2.WaitCh(): 85 case <-time.After(2 * time.Second): 86 t.Fatalf("timeout") 87 } 88 } 89 90 func TestRawExecDriver_Start_Artifact_basic(t *testing.T) { 91 var file, checksum string 92 switch runtime.GOOS { 93 case "darwin": 94 file = "hi_darwin_amd64" 95 checksum = "md5:d7f2fdb13b36dcb7407721d78926b335" 96 default: 97 file = "hi_linux_amd64" 98 checksum = "md5:a9b14903a8942748e4f8474e11f795d3" 99 } 100 101 task := &structs.Task{ 102 Name: "sleep", 103 Config: map[string]interface{}{ 104 "artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file), 105 "command": filepath.Join("$NOMAD_TASK_DIR", file), 106 "checksum": checksum, 107 }, 108 Resources: basicResources, 109 } 110 driverCtx := testDriverContext(task.Name) 111 ctx := testDriverExecContext(task, driverCtx) 112 defer ctx.AllocDir.Destroy() 113 114 d := NewRawExecDriver(driverCtx) 115 handle, err := d.Start(ctx, task) 116 if err != nil { 117 t.Fatalf("err: %v", err) 118 } 119 if handle == nil { 120 t.Fatalf("missing handle") 121 } 122 123 // Attempt to open 124 handle2, err := d.Open(ctx, handle.ID()) 125 if err != nil { 126 t.Fatalf("err: %v", err) 127 } 128 if handle2 == nil { 129 t.Fatalf("missing handle") 130 } 131 132 // Task should terminate quickly 133 select { 134 case <-handle2.WaitCh(): 135 case <-time.After(5 * time.Second): 136 t.Fatalf("timeout") 137 } 138 } 139 140 func TestRawExecDriver_Start_Artifact_expanded(t *testing.T) { 141 var file string 142 switch runtime.GOOS { 143 case "darwin": 144 file = "hi_darwin_amd64" 145 default: 146 file = "hi_linux_amd64" 147 } 148 149 task := &structs.Task{ 150 Name: "sleep", 151 Config: map[string]interface{}{ 152 "artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file), 153 "command": "/bin/bash", 154 "args": []string{ 155 "-c", 156 fmt.Sprintf(`'/bin/sleep 1 && %s'`, filepath.Join("$NOMAD_TASK_DIR", file)), 157 }, 158 }, 159 Resources: basicResources, 160 } 161 driverCtx := testDriverContext(task.Name) 162 ctx := testDriverExecContext(task, driverCtx) 163 defer ctx.AllocDir.Destroy() 164 165 d := NewRawExecDriver(driverCtx) 166 handle, err := d.Start(ctx, task) 167 if err != nil { 168 t.Fatalf("err: %v", err) 169 } 170 if handle == nil { 171 t.Fatalf("missing handle") 172 } 173 174 // Attempt to open 175 handle2, err := d.Open(ctx, handle.ID()) 176 if err != nil { 177 t.Fatalf("err: %v", err) 178 } 179 if handle2 == nil { 180 t.Fatalf("missing handle") 181 } 182 183 // Task should terminate quickly 184 select { 185 case <-handle2.WaitCh(): 186 case <-time.After(5 * time.Second): 187 t.Fatalf("timeout") 188 } 189 } 190 191 func TestRawExecDriver_Start_Wait(t *testing.T) { 192 task := &structs.Task{ 193 Name: "sleep", 194 Config: map[string]interface{}{ 195 "command": "/bin/sleep", 196 "args": []string{"1"}, 197 }, 198 Resources: basicResources, 199 } 200 201 driverCtx := testDriverContext(task.Name) 202 ctx := testDriverExecContext(task, driverCtx) 203 defer ctx.AllocDir.Destroy() 204 205 d := NewRawExecDriver(driverCtx) 206 handle, err := d.Start(ctx, task) 207 if err != nil { 208 t.Fatalf("err: %v", err) 209 } 210 if handle == nil { 211 t.Fatalf("missing handle") 212 } 213 214 // Update should be a no-op 215 err = handle.Update(task) 216 if err != nil { 217 t.Fatalf("err: %v", err) 218 } 219 220 // Task should terminate quickly 221 select { 222 case res := <-handle.WaitCh(): 223 if !res.Successful() { 224 t.Fatalf("err: %v", res) 225 } 226 case <-time.After(2 * time.Second): 227 t.Fatalf("timeout") 228 } 229 } 230 231 func TestRawExecDriver_Start_Wait_AllocDir(t *testing.T) { 232 exp := []byte{'w', 'i', 'n'} 233 file := "output.txt" 234 task := &structs.Task{ 235 Name: "sleep", 236 Config: map[string]interface{}{ 237 "command": "/bin/bash", 238 "args": []string{ 239 "-c", 240 fmt.Sprintf(`sleep 1; echo -n %s > $%s/%s`, string(exp), environment.AllocDir, file), 241 }, 242 }, 243 Resources: basicResources, 244 } 245 246 driverCtx := testDriverContext(task.Name) 247 ctx := testDriverExecContext(task, driverCtx) 248 defer ctx.AllocDir.Destroy() 249 250 d := NewRawExecDriver(driverCtx) 251 handle, err := d.Start(ctx, task) 252 if err != nil { 253 t.Fatalf("err: %v", err) 254 } 255 if handle == nil { 256 t.Fatalf("missing handle") 257 } 258 259 // Task should terminate quickly 260 select { 261 case res := <-handle.WaitCh(): 262 if !res.Successful() { 263 t.Fatalf("err: %v", res) 264 } 265 case <-time.After(2 * time.Second): 266 t.Fatalf("timeout") 267 } 268 269 // Check that data was written to the shared alloc directory. 270 outputFile := filepath.Join(ctx.AllocDir.SharedDir, file) 271 act, err := ioutil.ReadFile(outputFile) 272 if err != nil { 273 t.Fatalf("Couldn't read expected output: %v", err) 274 } 275 276 if !reflect.DeepEqual(act, exp) { 277 t.Fatalf("Command outputted %v; want %v", act, exp) 278 } 279 } 280 281 func TestRawExecDriver_Start_Kill_Wait(t *testing.T) { 282 task := &structs.Task{ 283 Name: "sleep", 284 Config: map[string]interface{}{ 285 "command": "/bin/sleep", 286 "args": []string{"1"}, 287 }, 288 Resources: basicResources, 289 } 290 291 driverCtx := testDriverContext(task.Name) 292 ctx := testDriverExecContext(task, driverCtx) 293 defer ctx.AllocDir.Destroy() 294 295 d := NewRawExecDriver(driverCtx) 296 handle, err := d.Start(ctx, task) 297 if err != nil { 298 t.Fatalf("err: %v", err) 299 } 300 if handle == nil { 301 t.Fatalf("missing handle") 302 } 303 304 go func() { 305 time.Sleep(100 * time.Millisecond) 306 err := handle.Kill() 307 if err != nil { 308 t.Fatalf("err: %v", err) 309 } 310 }() 311 312 // Task should terminate quickly 313 select { 314 case res := <-handle.WaitCh(): 315 if res.Successful() { 316 t.Fatal("should err") 317 } 318 case <-time.After(2 * time.Second): 319 t.Fatalf("timeout") 320 } 321 }