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