open-nomad/client/pluginmanager/drivermanager/instance_test.go

124 lines
4.4 KiB
Go
Raw Normal View History

package drivermanager
import (
"context"
"fmt"
"testing"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/nomad/helper/pluginutils/loader"
"github.com/hashicorp/nomad/helper/pluginutils/singleton"
"github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/plugins/base"
dtu "github.com/hashicorp/nomad/plugins/drivers/testutils"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
type mockedCatalog struct {
mock.Mock
}
func (m *mockedCatalog) Dispense(name, pluginType string, cfg *base.AgentConfig, logger log.Logger) (loader.PluginInstance, error) {
args := m.Called(name, pluginType, cfg, logger)
return loader.MockBasicExternalPlugin(&dtu.MockDriver{}, "0.1.0"), args.Error(0)
}
func (m *mockedCatalog) Reattach(name, pluginType string, config *plugin.ReattachConfig) (loader.PluginInstance, error) {
args := m.Called(name, pluginType, config)
return loader.MockBasicExternalPlugin(&dtu.MockDriver{}, "0.1.0"), args.Error(0)
}
func (m *mockedCatalog) Catalog() map[string][]*base.PluginInfoResponse {
m.Called()
return map[string][]*base.PluginInfoResponse{
base.PluginTypeDriver: {&base.PluginInfoResponse{Name: "mock", Type: base.PluginTypeDriver}},
}
}
func (m *mockedCatalog) resetMock() {
m.ExpectedCalls = []*mock.Call{}
m.Calls = []mock.Call{}
}
func TestInstanceManager_dispense(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cat := new(mockedCatalog)
cat.Test(t)
var fetchRet bool
i := &instanceManager{
logger: testlog.HCLogger(t),
ctx: ctx,
cancel: cancel,
loader: cat,
storeReattach: func(*plugin.ReattachConfig) error { return nil },
fetchReattach: func() (*plugin.ReattachConfig, bool) { return nil, fetchRet },
pluginConfig: &base.AgentConfig{},
id: &loader.PluginID{Name: "mock", PluginType: base.PluginTypeDriver},
updateNodeFromDriver: noopUpdater,
eventHandlerFactory: noopEventHandlerFactory,
firstFingerprintCh: make(chan struct{}),
}
require := require.New(t)
// First test the happy path, no reattach config is stored, plugin dispenses without error
fetchRet = false
cat.On("Dispense", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
plug, err := i.dispense()
require.NoError(err)
cat.AssertNumberOfCalls(t, "Dispense", 1)
cat.AssertNumberOfCalls(t, "Reattach", 0)
// Dispensing a second time should not dispense a new plugin from the catalog, but reuse the existing
plug2, err := i.dispense()
require.NoError(err)
cat.AssertNumberOfCalls(t, "Dispense", 1)
cat.AssertNumberOfCalls(t, "Reattach", 0)
require.Same(plug, plug2)
// If the plugin has exited test that the manager attempts to retry dispense
cat.resetMock()
i.plugin = nil
cat.On("Dispense", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(singleton.SingletonPluginExited)
_, err = i.dispense()
require.Error(err)
cat.AssertNumberOfCalls(t, "Dispense", 2)
cat.AssertNumberOfCalls(t, "Reattach", 0)
// Test that when a reattach config exists it attempts plugin reattachment
// First case is when plugin reattachment is successful
fetchRet = true
cat.resetMock()
i.plugin = nil
cat.On("Dispense", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
cat.On("Reattach", mock.Anything, mock.Anything, mock.Anything).Return(nil)
plug, err = i.dispense()
require.NoError(err)
cat.AssertNumberOfCalls(t, "Dispense", 0)
cat.AssertNumberOfCalls(t, "Reattach", 1)
// Dispensing a second time should not dispense a new plugin from the catalog
plug2, err = i.dispense()
require.NoError(err)
cat.AssertNumberOfCalls(t, "Dispense", 0)
cat.AssertNumberOfCalls(t, "Reattach", 1)
require.Same(plug, plug2)
// Finally test when reattachment fails. A new plugin should be dispensed
cat.resetMock()
i.plugin = nil
cat.On("Dispense", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
cat.On("Reattach", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("failed to dispense"))
plug, err = i.dispense()
require.NoError(err)
cat.AssertNumberOfCalls(t, "Dispense", 1)
cat.AssertNumberOfCalls(t, "Reattach", 1)
// Dispensing a second time should not dispense a new plugin from the catalog
plug2, err = i.dispense()
require.NoError(err)
cat.AssertNumberOfCalls(t, "Dispense", 1)
cat.AssertNumberOfCalls(t, "Reattach", 1)
require.Same(plug, plug2)
}