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