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  }