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