Skip to content

Commit

Permalink
dynamic host volumes: autocomplete for CLI
Browse files Browse the repository at this point in the history
Adds dynamic host volumes to argument autocomplete for the `volume status` and
`volume delete` commands. Adds flag autocompletion for those commands plus
`volume create`.

Ref: #24479
  • Loading branch information
tgross committed Nov 21, 2024
1 parent 0ef88f8 commit 5cff22e
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 31 deletions.
7 changes: 6 additions & 1 deletion command/node_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

humanize "github.com/dustin/go-humanize"
"github.com/hashicorp/go-set/v3"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/api/contexts"
"github.com/hashicorp/nomad/helper/pointer"
Expand Down Expand Up @@ -129,8 +130,12 @@ func (c *NodeStatusCommand) AutocompleteFlags() complete.Flags {
}

func (c *NodeStatusCommand) AutocompleteArgs() complete.Predictor {
return nodePredictor(c.Client, nil)
}

func nodePredictor(factory ApiClientFactory, filter *set.Set[string]) complete.Predictor {
return complete.PredictFunc(func(a complete.Args) []string {
client, err := c.Meta.Client()
client, err := factory()
if err != nil {
return nil
}
Expand Down
13 changes: 1 addition & 12 deletions command/plugin_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,10 @@ func (c *PluginStatusCommand) Synopsis() string {
return "Display status information about a plugin"
}

// predictVolumeType is also used in volume_status
var predictVolumeType = complete.PredictFunc(func(a complete.Args) []string {
types := []string{"csi"}
for _, t := range types {
if strings.Contains(t, a.Last) {
return []string{t}
}
}
return nil
})

func (c *PluginStatusCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-type": predictVolumeType,
"-type": complete.PredictSet("csi"),
"-short": complete.PredictNothing,
"-verbose": complete.PredictNothing,
"-json": complete.PredictNothing,
Expand Down
6 changes: 5 additions & 1 deletion command/volume_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ General Options:
}

func (c *VolumeCreateCommand) AutocompleteFlags() complete.Flags {
return c.Meta.AutocompleteFlags(FlagSetClient)
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-detach": complete.PredictNothing,
"-verbose": complete.PredictNothing,
})
}

func (c *VolumeCreateCommand) AutocompleteArgs() complete.Predictor {
Expand Down
11 changes: 7 additions & 4 deletions command/volume_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Delete Options:
-secret
Secrets to pass to the plugin to delete the snapshot. Accepts multiple
flags in the form -secret key=value
flags in the form -secret key=value. Only available for CSI volumes.
-type <type>
Type of volume to delete. Must be one of "csi" or "host". Defaults to "csi".
Expand All @@ -50,7 +50,10 @@ Delete Options:

func (c *VolumeDeleteCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{})
complete.Flags{
"-type": complete.PredictSet("csi", "host"),
"-secret": complete.PredictNothing,
})
}

func (c *VolumeDeleteCommand) AutocompleteArgs() complete.Predictor {
Expand All @@ -66,11 +69,11 @@ func (c *VolumeDeleteCommand) AutocompleteArgs() complete.Predictor {
}
matches := resp.Matches[contexts.Volumes]

resp, _, err = client.Search().PrefixSearch(a.Last, contexts.Nodes, nil)
resp, _, err = client.Search().PrefixSearch(a.Last, contexts.HostVolumes, nil)
if err != nil {
return []string{}
}
matches = append(matches, resp.Matches[contexts.Nodes]...)
matches = append(matches, resp.Matches[contexts.HostVolumes]...)
return matches
})
}
Expand Down
14 changes: 13 additions & 1 deletion command/volume_delete_host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/ci"
"github.com/mitchellh/cli"
"github.com/posener/complete"
"github.com/shoenig/test/must"
)

Expand Down Expand Up @@ -62,8 +63,18 @@ capability {

ui.OutputWriter.Reset()

// autocomplete
cmd := &VolumeDeleteCommand{Meta: Meta{Ui: ui, namespace: "*", flagAddress: url}}
prefix := id[:len(id)-5]
cargs := complete.Args{Last: prefix}
predictor := cmd.AutocompleteArgs()

res := predictor.Predict(cargs)
must.SliceLen(t, 1, res)
must.Eq(t, id, res[0])

// missing the namespace
cmd := &VolumeDeleteCommand{Meta: Meta{Ui: ui}}
cmd = &VolumeDeleteCommand{Meta: Meta{Ui: ui}}
args = []string{"-address", url, "-type", "host", id}
code = cmd.Run(args)
must.Eq(t, 1, code)
Expand All @@ -76,4 +87,5 @@ capability {
must.Eq(t, 0, code, must.Sprintf("got error: %s", ui.ErrorWriter.String()))
out = ui.OutputWriter.String()
must.StrContains(t, out, fmt.Sprintf("Successfully deleted volume %q!", id))

}
1 change: 0 additions & 1 deletion command/volume_deregister.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ func (c *VolumeDeregisterCommand) AutocompleteArgs() complete.Predictor {
return nil
}

// When multiple volume types are implemented, this search should merge contexts
resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Volumes, nil)
if err != nil {
return []string{}
Expand Down
25 changes: 15 additions & 10 deletions command/volume_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ func (c *VolumeStatusCommand) Synopsis() string {
func (c *VolumeStatusCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-type": predictVolumeType,
"-short": complete.PredictNothing,
"-verbose": complete.PredictNothing,
"-json": complete.PredictNothing,
"-t": complete.PredictAnything,

// TODO(1.10.0): wire-up predictions for nodes and node pools
"-node": complete.PredictNothing,
"-node-pool": complete.PredictNothing,
"-type": complete.PredictSet("csi", "host"),
"-short": complete.PredictNothing,
"-verbose": complete.PredictNothing,
"-json": complete.PredictNothing,
"-t": complete.PredictAnything,
"-node": nodePredictor(c.Client, nil),
"-node-pool": nodePoolPredictor(c.Client, nil),
})
}

Expand All @@ -92,7 +90,14 @@ func (c *VolumeStatusCommand) AutocompleteArgs() complete.Predictor {
if err != nil {
return []string{}
}
return resp.Matches[contexts.Volumes]
matches := resp.Matches[contexts.Volumes]

resp, _, err = client.Search().PrefixSearch(a.Last, contexts.HostVolumes, nil)
if err != nil {
return []string{}
}
matches = append(matches, resp.Matches[contexts.HostVolumes]...)
return matches
})
}

Expand Down
14 changes: 13 additions & 1 deletion command/volume_status_host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/ci"
"github.com/mitchellh/cli"
"github.com/posener/complete"
"github.com/shoenig/test/must"
)

Expand Down Expand Up @@ -141,8 +142,19 @@ capability {

ui.OutputWriter.Reset()

// autocomplete
cmd := &VolumeStatusCommand{Meta: Meta{Ui: ui, namespace: "*", flagAddress: url}}
cmd.Meta.namespace = "*"
prefix := id[:len(id)-5]
cargs := complete.Args{Last: prefix}
predictor := cmd.AutocompleteArgs()

res := predictor.Predict(cargs)
must.SliceLen(t, 1, res)
must.Eq(t, id, res[0])

// missing the namespace
cmd := &VolumeStatusCommand{Meta: Meta{Ui: ui}}
cmd = &VolumeStatusCommand{Meta: Meta{Ui: ui}}
args = []string{"-address", url, "-type", "host", id}
code = cmd.Run(args)
must.Eq(t, 1, code)
Expand Down

0 comments on commit 5cff22e

Please sign in to comment.