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