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