github.com/jmitchell/nomad@v0.1.3-0.20151007230021-7ab84c2862d8/client/driver/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/allocdir" 12 "github.com/hashicorp/nomad/client/config" 13 "github.com/hashicorp/nomad/client/driver/environment" 14 "github.com/hashicorp/nomad/nomad/structs" 15 16 ctestutils "github.com/hashicorp/nomad/client/testutil" 17 ) 18 19 func TestExecDriver_Fingerprint(t *testing.T) { 20 ctestutils.ExecCompatible(t) 21 d := NewExecDriver(testDriverContext("")) 22 node := &structs.Node{ 23 Attributes: make(map[string]string), 24 } 25 apply, err := d.Fingerprint(&config.Config{}, node) 26 if err != nil { 27 t.Fatalf("err: %v", err) 28 } 29 if !apply { 30 t.Fatalf("should apply") 31 } 32 if node.Attributes["driver.exec"] == "" { 33 t.Fatalf("missing driver") 34 } 35 } 36 37 /* 38 TODO: This test is disabled til a follow-up api changes the restore state interface. 39 The driver/executor interface will be changed from Open to Cleanup, in which 40 clean-up tears down previous allocs. 41 42 func TestExecDriver_StartOpen_Wait(t *testing.T) { 43 ctestutils.ExecCompatible(t) 44 task := &structs.Task{ 45 Name: "sleep", 46 Config: map[string]string{ 47 "command": "/bin/sleep", 48 "args": "5", 49 }, 50 Resources: basicResources, 51 } 52 53 driverCtx := testDriverContext(task.Name) 54 ctx := testDriverExecContext(task, driverCtx) 55 defer ctx.AllocDir.Destroy() 56 d := NewExecDriver(driverCtx) 57 58 if task.Resources == nil { 59 task.Resources = &structs.Resources{} 60 } 61 task.Resources.CPU = 0.5 62 task.Resources.MemoryMB = 2 63 64 handle, err := d.Start(ctx, task) 65 if err != nil { 66 t.Fatalf("err: %v", err) 67 } 68 if handle == nil { 69 t.Fatalf("missing handle") 70 } 71 72 // Attempt to open 73 handle2, err := d.Open(ctx, handle.ID()) 74 if err != nil { 75 t.Fatalf("err: %v", err) 76 } 77 if handle2 == nil { 78 t.Fatalf("missing handle") 79 } 80 } 81 */ 82 83 func TestExecDriver_Start_Wait(t *testing.T) { 84 ctestutils.ExecCompatible(t) 85 task := &structs.Task{ 86 Name: "sleep", 87 Config: map[string]string{ 88 "command": "/bin/sleep", 89 "args": "1", 90 }, 91 Resources: basicResources, 92 } 93 94 driverCtx := testDriverContext(task.Name) 95 ctx := testDriverExecContext(task, driverCtx) 96 defer ctx.AllocDir.Destroy() 97 d := NewExecDriver(driverCtx) 98 99 handle, err := d.Start(ctx, task) 100 if err != nil { 101 t.Fatalf("err: %v", err) 102 } 103 if handle == nil { 104 t.Fatalf("missing handle") 105 } 106 107 // Update should be a no-op 108 err = handle.Update(task) 109 if err != nil { 110 t.Fatalf("err: %v", err) 111 } 112 113 // Task should terminate quickly 114 select { 115 case err := <-handle.WaitCh(): 116 if err != nil { 117 t.Fatalf("err: %v", err) 118 } 119 case <-time.After(2 * time.Second): 120 t.Fatalf("timeout") 121 } 122 } 123 124 func TestExecDriver_Start_Wait_AllocDir(t *testing.T) { 125 ctestutils.ExecCompatible(t) 126 127 exp := []byte{'w', 'i', 'n'} 128 file := "output.txt" 129 task := &structs.Task{ 130 Name: "sleep", 131 Config: map[string]string{ 132 "command": "/bin/bash", 133 "args": fmt.Sprintf("-c \"sleep 1; echo -n %s > $%s/%s\"", string(exp), environment.AllocDir, file), 134 }, 135 Resources: basicResources, 136 } 137 138 driverCtx := testDriverContext(task.Name) 139 ctx := testDriverExecContext(task, driverCtx) 140 defer ctx.AllocDir.Destroy() 141 d := NewExecDriver(driverCtx) 142 143 handle, err := d.Start(ctx, task) 144 if err != nil { 145 t.Fatalf("err: %v", err) 146 } 147 if handle == nil { 148 t.Fatalf("missing handle") 149 } 150 151 // Task should terminate quickly 152 select { 153 case err := <-handle.WaitCh(): 154 if err != nil { 155 t.Fatalf("err: %v", err) 156 } 157 case <-time.After(2 * time.Second): 158 t.Fatalf("timeout") 159 } 160 161 // Check that data was written to the shared alloc directory. 162 outputFile := filepath.Join(ctx.AllocDir.AllocDir, allocdir.SharedAllocName, file) 163 act, err := ioutil.ReadFile(outputFile) 164 if err != nil { 165 t.Fatalf("Couldn't read expected output: %v", err) 166 } 167 168 if !reflect.DeepEqual(act, exp) { 169 t.Fatalf("Command outputted %v; want %v", act, exp) 170 } 171 } 172 173 func TestExecDriver_Start_Kill_Wait(t *testing.T) { 174 ctestutils.ExecCompatible(t) 175 task := &structs.Task{ 176 Name: "sleep", 177 Config: map[string]string{ 178 "command": "/bin/sleep", 179 "args": "1", 180 }, 181 Resources: basicResources, 182 } 183 184 driverCtx := testDriverContext(task.Name) 185 ctx := testDriverExecContext(task, driverCtx) 186 defer ctx.AllocDir.Destroy() 187 d := NewExecDriver(driverCtx) 188 189 handle, err := d.Start(ctx, task) 190 if err != nil { 191 t.Fatalf("err: %v", err) 192 } 193 if handle == nil { 194 t.Fatalf("missing handle") 195 } 196 197 go func() { 198 time.Sleep(100 * time.Millisecond) 199 err := handle.Kill() 200 if err != nil { 201 t.Fatalf("err: %v", err) 202 } 203 }() 204 205 // Task should terminate quickly 206 select { 207 case err := <-handle.WaitCh(): 208 if err == nil { 209 t.Fatal("should err") 210 } 211 case <-time.After(2 * time.Second): 212 t.Fatalf("timeout") 213 } 214 }