github.com/zhizhiboom/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/client/fingerprint_manager_test.go (about)

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