Skip to content

Commit

Permalink
Add basic autocompletion (#3223)
Browse files Browse the repository at this point in the history
* Add basic autocompletion

* Add autocomplete to some common commands

* Autocomplete the generate-root flags

* Add information about autocomplete to the docs
  • Loading branch information
briankassouf authored Aug 24, 2017
1 parent f526091 commit 41db075
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 7 deletions.
8 changes: 5 additions & 3 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ func RunCustom(args []string, commands map[string]cli.CommandFactory) int {
}

cli := &cli.CLI{
Args: args,
Commands: commands,
HelpFunc: cli.FilteredHelpFunc(commandsInclude, HelpFunc),
Args: args,
Commands: commands,
Name: "vault",
Autocomplete: true,
HelpFunc: cli.FilteredHelpFunc(commandsInclude, HelpFunc),
}

exitCode, err := cli.Run()
Expand Down
17 changes: 17 additions & 0 deletions command/audit_enable.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/vault/helper/kv-builder"
"github.com/hashicorp/vault/meta"
"github.com/mitchellh/mapstructure"
"github.com/posener/complete"
)

// AuditEnableCommand is a Command that mounts a new mount.
Expand Down Expand Up @@ -127,3 +128,19 @@ Audit Enable Options:
`
return strings.TrimSpace(helpText)
}

func (c *AuditEnableCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictSet(
"file",
"syslog",
"socket",
)
}

func (c *AuditEnableCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-description": complete.PredictNothing,
"-path": complete.PredictNothing,
"-local": complete.PredictNothing,
}
}
48 changes: 44 additions & 4 deletions command/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/hashicorp/vault/helper/password"
"github.com/hashicorp/vault/meta"
"github.com/mitchellh/mapstructure"
"github.com/posener/complete"
"github.com/ryanuber/columnize"
)

Expand Down Expand Up @@ -301,15 +302,22 @@ func (c *AuthCommand) Run(args []string) int {

}

func (c *AuthCommand) listMethods() int {
func (c *AuthCommand) getMethods() (map[string]*api.AuthMount, error) {
client, err := c.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf(
"Error initializing client: %s", err))
return 1
return nil, err
}

auth, err := client.Sys().ListAuth()
if err != nil {
return nil, err
}

return auth, nil
}

func (c *AuthCommand) listMethods() int {
auth, err := c.getMethods()
if err != nil {
c.Ui.Error(fmt.Sprintf(
"Error reading auth table: %s", err))
Expand Down Expand Up @@ -458,3 +466,35 @@ tokens are created via the API or command line interface (with the

return strings.TrimSpace(help)
}

func (c *AuthCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *AuthCommand) AutocompleteFlags() complete.Flags {
var predictFunc complete.PredictFunc = func(a complete.Args) []string {
auths, err := c.getMethods()
if err != nil {
return []string{}
}

methods := make([]string, 0, len(auths))
for _, auth := range auths {
if strings.HasPrefix(auth.Type, a.Last) {
methods = append(methods, auth.Type)
}
}

return methods
}

return complete.Flags{
"-method": predictFunc,
"-methods": complete.PredictNothing,
"-method-help": complete.PredictNothing,
"-no-verify": complete.PredictNothing,
"-no-store": complete.PredictNothing,
"-token-only": complete.PredictNothing,
"-path": complete.PredictNothing,
}
}
27 changes: 27 additions & 0 deletions command/auth_enable.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/meta"
"github.com/posener/complete"
)

// AuthEnableCommand is a Command that enables a new endpoint.
Expand Down Expand Up @@ -110,3 +111,29 @@ Auth Enable Options:
`
return strings.TrimSpace(helpText)
}

func (c *AuthEnableCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictSet(
"approle",
"cert",
"aws",
"app-id",
"gcp",
"github",
"userpass",
"ldap",
"okta",
"radius",
"plugin",
)

}

func (c *AuthEnableCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-description": complete.PredictNothing,
"-path": complete.PredictNothing,
"-plugin-name": complete.PredictNothing,
"-local": complete.PredictNothing,
}
}
3 changes: 3 additions & 0 deletions command/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ import (
"github.com/ghodss/yaml"
"github.com/hashicorp/vault/api"
"github.com/mitchellh/cli"
"github.com/posener/complete"
"github.com/ryanuber/columnize"
)

var predictFormat complete.Predictor = complete.PredictSet("json", "yaml")

func OutputSecret(ui cli.Ui, format string, secret *api.Secret) int {
return outputWithFormat(ui, format, secret, secret)
}
Expand Down
18 changes: 18 additions & 0 deletions command/generate-root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/hashicorp/vault/helper/pgpkeys"
"github.com/hashicorp/vault/helper/xor"
"github.com/hashicorp/vault/meta"
"github.com/posener/complete"
)

// GenerateRootCommand is a Command that generates a new root token.
Expand Down Expand Up @@ -352,3 +353,20 @@ Generate Root Options:
`
return strings.TrimSpace(helpText)
}

func (c *GenerateRootCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *GenerateRootCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-init": complete.PredictNothing,
"-cancel": complete.PredictNothing,
"-status": complete.PredictNothing,
"-decode": complete.PredictNothing,
"-genotp": complete.PredictNothing,
"-otp": complete.PredictNothing,
"-pgp-key": complete.PredictNothing,
"-nonce": complete.PredictNothing,
}
}
20 changes: 20 additions & 0 deletions command/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/vault/helper/pgpkeys"
"github.com/hashicorp/vault/meta"
"github.com/hashicorp/vault/physical/consul"
"github.com/posener/complete"
)

// InitCommand is a Command that initializes a new Vault server.
Expand Down Expand Up @@ -384,3 +385,22 @@ Init Options:
`
return strings.TrimSpace(helpText)
}

func (c *InitCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *InitCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-check": complete.PredictNothing,
"-key-shares": complete.PredictNothing,
"-key-threshold": complete.PredictNothing,
"-pgp-keys": complete.PredictNothing,
"-root-token-pgp-key": complete.PredictNothing,
"-recovery-shares": complete.PredictNothing,
"-recovery-threshold": complete.PredictNothing,
"-recovery-pgp-keys": complete.PredictNothing,
"-auto": complete.PredictNothing,
"-consul-service": complete.PredictNothing,
}
}
29 changes: 29 additions & 0 deletions command/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/meta"
"github.com/posener/complete"
)

// MountCommand is a Command that mounts a new mount.
Expand Down Expand Up @@ -133,3 +134,31 @@ Mount Options:
`
return strings.TrimSpace(helpText)
}

func (c *MountCommand) AutocompleteArgs() complete.Predictor {
// This list does not contain deprecated backends
return complete.PredictSet(
"aws",
"consul",
"pki",
"transit",
"ssh",
"rabbitmq",
"database",
"totp",
"plugin",
)

}

func (c *MountCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-description": complete.PredictNothing,
"-path": complete.PredictNothing,
"-default-lease-ttl": complete.PredictNothing,
"-max-lease-ttl": complete.PredictNothing,
"-force-no-cache": complete.PredictNothing,
"-plugin-name": complete.PredictNothing,
"-local": complete.PredictNothing,
}
}
12 changes: 12 additions & 0 deletions command/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/meta"
"github.com/posener/complete"
)

// ReadCommand is a Command that reads data from the Vault.
Expand Down Expand Up @@ -95,3 +96,14 @@ Read Options:
`
return strings.TrimSpace(helpText)
}

func (c *ReadCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *ReadCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-format": predictFormat,
"-field": complete.PredictNothing,
}
}
21 changes: 21 additions & 0 deletions command/rekey.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/vault/helper/password"
"github.com/hashicorp/vault/helper/pgpkeys"
"github.com/hashicorp/vault/meta"
"github.com/posener/complete"
)

// RekeyCommand is a Command that rekeys the vault.
Expand Down Expand Up @@ -418,3 +419,23 @@ Rekey Options:
`
return strings.TrimSpace(helpText)
}

func (c *RekeyCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *RekeyCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-init": complete.PredictNothing,
"-cancel": complete.PredictNothing,
"-status": complete.PredictNothing,
"-retrieve": complete.PredictNothing,
"-delete": complete.PredictNothing,
"-key-shares": complete.PredictNothing,
"-key-threshold": complete.PredictNothing,
"-nonce": complete.PredictNothing,
"-pgp-keys": complete.PredictNothing,
"-backup": complete.PredictNothing,
"-recovery-key": complete.PredictNothing,
}
}
15 changes: 15 additions & 0 deletions command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
colorable "github.com/mattn/go-colorable"
log "github.com/mgutz/logxi/v1"
testing "github.com/mitchellh/go-testing-interface"
"github.com/posener/complete"

"google.golang.org/grpc/grpclog"

Expand Down Expand Up @@ -1200,6 +1201,20 @@ General Options:
return strings.TrimSpace(helpText)
}

func (c *ServerCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *ServerCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-config": complete.PredictOr(complete.PredictFiles("*.hcl"), complete.PredictFiles("*.json")),
"-dev": complete.PredictNothing,
"-dev-root-token-id": complete.PredictNothing,
"-dev-listen-address": complete.PredictNothing,
"-log-level": complete.PredictSet("trace", "debug", "info", "warn", "err"),
}
}

// MakeShutdownCh returns a channel that can be used for shutdown
// notifications for commands. This channel will send a message for every
// SIGINT or SIGTERM received.
Expand Down
13 changes: 13 additions & 0 deletions command/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/hashicorp/vault/helper/kv-builder"
"github.com/hashicorp/vault/meta"
"github.com/posener/complete"
)

// WriteCommand is a Command that puts data into the Vault.
Expand Down Expand Up @@ -139,3 +140,15 @@ Write Options:
`
return strings.TrimSpace(helpText)
}

func (c *WriteCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

func (c *WriteCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-force": complete.PredictNothing,
"-format": predictFormat,
"-field": complete.PredictNothing,
}
}
16 changes: 16 additions & 0 deletions website/source/docs/commands/index.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,19 @@ with the `-h` argument.
The help output is very comprehensive, so we defer you to that for documentation.
We've included some guides to the left of common interactions with the
CLI.

## Autocompletion

The `vault` command features opt-in subcommand autocompletion that you can
enable for your shell with `vault -autocomplete-install`. After doing so,
you can invoke a new shell and use the feature.

For example, assume a tab is typed at the end of each prompt line:

```
$ vault au
audit-disable audit-enable audit-list auth auth-disable auth-enable
$ vault s
seal server ssh status step-down
```

0 comments on commit 41db075

Please sign in to comment.