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