open-nomad/api/csi_test.go
Tim Gross 23be116da0
csi: add -force flag to volume deregister (#8295)
The `nomad volume deregister` command currently returns an error if the volume
has any claims, but in cases where the claims can't be dropped because of
plugin errors, providing a `-force` flag gives the operator an escape hatch.

If the volume has no allocations or if they are all terminal, this flag
deletes the volume from the state store, immediately and implicitly dropping
all claims without further CSI RPCs. Note that this will not also
unmount/detach the volume, which we'll make the responsibility of a separate
`nomad volume detach` command.
2020-07-01 12:17:51 -04:00

102 lines
2.7 KiB
Go

package api
import (
"testing"
"github.com/stretchr/testify/require"
)
// TestCSIVolumes_CRUD fails because of a combination of removing the job to plugin creation
// pathway and checking for plugin existence (but not yet health) at registration time.
// There are two possible solutions:
// 1. Expose the test server RPC server and force a Node.Update to fingerprint a plugin
// 2. Build and deploy a dummy CSI plugin via a job, and have it really fingerprint
func TestCSIVolumes_CRUD(t *testing.T) {
t.Parallel()
c, s, root := makeACLClient(t, nil, nil)
defer s.Stop()
v := c.CSIVolumes()
// Successful empty result
vols, qm, err := v.List(nil)
require.NoError(t, err)
require.NotEqual(t, 0, qm.LastIndex)
require.Equal(t, 0, len(vols))
// FIXME we're bailing out here until one of the fixes is available
return
// Authorized QueryOpts. Use the root token to just bypass ACL details
opts := &QueryOptions{
Region: "global",
Namespace: "default",
AuthToken: root.SecretID,
}
wpts := &WriteOptions{
Region: "global",
Namespace: "default",
AuthToken: root.SecretID,
}
// Create node plugins
nodes, _, err := c.Nodes().List(nil)
require.NoError(t, err)
require.Equal(t, 1, len(nodes))
nodeStub := nodes[0]
node, _, err := c.Nodes().Info(nodeStub.ID, nil)
require.NoError(t, err)
node.CSINodePlugins = map[string]*CSIInfo{
"foo": {
PluginID: "foo",
Healthy: true,
RequiresControllerPlugin: false,
RequiresTopologies: false,
NodeInfo: &CSINodeInfo{
ID: nodeStub.ID,
MaxVolumes: 200,
},
},
}
// Register a volume
// This id is here as a string to avoid importing helper, which causes the lint
// rule that checks that the api package is isolated to fail
id := "DEADBEEF-31B5-8F78-7986-DD404FDA0CD1"
_, err = v.Register(&CSIVolume{
ID: id,
Namespace: "default",
PluginID: "foo",
AccessMode: CSIVolumeAccessModeMultiNodeSingleWriter,
AttachmentMode: CSIVolumeAttachmentModeFilesystem,
Topologies: []*CSITopology{{Segments: map[string]string{"foo": "bar"}}},
}, wpts)
require.NoError(t, err)
// Successful result with volumes
vols, qm, err = v.List(opts)
require.NoError(t, err)
require.NotEqual(t, 0, qm.LastIndex)
require.Equal(t, 1, len(vols))
// Successful info query
vol, qm, err := v.Info(id, opts)
require.NoError(t, err)
require.Equal(t, "bar", vol.Topologies[0].Segments["foo"])
// Deregister the volume
err = v.Deregister(id, true, wpts)
require.NoError(t, err)
// Successful empty result
vols, qm, err = v.List(nil)
require.NoError(t, err)
require.NotEqual(t, 0, qm.LastIndex)
require.Equal(t, 0, len(vols))
// Failed info query
vol, qm, err = v.Info(id, opts)
require.Error(t, err, "missing")
}