github.com/emate/nomad@v0.8.2-wo-binpacking/client/fingerprint_manager_test.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "testing" 8 9 "github.com/hashicorp/nomad/client/config" 10 "github.com/hashicorp/nomad/testutil" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestFingerprintManager_Run_MockDriver(t *testing.T) { 15 t.Parallel() 16 require := require.New(t) 17 testClient := TestClient(t, nil) 18 19 testClient.logger = log.New(os.Stderr, "", log.LstdFlags) 20 defer testClient.Shutdown() 21 22 fm := NewFingerprintManager( 23 testClient.GetConfig, 24 testClient.config.Node, 25 testClient.shutdownCh, 26 testClient.updateNodeFromFingerprint, 27 testClient.updateNodeFromDriver, 28 testLogger(), 29 ) 30 31 err := fm.Run() 32 require.Nil(err) 33 34 node := testClient.config.Node 35 36 require.NotNil(node.Drivers["mock_driver"]) 37 require.True(node.Drivers["mock_driver"].Detected) 38 require.True(node.Drivers["mock_driver"].Healthy) 39 } 40 41 func TestFingerprintManager_Run_ResourcesFingerprint(t *testing.T) { 42 t.Parallel() 43 require := require.New(t) 44 testClient := TestClient(t, nil) 45 46 testClient.logger = testLogger() 47 defer testClient.Shutdown() 48 49 fm := NewFingerprintManager( 50 testClient.GetConfig, 51 testClient.config.Node, 52 testClient.shutdownCh, 53 testClient.updateNodeFromFingerprint, 54 testClient.updateNodeFromDriver, 55 testClient.logger, 56 ) 57 58 err := fm.Run() 59 require.Nil(err) 60 61 node := testClient.config.Node 62 63 require.NotEqual(0, node.Resources.CPU) 64 require.NotEqual(0, node.Resources.MemoryMB) 65 require.NotZero(node.Resources.DiskMB) 66 } 67 68 func TestFingerprintManager_Fingerprint_Run(t *testing.T) { 69 t.Parallel() 70 require := require.New(t) 71 testClient := TestClient(t, nil) 72 73 testClient.logger = testLogger() 74 defer testClient.Shutdown() 75 76 fm := NewFingerprintManager( 77 testClient.GetConfig, 78 testClient.config.Node, 79 testClient.shutdownCh, 80 testClient.updateNodeFromFingerprint, 81 testClient.updateNodeFromDriver, 82 testClient.logger, 83 ) 84 85 err := fm.Run() 86 require.Nil(err) 87 88 node := testClient.config.Node 89 90 require.NotNil(node.Drivers["raw_exec"]) 91 require.True(node.Drivers["raw_exec"].Detected) 92 require.True(node.Drivers["raw_exec"].Healthy) 93 } 94 95 func TestFingerprintManager_Fingerprint_Periodic(t *testing.T) { 96 t.Parallel() 97 require := require.New(t) 98 testClient := TestClient(t, func(c *config.Config) { 99 c.Options = map[string]string{ 100 "test.shutdown_periodic_after": "true", 101 "test.shutdown_periodic_duration": "2", 102 } 103 }) 104 105 testClient.logger = testLogger() 106 defer testClient.Shutdown() 107 108 fm := NewFingerprintManager( 109 testClient.GetConfig, 110 testClient.config.Node, 111 testClient.shutdownCh, 112 testClient.updateNodeFromFingerprint, 113 testClient.updateNodeFromDriver, 114 testClient.logger, 115 ) 116 117 err := fm.Run() 118 require.Nil(err) 119 120 { 121 // Ensure the mock driver is registered and healthy on the client 122 testutil.WaitForResult(func() (bool, error) { 123 fm.nodeLock.Lock() 124 defer fm.nodeLock.Unlock() 125 node := fm.node 126 dinfo, ok := node.Drivers["mock_driver"] 127 if !ok || !dinfo.Detected || !dinfo.Healthy { 128 return false, fmt.Errorf("mock driver should be detected and healthy: %+v", dinfo) 129 } 130 131 return true, nil 132 }, func(err error) { 133 t.Fatalf("err: %v", err) 134 }) 135 } 136 // Ensure that the client fingerprinter eventually removes this attribute and 137 // marks the driver as unhealthy 138 { 139 testutil.WaitForResult(func() (bool, error) { 140 fm.nodeLock.Lock() 141 defer fm.nodeLock.Unlock() 142 node := fm.node 143 dinfo, ok := node.Drivers["mock_driver"] 144 if !ok || dinfo.Detected || dinfo.Healthy { 145 return false, fmt.Errorf("mock driver should not be detected and healthy") 146 } 147 return true, nil 148 }, func(err error) { 149 t.Fatalf("err: %v", err) 150 }) 151 } 152 } 153 154 // This is a temporary measure to check that a driver has both attributes on a 155 // node set as well as DriverInfo. 156 func TestFingerprintManager_HealthCheck_Driver(t *testing.T) { 157 t.Parallel() 158 require := require.New(t) 159 testClient := TestClient(t, func(c *config.Config) { 160 c.Options = map[string]string{ 161 "driver.raw_exec.enable": "1", 162 "test.shutdown_periodic_after": "true", 163 "test.shutdown_periodic_duration": "2", 164 } 165 }) 166 167 testClient.logger = testLogger() 168 defer testClient.Shutdown() 169 170 fm := NewFingerprintManager( 171 testClient.GetConfig, 172 testClient.config.Node, 173 testClient.shutdownCh, 174 testClient.updateNodeFromFingerprint, 175 testClient.updateNodeFromDriver, 176 testClient.logger, 177 ) 178 179 err := fm.Run() 180 require.Nil(err) 181 182 // Ensure the mock driver is registered and healthy on the client 183 testutil.WaitForResult(func() (bool, error) { 184 fm.nodeLock.Lock() 185 node := fm.node 186 defer fm.nodeLock.Unlock() 187 188 mockDriverAttribute := node.Attributes["driver.mock_driver"] 189 if mockDriverAttribute == "" { 190 return false, fmt.Errorf("mock driver info should be set on the client attributes") 191 } 192 mockDriverInfo := node.Drivers["mock_driver"] 193 if mockDriverInfo == nil { 194 return false, fmt.Errorf("mock driver info should be set on the client") 195 } 196 if !mockDriverInfo.Healthy { 197 return false, fmt.Errorf("mock driver info should be healthy") 198 } 199 return true, nil 200 }, func(err error) { 201 t.Fatalf("err: %v", err) 202 }) 203 204 // Ensure that a default driver without health checks enabled is registered and healthy on the client 205 testutil.WaitForResult(func() (bool, error) { 206 fm.nodeLock.Lock() 207 node := fm.node 208 defer fm.nodeLock.Unlock() 209 210 rawExecAttribute := node.Attributes["driver.raw_exec"] 211 if rawExecAttribute == "" { 212 return false, fmt.Errorf("raw exec info should be set on the client attributes") 213 } 214 rawExecInfo := node.Drivers["raw_exec"] 215 if rawExecInfo == nil { 216 return false, fmt.Errorf("raw exec driver info should be set on the client") 217 } 218 if !rawExecInfo.Detected { 219 return false, fmt.Errorf("raw exec driver should be detected") 220 } 221 return true, nil 222 }, func(err error) { 223 t.Fatalf("err: %v", err) 224 }) 225 226 // Ensure the mock driver is registered 227 testutil.WaitForResult(func() (bool, error) { 228 fm.nodeLock.Lock() 229 node := fm.node 230 defer fm.nodeLock.Unlock() 231 232 mockDriverAttribute := node.Attributes["driver.mock_driver"] 233 if mockDriverAttribute == "" { 234 return false, fmt.Errorf("mock driver info should set on the client attributes") 235 } 236 mockDriverInfo := node.Drivers["mock_driver"] 237 if mockDriverInfo == nil { 238 return false, fmt.Errorf("mock driver info should be set on the client") 239 } 240 if !mockDriverInfo.Healthy { 241 return false, fmt.Errorf("mock driver info should not be healthy") 242 } 243 return true, nil 244 }, func(err error) { 245 t.Fatalf("err: %v", err) 246 }) 247 248 // Ensure that we don't duplicate health check information on the driver 249 // health information 250 fm.nodeLock.Lock() 251 node := fm.node 252 fm.nodeLock.Unlock() 253 mockDriverAttributes := node.Drivers["mock_driver"].Attributes 254 require.NotContains(mockDriverAttributes, "driver.mock_driver") 255 } 256 257 func TestFingerprintManager_HealthCheck_Periodic(t *testing.T) { 258 t.Parallel() 259 require := require.New(t) 260 testClient := TestClient(t, func(c *config.Config) { 261 c.Options = map[string]string{ 262 "test.shutdown_periodic_after": "true", 263 "test.shutdown_periodic_duration": "2", 264 } 265 }) 266 267 testClient.logger = testLogger() 268 defer testClient.Shutdown() 269 270 fm := NewFingerprintManager( 271 testClient.GetConfig, 272 testClient.config.Node, 273 testClient.shutdownCh, 274 testClient.updateNodeFromFingerprint, 275 testClient.updateNodeFromDriver, 276 testClient.logger, 277 ) 278 279 err := fm.Run() 280 require.Nil(err) 281 282 { 283 // Ensure the mock driver is registered and healthy on the client 284 testutil.WaitForResult(func() (bool, error) { 285 fm.nodeLock.Lock() 286 node := fm.node 287 defer fm.nodeLock.Unlock() 288 289 mockDriverInfo := node.Drivers["mock_driver"] 290 if mockDriverInfo == nil { 291 return false, fmt.Errorf("mock driver info should be set on the client") 292 } 293 if !mockDriverInfo.Detected { 294 return false, fmt.Errorf("mock driver info should be detected") 295 } 296 if !mockDriverInfo.Healthy { 297 return false, fmt.Errorf("mock driver info should be healthy") 298 } 299 return true, nil 300 }, func(err error) { 301 t.Fatalf("err: %v", err) 302 }) 303 } 304 { 305 // Ensure that the client health check eventually removes this attribute and 306 // marks the driver as unhealthy 307 testutil.WaitForResult(func() (bool, error) { 308 fm.nodeLock.Lock() 309 node := fm.node 310 defer fm.nodeLock.Unlock() 311 312 mockDriverInfo := node.Drivers["mock_driver"] 313 if mockDriverInfo == nil { 314 return false, fmt.Errorf("mock driver info should be set on the client") 315 } 316 if !mockDriverInfo.Detected { 317 return false, fmt.Errorf("mock driver info should be detected") 318 } 319 if !mockDriverInfo.Healthy { 320 return false, fmt.Errorf("mock driver info should be healthy") 321 } 322 return true, nil 323 }, func(err error) { 324 t.Fatalf("err: %v", err) 325 }) 326 } 327 { 328 // Ensure that the client health check eventually removes this attribute and 329 // marks the driver as unhealthy 330 testutil.WaitForResult(func() (bool, error) { 331 fm.nodeLock.Lock() 332 node := fm.node 333 defer fm.nodeLock.Unlock() 334 335 mockDriverInfo := node.Drivers["mock_driver"] 336 if mockDriverInfo == nil { 337 return false, fmt.Errorf("mock driver info should be set on the client") 338 } 339 if mockDriverInfo.Detected { 340 return false, fmt.Errorf("mock driver should be detected") 341 } 342 if mockDriverInfo.Healthy { 343 return false, fmt.Errorf("mock driver should not be healthy") 344 } 345 return true, nil 346 }, func(err error) { 347 t.Fatalf("err: %v", err) 348 }) 349 } 350 } 351 352 func TestFimgerprintManager_Run_InWhitelist(t *testing.T) { 353 t.Parallel() 354 require := require.New(t) 355 356 testClient := TestClient(t, func(c *config.Config) { 357 c.Options = map[string]string{ 358 "test.shutdown_periodic_after": "true", 359 "test.shutdown_periodic_duration": "2", 360 } 361 }) 362 363 testClient.logger = testLogger() 364 defer testClient.Shutdown() 365 366 fm := NewFingerprintManager( 367 testClient.GetConfig, 368 testClient.config.Node, 369 testClient.shutdownCh, 370 testClient.updateNodeFromFingerprint, 371 testClient.updateNodeFromDriver, 372 testClient.logger, 373 ) 374 375 err := fm.Run() 376 require.Nil(err) 377 378 node := testClient.config.Node 379 380 require.NotEqual(node.Attributes["cpu.frequency"], "") 381 } 382 383 func TestFingerprintManager_Run_InBlacklist(t *testing.T) { 384 t.Parallel() 385 require := require.New(t) 386 testClient := TestClient(t, func(c *config.Config) { 387 c.Options = map[string]string{ 388 "fingerprint.whitelist": " arch,memory,foo,bar ", 389 "fingerprint.blacklist": " cpu ", 390 } 391 }) 392 393 testClient.logger = testLogger() 394 defer testClient.Shutdown() 395 396 fm := NewFingerprintManager( 397 testClient.GetConfig, 398 testClient.config.Node, 399 testClient.shutdownCh, 400 testClient.updateNodeFromFingerprint, 401 testClient.updateNodeFromDriver, 402 testClient.logger, 403 ) 404 405 err := fm.Run() 406 require.Nil(err) 407 408 node := testClient.config.Node 409 410 require.NotContains(node.Attributes, "cpu.frequency") 411 require.NotEqual(node.Attributes["memory.totalbytes"], "") 412 } 413 414 func TestFingerprintManager_Run_Combination(t *testing.T) { 415 t.Parallel() 416 require := require.New(t) 417 418 testClient := TestClient(t, func(c *config.Config) { 419 c.Options = map[string]string{ 420 "fingerprint.whitelist": " arch,cpu,memory,foo,bar ", 421 "fingerprint.blacklist": " memory,nomad ", 422 } 423 }) 424 425 testClient.logger = testLogger() 426 defer testClient.Shutdown() 427 428 fm := NewFingerprintManager( 429 testClient.GetConfig, 430 testClient.config.Node, 431 testClient.shutdownCh, 432 testClient.updateNodeFromFingerprint, 433 testClient.updateNodeFromDriver, 434 testClient.logger, 435 ) 436 437 err := fm.Run() 438 require.Nil(err) 439 440 node := testClient.config.Node 441 442 require.NotEqual(node.Attributes["cpu.frequency"], "") 443 require.NotEqual(node.Attributes["cpu.arch"], "") 444 require.NotContains(node.Attributes, "memory.totalbytes") 445 require.NotContains(node.Attributes, "nomad.version") 446 } 447 448 func TestFingerprintManager_Run_WhitelistDrivers(t *testing.T) { 449 t.Parallel() 450 require := require.New(t) 451 testClient := TestClient(t, func(c *config.Config) { 452 c.Options = map[string]string{ 453 "driver.raw_exec.enable": "1", 454 "driver.whitelist": " raw_exec , foo ", 455 } 456 }) 457 458 testClient.logger = testLogger() 459 defer testClient.Shutdown() 460 461 fm := NewFingerprintManager( 462 testClient.GetConfig, 463 testClient.config.Node, 464 testClient.shutdownCh, 465 testClient.updateNodeFromFingerprint, 466 testClient.updateNodeFromDriver, 467 testClient.logger, 468 ) 469 470 err := fm.Run() 471 require.Nil(err) 472 473 node := testClient.config.Node 474 require.NotNil(node.Drivers["raw_exec"]) 475 require.NotContains(node.Drivers, "java") 476 } 477 478 func TestFingerprintManager_Run_AllDriversBlacklisted(t *testing.T) { 479 t.Parallel() 480 require := require.New(t) 481 482 testClient := TestClient(t, func(c *config.Config) { 483 c.Options = map[string]string{ 484 "driver.whitelist": " foo,bar,baz ", 485 } 486 }) 487 488 testClient.logger = testLogger() 489 defer testClient.Shutdown() 490 491 fm := NewFingerprintManager( 492 testClient.GetConfig, 493 testClient.config.Node, 494 testClient.shutdownCh, 495 testClient.updateNodeFromFingerprint, 496 testClient.updateNodeFromDriver, 497 testClient.logger, 498 ) 499 500 err := fm.Run() 501 require.Nil(err) 502 503 node := testClient.config.Node 504 505 require.NotContains(node.Attributes, "driver.raw_exec") 506 require.NotContains(node.Attributes, "driver.exec") 507 require.NotContains(node.Attributes, "driver.docker") 508 } 509 510 func TestFingerprintManager_Run_DriversWhiteListBlacklistCombination(t *testing.T) { 511 t.Parallel() 512 require := require.New(t) 513 514 testClient := TestClient(t, func(c *config.Config) { 515 c.Options = map[string]string{ 516 "driver.raw_exec.enable": "1", 517 "driver.whitelist": " raw_exec,exec,foo,bar,baz ", 518 "driver.blacklist": " exec,foo,bar,baz ", 519 } 520 }) 521 522 testClient.logger = testLogger() 523 defer testClient.Shutdown() 524 525 fm := NewFingerprintManager( 526 testClient.GetConfig, 527 testClient.config.Node, 528 testClient.shutdownCh, 529 testClient.updateNodeFromFingerprint, 530 testClient.updateNodeFromDriver, 531 testClient.logger, 532 ) 533 534 err := fm.Run() 535 require.Nil(err) 536 537 node := testClient.config.Node 538 539 require.NotNil(node.Drivers["raw_exec"]) 540 require.NotContains(node.Drivers, "exec") 541 } 542 543 func TestFingerprintManager_Run_DriversInBlacklist(t *testing.T) { 544 t.Parallel() 545 require := require.New(t) 546 547 testClient := TestClient(t, func(c *config.Config) { 548 c.Options = map[string]string{ 549 "driver.raw_exec.enable": "1", 550 "driver.whitelist": " raw_exec,foo,bar,baz ", 551 "driver.blacklist": " exec,foo,bar,baz ", 552 } 553 }) 554 555 testClient.logger = testLogger() 556 defer testClient.Shutdown() 557 558 fm := NewFingerprintManager( 559 testClient.GetConfig, 560 testClient.config.Node, 561 testClient.shutdownCh, 562 testClient.updateNodeFromFingerprint, 563 testClient.updateNodeFromDriver, 564 testClient.logger, 565 ) 566 567 err := fm.Run() 568 require.Nil(err) 569 570 node := testClient.config.Node 571 572 require.NotNil(node.Drivers["raw_exec"]) 573 require.NotContains(node.Drivers, "exec") 574 }