CSI: add support for wildcard namespaces on plugin status (#20551)

The `nomad plugin status :plugin_id` command lists allocations that implement
the plugin being queried. This list is filtered by the `-namespace` flag as
usual. Cluster admins will likely deploy plugins to a single namespace, but for
convenience they may want to have the wildcard namespace set in their command
environment.

Add support for handling the wildcard namespace to the CSI plugin RPC handler.

Fixes: https://github.com/hashicorp/nomad/issues/20537
This commit is contained in:
Tim Gross
2024-05-13 15:42:35 -04:00
committed by GitHub
parent 0fb22eeab3
commit 5b328d9adc
3 changed files with 27 additions and 5 deletions

3
.changelog/20551.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
csi: Added support for wildcard namespace to `plugin status` command
```

View File

@@ -1797,7 +1797,8 @@ func (v *CSIPlugin) Get(args *structs.CSIPluginGetRequest, reply *structs.CSIPlu
return structs.ErrPermissionDenied
}
withAllocs := aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilityReadJob)
ns := args.RequestNamespace()
withAllocs := aclObj.AllowNsOp(ns, acl.NamespaceCapabilityReadJob)
if args.ID == "" {
return fmt.Errorf("missing plugin ID")
@@ -1821,18 +1822,22 @@ func (v *CSIPlugin) Get(args *structs.CSIPluginGetRequest, reply *structs.CSIPlu
return nil
}
// if we're not allowed access to the namespace at all, we skip this
// copy as an optimization. withAllocs will be true for the wildcard
// namespace
if withAllocs {
plug, err = snap.CSIPluginDenormalize(ws, plug.Copy())
if err != nil {
return err
}
// Filter the allocation stubs by our namespace. withAllocs
// means we're allowed
// Filter the allocation stubs by allowed namespace
var as []*structs.AllocListStub
for _, a := range plug.Allocations {
if a.Namespace == args.RequestNamespace() {
as = append(as, a)
if ns == structs.AllNamespacesSentinel || a.Namespace == ns {
if aclObj.AllowNsOp(a.Namespace, acl.NamespaceCapabilityReadJob) {
as = append(as, a)
}
}
}
plug.Allocations = as

View File

@@ -2478,10 +2478,24 @@ func TestCSIPluginEndpoint_ACLNamespaceFilterAlloc(t *testing.T) {
must.Eq(t, structs.DefaultNamespace, a.Namespace)
}
// filter out all allocs
p2 := mock.PluginPolicy("read")
t2 := mock.CreatePolicyAndToken(t, s, 1004, "plugin-read2", p2)
req.AuthToken = t2.SecretID
err = msgpackrpc.CallWithCodec(codec, "CSIPlugin.Get", req, resp)
must.NoError(t, err)
must.Eq(t, 0, len(resp.Plugin.Allocations))
// wildcard namespace filter
p3 := mock.PluginPolicy("read") +
mock.NamespacePolicy(ns1.Name, "", []string{acl.NamespaceCapabilityReadJob})
t3 := mock.CreatePolicyAndToken(t, s, 1005, "plugin-read", p3)
req.Namespace = structs.AllNamespacesSentinel
req.AuthToken = t3.SecretID
resp = &structs.CSIPluginGetResponse{}
err = msgpackrpc.CallWithCodec(codec, "CSIPlugin.Get", req, resp)
must.NoError(t, err)
must.Eq(t, 1, len(resp.Plugin.Allocations))
must.Eq(t, ns1.Name, resp.Plugin.Allocations[0].Namespace)
}