diff --git a/.changelog/11724.txt b/.changelog/11724.txt new file mode 100644 index 000000000..4231e83f7 --- /dev/null +++ b/.changelog/11724.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: Updated the CSI volumes list API to respect wildcard namespaces +``` diff --git a/nomad/csi_endpoint.go b/nomad/csi_endpoint.go index 825abf4be..fea730dfc 100644 --- a/nomad/csi_endpoint.go +++ b/nomad/csi_endpoint.go @@ -129,6 +129,8 @@ func (v *CSIVolume) List(args *structs.CSIVolumeListRequest, reply *structs.CSIV iter, err = snap.CSIVolumesByNodeID(ws, prefix, args.NodeID) } else if args.PluginID != "" { iter, err = snap.CSIVolumesByPluginID(ws, ns, prefix, args.PluginID) + } else if ns == structs.AllNamespacesSentinel { + iter, err = snap.CSIVolumes(ws) } else { iter, err = snap.CSIVolumesByNamespace(ws, ns, prefix) } @@ -155,7 +157,7 @@ func (v *CSIVolume) List(args *structs.CSIVolumeListRequest, reply *structs.CSIV // Remove by Namespace, since CSIVolumesByNodeID hasn't used // the Namespace yet - if vol.Namespace != ns { + if ns != structs.AllNamespacesSentinel && vol.Namespace != ns { continue } diff --git a/nomad/csi_endpoint_test.go b/nomad/csi_endpoint_test.go index 35cafb269..312a93465 100644 --- a/nomad/csi_endpoint_test.go +++ b/nomad/csi_endpoint_test.go @@ -669,6 +669,72 @@ func TestCSIVolumeEndpoint_List(t *testing.T) { require.Equal(t, vols[1].ID, resp.Volumes[0].ID) } +func TestCSIVolumeEndpoint_ListAllNamespaces(t *testing.T) { + t.Parallel() + srv, shutdown := TestServer(t, func(c *Config) { + c.NumSchedulers = 0 // Prevent automatic dequeue + }) + defer shutdown() + testutil.WaitForLeader(t, srv.RPC) + + state := srv.fsm.State() + codec := rpcClient(t, srv) + + // Create namespaces. + ns0 := structs.DefaultNamespace + ns1 := "namespace-1" + ns2 := "namespace-2" + err := state.UpsertNamespaces(1000, []*structs.Namespace{{Name: ns1}, {Name: ns2}}) + require.NoError(t, err) + + // Create volumes in multiple namespaces. + id0 := uuid.Generate() + id1 := uuid.Generate() + id2 := uuid.Generate() + vols := []*structs.CSIVolume{{ + ID: id0, + Namespace: ns0, + PluginID: "minnie", + Secrets: structs.CSISecrets{"mysecret": "secretvalue"}, + RequestedCapabilities: []*structs.CSIVolumeCapability{{ + AccessMode: structs.CSIVolumeAccessModeMultiNodeReader, + AttachmentMode: structs.CSIVolumeAttachmentModeFilesystem, + }}, + }, { + ID: id1, + Namespace: ns1, + PluginID: "adam", + RequestedCapabilities: []*structs.CSIVolumeCapability{{ + AccessMode: structs.CSIVolumeAccessModeMultiNodeSingleWriter, + AttachmentMode: structs.CSIVolumeAttachmentModeFilesystem, + }}, + }, { + ID: id2, + Namespace: ns2, + PluginID: "beth", + RequestedCapabilities: []*structs.CSIVolumeCapability{{ + AccessMode: structs.CSIVolumeAccessModeMultiNodeSingleWriter, + AttachmentMode: structs.CSIVolumeAttachmentModeFilesystem, + }}, + }, + } + err = state.CSIVolumeRegister(1001, vols) + require.NoError(t, err) + + // Lookup volumes in all namespaces + get := &structs.CSIVolumeListRequest{ + QueryOptions: structs.QueryOptions{ + Region: "global", + Namespace: "*", + }, + } + var resp structs.CSIVolumeListResponse + err = msgpackrpc.CallWithCodec(codec, "CSIVolume.List", get, &resp) + require.NoError(t, err) + require.Equal(t, uint64(1001), resp.Index) + require.Len(t, resp.Volumes, len(vols)) +} + func TestCSIVolumeEndpoint_Create(t *testing.T) { t.Parallel() var err error