mirror of
https://github.com/status-im/consul.git
synced 2025-02-24 03:18:26 +00:00
Add kv get
This commit is contained in:
parent
87ad6d466c
commit
c8fdc5c50d
226
command/kv_get.go
Normal file
226
command/kv_get.go
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KVGetCommand is a Command implementation that is used to setup
|
||||||
|
// a "watch" which uses a sub-process
|
||||||
|
type KVGetCommand struct {
|
||||||
|
Ui cli.Ui
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *KVGetCommand) Help() string {
|
||||||
|
helpText := `
|
||||||
|
Usage: consul kv get [options] [KEY_OR_PREFIX]
|
||||||
|
|
||||||
|
Retrieves the value from Consul's key-value store at the given key name. If no
|
||||||
|
key exists with that name, an error is returned. If a key exists with that
|
||||||
|
name but has no data, nothing is returned. If the name or prefix is omitted,
|
||||||
|
it defaults to "" which is the root of the key-value store.
|
||||||
|
|
||||||
|
To retrieve the value for the key named "foo" in the key-value store:
|
||||||
|
|
||||||
|
$ consul kv get foo
|
||||||
|
|
||||||
|
This will return the original, raw value stored in Consul. To view detailed
|
||||||
|
information about the key, specify the "-detailed" flag. This will output all
|
||||||
|
known metadata about the key including ModifyIndex and any user-supplied
|
||||||
|
flags:
|
||||||
|
|
||||||
|
$ consul kv get -detailed foo
|
||||||
|
|
||||||
|
To treat the path as a prefix and list all keys which start with the given
|
||||||
|
prefix, specify the "-recurse" flag:
|
||||||
|
|
||||||
|
$ consul kv get -recurse foo
|
||||||
|
|
||||||
|
This will return all key-vlaue pairs. To just list the keys which start with
|
||||||
|
the specified prefix, use the "-keys" option instead:
|
||||||
|
|
||||||
|
$ consul kv get -keys foo
|
||||||
|
|
||||||
|
For a full list of options and examples, please see the Consul documentation.
|
||||||
|
|
||||||
|
` + apiOptsText + `
|
||||||
|
|
||||||
|
KV Get Options:
|
||||||
|
|
||||||
|
-detailed Provide additional metadata about the key in addition
|
||||||
|
to the value such as the ModifyIndex and any flags
|
||||||
|
that may have been set on the key. The default value
|
||||||
|
is false.
|
||||||
|
|
||||||
|
-keys List keys which start with the given prefix, but not
|
||||||
|
their values. This is especially useful if you only
|
||||||
|
need the key names themselves. This option is commonly
|
||||||
|
combined with the -separator option. The default value
|
||||||
|
is false.
|
||||||
|
|
||||||
|
-recurse Recursively look at all keys prefixed with the given
|
||||||
|
path. The default value is false.
|
||||||
|
|
||||||
|
-separator=<string> String to use as a separator between keys. The default
|
||||||
|
value is "/", but this option is only taken into
|
||||||
|
account when paired with the -keys flag.
|
||||||
|
|
||||||
|
`
|
||||||
|
return strings.TrimSpace(helpText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *KVGetCommand) Run(args []string) int {
|
||||||
|
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
||||||
|
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||||
|
datacenter := cmdFlags.String("datacenter", "", "")
|
||||||
|
token := cmdFlags.String("token", "", "")
|
||||||
|
stale := cmdFlags.Bool("stale", false, "")
|
||||||
|
detailed := cmdFlags.Bool("detailed", false, "")
|
||||||
|
keys := cmdFlags.Bool("keys", false, "")
|
||||||
|
recurse := cmdFlags.Bool("recurse", false, "")
|
||||||
|
separator := cmdFlags.String("separator", "/", "")
|
||||||
|
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||||
|
if err := cmdFlags.Parse(args); err != nil {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
key := ""
|
||||||
|
|
||||||
|
// Check for arg validation
|
||||||
|
args = cmdFlags.Args()
|
||||||
|
switch len(args) {
|
||||||
|
case 0:
|
||||||
|
key = ""
|
||||||
|
case 1:
|
||||||
|
key = args[0]
|
||||||
|
default:
|
||||||
|
c.Ui.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is just a "nice" thing to do. Since pairs cannot start with a /, but
|
||||||
|
// users will likely put "/" or "/foo", lets go ahead and strip that for them
|
||||||
|
// here.
|
||||||
|
if len(key) > 0 && key[0] == '/' {
|
||||||
|
key = key[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the key is empty and we are not doing a recursive or key-based lookup,
|
||||||
|
// this is an error.
|
||||||
|
if key == "" && !(*recurse || *keys) {
|
||||||
|
c.Ui.Error("Error! Missing KEY argument")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and test the HTTP client
|
||||||
|
conf := api.DefaultConfig()
|
||||||
|
conf.Address = *httpAddr
|
||||||
|
conf.Token = *token
|
||||||
|
client, err := api.NewClient(conf)
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case *keys:
|
||||||
|
keys, _, err := client.KV().Keys(key, *separator, &api.QueryOptions{
|
||||||
|
Datacenter: *datacenter,
|
||||||
|
AllowStale: *stale,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range keys {
|
||||||
|
c.Ui.Info(string(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
case *recurse:
|
||||||
|
pairs, _, err := client.KV().List(key, &api.QueryOptions{
|
||||||
|
Datacenter: *datacenter,
|
||||||
|
AllowStale: *stale,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, pair := range pairs {
|
||||||
|
if *detailed {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := prettyKVPair(&b, pair); err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error rendering KV pair: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Ui.Info(b.String())
|
||||||
|
|
||||||
|
if i < len(pairs)-1 {
|
||||||
|
c.Ui.Info("")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.Ui.Info(fmt.Sprintf("%s:%s", pair.Key, pair.Value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
default:
|
||||||
|
pair, _, err := client.KV().Get(key, &api.QueryOptions{
|
||||||
|
Datacenter: *datacenter,
|
||||||
|
AllowStale: *stale,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if pair == nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error! No key exists at: %s", key))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if *detailed {
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := prettyKVPair(&b, pair); err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error rendering KV pair: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Ui.Info(b.String())
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
c.Ui.Info(string(pair.Value))
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *KVGetCommand) Synopsis() string {
|
||||||
|
return "Retrieves or lists data from the KV store"
|
||||||
|
}
|
||||||
|
|
||||||
|
func prettyKVPair(w io.Writer, pair *api.KVPair) error {
|
||||||
|
tw := tabwriter.NewWriter(w, 0, 2, 6, ' ', 0)
|
||||||
|
fmt.Fprintf(tw, "CreateIndex\t%d\n", pair.CreateIndex)
|
||||||
|
fmt.Fprintf(tw, "Flags\t%d\n", pair.Flags)
|
||||||
|
fmt.Fprintf(tw, "Key\t%s\n", pair.Key)
|
||||||
|
fmt.Fprintf(tw, "LockIndex\t%d\n", pair.LockIndex)
|
||||||
|
fmt.Fprintf(tw, "ModifyIndex\t%d\n", pair.ModifyIndex)
|
||||||
|
if pair.Session == "" {
|
||||||
|
fmt.Fprintf(tw, "Session\t-\n")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(tw, "Session\t%s\n", pair.Session)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(tw, "Value\t%s", pair.Value)
|
||||||
|
return tw.Flush()
|
||||||
|
}
|
252
command/kv_get_test.go
Normal file
252
command/kv_get_test.go
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKVGetCommand_implements(t *testing.T) {
|
||||||
|
var _ cli.Command = &KVGetCommand{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_noTabs(t *testing.T) {
|
||||||
|
assertNoTabs(t, new(KVGetCommand))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_Validation(t *testing.T) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &KVGetCommand{Ui: ui}
|
||||||
|
|
||||||
|
cases := map[string]struct {
|
||||||
|
args []string
|
||||||
|
output string
|
||||||
|
}{
|
||||||
|
"no key": {
|
||||||
|
[]string{},
|
||||||
|
"Missing KEY argument",
|
||||||
|
},
|
||||||
|
"extra args": {
|
||||||
|
[]string{"foo", "bar", "baz"},
|
||||||
|
"Too many arguments",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tc := range cases {
|
||||||
|
// Ensure our buffer is always clear
|
||||||
|
if ui.ErrorWriter != nil {
|
||||||
|
ui.ErrorWriter.Reset()
|
||||||
|
}
|
||||||
|
if ui.OutputWriter != nil {
|
||||||
|
ui.OutputWriter.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(tc.args)
|
||||||
|
if code == 0 {
|
||||||
|
t.Errorf("%s: expected non-zero exit", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := ui.ErrorWriter.String()
|
||||||
|
if !strings.Contains(output, tc.output) {
|
||||||
|
t.Errorf("%s: expected %q to contain %q", name, output, tc.output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_Run(t *testing.T) {
|
||||||
|
srv, client := testAgentWithAPIClient(t)
|
||||||
|
defer srv.Shutdown()
|
||||||
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &KVGetCommand{Ui: ui}
|
||||||
|
|
||||||
|
pair := &api.KVPair{
|
||||||
|
Key: "foo",
|
||||||
|
Value: []byte("bar"),
|
||||||
|
}
|
||||||
|
_, err := client.KV().Put(pair, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + srv.httpAddr,
|
||||||
|
"foo",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
output := ui.OutputWriter.String()
|
||||||
|
if !strings.Contains(output, "bar") {
|
||||||
|
t.Errorf("bad: %#v", output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_Missing(t *testing.T) {
|
||||||
|
srv, _ := testAgentWithAPIClient(t)
|
||||||
|
defer srv.Shutdown()
|
||||||
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &KVGetCommand{Ui: ui}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + srv.httpAddr,
|
||||||
|
"not-a-real-key",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code == 0 {
|
||||||
|
t.Fatalf("expected bad code")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_Empty(t *testing.T) {
|
||||||
|
srv, client := testAgentWithAPIClient(t)
|
||||||
|
defer srv.Shutdown()
|
||||||
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &KVGetCommand{Ui: ui}
|
||||||
|
|
||||||
|
pair := &api.KVPair{
|
||||||
|
Key: "empty",
|
||||||
|
Value: []byte(""),
|
||||||
|
}
|
||||||
|
_, err := client.KV().Put(pair, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + srv.httpAddr,
|
||||||
|
"empty",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_Detailed(t *testing.T) {
|
||||||
|
srv, client := testAgentWithAPIClient(t)
|
||||||
|
defer srv.Shutdown()
|
||||||
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &KVGetCommand{Ui: ui}
|
||||||
|
|
||||||
|
pair := &api.KVPair{
|
||||||
|
Key: "foo",
|
||||||
|
Value: []byte("bar"),
|
||||||
|
}
|
||||||
|
_, err := client.KV().Put(pair, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + srv.httpAddr,
|
||||||
|
"-detailed",
|
||||||
|
"foo",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
output := ui.OutputWriter.String()
|
||||||
|
for _, key := range []string{
|
||||||
|
"CreateIndex",
|
||||||
|
"LockIndex",
|
||||||
|
"ModifyIndex",
|
||||||
|
"Flags",
|
||||||
|
"Session",
|
||||||
|
"Value",
|
||||||
|
} {
|
||||||
|
if !strings.Contains(output, key) {
|
||||||
|
t.Fatalf("bad %#v, missing %q", output, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_Keys(t *testing.T) {
|
||||||
|
srv, client := testAgentWithAPIClient(t)
|
||||||
|
defer srv.Shutdown()
|
||||||
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &KVGetCommand{Ui: ui}
|
||||||
|
|
||||||
|
keys := []string{"foo/bar", "foo/baz", "foo/zip"}
|
||||||
|
for _, key := range keys {
|
||||||
|
if _, err := client.KV().Put(&api.KVPair{Key: key}, nil); err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + srv.httpAddr,
|
||||||
|
"-keys",
|
||||||
|
"foo/",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
output := ui.OutputWriter.String()
|
||||||
|
for _, key := range keys {
|
||||||
|
if !strings.Contains(output, key) {
|
||||||
|
t.Fatalf("bad %#v missing %q", output, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVGetCommand_Recurse(t *testing.T) {
|
||||||
|
srv, client := testAgentWithAPIClient(t)
|
||||||
|
defer srv.Shutdown()
|
||||||
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &KVGetCommand{Ui: ui}
|
||||||
|
|
||||||
|
keys := map[string]string{
|
||||||
|
"foo/a": "a",
|
||||||
|
"foo/b": "b",
|
||||||
|
"foo/c": "c",
|
||||||
|
}
|
||||||
|
for k, v := range keys {
|
||||||
|
pair := &api.KVPair{Key: k, Value: []byte(v)}
|
||||||
|
if _, err := client.KV().Put(pair, nil); err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + srv.httpAddr,
|
||||||
|
"-recurse",
|
||||||
|
"foo",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
output := ui.OutputWriter.String()
|
||||||
|
for key, value := range keys {
|
||||||
|
if !strings.Contains(output, key+":"+value) {
|
||||||
|
t.Fatalf("bad %#v missing %q", output, key+"adafa")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -59,6 +59,12 @@ func init() {
|
|||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"kv get": func() (cli.Command, error) {
|
||||||
|
return &command.KVGetCommand{
|
||||||
|
Ui: ui,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
|
||||||
"join": func() (cli.Command, error) {
|
"join": func() (cli.Command, error) {
|
||||||
return &command.JoinCommand{
|
return &command.JoinCommand{
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
16
website/source/docs/commands/_http_api_options.html.markdown
Normal file
16
website/source/docs/commands/_http_api_options.html.markdown
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
* `-http-addr=<addr>` - Address of the Consul agent with the port. This can be
|
||||||
|
an IP address or DNS address, but it must include the port. This can also be
|
||||||
|
specified via the CONSUL_HTTP_ADDR environment variable. The default value is
|
||||||
|
127.0.0.1:8500.
|
||||||
|
|
||||||
|
* `-datacenter=<name>` - Name of the datacenter to query. If unspecified, the
|
||||||
|
query will default to the datacenter of the Consul agent at the HTTP address.
|
||||||
|
|
||||||
|
* `-token=<value>` - ACL token to use in the request. This can also be specified
|
||||||
|
via the `CONSUL_HTTP_TOKEN` environment variable. If unspecified, the query
|
||||||
|
will default to the token of the Consul agent at the HTTP address.
|
||||||
|
|
||||||
|
* `-stale` - Permit any Consul server (non-leader) to respond to this request.
|
||||||
|
This allows for lower latency and higher throughput, but can result in stale
|
||||||
|
data. This option has no effect on non-read operations. The default value is
|
||||||
|
false.
|
@ -27,6 +27,7 @@ usage: consul [--version] [--help] <command> [<args>]
|
|||||||
|
|
||||||
Available commands are:
|
Available commands are:
|
||||||
agent Runs a Consul agent
|
agent Runs a Consul agent
|
||||||
|
configtest Validate config file
|
||||||
event Fire a new event
|
event Fire a new event
|
||||||
exec Executes a command on Consul nodes
|
exec Executes a command on Consul nodes
|
||||||
force-leave Forces a member of the cluster to enter the "left" state
|
force-leave Forces a member of the cluster to enter the "left" state
|
||||||
@ -34,8 +35,10 @@ Available commands are:
|
|||||||
join Tell Consul agent to join cluster
|
join Tell Consul agent to join cluster
|
||||||
keygen Generates a new encryption key
|
keygen Generates a new encryption key
|
||||||
keyring Manages gossip layer encryption keys
|
keyring Manages gossip layer encryption keys
|
||||||
|
kv Interact with the key-value store
|
||||||
leave Gracefully leaves the Consul cluster and shuts down
|
leave Gracefully leaves the Consul cluster and shuts down
|
||||||
lock Execute a command holding a lock
|
lock Execute a command holding a lock
|
||||||
|
maint Controls node or service maintenance mode
|
||||||
members Lists the members of a Consul cluster
|
members Lists the members of a Consul cluster
|
||||||
monitor Stream logs from a Consul agent
|
monitor Stream logs from a Consul agent
|
||||||
operator Provides cluster-level tools for Consul operators
|
operator Provides cluster-level tools for Consul operators
|
||||||
|
150
website/source/docs/commands/kv/get.html.markdown.erb
Normal file
150
website/source/docs/commands/kv/get.html.markdown.erb
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
layout: "docs"
|
||||||
|
page_title: "Commands: KV Get"
|
||||||
|
sidebar_current: "docs-commands-kv-get"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Consul KV Get
|
||||||
|
|
||||||
|
Command: `consul kv get`
|
||||||
|
|
||||||
|
The `kv get` command is used to retrieves the value from Consul's key-value
|
||||||
|
store at the given key name. If no key exists with that name, an error is
|
||||||
|
returned. If a key exists with that name but has no data, nothing is returned.
|
||||||
|
If the name or prefix is omitted, it defaults to "" which is the root of the
|
||||||
|
key-value store.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Usage: `consul kv get [options] [KEY_OR_PREFIX]`
|
||||||
|
|
||||||
|
#### API Options
|
||||||
|
|
||||||
|
<%= partial "docs/commands/http_api_options" %>
|
||||||
|
|
||||||
|
#### KV Get Options
|
||||||
|
|
||||||
|
* `-detailed` - Provide additional metadata about the key in addition to the
|
||||||
|
value such as the ModifyIndex and any flags that may have been set on the key.
|
||||||
|
The default value is false.
|
||||||
|
|
||||||
|
* `-keys` - List keys which start with the given prefix, but not their values.
|
||||||
|
This is especially useful if you only need the key names themselves. This
|
||||||
|
option is commonly combined with the -separator option. The default value is
|
||||||
|
false.
|
||||||
|
|
||||||
|
* `-recurse` - Recursively look at all keys prefixed with the given path. The
|
||||||
|
default value is false.
|
||||||
|
|
||||||
|
* `-separator=<string>` - String to use as a separator between keys. The default
|
||||||
|
value is "/", but this option is only taken into account when paired with the
|
||||||
|
-keys flag.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
To retrieve the value for the key named "redis/config/connections" in the
|
||||||
|
key-value store:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get redis/config/connections
|
||||||
|
5
|
||||||
|
```
|
||||||
|
|
||||||
|
This will return the original, raw value stored in Consul. To view detailed
|
||||||
|
information about the key, specify the "-detailed" flag. This will output all
|
||||||
|
known metadata about the key including ModifyIndex and any user-supplied
|
||||||
|
flags:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get -detailed redis/config/connections
|
||||||
|
CreateIndex 336
|
||||||
|
Flags 0
|
||||||
|
Key redis/config/connections
|
||||||
|
LockIndex 0
|
||||||
|
ModifyIndex 336
|
||||||
|
Session -
|
||||||
|
Value 5
|
||||||
|
```
|
||||||
|
|
||||||
|
If the key with the given name does not exist, an error is returned:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get not-a-real-key
|
||||||
|
Error! No key exists at: not-a-real-key
|
||||||
|
```
|
||||||
|
|
||||||
|
To treat the path as a prefix and list all keys which start with the given
|
||||||
|
prefix, specify the "-recurse" flag:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get -recurse redis/
|
||||||
|
redis/config/connections:5
|
||||||
|
redis/config/cpu:128
|
||||||
|
redis/config/memory:512
|
||||||
|
```
|
||||||
|
|
||||||
|
Or list detailed information about all pairs under a prefix:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get -recurse -detailed redis
|
||||||
|
CreateIndex 336
|
||||||
|
Flags 0
|
||||||
|
Key redis/config/connections
|
||||||
|
LockIndex 0
|
||||||
|
ModifyIndex 336
|
||||||
|
Session -
|
||||||
|
Value 5
|
||||||
|
|
||||||
|
CreateIndex 472
|
||||||
|
Flags 0
|
||||||
|
Key redis/config/cpu
|
||||||
|
LockIndex 0
|
||||||
|
ModifyIndex 472
|
||||||
|
Session -
|
||||||
|
Value 128
|
||||||
|
|
||||||
|
CreateIndex 471
|
||||||
|
Flags 0
|
||||||
|
Key redis/config/memory
|
||||||
|
LockIndex 0
|
||||||
|
ModifyIndex 471
|
||||||
|
Session -
|
||||||
|
Value 512
|
||||||
|
```
|
||||||
|
|
||||||
|
To just list the keys which start with the specified prefix, use the "-keys"
|
||||||
|
option instead. This is more performant and results in a smaller payload:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get -keys redis/config/
|
||||||
|
redis/config/connections
|
||||||
|
redis/config/cpu
|
||||||
|
redis/config/memory
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the `-keys` operation uses a separator of "/", meaning it will not
|
||||||
|
recurse beyond that separator. You can choose a different separator by setting
|
||||||
|
`-separator="<string>"`.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get -keys -separator="s" redis
|
||||||
|
redis/c
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can disable the separator altogether by setting it to the
|
||||||
|
empty string:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get -keys -separator="" redis
|
||||||
|
redis/config/connections
|
||||||
|
redis/config/cpu
|
||||||
|
redis/config/memory
|
||||||
|
```
|
||||||
|
|
||||||
|
To list all keys at the root, simply omit the prefix parameter:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ consul kv get -keys
|
||||||
|
memcached/
|
||||||
|
redis/
|
||||||
|
```
|
@ -99,6 +99,15 @@
|
|||||||
<a href="/docs/commands/keyring.html">keyring</a>
|
<a href="/docs/commands/keyring.html">keyring</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-commands-kv") %>>
|
||||||
|
<a href="/docs/commands/kv.html">kv</a>
|
||||||
|
<ul class="subnav">
|
||||||
|
<li<%= sidebar_current("docs-commands-kv-get") %>>
|
||||||
|
<a href="/docs/commands/kv/get.html">get</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-commands-leave") %>>
|
<li<%= sidebar_current("docs-commands-leave") %>>
|
||||||
<a href="/docs/commands/leave.html">leave</a></li>
|
<a href="/docs/commands/leave.html">leave</a></li>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user