Convert kv commands to use base.Command
This commit is contained in:
parent
d3b24d2d12
commit
b35acaac33
|
@ -62,6 +62,12 @@ func (c *Command) HTTPDatacenter() string {
|
|||
return c.datacenter.String()
|
||||
}
|
||||
|
||||
func (c *Command) HTTPStale() bool {
|
||||
var stale bool
|
||||
c.stale.Merge(&stale)
|
||||
return stale
|
||||
}
|
||||
|
||||
// httpFlagsClient is the list of flags that apply to HTTP connections.
|
||||
func (c *Command) httpFlagsClient(f *flag.FlagSet) *flag.FlagSet {
|
||||
if f == nil {
|
||||
|
@ -134,6 +140,9 @@ func (c *Command) Parse(args []string) error {
|
|||
|
||||
// Help returns the help for this flagSet.
|
||||
func (c *Command) Help() string {
|
||||
if c.flagSet == nil {
|
||||
return ""
|
||||
}
|
||||
return c.helpFlagsFor(c.flagSet)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,14 @@ package command
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// KVCommand is a Command implementation that just shows help for
|
||||
// the subcommands nested below it.
|
||||
type KVCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVCommand) Run(args []string) int {
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVDeleteCommand is a Command implementation that is used to delete a key or
|
||||
// prefix of keys from the key-value store.
|
||||
type KVDeleteCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVDeleteCommand) Help() string {
|
||||
|
@ -33,40 +32,30 @@ Usage: consul kv delete [options] KEY_OR_PREFIX
|
|||
This will delete the keys named "foo", "food", and "foo/bar/zip" if they
|
||||
existed.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Delete Options:
|
||||
|
||||
-cas Perform a Check-And-Set operation. Specifying this
|
||||
value also requires the -modify-index flag to be set.
|
||||
The default value is false.
|
||||
|
||||
-modify-index=<int> Unsigned integer representing the ModifyIndex of the
|
||||
key. This is used in combination with the -cas flag.
|
||||
|
||||
-recurse Recursively delete all keys with the path. The default
|
||||
value is false.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVDeleteCommand) 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", "", "")
|
||||
cas := cmdFlags.Bool("cas", false, "")
|
||||
modifyIndex := cmdFlags.Uint64("modify-index", 0, "")
|
||||
recurse := cmdFlags.Bool("recurse", false, "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
cas := f.Bool("cas", false,
|
||||
"Perform a Check-And-Set operation. Specifying this value also requires "+
|
||||
"the -modify-index flag to be set. The default value is false.")
|
||||
modifyIndex := f.Uint64("modify-index", 0,
|
||||
"Unsigned integer representing the ModifyIndex of the key. This is "+
|
||||
"used in combination with the -cas flag.")
|
||||
recurse := f.Bool("recurse", false,
|
||||
"Recursively delete all keys with the path. The default value is false.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
key := ""
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
key = ""
|
||||
|
@ -109,22 +98,15 @@ func (c *KVDeleteCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
wo := &api.WriteOptions{
|
||||
Datacenter: *datacenter,
|
||||
}
|
||||
|
||||
switch {
|
||||
case *recurse:
|
||||
if _, err := client.KV().DeleteTree(key, wo); err != nil {
|
||||
if _, err := client.KV().DeleteTree(key, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Did not delete prefix %s: %s", key, err))
|
||||
return 1
|
||||
}
|
||||
|
@ -137,7 +119,7 @@ func (c *KVDeleteCommand) Run(args []string) int {
|
|||
ModifyIndex: *modifyIndex,
|
||||
}
|
||||
|
||||
success, _, err := client.KV().DeleteCAS(pair, wo)
|
||||
success, _, err := client.KV().DeleteCAS(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Did not delete key %s: %s", key, err))
|
||||
return 1
|
||||
|
@ -150,7 +132,7 @@ func (c *KVDeleteCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Deleted key: %s", key))
|
||||
return 0
|
||||
default:
|
||||
if _, err := client.KV().Delete(key, wo); err != nil {
|
||||
if _, err := client.KV().Delete(key, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error deleting key %s: %s", key, err))
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -6,9 +6,20 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testKVDeleteCommand(t *testing.T) (*cli.MockUi, *KVDeleteCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &KVDeleteCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestKVDeleteCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &KVDeleteCommand{}
|
||||
}
|
||||
|
@ -18,8 +29,7 @@ func TestKVDeleteCommand_noTabs(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKVDeleteCommand_Validation(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
cases := map[string]struct {
|
||||
args []string
|
||||
|
@ -73,8 +83,7 @@ func TestKVDeleteCommand_Run(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
@ -109,8 +118,7 @@ func TestKVDeleteCommand_Recurse(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
keys := []string{"foo/a", "foo/b", "food"}
|
||||
|
||||
|
@ -152,8 +160,7 @@ func TestKVDeleteCommand_CAS(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
|
|
@ -3,18 +3,17 @@ package command
|
|||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVExportCommand is a Command implementation that is used to export
|
||||
// a KV tree as JSON
|
||||
type KVExportCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVExportCommand) Synopsis() string {
|
||||
|
@ -33,29 +32,20 @@ Usage: consul kv export [KEY_OR_PREFIX]
|
|||
|
||||
For a full list of options and examples, please see the Consul documentation.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Export Options:
|
||||
|
||||
None.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVExportCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("export", flag.ContinueOnError)
|
||||
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
stale := cmdFlags.Bool("stale", false, "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
key := ""
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
key = ""
|
||||
|
@ -74,18 +64,14 @@ func (c *KVExportCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
pairs, _, err := client.KV().List(key, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
|
@ -15,7 +16,12 @@ func TestKVExportCommand_Run(t *testing.T) {
|
|||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVExportCommand{Ui: ui}
|
||||
c := KVExportCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
|
||||
keys := map[string]string{
|
||||
"foo/a": "a",
|
||||
|
|
|
@ -3,20 +3,19 @@ package command
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVGetCommand is a Command implementation that is used to fetch the value of
|
||||
// a key from the key-value store.
|
||||
type KVGetCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVGetCommand) Help() string {
|
||||
|
@ -51,54 +50,39 @@ Usage: consul kv get [options] [KEY_OR_PREFIX]
|
|||
|
||||
For a full list of options and examples, please see the Consul documentation.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Get Options:
|
||||
|
||||
-base64 Base64 encode the value. The default value is false.
|
||||
|
||||
-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, "")
|
||||
base64encode := cmdFlags.Bool("base64", false, "")
|
||||
recurse := cmdFlags.Bool("recurse", false, "")
|
||||
separator := cmdFlags.String("separator", "/", "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
detailed := f.Bool("detailed", false,
|
||||
"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 := f.Bool("keys", false,
|
||||
"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.")
|
||||
base64encode := f.Bool("base64", false,
|
||||
"Base64 encode the value. The default value is false.")
|
||||
recurse := f.Bool("recurse", false,
|
||||
"Recursively look at all keys prefixed with the given path. The default "+
|
||||
"value is false.")
|
||||
separator := f.String("separator", "/",
|
||||
"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.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
key := ""
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
key = ""
|
||||
|
@ -124,10 +108,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -136,8 +117,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
switch {
|
||||
case *keys:
|
||||
keys, _, err := client.KV().Keys(key, *separator, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
@ -151,8 +131,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
return 0
|
||||
case *recurse:
|
||||
pairs, _, err := client.KV().List(key, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
@ -184,8 +163,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
return 0
|
||||
default:
|
||||
pair, _, err := client.KV().Get(key, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
|
|
@ -6,9 +6,20 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testKVGetCommand(t *testing.T) (*cli.MockUi, *KVGetCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &KVGetCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestKVGetCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &KVGetCommand{}
|
||||
}
|
||||
|
@ -18,8 +29,7 @@ func TestKVGetCommand_noTabs(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKVGetCommand_Validation(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
cases := map[string]struct {
|
||||
args []string
|
||||
|
@ -61,8 +71,7 @@ func TestKVGetCommand_Run(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
@ -94,8 +103,7 @@ func TestKVGetCommand_Missing(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
_, c := testKVGetCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -113,8 +121,7 @@ func TestKVGetCommand_Empty(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "empty",
|
||||
|
@ -141,8 +148,7 @@ func TestKVGetCommand_Detailed(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
@ -184,8 +190,7 @@ func TestKVGetCommand_Keys(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
keys := []string{"foo/bar", "foo/baz", "foo/zip"}
|
||||
for _, key := range keys {
|
||||
|
@ -218,8 +223,7 @@ func TestKVGetCommand_Recurse(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
keys := map[string]string{
|
||||
"foo/a": "a",
|
||||
|
@ -257,8 +261,7 @@ func TestKVGetCommand_RecurseBase64(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
keys := map[string]string{
|
||||
"foo/a": "Hello World 1",
|
||||
|
@ -297,8 +300,7 @@ func TestKVGetCommand_DetailedBase64(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -13,13 +12,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVImportCommand is a Command implementation that is used to import
|
||||
// a KV tree stored as JSON
|
||||
type KVImportCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
|
||||
// testStdin is the input for testing.
|
||||
testStdin io.Reader
|
||||
|
@ -50,27 +49,20 @@ Usage: consul kv import [DATA]
|
|||
|
||||
For a full list of options and examples, please see the Consul documentation.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Import Options:
|
||||
|
||||
None.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVImportCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("import", flag.ContinueOnError)
|
||||
f := c.Command.NewFlagSet(c)
|
||||
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
data, err := c.dataFromArgs(args)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! %s", err))
|
||||
|
@ -78,10 +70,7 @@ func (c *KVImportCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -106,12 +95,7 @@ func (c *KVImportCommand) Run(args []string) int {
|
|||
Value: value,
|
||||
}
|
||||
|
||||
wo := &api.WriteOptions{
|
||||
Datacenter: *datacenter,
|
||||
Token: *token,
|
||||
}
|
||||
|
||||
if _, err := client.KV().Put(pair, wo); err != nil {
|
||||
if _, err := client.KV().Put(pair, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data for key %s: %s", pair.Key, err))
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
|
@ -27,7 +28,10 @@ func TestKVImportCommand_Run(t *testing.T) {
|
|||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVImportCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
testStdin: strings.NewReader(json),
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package command
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -11,13 +10,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVPutCommand is a Command implementation that is used to write data to the
|
||||
// key-value store.
|
||||
type KVPutCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
|
||||
// testStdin is the input for testing.
|
||||
testStdin io.Reader
|
||||
|
@ -57,62 +56,45 @@ Usage: consul kv put [options] KEY [DATA]
|
|||
|
||||
Additional flags and more advanced use cases are detailed below.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Put Options:
|
||||
|
||||
-acquire Obtain a lock on the key. If the key does not exist,
|
||||
this operation will create the key and obtain the
|
||||
lock. The session must already exist and be specified
|
||||
via the -session flag. The default value is false.
|
||||
|
||||
-base64 Treat the data as base 64 encoded. The default value
|
||||
is false.
|
||||
|
||||
-cas Perform a Check-And-Set operation. Specifying this
|
||||
value also requires the -modify-index flag to be set.
|
||||
The default value is false.
|
||||
|
||||
-flags=<int> Unsigned integer value to assign to this key-value
|
||||
pair. This value is not read by Consul, so clients can
|
||||
use this value however makes sense for their use case.
|
||||
The default value is 0 (no flags).
|
||||
|
||||
-modify-index=<int> Unsigned integer representing the ModifyIndex of the
|
||||
key. This is used in combination with the -cas flag.
|
||||
|
||||
-release Forfeit the lock on the key at the given path. This
|
||||
requires the -session flag to be set. The key must be
|
||||
held by the session in order to be unlocked. The
|
||||
default value is false.
|
||||
|
||||
-session=<string> User-defined identifer for this session as a string.
|
||||
This is commonly used with the -acquire and -release
|
||||
operations to build robust locking, but it can be set
|
||||
on any key. The default value is empty (no session).
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVPutCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
cas := cmdFlags.Bool("cas", false, "")
|
||||
flags := cmdFlags.Uint64("flags", 0, "")
|
||||
base64encoded := cmdFlags.Bool("base64", false, "")
|
||||
modifyIndex := cmdFlags.Uint64("modify-index", 0, "")
|
||||
session := cmdFlags.String("session", "", "")
|
||||
acquire := cmdFlags.Bool("acquire", false, "")
|
||||
release := cmdFlags.Bool("release", false, "")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
cas := f.Bool("cas", false,
|
||||
"Perform a Check-And-Set operation. Specifying this value also "+
|
||||
"requires the -modify-index flag to be set. The default value "+
|
||||
"is false.")
|
||||
flags := f.Uint64("flags", 0,
|
||||
"Unsigned integer value to assign to this key-value pair. This "+
|
||||
"value is not read by Consul, so clients can use this value however "+
|
||||
"makes sense for their use case. The default value is 0 (no flags).")
|
||||
base64encoded := f.Bool("base64", false,
|
||||
"Treat the data as base 64 encoded. The default value is false.")
|
||||
modifyIndex := f.Uint64("modify-index", 0,
|
||||
"Unsigned integer representing the ModifyIndex of the key. This is "+
|
||||
"used in combination with the -cas flag.")
|
||||
session := f.String("session", "",
|
||||
"User-defined identifer for this session as a string. This is commonly "+
|
||||
"used with the -acquire and -release operations to build robust locking, "+
|
||||
"but it can be set on any key. The default value is empty (no session).")
|
||||
acquire := f.Bool("acquire", false,
|
||||
"Obtain a lock on the key. If the key does not exist, this operation "+
|
||||
"will create the key and obtain the lock. The session must already "+
|
||||
"exist and be specified via the -session flag. The default value is false.")
|
||||
release := f.Bool("release", false,
|
||||
"Forfeit the lock on the key at the given path. This requires the "+
|
||||
"-session flag to be set. The key must be held by the session in order to "+
|
||||
"be unlocked. The default value is false.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
key, data, err := c.dataFromArgs(args)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! %s", err))
|
||||
|
@ -140,10 +122,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -157,14 +136,9 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
Session: *session,
|
||||
}
|
||||
|
||||
wo := &api.WriteOptions{
|
||||
Datacenter: *datacenter,
|
||||
Token: *token,
|
||||
}
|
||||
|
||||
switch {
|
||||
case *cas:
|
||||
ok, _, err := client.KV().CAS(pair, wo)
|
||||
ok, _, err := client.KV().CAS(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Did not write to %s: %s", key, err))
|
||||
return 1
|
||||
|
@ -177,7 +151,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Data written to: %s", key))
|
||||
return 0
|
||||
case *acquire:
|
||||
ok, _, err := client.KV().Acquire(pair, wo)
|
||||
ok, _, err := client.KV().Acquire(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data: %s", err))
|
||||
return 1
|
||||
|
@ -190,7 +164,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Lock acquired on: %s", key))
|
||||
return 0
|
||||
case *release:
|
||||
ok, _, err := client.KV().Release(pair, wo)
|
||||
ok, _, err := client.KV().Release(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data: %s", key))
|
||||
return 1
|
||||
|
@ -203,7 +177,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Lock released on: %s", key))
|
||||
return 0
|
||||
default:
|
||||
if _, err := client.KV().Put(pair, wo); err != nil {
|
||||
if _, err := client.KV().Put(pair, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -11,20 +11,30 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testKVPutCommand(t *testing.T) (*cli.MockUi, *KVPutCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &KVPutCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestKVPutCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &KVPutCommand{}
|
||||
}
|
||||
|
||||
func TestKVPutCommand_noTabs(t *testing.T) {
|
||||
assertNoTabs(t, new(KVPutCommand))
|
||||
assertNoTabs(t, new(KVDeleteCommand))
|
||||
}
|
||||
|
||||
func TestKVPutCommand_Validation(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
cases := map[string]struct {
|
||||
args []string
|
||||
|
@ -78,8 +88,7 @@ func TestKVPutCommand_Run(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -106,8 +115,7 @@ func TestKVPutCommand_RunEmptyDataQuoted(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -134,8 +142,7 @@ func TestKVPutCommand_RunBase64(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
const encodedString = "aGVsbG8gd29ybGQK"
|
||||
|
||||
|
@ -170,8 +177,7 @@ func TestKVPutCommand_File(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
f, err := ioutil.TempFile("", "kv-put-command-file")
|
||||
if err != nil {
|
||||
|
@ -203,8 +209,7 @@ func TestKVPutCommand_File(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKVPutCommand_FileNoExist(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"foo", "@/nope/definitely/not-a-real-file.txt",
|
||||
|
@ -228,11 +233,8 @@ func TestKVPutCommand_Stdin(t *testing.T) {
|
|||
|
||||
stdinR, stdinW := io.Pipe()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{
|
||||
Ui: ui,
|
||||
testStdin: stdinR,
|
||||
}
|
||||
ui, c := testKVPutCommand(t)
|
||||
c.testStdin = stdinR
|
||||
|
||||
go func() {
|
||||
stdinW.Write([]byte("bar"))
|
||||
|
@ -264,8 +266,7 @@ func TestKVPutCommand_NegativeVal(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -292,8 +293,7 @@ func TestKVPutCommand_Flags(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -330,8 +330,7 @@ func TestKVPutCommand_CAS(t *testing.T) {
|
|||
t.Fatalf("err: %#v", err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
|
30
commands.go
30
commands.go
|
@ -105,37 +105,55 @@ func init() {
|
|||
|
||||
"kv": func() (cli.Command, error) {
|
||||
return &command.KVCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetNone,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv delete": func() (cli.Command, error) {
|
||||
return &command.KVDeleteCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv get": func() (cli.Command, error) {
|
||||
return &command.KVGetCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv put": func() (cli.Command, error) {
|
||||
return &command.KVPutCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv export": func() (cli.Command, error) {
|
||||
return &command.KVExportCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv import": func() (cli.Command, error) {
|
||||
return &command.KVImportCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue