github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/client/driver/raw_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/environment" 13 "github.com/hashicorp/nomad/nomad/structs" 14 ) 15 16 func TestRawExecDriver_Fingerprint(t *testing.T) { 17 d := NewRawExecDriver(testDriverContext("")) 18 node := &structs.Node{ 19 Attributes: make(map[string]string), 20 } 21 22 // Disable raw exec. 23 cfg := &config.Config{Options: map[string]string{rawExecConfigOption: "false"}} 24 25 apply, err := d.Fingerprint(cfg, node) 26 if err != nil { 27 t.Fatalf("err: %v", err) 28 } 29 if apply { 30 t.Fatalf("should not apply") 31 } 32 if node.Attributes["driver.raw_exec"] != "" { 33 t.Fatalf("driver incorrectly enabled") 34 } 35 36 // Enable raw exec. 37 cfg.Options[rawExecConfigOption] = "true" 38 apply, err = d.Fingerprint(cfg, node) 39 if err != nil { 40 t.Fatalf("err: %v", err) 41 } 42 if !apply { 43 t.Fatalf("should apply") 44 } 45 if node.Attributes["driver.raw_exec"] != "1" { 46 t.Fatalf("driver not enabled") 47 } 48 } 49 50 func TestRawExecDriver_StartOpen_Wait(t *testing.T) { 51 task := &structs.Task{ 52 Name: "sleep", 53 Config: map[string]string{ 54 "command": "/bin/sleep", 55 "args": "1", 56 }, 57 } 58 driverCtx := testDriverContext(task.Name) 59 ctx := testDriverExecContext(task, driverCtx) 60 defer ctx.AllocDir.Destroy() 61 62 d := NewRawExecDriver(driverCtx) 63 handle, err := d.Start(ctx, task) 64 if err != nil { 65 t.Fatalf("err: %v", err) 66 } 67 if handle == nil { 68 t.Fatalf("missing handle") 69 } 70 71 // Attempt to open 72 handle2, err := d.Open(ctx, handle.ID()) 73 if err != nil { 74 t.Fatalf("err: %v", err) 75 } 76 if handle2 == nil { 77 t.Fatalf("missing handle") 78 } 79 80 // Task should terminate quickly 81 select { 82 case <-handle2.WaitCh(): 83 case <-time.After(2 * time.Second): 84 t.Fatalf("timeout") 85 } 86 87 // Check they are both tracking the same PID. 88 pid1 := handle.(*rawExecHandle).proc.Pid 89 pid2 := handle2.(*rawExecHandle).proc.Pid 90 if pid1 != pid2 { 91 t.Fatalf("tracking incorrect Pid; %v != %v", pid1, pid2) 92 } 93 } 94 95 func TestRawExecDriver_Start_Wait(t *testing.T) { 96 task := &structs.Task{ 97 Name: "sleep", 98 Config: map[string]string{ 99 "command": "/bin/sleep", 100 "args": "1", 101 }, 102 } 103 104 driverCtx := testDriverContext(task.Name) 105 ctx := testDriverExecContext(task, driverCtx) 106 defer ctx.AllocDir.Destroy() 107 108 d := NewRawExecDriver(driverCtx) 109 handle, err := d.Start(ctx, task) 110 if err != nil { 111 t.Fatalf("err: %v", err) 112 } 113 if handle == nil { 114 t.Fatalf("missing handle") 115 } 116 117 // Update should be a no-op 118 err = handle.Update(task) 119 if err != nil { 120 t.Fatalf("err: %v", err) 121 } 122 123 // Task should terminate quickly 124 select { 125 case err := <-handle.WaitCh(): 126 if err != nil { 127 t.Fatalf("err: %v", err) 128 } 129 case <-time.After(2 * time.Second): 130 t.Fatalf("timeout") 131 } 132 } 133 134 func TestRawExecDriver_Start_Wait_AllocDir(t *testing.T) { 135 exp := []byte{'w', 'i', 'n'} 136 file := "output.txt" 137 task := &structs.Task{ 138 Name: "sleep", 139 Config: map[string]string{ 140 "command": "/bin/bash", 141 "args": fmt.Sprintf(`-c "sleep 1; echo -n %s > $%s/%s"`, string(exp), environment.AllocDir, file), 142 }, 143 } 144 145 driverCtx := testDriverContext(task.Name) 146 ctx := testDriverExecContext(task, driverCtx) 147 defer ctx.AllocDir.Destroy() 148 149 d := NewRawExecDriver(driverCtx) 150 handle, err := d.Start(ctx, task) 151 if err != nil { 152 t.Fatalf("err: %v", err) 153 } 154 if handle == nil { 155 t.Fatalf("missing handle") 156 } 157 158 // Task should terminate quickly 159 select { 160 case err := <-handle.WaitCh(): 161 if err != nil { 162 t.Fatalf("err: %v", err) 163 } 164 case <-time.After(2 * time.Second): 165 t.Fatalf("timeout") 166 } 167 168 // Check that data was written to the shared alloc directory. 169 outputFile := filepath.Join(ctx.AllocDir.SharedDir, file) 170 act, err := ioutil.ReadFile(outputFile) 171 if err != nil { 172 t.Fatalf("Couldn't read expected output: %v", err) 173 } 174 175 if !reflect.DeepEqual(act, exp) { 176 t.Fatalf("Command outputted %v; want %v", act, exp) 177 } 178 } 179 180 func TestRawExecDriver_Start_Kill_Wait(t *testing.T) { 181 task := &structs.Task{ 182 Name: "sleep", 183 Config: map[string]string{ 184 "command": "/bin/sleep", 185 "args": "1", 186 }, 187 } 188 189 driverCtx := testDriverContext(task.Name) 190 ctx := testDriverExecContext(task, driverCtx) 191 defer ctx.AllocDir.Destroy() 192 193 d := NewRawExecDriver(driverCtx) 194 handle, err := d.Start(ctx, task) 195 if err != nil { 196 t.Fatalf("err: %v", err) 197 } 198 if handle == nil { 199 t.Fatalf("missing handle") 200 } 201 202 go func() { 203 time.Sleep(100 * time.Millisecond) 204 err := handle.Kill() 205 if err != nil { 206 t.Fatalf("err: %v", err) 207 } 208 }() 209 210 // Task should terminate quickly 211 select { 212 case err := <-handle.WaitCh(): 213 if err == nil { 214 t.Fatal("should err") 215 } 216 case <-time.After(2 * time.Second): 217 t.Fatalf("timeout") 218 } 219 }