github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/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  	"syscall"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/hashicorp/nomad/client/config"
    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  	// Signal should be an error
   164  	if err = handle.Signal(syscall.SIGTERM); err == nil {
   165  		t.Fatalf("err: %v", err)
   166  	}
   167  
   168  	select {
   169  	case res := <-handle.WaitCh():
   170  		if !res.Successful() {
   171  			t.Fatalf("err: %v", res)
   172  		}
   173  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   174  		t.Fatalf("timeout")
   175  	}
   176  }
   177  
   178  func TestRktDriver_Start_Wait_Skip_Trust(t *testing.T) {
   179  	if os.Getenv("NOMAD_TEST_RKT") == "" {
   180  		t.Skip("skipping rkt tests")
   181  	}
   182  
   183  	ctestutils.RktCompatible(t)
   184  	task := &structs.Task{
   185  		Name: "etcd",
   186  		Config: map[string]interface{}{
   187  			"image":   "coreos.com/etcd:v2.0.4",
   188  			"command": "/etcd",
   189  			"args":    []string{"--version"},
   190  		},
   191  		LogConfig: &structs.LogConfig{
   192  			MaxFiles:      10,
   193  			MaxFileSizeMB: 10,
   194  		},
   195  		Resources: &structs.Resources{
   196  			MemoryMB: 128,
   197  			CPU:      100,
   198  		},
   199  	}
   200  
   201  	driverCtx, execCtx := testDriverContexts(task)
   202  	defer execCtx.AllocDir.Destroy()
   203  	d := NewRktDriver(driverCtx)
   204  
   205  	handle, err := d.Start(execCtx, task)
   206  	if err != nil {
   207  		t.Fatalf("err: %v", err)
   208  	}
   209  	if handle == nil {
   210  		t.Fatalf("missing handle")
   211  	}
   212  	defer handle.Kill()
   213  
   214  	// Update should be a no-op
   215  	err = handle.Update(task)
   216  	if err != nil {
   217  		t.Fatalf("err: %v", err)
   218  	}
   219  
   220  	select {
   221  	case res := <-handle.WaitCh():
   222  		if !res.Successful() {
   223  			t.Fatalf("err: %v", res)
   224  		}
   225  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   226  		t.Fatalf("timeout")
   227  	}
   228  }
   229  
   230  func TestRktDriver_Start_Wait_AllocDir(t *testing.T) {
   231  	if os.Getenv("NOMAD_TEST_RKT") == "" {
   232  		t.Skip("skipping rkt tests")
   233  	}
   234  
   235  	ctestutils.RktCompatible(t)
   236  
   237  	exp := []byte{'w', 'i', 'n'}
   238  	file := "output.txt"
   239  	tmpvol, err := ioutil.TempDir("", "nomadtest_rktdriver_volumes")
   240  	if err != nil {
   241  		t.Fatalf("error creating temporary dir: %v", err)
   242  	}
   243  	defer os.RemoveAll(tmpvol)
   244  	hostpath := filepath.Join(tmpvol, file)
   245  
   246  	task := &structs.Task{
   247  		Name: "alpine",
   248  		Config: map[string]interface{}{
   249  			"image":   "docker://alpine",
   250  			"command": "/bin/sh",
   251  			"args": []string{
   252  				"-c",
   253  				fmt.Sprintf(`echo -n %s > foo/%s`, string(exp), file),
   254  			},
   255  			"volumes": []string{fmt.Sprintf("%s:/foo", tmpvol)},
   256  		},
   257  		LogConfig: &structs.LogConfig{
   258  			MaxFiles:      10,
   259  			MaxFileSizeMB: 10,
   260  		},
   261  		Resources: &structs.Resources{
   262  			MemoryMB: 128,
   263  			CPU:      100,
   264  		},
   265  	}
   266  
   267  	driverCtx, execCtx := testDriverContexts(task)
   268  	defer execCtx.AllocDir.Destroy()
   269  	d := NewRktDriver(driverCtx)
   270  
   271  	handle, err := d.Start(execCtx, task)
   272  	if err != nil {
   273  		t.Fatalf("err: %v", err)
   274  	}
   275  	if handle == nil {
   276  		t.Fatalf("missing handle")
   277  	}
   278  	defer handle.Kill()
   279  
   280  	select {
   281  	case res := <-handle.WaitCh():
   282  		if !res.Successful() {
   283  			t.Fatalf("err: %v", res)
   284  		}
   285  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   286  		t.Fatalf("timeout")
   287  	}
   288  
   289  	// Check that data was written to the shared alloc directory.
   290  	act, err := ioutil.ReadFile(hostpath)
   291  	if err != nil {
   292  		t.Fatalf("Couldn't read expected output: %v", err)
   293  	}
   294  
   295  	if !reflect.DeepEqual(act, exp) {
   296  		t.Fatalf("Command output is %v; expected %v", act, exp)
   297  	}
   298  }
   299  
   300  func TestRktDriverUser(t *testing.T) {
   301  	if os.Getenv("NOMAD_TEST_RKT") == "" {
   302  		t.Skip("skipping rkt tests")
   303  	}
   304  
   305  	ctestutils.RktCompatible(t)
   306  	task := &structs.Task{
   307  		Name: "etcd",
   308  		User: "alice",
   309  		Config: map[string]interface{}{
   310  			"trust_prefix": "coreos.com/etcd",
   311  			"image":        "coreos.com/etcd:v2.0.4",
   312  			"command":      "/etcd",
   313  			"args":         []string{"--version"},
   314  		},
   315  		LogConfig: &structs.LogConfig{
   316  			MaxFiles:      10,
   317  			MaxFileSizeMB: 10,
   318  		},
   319  		Resources: &structs.Resources{
   320  			MemoryMB: 128,
   321  			CPU:      100,
   322  		},
   323  	}
   324  
   325  	driverCtx, execCtx := testDriverContexts(task)
   326  	defer execCtx.AllocDir.Destroy()
   327  	d := NewRktDriver(driverCtx)
   328  
   329  	handle, err := d.Start(execCtx, task)
   330  	if err == nil {
   331  		handle.Kill()
   332  		t.Fatalf("Should've failed")
   333  	}
   334  	msg := "unknown user alice"
   335  	if !strings.Contains(err.Error(), msg) {
   336  		t.Fatalf("Expecting '%v' in '%v'", msg, err)
   337  	}
   338  }
   339  
   340  func TestRktTrustPrefix(t *testing.T) {
   341  	if os.Getenv("NOMAD_TEST_RKT") == "" {
   342  		t.Skip("skipping rkt tests")
   343  	}
   344  	ctestutils.RktCompatible(t)
   345  	task := &structs.Task{
   346  		Name: "etcd",
   347  		Config: map[string]interface{}{
   348  			"trust_prefix": "example.com/invalid",
   349  			"image":        "coreos.com/etcd:v2.0.4",
   350  			"command":      "/etcd",
   351  			"args":         []string{"--version"},
   352  		},
   353  		LogConfig: &structs.LogConfig{
   354  			MaxFiles:      10,
   355  			MaxFileSizeMB: 10,
   356  		},
   357  		Resources: &structs.Resources{
   358  			MemoryMB: 128,
   359  			CPU:      100,
   360  		},
   361  	}
   362  	driverCtx, execCtx := testDriverContexts(task)
   363  	defer execCtx.AllocDir.Destroy()
   364  
   365  	d := NewRktDriver(driverCtx)
   366  
   367  	handle, err := d.Start(execCtx, task)
   368  	if err == nil {
   369  		handle.Kill()
   370  		t.Fatalf("Should've failed")
   371  	}
   372  	msg := "Error running rkt trust"
   373  	if !strings.Contains(err.Error(), msg) {
   374  		t.Fatalf("Expecting '%v' in '%v'", msg, err)
   375  	}
   376  }
   377  
   378  func TestRktTaskValidate(t *testing.T) {
   379  	ctestutils.RktCompatible(t)
   380  	task := &structs.Task{
   381  		Name: "etcd",
   382  		Config: map[string]interface{}{
   383  			"trust_prefix":       "coreos.com/etcd",
   384  			"image":              "coreos.com/etcd:v2.0.4",
   385  			"command":            "/etcd",
   386  			"args":               []string{"--version"},
   387  			"dns_servers":        []string{"8.8.8.8", "8.8.4.4"},
   388  			"dns_search_domains": []string{"example.com", "example.org", "example.net"},
   389  		},
   390  		Resources: basicResources,
   391  	}
   392  	driverCtx, execCtx := testDriverContexts(task)
   393  	defer execCtx.AllocDir.Destroy()
   394  
   395  	d := NewRktDriver(driverCtx)
   396  	if err := d.Validate(task.Config); err != nil {
   397  		t.Fatalf("Validation error in TaskConfig : '%v'", err)
   398  	}
   399  }
   400  
   401  // TODO: Port Mapping test should be ran with proper ACI image and test the port access.
   402  func TestRktDriver_PortsMapping(t *testing.T) {
   403  	if os.Getenv("NOMAD_TEST_RKT") == "" {
   404  		t.Skip("skipping rkt tests")
   405  	}
   406  
   407  	ctestutils.RktCompatible(t)
   408  	task := &structs.Task{
   409  		Name: "etcd",
   410  		Config: map[string]interface{}{
   411  			"image": "docker://redis:latest",
   412  			"args":  []string{"--version"},
   413  			"port_map": []map[string]string{
   414  				map[string]string{
   415  					"main": "6379-tcp",
   416  				},
   417  			},
   418  			"debug": "true",
   419  		},
   420  		LogConfig: &structs.LogConfig{
   421  			MaxFiles:      10,
   422  			MaxFileSizeMB: 10,
   423  		},
   424  		Resources: &structs.Resources{
   425  			MemoryMB: 256,
   426  			CPU:      512,
   427  			Networks: []*structs.NetworkResource{
   428  				&structs.NetworkResource{
   429  					IP:            "127.0.0.1",
   430  					ReservedPorts: []structs.Port{{"main", 8080}},
   431  				},
   432  			},
   433  		},
   434  	}
   435  
   436  	driverCtx, execCtx := testDriverContexts(task)
   437  	defer execCtx.AllocDir.Destroy()
   438  
   439  	d := NewRktDriver(driverCtx)
   440  
   441  	handle, err := d.Start(execCtx, task)
   442  	if err != nil {
   443  		t.Fatalf("err: %v", err)
   444  	}
   445  	if handle == nil {
   446  		t.Fatalf("missing handle")
   447  	}
   448  	defer handle.Kill()
   449  
   450  	select {
   451  	case res := <-handle.WaitCh():
   452  		if !res.Successful() {
   453  			t.Fatalf("err: %v", res)
   454  		}
   455  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   456  		t.Fatalf("timeout")
   457  	}
   458  }