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  }