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