github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/nomad/structs/node_class_test.go (about)

     1  package structs
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/nomad/helper/uuid"
     8  )
     9  
    10  func testNode() *Node {
    11  	return &Node{
    12  		ID:         uuid.Generate(),
    13  		Datacenter: "dc1",
    14  		Name:       "foobar",
    15  		Attributes: map[string]string{
    16  			"kernel.name": "linux",
    17  			"arch":        "x86",
    18  			"version":     "0.1.0",
    19  			"driver.exec": "1",
    20  		},
    21  		Resources: &Resources{
    22  			CPU:      4000,
    23  			MemoryMB: 8192,
    24  			DiskMB:   100 * 1024,
    25  			IOPS:     150,
    26  			Networks: []*NetworkResource{
    27  				{
    28  					Device: "eth0",
    29  					CIDR:   "192.168.0.100/32",
    30  					MBits:  1000,
    31  				},
    32  			},
    33  		},
    34  		Links: map[string]string{
    35  			"consul": "foobar.dc1",
    36  		},
    37  		Meta: map[string]string{
    38  			"pci-dss": "true",
    39  		},
    40  		NodeClass: "linux-medium-pci",
    41  		Status:    NodeStatusReady,
    42  	}
    43  }
    44  
    45  func TestNode_ComputedClass(t *testing.T) {
    46  	// Create a node and gets it computed class
    47  	n := testNode()
    48  	if err := n.ComputeClass(); err != nil {
    49  		t.Fatalf("ComputeClass() failed: %v", err)
    50  	}
    51  	if n.ComputedClass == "" {
    52  		t.Fatal("ComputeClass() didn't set computed class")
    53  	}
    54  	old := n.ComputedClass
    55  
    56  	// Compute again to ensure determinism
    57  	if err := n.ComputeClass(); err != nil {
    58  		t.Fatalf("ComputeClass() failed: %v", err)
    59  	}
    60  	if old != n.ComputedClass {
    61  		t.Fatalf("ComputeClass() should have returned same class; got %v; want %v", n.ComputedClass, old)
    62  	}
    63  
    64  	// Modify a field and compute the class again.
    65  	n.Datacenter = "New DC"
    66  	if err := n.ComputeClass(); err != nil {
    67  		t.Fatalf("ComputeClass() failed: %v", err)
    68  	}
    69  	if n.ComputedClass == "" {
    70  		t.Fatal("ComputeClass() didn't set computed class")
    71  	}
    72  
    73  	if old == n.ComputedClass {
    74  		t.Fatal("ComputeClass() returned same computed class")
    75  	}
    76  }
    77  
    78  func TestNode_ComputedClass_Ignore(t *testing.T) {
    79  	// Create a node and gets it computed class
    80  	n := testNode()
    81  	if err := n.ComputeClass(); err != nil {
    82  		t.Fatalf("ComputeClass() failed: %v", err)
    83  	}
    84  	if n.ComputedClass == "" {
    85  		t.Fatal("ComputeClass() didn't set computed class")
    86  	}
    87  	old := n.ComputedClass
    88  
    89  	// Modify an ignored field and compute the class again.
    90  	n.ID = "New ID"
    91  	if err := n.ComputeClass(); err != nil {
    92  		t.Fatalf("ComputeClass() failed: %v", err)
    93  	}
    94  	if n.ComputedClass == "" {
    95  		t.Fatal("ComputeClass() didn't set computed class")
    96  	}
    97  
    98  	if old != n.ComputedClass {
    99  		t.Fatal("ComputeClass() should have ignored field")
   100  	}
   101  }
   102  
   103  func TestNode_ComputedClass_Attr(t *testing.T) {
   104  	// Create a node and gets it computed class
   105  	n := testNode()
   106  	if err := n.ComputeClass(); err != nil {
   107  		t.Fatalf("ComputeClass() failed: %v", err)
   108  	}
   109  	if n.ComputedClass == "" {
   110  		t.Fatal("ComputeClass() didn't set computed class")
   111  	}
   112  	old := n.ComputedClass
   113  
   114  	// Add a unique addr and compute the class again
   115  	n.Attributes["unique.foo"] = "bar"
   116  	if err := n.ComputeClass(); err != nil {
   117  		t.Fatalf("ComputeClass() failed: %v", err)
   118  	}
   119  	if old != n.ComputedClass {
   120  		t.Fatal("ComputeClass() didn't ignore unique attr suffix")
   121  	}
   122  
   123  	// Modify an attribute and compute the class again.
   124  	n.Attributes["version"] = "New Version"
   125  	if err := n.ComputeClass(); err != nil {
   126  		t.Fatalf("ComputeClass() failed: %v", err)
   127  	}
   128  	if n.ComputedClass == "" {
   129  		t.Fatal("ComputeClass() didn't set computed class")
   130  	}
   131  	if old == n.ComputedClass {
   132  		t.Fatal("ComputeClass() ignored attribute change")
   133  	}
   134  
   135  	// Remove and attribute and compute the class again.
   136  	old = n.ComputedClass
   137  	delete(n.Attributes, "driver.exec")
   138  	if err := n.ComputeClass(); err != nil {
   139  		t.Fatalf("ComputedClass() failed: %v", err)
   140  	}
   141  	if n.ComputedClass == "" {
   142  		t.Fatal("ComputeClass() didn't set computed class")
   143  	}
   144  	if old == n.ComputedClass {
   145  		t.Fatalf("ComputedClass() ignored removal of attribute key")
   146  	}
   147  }
   148  
   149  func TestNode_ComputedClass_Meta(t *testing.T) {
   150  	// Create a node and gets it computed class
   151  	n := testNode()
   152  	if err := n.ComputeClass(); err != nil {
   153  		t.Fatalf("ComputeClass() failed: %v", err)
   154  	}
   155  	if n.ComputedClass == "" {
   156  		t.Fatal("ComputeClass() didn't set computed class")
   157  	}
   158  	old := n.ComputedClass
   159  
   160  	// Modify a meta key and compute the class again.
   161  	n.Meta["pci-dss"] = "false"
   162  	if err := n.ComputeClass(); err != nil {
   163  		t.Fatalf("ComputeClass() failed: %v", err)
   164  	}
   165  	if n.ComputedClass == "" {
   166  		t.Fatal("ComputeClass() didn't set computed class")
   167  	}
   168  	if old == n.ComputedClass {
   169  		t.Fatal("ComputeClass() ignored meta change")
   170  	}
   171  	old = n.ComputedClass
   172  
   173  	// Add a unique meta key and compute the class again.
   174  	n.Meta["unique.foo"] = "ignore"
   175  	if err := n.ComputeClass(); err != nil {
   176  		t.Fatalf("ComputeClass() failed: %v", err)
   177  	}
   178  	if n.ComputedClass == "" {
   179  		t.Fatal("ComputeClass() didn't set computed class")
   180  	}
   181  	if old != n.ComputedClass {
   182  		t.Fatal("ComputeClass() didn't ignore unique meta key")
   183  	}
   184  }
   185  
   186  func TestNode_EscapedConstraints(t *testing.T) {
   187  	// Non-escaped constraints
   188  	ne1 := &Constraint{
   189  		LTarget: "${attr.kernel.name}",
   190  		RTarget: "linux",
   191  		Operand: "=",
   192  	}
   193  	ne2 := &Constraint{
   194  		LTarget: "${meta.key_foo}",
   195  		RTarget: "linux",
   196  		Operand: "<",
   197  	}
   198  	ne3 := &Constraint{
   199  		LTarget: "${node.dc}",
   200  		RTarget: "test",
   201  		Operand: "!=",
   202  	}
   203  
   204  	// Escaped constraints
   205  	e1 := &Constraint{
   206  		LTarget: "${attr.unique.kernel.name}",
   207  		RTarget: "linux",
   208  		Operand: "=",
   209  	}
   210  	e2 := &Constraint{
   211  		LTarget: "${meta.unique.key_foo}",
   212  		RTarget: "linux",
   213  		Operand: "<",
   214  	}
   215  	e3 := &Constraint{
   216  		LTarget: "${unique.node.id}",
   217  		RTarget: "test",
   218  		Operand: "!=",
   219  	}
   220  	constraints := []*Constraint{ne1, ne2, ne3, e1, e2, e3}
   221  	expected := []*Constraint{ne1, ne2, ne3}
   222  	if act := EscapedConstraints(constraints); reflect.DeepEqual(act, expected) {
   223  		t.Fatalf("EscapedConstraints(%v) returned %v; want %v", constraints, act, expected)
   224  	}
   225  }