083b35d651
Adds a `CSIVolumeClaim` type to be tracked as current and past claims on a volume. Allows for a client RPC failure during node or controller detachment without having to keep the allocation around after the first garbage collection eval. This changeset lays groundwork for moving the actual detachment RPCs into a volume watching loop outside the GC eval.
81 lines
2.1 KiB
Go
81 lines
2.1 KiB
Go
package csimanager
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/nomad/client/dynamicplugins"
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
"github.com/hashicorp/nomad/plugins/csi"
|
|
"github.com/hashicorp/nomad/plugins/csi/fake"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func setupTestNodeInstanceManager(t *testing.T) (*fake.Client, *instanceManager) {
|
|
tp := &fake.Client{}
|
|
|
|
logger := testlog.HCLogger(t)
|
|
pinfo := &dynamicplugins.PluginInfo{
|
|
Name: "test-plugin",
|
|
}
|
|
|
|
return tp, &instanceManager{
|
|
logger: logger,
|
|
info: pinfo,
|
|
client: tp,
|
|
fp: &pluginFingerprinter{
|
|
logger: logger.Named("fingerprinter"),
|
|
info: pinfo,
|
|
client: tp,
|
|
fingerprintNode: true,
|
|
hadFirstSuccessfulFingerprintCh: make(chan struct{}),
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestInstanceManager_Shutdown(t *testing.T) {
|
|
|
|
var pluginHealth bool
|
|
var lock sync.Mutex
|
|
ctx, cancelFn := context.WithCancel(context.Background())
|
|
client, im := setupTestNodeInstanceManager(t)
|
|
im.shutdownCtx = ctx
|
|
im.shutdownCtxCancelFn = cancelFn
|
|
im.shutdownCh = make(chan struct{})
|
|
im.updater = func(_ string, info *structs.CSIInfo) {
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
pluginHealth = info.Healthy
|
|
}
|
|
|
|
// set up a mock successful fingerprint so that we can get
|
|
// a healthy plugin before shutting down
|
|
client.NextPluginGetCapabilitiesResponse = &csi.PluginCapabilitySet{}
|
|
client.NextPluginGetCapabilitiesErr = nil
|
|
client.NextNodeGetInfoResponse = &csi.NodeGetInfoResponse{NodeID: "foo"}
|
|
client.NextNodeGetInfoErr = nil
|
|
client.NextNodeGetCapabilitiesResponse = &csi.NodeCapabilitySet{}
|
|
client.NextNodeGetCapabilitiesErr = nil
|
|
client.NextPluginProbeResponse = true
|
|
|
|
go im.runLoop()
|
|
|
|
require.Eventually(t, func() bool {
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
return pluginHealth
|
|
}, 1*time.Second, 10*time.Millisecond)
|
|
|
|
cancelFn() // fires im.shutdown()
|
|
|
|
require.Eventually(t, func() bool {
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
return !pluginHealth
|
|
}, 1*time.Second, 10*time.Millisecond)
|
|
|
|
}
|