Files
nomad/client/driver_manager_test.go
Luiz Aoqui 9d4f7bcb68 mock_driver: fix fingreprint key (#20351)
The `mock_driver` is an internal task driver used mostly for testing and
simulating workloads. During the allocrunner v2 work (#4792) its name
changed from `mock_driver` to just `mock` and then back to
`mock_driver`, but the fingreprint key was kept as `driver.mock`.

This results in tasks configured with `driver = "mock"` to be scheduled
(because Nomad thinks the client has a task driver called `mock`), but
fail to actually run (because the Nomad client can't find a driver
called `mock` in its catalog).

Fingerprinting the right name prevents the job from being scheduled in
the first place.

Also removes mentions of the mock driver from documentation since its an
internal driver and not available in any production release.
2024-04-16 07:16:55 +01:00

195 lines
5.3 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package client
import (
"fmt"
"testing"
"time"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/lib/numalib"
"github.com/hashicorp/nomad/client/pluginmanager/drivermanager"
"github.com/hashicorp/nomad/helper/pluginutils/catalog"
nconfig "github.com/hashicorp/nomad/nomad/structs/config"
"github.com/hashicorp/nomad/testutil"
"github.com/stretchr/testify/require"
)
var (
topology = numalib.Scan(numalib.PlatformScanners())
)
// TestDriverManager_Fingerprint_Run asserts that node is populated with
// driver fingerprints
func TestDriverManager_Fingerprint_Run(t *testing.T) {
ci.Parallel(t)
testClient, cleanup := TestClient(t, nil)
defer cleanup()
conf := testClient.GetConfig()
dm := drivermanager.New(&drivermanager.Config{
Logger: testClient.logger,
Loader: conf.PluginSingletonLoader,
PluginConfig: conf.NomadPluginConfig(topology),
Updater: testClient.updateNodeFromDriver,
EventHandlerFactory: testClient.GetTaskEventHandler,
State: testClient.stateDB,
})
go dm.Run()
defer dm.Shutdown()
testutil.WaitForResult(func() (bool, error) {
node := testClient.Node()
d, ok := node.Drivers["mock_driver"]
if !ok {
return false, fmt.Errorf("mock_driver driver is not present: %+v", node.Drivers)
}
if !d.Detected || !d.Healthy {
return false, fmt.Errorf("mock_driver driver is not marked healthy: %+v", d)
}
return true, nil
}, func(err error) {
require.NoError(t, err)
})
}
// TestDriverManager_Fingerprint_Run asserts that node is populated with
// driver fingerprints and it's updated periodically
func TestDriverManager_Fingerprint_Periodic(t *testing.T) {
ci.Parallel(t)
testClient, cleanup := TestClient(t, func(c *config.Config) {
pluginConfig := []*nconfig.PluginConfig{
{
Name: "mock_driver",
Config: map[string]interface{}{
"shutdown_periodic_after": true,
"shutdown_periodic_duration": 2 * time.Second,
},
},
}
c.PluginLoader = catalog.TestPluginLoaderWithOptions(t, "", map[string]string{}, pluginConfig)
})
defer cleanup()
conf := testClient.GetConfig()
dm := drivermanager.New(&drivermanager.Config{
Logger: testClient.logger,
Loader: conf.PluginSingletonLoader,
PluginConfig: conf.NomadPluginConfig(topology),
Updater: testClient.updateNodeFromDriver,
EventHandlerFactory: testClient.GetTaskEventHandler,
State: testClient.stateDB,
})
go dm.Run()
defer dm.Shutdown()
// we get a healthy mock_driver first
testutil.WaitForResult(func() (bool, error) {
node := testClient.Node()
d, ok := node.Drivers["mock_driver"]
if !ok {
return false, fmt.Errorf("mock_driver driver is not present: %+v", node.Drivers)
}
if !d.Detected || !d.Healthy {
return false, fmt.Errorf("mock_driver driver is not marked healthy: %+v", d)
}
return true, nil
}, func(err error) {
require.NoError(t, err)
})
// eventually, the mock_driver is marked as unhealthy
testutil.WaitForResult(func() (bool, error) {
node := testClient.Node()
d, ok := node.Drivers["mock_driver"]
if !ok {
return false, fmt.Errorf("mock_driver driver is not present: %+v", node.Drivers)
}
if d.Detected || d.Healthy {
return false, fmt.Errorf("mock_driver driver is still marked as healthy: %+v", d)
}
return true, nil
}, func(err error) {
require.NoError(t, err)
})
}
// TestDriverManager_NodeAttributes_Run asserts that node attributes are populated
// in addition to node.Drivers until we fully deprecate it
func TestDriverManager_NodeAttributes_Run(t *testing.T) {
ci.Parallel(t)
testClient, cleanup := TestClient(t, func(c *config.Config) {
c.Options = map[string]string{
"driver.raw_exec.enable": "1",
}
})
defer cleanup()
conf := testClient.GetConfig()
dm := drivermanager.New(&drivermanager.Config{
Logger: testClient.logger,
Loader: conf.PluginSingletonLoader,
PluginConfig: conf.NomadPluginConfig(topology),
Updater: testClient.updateNodeFromDriver,
EventHandlerFactory: testClient.GetTaskEventHandler,
State: testClient.stateDB,
})
go dm.Run()
defer dm.Shutdown()
// we should have mock_driver as well as raw_exec in node attributes
testutil.WaitForResult(func() (bool, error) {
node := testClient.Node()
// check mock driver
if node.Attributes["driver.mock_driver"] == "" {
return false, fmt.Errorf("mock_driver is not present in attributes: %#v", node.Attributes)
}
d, ok := node.Drivers["mock_driver"]
if !ok {
return false, fmt.Errorf("mock_driver is not present in drivers: %#v", node.Drivers)
}
if !d.Detected || !d.Healthy {
return false, fmt.Errorf("mock_driver driver is not marked as healthy: %+v", d)
}
// check raw_exec
if node.Attributes["driver.raw_exec"] == "" {
return false, fmt.Errorf("raw_exec is not present in attributes: %#v", node.Attributes)
}
d, ok = node.Drivers["raw_exec"]
if !ok {
return false, fmt.Errorf("raw_exec is not present in drivers: %#v", node.Drivers)
}
if !d.Detected || !d.Healthy {
return false, fmt.Errorf("raw_exec driver is not marked as healthy: %+v", d)
}
return true, nil
}, func(err error) {
require.NoError(t, err)
})
}