mirror of
https://github.com/kemko/nomad.git
synced 2026-01-05 01:45:44 +03:00
client: Implement ClientCSI.ControllerValidateVolume
This commit is contained in:
committed by
Tim Gross
parent
7ffdba7636
commit
9dff902a36
@@ -30,6 +30,36 @@ var (
|
||||
ErrPluginTypeError = errors.New("CSI Plugin loaded incorrectly")
|
||||
)
|
||||
|
||||
// CSIControllerValidateVolume is used during volume registration to validate
|
||||
// that a volume exists and that the capabilities it was registered with are
|
||||
// supported by the CSI Plugin and external volume configuration.
|
||||
func (c *ClientCSI) CSIControllerValidateVolume(req *structs.ClientCSIControllerValidateVolumeRequest, resp *structs.ClientCSIControllerValidateVolumeResponse) error {
|
||||
defer metrics.MeasureSince([]string{"client", "csi_controller", "validate_volume"}, time.Now())
|
||||
|
||||
if req.VolumeID == "" {
|
||||
return errors.New("VolumeID is required")
|
||||
}
|
||||
|
||||
if req.PluginID == "" {
|
||||
return errors.New("PluginID is required")
|
||||
}
|
||||
|
||||
plugin, err := c.findControllerPlugin(req.PluginID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer plugin.Close()
|
||||
|
||||
caps, err := csi.VolumeCapabilityFromStructs(req.AttachmentMode, req.AccessMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFn := c.requestContext()
|
||||
defer cancelFn()
|
||||
return plugin.ControllerValidateCapabilties(ctx, req.VolumeID, caps)
|
||||
}
|
||||
|
||||
// CSIControllerAttachVolume is used to attach a volume from a CSI Cluster to
|
||||
// the storage node provided in the request.
|
||||
//
|
||||
|
||||
@@ -147,3 +147,92 @@ func TestClientCSI_CSIControllerAttachVolume(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientCSI_CSIControllerValidateVolume(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
ClientSetupFunc func(*fake.Client)
|
||||
Request *structs.ClientCSIControllerValidateVolumeRequest
|
||||
ExpectedErr error
|
||||
ExpectedResponse *structs.ClientCSIControllerValidateVolumeResponse
|
||||
}{
|
||||
{
|
||||
Name: "validates volumeid is not empty",
|
||||
Request: &structs.ClientCSIControllerValidateVolumeRequest{
|
||||
PluginID: fakePlugin.Name,
|
||||
},
|
||||
ExpectedErr: errors.New("VolumeID is required"),
|
||||
},
|
||||
{
|
||||
Name: "returns plugin not found errors",
|
||||
Request: &structs.ClientCSIControllerValidateVolumeRequest{
|
||||
PluginID: "some-garbage",
|
||||
VolumeID: "foo",
|
||||
},
|
||||
ExpectedErr: errors.New("plugin some-garbage for type csi-controller not found"),
|
||||
},
|
||||
{
|
||||
Name: "validates attachmentmode",
|
||||
Request: &structs.ClientCSIControllerValidateVolumeRequest{
|
||||
PluginID: fakePlugin.Name,
|
||||
VolumeID: "1234-4321-1234-4321",
|
||||
AttachmentMode: nstructs.CSIVolumeAttachmentMode("bar"),
|
||||
AccessMode: nstructs.CSIVolumeAccessModeMultiNodeReader,
|
||||
},
|
||||
ExpectedErr: errors.New("Unknown volume attachment mode: bar"),
|
||||
},
|
||||
{
|
||||
Name: "validates AccessMode",
|
||||
Request: &structs.ClientCSIControllerValidateVolumeRequest{
|
||||
PluginID: fakePlugin.Name,
|
||||
VolumeID: "1234-4321-1234-4321",
|
||||
AttachmentMode: nstructs.CSIVolumeAttachmentModeFilesystem,
|
||||
AccessMode: nstructs.CSIVolumeAccessMode("foo"),
|
||||
},
|
||||
ExpectedErr: errors.New("Unknown volume access mode: foo"),
|
||||
},
|
||||
{
|
||||
Name: "returns transitive errors",
|
||||
ClientSetupFunc: func(fc *fake.Client) {
|
||||
fc.NextControllerValidateVolumeErr = errors.New("hello")
|
||||
},
|
||||
Request: &structs.ClientCSIControllerValidateVolumeRequest{
|
||||
PluginID: fakePlugin.Name,
|
||||
VolumeID: "1234-4321-1234-4321",
|
||||
AccessMode: nstructs.CSIVolumeAccessModeSingleNodeWriter,
|
||||
AttachmentMode: nstructs.CSIVolumeAttachmentModeFilesystem,
|
||||
},
|
||||
ExpectedErr: errors.New("hello"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
client, cleanup := TestClient(t, nil)
|
||||
defer cleanup()
|
||||
|
||||
fakeClient := &fake.Client{}
|
||||
if tc.ClientSetupFunc != nil {
|
||||
tc.ClientSetupFunc(fakeClient)
|
||||
}
|
||||
|
||||
dispenserFunc := func(*dynamicplugins.PluginInfo) (interface{}, error) {
|
||||
return fakeClient, nil
|
||||
}
|
||||
client.dynamicRegistry.StubDispenserForType(dynamicplugins.PluginTypeCSIController, dispenserFunc)
|
||||
|
||||
err := client.dynamicRegistry.RegisterPlugin(fakePlugin)
|
||||
require.Nil(err)
|
||||
|
||||
var resp structs.ClientCSIControllerValidateVolumeResponse
|
||||
err = client.ClientRPC("ClientCSI.CSIControllerValidateVolume", tc.Request, &resp)
|
||||
require.Equal(tc.ExpectedErr, err)
|
||||
if tc.ExpectedResponse != nil {
|
||||
require.Equal(tc.ExpectedResponse, &resp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,17 @@ type CSIVolumeMountOptions struct {
|
||||
MountFlags []string
|
||||
}
|
||||
|
||||
type ClientCSIControllerValidateVolumeRequest struct {
|
||||
PluginID string
|
||||
VolumeID string
|
||||
|
||||
AttachmentMode structs.CSIVolumeAttachmentMode
|
||||
AccessMode structs.CSIVolumeAccessMode
|
||||
}
|
||||
|
||||
type ClientCSIControllerValidateVolumeResponse struct {
|
||||
}
|
||||
|
||||
type ClientCSIControllerAttachVolumeRequest struct {
|
||||
PluginName string
|
||||
|
||||
|
||||
Reference in New Issue
Block a user