github.com/mattyr/nomad@v0.3.3-0.20160919021406-3485a065154a/client/driver/rkt_test.go (about) 1 package driver 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "reflect" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/hashicorp/nomad/client/config" 14 "github.com/hashicorp/nomad/client/driver/env" 15 "github.com/hashicorp/nomad/nomad/structs" 16 "github.com/hashicorp/nomad/testutil" 17 18 ctestutils "github.com/hashicorp/nomad/client/testutil" 19 ) 20 21 func TestRktVersionRegex(t *testing.T) { 22 if os.Getenv("NOMAD_TEST_RKT") == "" { 23 t.Skip("skipping rkt tests") 24 } 25 26 input_rkt := "rkt version 0.8.1" 27 input_appc := "appc version 1.2.0" 28 expected_rkt := "0.8.1" 29 expected_appc := "1.2.0" 30 rktMatches := reRktVersion.FindStringSubmatch(input_rkt) 31 appcMatches := reAppcVersion.FindStringSubmatch(input_appc) 32 if rktMatches[1] != expected_rkt { 33 fmt.Printf("Test failed; got %q; want %q\n", rktMatches[1], expected_rkt) 34 } 35 if appcMatches[1] != expected_appc { 36 fmt.Printf("Test failed; got %q; want %q\n", appcMatches[1], expected_appc) 37 } 38 } 39 40 // The fingerprinter test should always pass, even if rkt is not installed. 41 func TestRktDriver_Fingerprint(t *testing.T) { 42 if os.Getenv("NOMAD_TEST_RKT") == "" { 43 t.Skip("skipping rkt tests") 44 } 45 46 ctestutils.RktCompatible(t) 47 driverCtx, _ := testDriverContexts(&structs.Task{Name: "foo"}) 48 d := NewRktDriver(driverCtx) 49 node := &structs.Node{ 50 Attributes: make(map[string]string), 51 } 52 apply, err := d.Fingerprint(&config.Config{}, node) 53 if err != nil { 54 t.Fatalf("err: %v", err) 55 } 56 if !apply { 57 t.Fatalf("should apply") 58 } 59 if node.Attributes["driver.rkt"] != "1" { 60 t.Fatalf("Missing Rkt driver") 61 } 62 if node.Attributes["driver.rkt.version"] == "" { 63 t.Fatalf("Missing Rkt driver version") 64 } 65 if node.Attributes["driver.rkt.appc.version"] == "" { 66 t.Fatalf("Missing appc version for the Rkt driver") 67 } 68 } 69 70 func TestRktDriver_Start_DNS(t *testing.T) { 71 if os.Getenv("NOMAD_TEST_RKT") == "" { 72 t.Skip("skipping rkt tests") 73 } 74 75 ctestutils.RktCompatible(t) 76 // TODO: use test server to load from a fixture 77 task := &structs.Task{ 78 Name: "etcd", 79 Config: map[string]interface{}{ 80 "trust_prefix": "coreos.com/etcd", 81 "image": "coreos.com/etcd:v2.0.4", 82 "command": "/etcd", 83 "dns_servers": []string{"8.8.8.8", "8.8.4.4"}, 84 "dns_search_domains": []string{"example.com", "example.org", "example.net"}, 85 }, 86 LogConfig: &structs.LogConfig{ 87 MaxFiles: 10, 88 MaxFileSizeMB: 10, 89 }, 90 Resources: &structs.Resources{ 91 MemoryMB: 128, 92 CPU: 100, 93 }, 94 } 95 96 driverCtx, execCtx := testDriverContexts(task) 97 defer execCtx.AllocDir.Destroy() 98 99 d := NewRktDriver(driverCtx) 100 101 handle, err := d.Start(execCtx, task) 102 if err != nil { 103 t.Fatalf("err: %v", err) 104 } 105 if handle == nil { 106 t.Fatalf("missing handle") 107 } 108 defer handle.Kill() 109 110 // Attempt to open 111 handle2, err := d.Open(execCtx, handle.ID()) 112 if err != nil { 113 t.Fatalf("err: %v", err) 114 } 115 if handle2 == nil { 116 t.Fatalf("missing handle") 117 } 118 } 119 120 func TestRktDriver_Start_Wait(t *testing.T) { 121 if os.Getenv("NOMAD_TEST_RKT") == "" { 122 t.Skip("skipping rkt tests") 123 } 124 125 ctestutils.RktCompatible(t) 126 task := &structs.Task{ 127 Name: "etcd", 128 Config: map[string]interface{}{ 129 "trust_prefix": "coreos.com/etcd", 130 "image": "coreos.com/etcd:v2.0.4", 131 "command": "/etcd", 132 "args": []string{"--version"}, 133 }, 134 LogConfig: &structs.LogConfig{ 135 MaxFiles: 10, 136 MaxFileSizeMB: 10, 137 }, 138 Resources: &structs.Resources{ 139 MemoryMB: 128, 140 CPU: 100, 141 }, 142 } 143 144 driverCtx, execCtx := testDriverContexts(task) 145 defer execCtx.AllocDir.Destroy() 146 d := NewRktDriver(driverCtx) 147 148 handle, err := d.Start(execCtx, task) 149 if err != nil { 150 t.Fatalf("err: %v", err) 151 } 152 if handle == nil { 153 t.Fatalf("missing handle") 154 } 155 defer handle.Kill() 156 157 // Update should be a no-op 158 err = handle.Update(task) 159 if err != nil { 160 t.Fatalf("err: %v", err) 161 } 162 163 select { 164 case res := <-handle.WaitCh(): 165 if !res.Successful() { 166 t.Fatalf("err: %v", res) 167 } 168 case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second): 169 t.Fatalf("timeout") 170 } 171 } 172 173 func TestRktDriver_Start_Wait_Skip_Trust(t *testing.T) { 174 if os.Getenv("NOMAD_TEST_RKT") == "" { 175 t.Skip("skipping rkt tests") 176 } 177 178 ctestutils.RktCompatible(t) 179 task := &structs.Task{ 180 Name: "etcd", 181 Config: map[string]interface{}{ 182 "image": "coreos.com/etcd:v2.0.4", 183 "command": "/etcd", 184 "args": []string{"--version"}, 185 }, 186 LogConfig: &structs.LogConfig{ 187 MaxFiles: 10, 188 MaxFileSizeMB: 10, 189 }, 190 Resources: &structs.Resources{ 191 MemoryMB: 128, 192 CPU: 100, 193 }, 194 } 195 196 driverCtx, execCtx := testDriverContexts(task) 197 defer execCtx.AllocDir.Destroy() 198 d := NewRktDriver(driverCtx) 199 200 handle, err := d.Start(execCtx, task) 201 if err != nil { 202 t.Fatalf("err: %v", err) 203 } 204 if handle == nil { 205 t.Fatalf("missing handle") 206 } 207 defer handle.Kill() 208 209 // Update should be a no-op 210 err = handle.Update(task) 211 if err != nil { 212 t.Fatalf("err: %v", err) 213 } 214 215 select { 216 case res := <-handle.WaitCh(): 217 if !res.Successful() { 218 t.Fatalf("err: %v", res) 219 } 220 case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second): 221 t.Fatalf("timeout") 222 } 223 } 224 225 func TestRktDriver_Start_Wait_AllocDir(t *testing.T) { 226 if os.Getenv("NOMAD_TEST_RKT") == "" { 227 t.Skip("skipping rkt tests") 228 } 229 230 ctestutils.RktCompatible(t) 231 232 exp := []byte{'w', 'i', 'n'} 233 file := "output.txt" 234 235 task := &structs.Task{ 236 Name: "alpine", 237 Config: map[string]interface{}{ 238 "image": "docker://alpine", 239 "command": "/bin/sh", 240 "args": []string{ 241 "-c", 242 fmt.Sprintf(`echo -n %s > ${%s}/%s`, string(exp), env.AllocDir, file), 243 }, 244 }, 245 LogConfig: &structs.LogConfig{ 246 MaxFiles: 10, 247 MaxFileSizeMB: 10, 248 }, 249 Resources: &structs.Resources{ 250 MemoryMB: 128, 251 CPU: 100, 252 }, 253 } 254 255 driverCtx, execCtx := testDriverContexts(task) 256 defer execCtx.AllocDir.Destroy() 257 d := NewRktDriver(driverCtx) 258 259 handle, err := d.Start(execCtx, task) 260 if err != nil { 261 t.Fatalf("err: %v", err) 262 } 263 if handle == nil { 264 t.Fatalf("missing handle") 265 } 266 defer handle.Kill() 267 268 select { 269 case res := <-handle.WaitCh(): 270 if !res.Successful() { 271 t.Fatalf("err: %v", res) 272 } 273 case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second): 274 t.Fatalf("timeout") 275 } 276 277 // Check that data was written to the shared alloc directory. 278 outputFile := filepath.Join(execCtx.AllocDir.SharedDir, file) 279 act, err := ioutil.ReadFile(outputFile) 280 if err != nil { 281 t.Fatalf("Couldn't read expected output: %v", err) 282 } 283 284 if !reflect.DeepEqual(act, exp) { 285 t.Fatalf("Command output is %v; expected %v", act, exp) 286 } 287 } 288 289 func TestRktDriverUser(t *testing.T) { 290 if os.Getenv("NOMAD_TEST_RKT") == "" { 291 t.Skip("skipping rkt tests") 292 } 293 294 ctestutils.RktCompatible(t) 295 task := &structs.Task{ 296 Name: "etcd", 297 User: "alice", 298 Config: map[string]interface{}{ 299 "trust_prefix": "coreos.com/etcd", 300 "image": "coreos.com/etcd:v2.0.4", 301 "command": "/etcd", 302 "args": []string{"--version"}, 303 }, 304 LogConfig: &structs.LogConfig{ 305 MaxFiles: 10, 306 MaxFileSizeMB: 10, 307 }, 308 Resources: &structs.Resources{ 309 MemoryMB: 128, 310 CPU: 100, 311 }, 312 } 313 314 driverCtx, execCtx := testDriverContexts(task) 315 defer execCtx.AllocDir.Destroy() 316 d := NewRktDriver(driverCtx) 317 318 handle, err := d.Start(execCtx, task) 319 if err == nil { 320 handle.Kill() 321 t.Fatalf("Should've failed") 322 } 323 msg := "unknown user alice" 324 if !strings.Contains(err.Error(), msg) { 325 t.Fatalf("Expecting '%v' in '%v'", msg, err) 326 } 327 } 328 329 func TestRktTrustPrefix(t *testing.T) { 330 if os.Getenv("NOMAD_TEST_RKT") == "" { 331 t.Skip("skipping rkt tests") 332 } 333 ctestutils.RktCompatible(t) 334 task := &structs.Task{ 335 Name: "etcd", 336 Config: map[string]interface{}{ 337 "trust_prefix": "example.com/invalid", 338 "image": "coreos.com/etcd:v2.0.4", 339 "command": "/etcd", 340 "args": []string{"--version"}, 341 }, 342 LogConfig: &structs.LogConfig{ 343 MaxFiles: 10, 344 MaxFileSizeMB: 10, 345 }, 346 Resources: &structs.Resources{ 347 MemoryMB: 128, 348 CPU: 100, 349 }, 350 } 351 driverCtx, execCtx := testDriverContexts(task) 352 defer execCtx.AllocDir.Destroy() 353 354 d := NewRktDriver(driverCtx) 355 356 handle, err := d.Start(execCtx, task) 357 if err == nil { 358 handle.Kill() 359 t.Fatalf("Should've failed") 360 } 361 msg := "Error running rkt trust" 362 if !strings.Contains(err.Error(), msg) { 363 t.Fatalf("Expecting '%v' in '%v'", msg, err) 364 } 365 } 366 367 func TestRktTaskValidate(t *testing.T) { 368 ctestutils.RktCompatible(t) 369 task := &structs.Task{ 370 Name: "etcd", 371 Config: map[string]interface{}{ 372 "trust_prefix": "coreos.com/etcd", 373 "image": "coreos.com/etcd:v2.0.4", 374 "command": "/etcd", 375 "args": []string{"--version"}, 376 "dns_servers": []string{"8.8.8.8", "8.8.4.4"}, 377 "dns_search_domains": []string{"example.com", "example.org", "example.net"}, 378 }, 379 Resources: basicResources, 380 } 381 driverCtx, execCtx := testDriverContexts(task) 382 defer execCtx.AllocDir.Destroy() 383 384 d := NewRktDriver(driverCtx) 385 if err := d.Validate(task.Config); err != nil { 386 t.Fatalf("Validation error in TaskConfig : '%v'", err) 387 } 388 }