github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/client/executor/exec_linux_test.go (about) 1 package executor 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "testing" 9 "time" 10 11 "github.com/hashicorp/nomad/client/allocdir" 12 "github.com/hashicorp/nomad/nomad/mock" 13 "github.com/hashicorp/nomad/nomad/structs" 14 15 ctestutil "github.com/hashicorp/nomad/client/testutil" 16 ) 17 18 var ( 19 constraint = &structs.Resources{ 20 CPU: 250, 21 MemoryMB: 256, 22 Networks: []*structs.NetworkResource{ 23 &structs.NetworkResource{ 24 MBits: 50, 25 DynamicPorts: []string{"http"}, 26 }, 27 }, 28 } 29 ) 30 31 func mockAllocDir(t *testing.T) (string, *allocdir.AllocDir) { 32 alloc := mock.Alloc() 33 task := alloc.Job.TaskGroups[0].Tasks[0] 34 35 allocDir := allocdir.NewAllocDir(filepath.Join(os.TempDir(), alloc.ID)) 36 if err := allocDir.Build([]*structs.Task{task}); err != nil { 37 t.Fatalf("allocDir.Build() failed: %v", err) 38 } 39 40 return task.Name, allocDir 41 } 42 43 func TestExecutorLinux_Start_Invalid(t *testing.T) { 44 ctestutil.ExecCompatible(t) 45 invalid := "/bin/foobar" 46 e := Command(invalid, "1") 47 48 if err := e.Limit(constraint); err != nil { 49 t.Fatalf("Limit() failed: %v", err) 50 } 51 52 task, alloc := mockAllocDir(t) 53 defer alloc.Destroy() 54 if err := e.ConfigureTaskDir(task, alloc); err != nil { 55 t.Fatalf("ConfigureTaskDir(%v, %v) failed: %v", task, alloc, err) 56 } 57 58 if err := e.Start(); err == nil { 59 t.Fatalf("Start(%v) should have failed", invalid) 60 } 61 } 62 63 func TestExecutorLinux_Start_Wait_Failure_Code(t *testing.T) { 64 ctestutil.ExecCompatible(t) 65 e := Command("/bin/date", "-invalid") 66 67 if err := e.Limit(constraint); err != nil { 68 t.Fatalf("Limit() failed: %v", err) 69 } 70 71 task, alloc := mockAllocDir(t) 72 defer alloc.Destroy() 73 if err := e.ConfigureTaskDir(task, alloc); err != nil { 74 t.Fatalf("ConfigureTaskDir(%v, %v) failed: %v", task, alloc, err) 75 } 76 77 if err := e.Start(); err != nil { 78 t.Fatalf("Start() failed: %v", err) 79 } 80 81 if err := e.Wait(); err == nil { 82 t.Fatalf("Wait() should have failed") 83 } 84 } 85 86 func TestExecutorLinux_Start_Wait(t *testing.T) { 87 ctestutil.ExecCompatible(t) 88 task, alloc := mockAllocDir(t) 89 defer alloc.Destroy() 90 91 taskDir, ok := alloc.TaskDirs[task] 92 if !ok { 93 t.Fatalf("No task directory found for task %v", task) 94 } 95 96 expected := "hello world" 97 file := filepath.Join(allocdir.TaskLocal, "output.txt") 98 absFilePath := filepath.Join(taskDir, file) 99 cmd := fmt.Sprintf(`"%v \"%v\" > %v"`, "/bin/sleep 1 ; echo -n", expected, file) 100 e := Command("/bin/bash", "-c", cmd) 101 102 if err := e.Limit(constraint); err != nil { 103 t.Fatalf("Limit() failed: %v", err) 104 } 105 106 if err := e.ConfigureTaskDir(task, alloc); err != nil { 107 t.Fatalf("ConfigureTaskDir(%v, %v) failed: %v", task, alloc, err) 108 } 109 110 if err := e.Start(); err != nil { 111 t.Fatalf("Start() failed: %v", err) 112 } 113 114 if err := e.Wait(); err != nil { 115 t.Fatalf("Wait() failed: %v", err) 116 } 117 118 output, err := ioutil.ReadFile(absFilePath) 119 if err != nil { 120 t.Fatalf("Couldn't read file %v", absFilePath) 121 } 122 123 act := string(output) 124 if act != expected { 125 t.Fatalf("Command output incorrectly: want %v; got %v", expected, act) 126 } 127 } 128 129 func TestExecutorLinux_Start_Kill(t *testing.T) { 130 ctestutil.ExecCompatible(t) 131 task, alloc := mockAllocDir(t) 132 defer alloc.Destroy() 133 134 taskDir, ok := alloc.TaskDirs[task] 135 if !ok { 136 t.Fatalf("No task directory found for task %v", task) 137 } 138 139 filePath := filepath.Join(taskDir, "output") 140 e := Command("/bin/bash", "-c", "sleep 1 ; echo \"failure\" > "+filePath) 141 142 // This test can only be run if cgroups are enabled. 143 if !e.(*LinuxExecutor).cgroupEnabled { 144 t.SkipNow() 145 } 146 147 if err := e.Limit(constraint); err != nil { 148 t.Fatalf("Limit() failed: %v", err) 149 } 150 151 if err := e.ConfigureTaskDir(task, alloc); err != nil { 152 t.Fatalf("ConfigureTaskDir(%v, %v) failed: %v", task, alloc, err) 153 } 154 155 if err := e.Start(); err != nil { 156 t.Fatalf("Start() failed: %v", err) 157 } 158 159 if err := e.Shutdown(); err != nil { 160 t.Fatalf("Shutdown() failed: %v", err) 161 } 162 163 time.Sleep(1500 * time.Millisecond) 164 165 // Check that the file doesn't exist. 166 if _, err := os.Stat(filePath); err == nil { 167 t.Fatalf("Stat(%v) should have failed: task not killed", filePath) 168 } 169 } 170 171 func TestExecutorLinux_Open(t *testing.T) { 172 ctestutil.ExecCompatible(t) 173 task, alloc := mockAllocDir(t) 174 defer alloc.Destroy() 175 176 taskDir, ok := alloc.TaskDirs[task] 177 if !ok { 178 t.Fatalf("No task directory found for task %v", task) 179 } 180 181 filePath := filepath.Join(taskDir, "output") 182 e := Command("/bin/bash", "-c", "sleep 1 ; echo \"failure\" > "+filePath) 183 184 // This test can only be run if cgroups are enabled. 185 if !e.(*LinuxExecutor).cgroupEnabled { 186 t.SkipNow() 187 } 188 189 if err := e.Limit(constraint); err != nil { 190 t.Fatalf("Limit() failed: %v", err) 191 } 192 193 if err := e.ConfigureTaskDir(task, alloc); err != nil { 194 t.Fatalf("ConfigureTaskDir(%v, %v) failed: %v", task, alloc, err) 195 } 196 197 if err := e.Start(); err != nil { 198 t.Fatalf("Start() failed: %v", err) 199 } 200 201 id, err := e.ID() 202 if err != nil { 203 t.Fatalf("ID() failed: %v", err) 204 } 205 206 if _, err := OpenId(id); err == nil { 207 t.Fatalf("Open(%v) should have failed", id) 208 } 209 210 time.Sleep(1500 * time.Millisecond) 211 212 // Check that the file doesn't exist, open should have killed the process. 213 if _, err := os.Stat(filePath); err == nil { 214 t.Fatalf("Stat(%v) should have failed: task not killed", filePath) 215 } 216 }