Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic autocompletion #3223

Merged
merged 6 commits into from
Aug 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
```