Convert kv commands to use base.Command

This commit is contained in:
Kyle Havlovitz 2017-02-08 19:26:24 -05:00
parent abdf1fbab3
commit 14a7ffc098
No known key found for this signature in database
GPG Key ID: 8A5E6B173056AD6C
13 changed files with 205 additions and 255 deletions

View File

@ -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)
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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",

View File

@ -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))

View File

@ -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",

View File

@ -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))

View File

@ -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",

View File

@ -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
}

View File

@ -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),
}

View File

@ -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
}

View File

@ -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,

View File

@ -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
},