github.com/blixtra/nomad@v0.7.2-0.20171221000451-da9a1d7bb050/nomad/structs/funcs_test.go (about)

     1  package structs
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	lru "github.com/hashicorp/golang-lru"
     8  	"github.com/hashicorp/nomad/helper/uuid"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestRemoveAllocs(t *testing.T) {
    13  	l := []*Allocation{
    14  		{ID: "foo"},
    15  		{ID: "bar"},
    16  		{ID: "baz"},
    17  		{ID: "zip"},
    18  	}
    19  
    20  	out := RemoveAllocs(l, []*Allocation{l[1], l[3]})
    21  	if len(out) != 2 {
    22  		t.Fatalf("bad: %#v", out)
    23  	}
    24  	if out[0].ID != "foo" && out[1].ID != "baz" {
    25  		t.Fatalf("bad: %#v", out)
    26  	}
    27  }
    28  
    29  func TestFilterTerminalAllocs(t *testing.T) {
    30  	l := []*Allocation{
    31  		{
    32  			ID:            "bar",
    33  			Name:          "myname1",
    34  			DesiredStatus: AllocDesiredStatusEvict,
    35  		},
    36  		{ID: "baz", DesiredStatus: AllocDesiredStatusStop},
    37  		{
    38  			ID:            "foo",
    39  			DesiredStatus: AllocDesiredStatusRun,
    40  			ClientStatus:  AllocClientStatusPending,
    41  		},
    42  		{
    43  			ID:            "bam",
    44  			Name:          "myname",
    45  			DesiredStatus: AllocDesiredStatusRun,
    46  			ClientStatus:  AllocClientStatusComplete,
    47  			CreateIndex:   5,
    48  		},
    49  		{
    50  			ID:            "lol",
    51  			Name:          "myname",
    52  			DesiredStatus: AllocDesiredStatusRun,
    53  			ClientStatus:  AllocClientStatusComplete,
    54  			CreateIndex:   2,
    55  		},
    56  	}
    57  
    58  	out, terminalAllocs := FilterTerminalAllocs(l)
    59  	if len(out) != 1 {
    60  		t.Fatalf("bad: %#v", out)
    61  	}
    62  	if out[0].ID != "foo" {
    63  		t.Fatalf("bad: %#v", out)
    64  	}
    65  
    66  	if len(terminalAllocs) != 3 {
    67  		for _, o := range terminalAllocs {
    68  			fmt.Printf("%#v \n", o)
    69  		}
    70  
    71  		t.Fatalf("bad: %#v", terminalAllocs)
    72  	}
    73  
    74  	if terminalAllocs["myname"].ID != "bam" {
    75  		t.Fatalf("bad: %#v", terminalAllocs["myname"])
    76  	}
    77  }
    78  
    79  func TestAllocsFit_PortsOvercommitted(t *testing.T) {
    80  	n := &Node{
    81  		Resources: &Resources{
    82  			Networks: []*NetworkResource{
    83  				{
    84  					Device: "eth0",
    85  					CIDR:   "10.0.0.0/8",
    86  					MBits:  100,
    87  				},
    88  			},
    89  		},
    90  	}
    91  
    92  	a1 := &Allocation{
    93  		Job: &Job{
    94  			TaskGroups: []*TaskGroup{
    95  				{
    96  					Name:          "web",
    97  					EphemeralDisk: DefaultEphemeralDisk(),
    98  				},
    99  			},
   100  		},
   101  		TaskResources: map[string]*Resources{
   102  			"web": {
   103  				Networks: []*NetworkResource{
   104  					{
   105  						Device:        "eth0",
   106  						IP:            "10.0.0.1",
   107  						MBits:         50,
   108  						ReservedPorts: []Port{{"main", 8000}},
   109  					},
   110  				},
   111  			},
   112  		},
   113  	}
   114  
   115  	// Should fit one allocation
   116  	fit, dim, _, err := AllocsFit(n, []*Allocation{a1}, nil)
   117  	if err != nil {
   118  		t.Fatalf("err: %v", err)
   119  	}
   120  	if !fit {
   121  		t.Fatalf("Bad: %s", dim)
   122  	}
   123  
   124  	// Should not fit second allocation
   125  	fit, _, _, err = AllocsFit(n, []*Allocation{a1, a1}, nil)
   126  	if err != nil {
   127  		t.Fatalf("err: %v", err)
   128  	}
   129  	if fit {
   130  		t.Fatalf("Bad")
   131  	}
   132  }
   133  
   134  func TestAllocsFit(t *testing.T) {
   135  	n := &Node{
   136  		Resources: &Resources{
   137  			CPU:      2000,
   138  			MemoryMB: 2048,
   139  			DiskMB:   10000,
   140  			IOPS:     100,
   141  			Networks: []*NetworkResource{
   142  				{
   143  					Device: "eth0",
   144  					CIDR:   "10.0.0.0/8",
   145  					MBits:  100,
   146  				},
   147  			},
   148  		},
   149  		Reserved: &Resources{
   150  			CPU:      1000,
   151  			MemoryMB: 1024,
   152  			DiskMB:   5000,
   153  			IOPS:     50,
   154  			Networks: []*NetworkResource{
   155  				{
   156  					Device:        "eth0",
   157  					IP:            "10.0.0.1",
   158  					MBits:         50,
   159  					ReservedPorts: []Port{{"main", 80}},
   160  				},
   161  			},
   162  		},
   163  	}
   164  
   165  	a1 := &Allocation{
   166  		Resources: &Resources{
   167  			CPU:      1000,
   168  			MemoryMB: 1024,
   169  			DiskMB:   5000,
   170  			IOPS:     50,
   171  			Networks: []*NetworkResource{
   172  				{
   173  					Device:        "eth0",
   174  					IP:            "10.0.0.1",
   175  					MBits:         50,
   176  					ReservedPorts: []Port{{"main", 8000}},
   177  				},
   178  			},
   179  		},
   180  	}
   181  
   182  	// Should fit one allocation
   183  	fit, _, used, err := AllocsFit(n, []*Allocation{a1}, nil)
   184  	if err != nil {
   185  		t.Fatalf("err: %v", err)
   186  	}
   187  	if !fit {
   188  		t.Fatalf("Bad")
   189  	}
   190  
   191  	// Sanity check the used resources
   192  	if used.CPU != 2000 {
   193  		t.Fatalf("bad: %#v", used)
   194  	}
   195  	if used.MemoryMB != 2048 {
   196  		t.Fatalf("bad: %#v", used)
   197  	}
   198  
   199  	// Should not fit second allocation
   200  	fit, _, used, err = AllocsFit(n, []*Allocation{a1, a1}, nil)
   201  	if err != nil {
   202  		t.Fatalf("err: %v", err)
   203  	}
   204  	if fit {
   205  		t.Fatalf("Bad")
   206  	}
   207  
   208  	// Sanity check the used resources
   209  	if used.CPU != 3000 {
   210  		t.Fatalf("bad: %#v", used)
   211  	}
   212  	if used.MemoryMB != 3072 {
   213  		t.Fatalf("bad: %#v", used)
   214  	}
   215  
   216  }
   217  
   218  func TestScoreFit(t *testing.T) {
   219  	node := &Node{}
   220  	node.Resources = &Resources{
   221  		CPU:      4096,
   222  		MemoryMB: 8192,
   223  	}
   224  	node.Reserved = &Resources{
   225  		CPU:      2048,
   226  		MemoryMB: 4096,
   227  	}
   228  
   229  	// Test a perfect fit
   230  	util := &Resources{
   231  		CPU:      2048,
   232  		MemoryMB: 4096,
   233  	}
   234  	score := ScoreFit(node, util)
   235  	if score != 18.0 {
   236  		t.Fatalf("bad: %v", score)
   237  	}
   238  
   239  	// Test the worst fit
   240  	util = &Resources{
   241  		CPU:      0,
   242  		MemoryMB: 0,
   243  	}
   244  	score = ScoreFit(node, util)
   245  	if score != 0.0 {
   246  		t.Fatalf("bad: %v", score)
   247  	}
   248  
   249  	// Test a mid-case scenario
   250  	util = &Resources{
   251  		CPU:      1024,
   252  		MemoryMB: 2048,
   253  	}
   254  	score = ScoreFit(node, util)
   255  	if score < 10.0 || score > 16.0 {
   256  		t.Fatalf("bad: %v", score)
   257  	}
   258  }
   259  
   260  func TestACLPolicyListHash(t *testing.T) {
   261  	h1 := ACLPolicyListHash(nil)
   262  	assert.NotEqual(t, "", h1)
   263  
   264  	p1 := &ACLPolicy{
   265  		Name:        fmt.Sprintf("policy-%s", uuid.Generate()),
   266  		Description: "Super cool policy!",
   267  		Rules: `
   268  		namespace "default" {
   269  			policy = "write"
   270  		}
   271  		node {
   272  			policy = "read"
   273  		}
   274  		agent {
   275  			policy = "read"
   276  		}
   277  		`,
   278  		CreateIndex: 10,
   279  		ModifyIndex: 20,
   280  	}
   281  
   282  	h2 := ACLPolicyListHash([]*ACLPolicy{p1})
   283  	assert.NotEqual(t, "", h2)
   284  	assert.NotEqual(t, h1, h2)
   285  
   286  	// Create P2 as copy of P1 with new name
   287  	p2 := &ACLPolicy{}
   288  	*p2 = *p1
   289  	p2.Name = fmt.Sprintf("policy-%s", uuid.Generate())
   290  
   291  	h3 := ACLPolicyListHash([]*ACLPolicy{p1, p2})
   292  	assert.NotEqual(t, "", h3)
   293  	assert.NotEqual(t, h2, h3)
   294  
   295  	h4 := ACLPolicyListHash([]*ACLPolicy{p2})
   296  	assert.NotEqual(t, "", h4)
   297  	assert.NotEqual(t, h3, h4)
   298  
   299  	// ModifyIndex should change the hash
   300  	p2.ModifyIndex++
   301  	h5 := ACLPolicyListHash([]*ACLPolicy{p2})
   302  	assert.NotEqual(t, "", h5)
   303  	assert.NotEqual(t, h4, h5)
   304  }
   305  
   306  func TestCompileACLObject(t *testing.T) {
   307  	p1 := &ACLPolicy{
   308  		Name:        fmt.Sprintf("policy-%s", uuid.Generate()),
   309  		Description: "Super cool policy!",
   310  		Rules: `
   311  		namespace "default" {
   312  			policy = "write"
   313  		}
   314  		node {
   315  			policy = "read"
   316  		}
   317  		agent {
   318  			policy = "read"
   319  		}
   320  		`,
   321  		CreateIndex: 10,
   322  		ModifyIndex: 20,
   323  	}
   324  
   325  	// Create P2 as copy of P1 with new name
   326  	p2 := &ACLPolicy{}
   327  	*p2 = *p1
   328  	p2.Name = fmt.Sprintf("policy-%s", uuid.Generate())
   329  
   330  	// Create a small cache
   331  	cache, err := lru.New2Q(16)
   332  	assert.Nil(t, err)
   333  
   334  	// Test compilation
   335  	aclObj, err := CompileACLObject(cache, []*ACLPolicy{p1})
   336  	assert.Nil(t, err)
   337  	assert.NotNil(t, aclObj)
   338  
   339  	// Should get the same object
   340  	aclObj2, err := CompileACLObject(cache, []*ACLPolicy{p1})
   341  	assert.Nil(t, err)
   342  	if aclObj != aclObj2 {
   343  		t.Fatalf("expected the same object")
   344  	}
   345  
   346  	// Should get another object
   347  	aclObj3, err := CompileACLObject(cache, []*ACLPolicy{p1, p2})
   348  	assert.Nil(t, err)
   349  	assert.NotNil(t, aclObj3)
   350  	if aclObj == aclObj3 {
   351  		t.Fatalf("unexpected same object")
   352  	}
   353  
   354  	// Should be order independent
   355  	aclObj4, err := CompileACLObject(cache, []*ACLPolicy{p2, p1})
   356  	assert.Nil(t, err)
   357  	assert.NotNil(t, aclObj4)
   358  	if aclObj3 != aclObj4 {
   359  		t.Fatalf("expected same object")
   360  	}
   361  }