improve kv CLI to remove data or custom metadata using kv patch (#18067)
* improve kv CLI to remove data or custom metadata using kv patch * CL * adding a comment
This commit is contained in:
parent
1c0b2df8f1
commit
22f51dc6d6
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
cli/kv: improve kv CLI to remove data or custom metadata using kv patch
|
||||||
|
```
|
|
@ -20,12 +20,13 @@ var (
|
||||||
type KVMetadataPatchCommand struct {
|
type KVMetadataPatchCommand struct {
|
||||||
*BaseCommand
|
*BaseCommand
|
||||||
|
|
||||||
flagMaxVersions int
|
flagMaxVersions int
|
||||||
flagCASRequired BoolPtr
|
flagCASRequired BoolPtr
|
||||||
flagDeleteVersionAfter time.Duration
|
flagDeleteVersionAfter time.Duration
|
||||||
flagCustomMetadata map[string]string
|
flagCustomMetadata map[string]string
|
||||||
flagMount string
|
flagRemoveCustomMetadata []string
|
||||||
testStdin io.Reader // for tests
|
flagMount string
|
||||||
|
testStdin io.Reader // for tests
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *KVMetadataPatchCommand) Synopsis() string {
|
func (c *KVMetadataPatchCommand) Synopsis() string {
|
||||||
|
@ -65,6 +66,10 @@ Usage: vault kv metadata patch [options] KEY
|
||||||
|
|
||||||
$ vault kv metadata patch -mount=secret -custom-metadata=foo=abc -custom-metadata=bar=123 foo
|
$ vault kv metadata patch -mount=secret -custom-metadata=foo=abc -custom-metadata=bar=123 foo
|
||||||
|
|
||||||
|
To remove custom meta data from the corresponding path in the key-value store, kv metadata patch can be used.
|
||||||
|
|
||||||
|
$ vault kv metadata patch -mount=secret -remove-custom-metadata=bar foo
|
||||||
|
|
||||||
Additional flags and more advanced use cases are detailed below.
|
Additional flags and more advanced use cases are detailed below.
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
|
@ -111,6 +116,13 @@ func (c *KVMetadataPatchCommand) Flags() *FlagSets {
|
||||||
This can be specified multiple times to add multiple pieces of metadata.`,
|
This can be specified multiple times to add multiple pieces of metadata.`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
f.StringSliceVar(&StringSliceVar{
|
||||||
|
Name: "remove-custom-metadata",
|
||||||
|
Target: &c.flagRemoveCustomMetadata,
|
||||||
|
Default: []string{},
|
||||||
|
Usage: "Key to remove from custom metadata. To specify multiple values, specify this flag multiple times.",
|
||||||
|
})
|
||||||
|
|
||||||
f.StringVar(&StringVar{
|
f.StringVar(&StringVar{
|
||||||
Name: "mount",
|
Name: "mount",
|
||||||
Target: &c.flagMount,
|
Target: &c.flagMount,
|
||||||
|
@ -198,7 +210,7 @@ func (c *KVMetadataPatchCommand) Run(args []string) int {
|
||||||
|
|
||||||
fullPath := addPrefixToKVPath(partialPath, mountPath, "metadata")
|
fullPath := addPrefixToKVPath(partialPath, mountPath, "metadata")
|
||||||
|
|
||||||
data := map[string]interface{}{}
|
data := make(map[string]interface{}, 0)
|
||||||
|
|
||||||
if c.flagMaxVersions >= 0 {
|
if c.flagMaxVersions >= 0 {
|
||||||
data["max_versions"] = c.flagMaxVersions
|
data["max_versions"] = c.flagMaxVersions
|
||||||
|
@ -212,10 +224,19 @@ func (c *KVMetadataPatchCommand) Run(args []string) int {
|
||||||
data["delete_version_after"] = c.flagDeleteVersionAfter.String()
|
data["delete_version_after"] = c.flagDeleteVersionAfter.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.flagCustomMetadata) > 0 {
|
customMetadata := make(map[string]interface{})
|
||||||
data["custom_metadata"] = c.flagCustomMetadata
|
|
||||||
|
for key, value := range c.flagCustomMetadata {
|
||||||
|
customMetadata[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, key := range c.flagRemoveCustomMetadata {
|
||||||
|
// A null in a JSON merge patch payload will remove the associated key
|
||||||
|
customMetadata[key] = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data["custom_metadata"] = customMetadata
|
||||||
|
|
||||||
secret, err := client.Logical().JSONMergePatch(context.Background(), fullPath, data)
|
secret, err := client.Logical().JSONMergePatch(context.Background(), fullPath, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(fmt.Sprintf("Error writing data to %s: %s", fullPath, err))
|
c.UI.Error(fmt.Sprintf("Error writing data to %s: %s", fullPath, err))
|
||||||
|
|
|
@ -122,6 +122,29 @@ func TestKvMetadataPatchCommand_Flags(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"remove-custom_metadata",
|
||||||
|
[]string{"-custom-metadata=baz=ghi", "-remove-custom-metadata=foo"},
|
||||||
|
"Success!",
|
||||||
|
0,
|
||||||
|
map[string]interface{}{
|
||||||
|
"custom_metadata": map[string]interface{}{
|
||||||
|
"bar": "def",
|
||||||
|
"baz": "ghi",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"remove-custom_metadata-multiple",
|
||||||
|
[]string{"-custom-metadata=baz=ghi", "-remove-custom-metadata=foo", "-remove-custom-metadata=bar"},
|
||||||
|
"Success!",
|
||||||
|
0,
|
||||||
|
map[string]interface{}{
|
||||||
|
"custom_metadata": map[string]interface{}{
|
||||||
|
"baz": "ghi",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"delete_version_after_success",
|
"delete_version_after_success",
|
||||||
[]string{"-delete-version-after=5s"},
|
[]string{"-delete-version-after=5s"},
|
||||||
|
|
|
@ -21,10 +21,11 @@ var (
|
||||||
type KVPatchCommand struct {
|
type KVPatchCommand struct {
|
||||||
*BaseCommand
|
*BaseCommand
|
||||||
|
|
||||||
flagCAS int
|
flagCAS int
|
||||||
flagMethod string
|
flagMethod string
|
||||||
flagMount string
|
flagMount string
|
||||||
testStdin io.Reader // for tests
|
testStdin io.Reader // for tests
|
||||||
|
flagRemoveData []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *KVPatchCommand) Synopsis() string {
|
func (c *KVPatchCommand) Synopsis() string {
|
||||||
|
@ -76,6 +77,10 @@ Usage: vault kv patch [options] KEY [DATA]
|
||||||
|
|
||||||
$ vault kv patch -mount=secret -method=rw foo bar=baz
|
$ vault kv patch -mount=secret -method=rw foo bar=baz
|
||||||
|
|
||||||
|
To remove data from the corresponding path in the key-value store, kv patch can be used.
|
||||||
|
|
||||||
|
$ vault kv patch -mount=secret -remove-data=bar foo
|
||||||
|
|
||||||
Additional flags and more advanced use cases are detailed below.
|
Additional flags and more advanced use cases are detailed below.
|
||||||
|
|
||||||
` + c.Flags().Help()
|
` + c.Flags().Help()
|
||||||
|
@ -117,6 +122,13 @@ func (c *KVPatchCommand) Flags() *FlagSets {
|
||||||
v2 secrets.`,
|
v2 secrets.`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
f.StringSliceVar(&StringSliceVar{
|
||||||
|
Name: "remove-data",
|
||||||
|
Target: &c.flagRemoveData,
|
||||||
|
Default: []string{},
|
||||||
|
Usage: "Key to remove from data. To specify multiple values, specify this flag multiple times.",
|
||||||
|
})
|
||||||
|
|
||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +159,7 @@ func (c *KVPatchCommand) Run(args []string) int {
|
||||||
case len(args) < 1:
|
case len(args) < 1:
|
||||||
c.UI.Error(fmt.Sprintf("Not enough arguments (expected >1, got %d)", len(args)))
|
c.UI.Error(fmt.Sprintf("Not enough arguments (expected >1, got %d)", len(args)))
|
||||||
return 1
|
return 1
|
||||||
case len(args) == 1:
|
case len(c.flagRemoveData) == 0 && len(args) == 1:
|
||||||
c.UI.Error("Must supply data")
|
c.UI.Error("Must supply data")
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -211,6 +223,16 @@ func (c *KVPatchCommand) Run(args []string) int {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collecting data to be removed
|
||||||
|
if newData == nil {
|
||||||
|
newData = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range c.flagRemoveData {
|
||||||
|
// A null in a JSON merge patch payload will remove the associated key
|
||||||
|
newData[key] = nil
|
||||||
|
}
|
||||||
|
|
||||||
// Check the method and behave accordingly
|
// Check the method and behave accordingly
|
||||||
var secret *api.Secret
|
var secret *api.Secret
|
||||||
var code int
|
var code int
|
||||||
|
|
|
@ -249,6 +249,7 @@ func TestKV_Patch_RootToken(t *testing.T) {
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"data": map[string]interface{}{
|
||||||
"bar": "baz",
|
"bar": "baz",
|
||||||
|
"foo": "qux",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +264,7 @@ func TestKV_Patch_RootToken(t *testing.T) {
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"data": map[string]interface{}{
|
||||||
"bar": "quux",
|
"bar": "quux",
|
||||||
|
"foo": nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return client.Logical().JSONMergePatch(context.Background(), "kv/data/foo", data)
|
return client.Logical().JSONMergePatch(context.Background(), "kv/data/foo", data)
|
||||||
|
@ -288,4 +290,8 @@ func TestKV_Patch_RootToken(t *testing.T) {
|
||||||
if bar != "quux" {
|
if bar != "quux" {
|
||||||
t.Fatalf("expected bar to be quux but it was %q", bar)
|
t.Fatalf("expected bar to be quux but it was %q", bar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := secret.Data["data"].(map[string]interface{})["foo"]; ok {
|
||||||
|
t.Fatalf("expected data not to include foo")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue