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 }