Skip to content

Commit

Permalink
CSI: display plugin capabilities in verbose status (#12116)
Browse files Browse the repository at this point in the history
The behaviors of CSI plugins are governed by their capabilities as
defined by the CSI specification. When debugging plugin issues, it's
useful to know which behaviors are expected so they can be matched
against RPC calls made to the plugin allocations.

Expose the plugin capabilities as named in the CSI spec in the `nomad
plugin status -verbose` output.
  • Loading branch information
tgross committed Feb 24, 2022
1 parent 4818477 commit 59f6c75
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/12116.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
csi: Display plugin capabilities in `nomad plugin status -verbose` output
```
98 changes: 97 additions & 1 deletion command/plugin_status_csi.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,105 @@ func (c *PluginStatusCommand) csiFormatPlugin(plug *api.CSIPlugin) (string, erro
return formatKV(output), nil
}

full := []string{formatKV(output)}

if c.verbose {
controllerCaps := c.formatControllerCaps(plug.Controllers)
if controllerCaps != "" {
full = append(full, c.Colorize().Color("\n[bold]Controller Capabilities[reset]"))
full = append(full, controllerCaps)
}
nodeCaps := c.formatNodeCaps(plug.Nodes)
if nodeCaps != "" {
full = append(full, c.Colorize().Color("\n[bold]Node Capabilities[reset]"))
full = append(full, nodeCaps)
}
}

// Format the allocs
banner := c.Colorize().Color("\n[bold]Allocations[reset]")
allocs := formatAllocListStubs(plug.Allocations, c.verbose, c.length)
full := []string{formatKV(output), banner, allocs}
full = append(full, banner)
full = append(full, allocs)
return strings.Join(full, "\n"), nil
}

func (c *PluginStatusCommand) formatControllerCaps(controllers map[string]*api.CSIInfo) string {
caps := []string{}
for _, controller := range controllers {
switch info := controller.ControllerInfo; {
case info.SupportsCreateDelete:
caps = append(caps, "CREATE_DELETE_VOLUME")
fallthrough
case info.SupportsAttachDetach:
caps = append(caps, "CONTROLLER_ATTACH_DETACH")
fallthrough
case info.SupportsListVolumes:
caps = append(caps, "LIST_VOLUMES")
fallthrough
case info.SupportsGetCapacity:
caps = append(caps, "GET_CAPACITY")
fallthrough
case info.SupportsCreateDeleteSnapshot:
caps = append(caps, "CREATE_DELETE_SNAPSHOT")
fallthrough
case info.SupportsListSnapshots:
caps = append(caps, "CREATE_LIST_SNAPSHOTS")
fallthrough
case info.SupportsClone:
caps = append(caps, "CLONE_VOLUME")
fallthrough
case info.SupportsReadOnlyAttach:
caps = append(caps, "ATTACH_READONLY")
fallthrough
case info.SupportsExpand:
caps = append(caps, "EXPAND_VOLUME")
fallthrough
case info.SupportsListVolumesAttachedNodes:
caps = append(caps, "LIST_VOLUMES_PUBLISHED_NODES")
fallthrough
case info.SupportsCondition:
caps = append(caps, "VOLUME_CONDITION")
fallthrough
case info.SupportsGet:
caps = append(caps, "GET_VOLUME")
fallthrough
default:
}
break
}

if len(caps) == 0 {
return ""
}

return strings.Join(caps, "\n\t")
}

func (c *PluginStatusCommand) formatNodeCaps(nodes map[string]*api.CSIInfo) string {
caps := []string{}
for _, node := range nodes {
switch info := node.NodeInfo; {
case info.RequiresNodeStageVolume:
caps = append(caps, "STAGE_UNSTAGE_VOLUME")
fallthrough
case info.SupportsStats:
caps = append(caps, "GET_VOLUME_STATS")
fallthrough
case info.SupportsExpand:
caps = append(caps, "EXPAND_VOLUME")
fallthrough
case info.SupportsCondition:
caps = append(caps, "VOLUME_CONDITION")
fallthrough
default:
}
break
}

if len(caps) == 0 {
return ""
}

return " " + strings.Join(caps, "\n ")
}

0 comments on commit 59f6c75

Please sign in to comment.