logical: add support for passing data to delete (#7139)

* logical: add support for passing data to delete

* add back raft bit

* add back raft bit

* update error message

* fix command delete tests
This commit is contained in:
Calvin Leung Huang 2019-07-18 10:42:36 -07:00 committed by GitHub
parent 304c6cabdf
commit e869893df3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 32 deletions

View File

@ -161,8 +161,26 @@ func (c *Logical) Write(path string, data map[string]interface{}) (*Secret, erro
}
func (c *Logical) Delete(path string) (*Secret, error) {
return c.DeleteWithData(path, nil)
}
func (c *Logical) DeleteWithData(path string, data map[string][]string) (*Secret, error) {
r := c.c.NewRequest("DELETE", "/v1/"+path)
var values url.Values
for k, v := range data {
if values == nil {
values = make(url.Values)
}
for _, val := range v {
values.Add(k, val)
}
}
if values != nil {
r.Params = values
}
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
resp, err := c.c.RawRequestWithContext(ctx, r)

View File

@ -2,6 +2,8 @@ package command
import (
"fmt"
"io"
"os"
"strings"
"github.com/mitchellh/cli"
@ -13,6 +15,8 @@ var _ cli.CommandAutocomplete = (*DeleteCommand)(nil)
type DeleteCommand struct {
*BaseCommand
testStdin io.Reader // for tests
}
func (c *DeleteCommand) Synopsis() string {
@ -69,10 +73,7 @@ func (c *DeleteCommand) Run(args []string) int {
args = f.Args()
switch {
case len(args) < 1:
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
return 1
case len(args) > 1:
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
c.UI.Error(fmt.Sprintf("Not enough arguments (expected at least 1, got %d)", len(args)))
return 1
}
@ -82,9 +83,21 @@ func (c *DeleteCommand) Run(args []string) int {
return 2
}
// Pull our fake stdin if needed
stdin := (io.Reader)(os.Stdin)
if c.testStdin != nil {
stdin = c.testStdin
}
path := sanitizePath(args[0])
secret, err := client.Logical().Delete(path)
data, err := parseArgsDataStringLists(stdin, args[1:])
if err != nil {
c.UI.Error(fmt.Sprintf("Failed to parse K=V data: %s", err))
return 1
}
secret, err := client.Logical().DeleteWithData(path, data)
if err != nil {
c.UI.Error(fmt.Sprintf("Error deleting %s: %s", path, err))
if secret != nil {

View File

@ -27,18 +27,24 @@ func TestDeleteCommand_Run(t *testing.T) {
out string
code int
}{
{
"default",
[]string{"secret/foo"},
"",
0,
},
{
"optional_args",
[]string{"secret/foo", "bar=baz"},
"",
0,
},
{
"not_enough_args",
[]string{},
"Not enough arguments",
1,
},
{
"too_many_args",
[]string{"foo", "bar"},
"Too many arguments",
1,
},
}
t.Run("validations", func(t *testing.T) {

View File

@ -455,6 +455,29 @@ func (fs *UIAssetWrapper) Open(name string) (http.File, error) {
return nil, err
}
func parseQuery(values url.Values) map[string]interface{} {
data := map[string]interface{}{}
for k, v := range values {
// Skip the help key as this is a reserved parameter
if k == "help" {
continue
}
switch {
case len(v) == 0:
case len(v) == 1:
data[k] = v[0]
default:
data[k] = v
}
}
if len(data) > 0 {
return data
}
return nil
}
func parseRequest(core *vault.Core, r *http.Request, w http.ResponseWriter, out interface{}) (io.ReadCloser, error) {
// Limit the maximum number of bytes to MaxRequestSize to protect
// against an indefinite amount of data being read.

View File

@ -35,7 +35,7 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques
switch r.Method {
case "DELETE":
op = logical.DeleteOperation
data = parseQuery(r.URL.Query())
case "GET":
op = logical.ReadOperation
queryVals := r.URL.Query()
@ -56,27 +56,9 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques
}
if !list {
getData := map[string]interface{}{}
for k, v := range r.URL.Query() {
// Skip the help key as this is a reserved parameter
if k == "help" {
continue
}
switch {
case len(v) == 0:
case len(v) == 1:
getData[k] = v[0]
default:
getData[k] = v
}
}
if len(getData) > 0 {
data = getData
}
data = parseQuery(queryVals)
}
if path == "sys/storage/raft/snapshot" {
responseWriter = w
}