Add TypeKVPairs field type (#3535)
This commit is contained in:
parent
2b8d8f77d2
commit
fe52ce1115
|
@ -614,6 +614,8 @@ func (t FieldType) Zero() interface{} {
|
|||
return false
|
||||
case TypeMap:
|
||||
return map[string]interface{}{}
|
||||
case TypeKVPairs:
|
||||
return map[string]string{}
|
||||
case TypeDurationSecond:
|
||||
return 0
|
||||
case TypeSlice:
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/vault/helper/parseutil"
|
||||
"github.com/hashicorp/vault/helper/strutil"
|
||||
|
@ -34,7 +35,8 @@ func (d *FieldData) Validate() error {
|
|||
|
||||
switch schema.Type {
|
||||
case TypeBool, TypeInt, TypeMap, TypeDurationSecond, TypeString,
|
||||
TypeNameString, TypeSlice, TypeStringSlice, TypeCommaStringSlice:
|
||||
TypeNameString, TypeSlice, TypeStringSlice, TypeCommaStringSlice,
|
||||
TypeKVPairs:
|
||||
_, _, err := d.getPrimitive(field, schema)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error converting input %v for field %s: %s", value, field, err)
|
||||
|
@ -110,7 +112,8 @@ func (d *FieldData) GetOkErr(k string) (interface{}, bool, error) {
|
|||
|
||||
switch schema.Type {
|
||||
case TypeBool, TypeInt, TypeMap, TypeDurationSecond, TypeString,
|
||||
TypeNameString, TypeSlice, TypeStringSlice, TypeCommaStringSlice:
|
||||
TypeNameString, TypeSlice, TypeStringSlice, TypeCommaStringSlice,
|
||||
TypeKVPairs:
|
||||
return d.getPrimitive(k, schema)
|
||||
default:
|
||||
return nil, false,
|
||||
|
@ -236,6 +239,29 @@ func (d *FieldData) getPrimitive(
|
|||
}
|
||||
return strutil.TrimStrings(result), true, nil
|
||||
|
||||
case TypeKVPairs:
|
||||
// First try to parse this as a map
|
||||
var mapResult map[string]string
|
||||
if err := mapstructure.WeakDecode(raw, &mapResult); err == nil {
|
||||
return mapResult, true, nil
|
||||
}
|
||||
|
||||
// If map parse fails, parse as a string list of = delimited pairs
|
||||
var listResult []string
|
||||
if err := mapstructure.WeakDecode(raw, &listResult); err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
|
||||
result := make(map[string]string, len(listResult))
|
||||
for _, keyPair := range listResult {
|
||||
keyPairSlice := strings.SplitN(keyPair, "=", 2)
|
||||
if len(keyPairSlice) != 2 || keyPairSlice[0] == "" {
|
||||
return nil, false, fmt.Errorf("invalid key pair %q", keyPair)
|
||||
}
|
||||
result[keyPairSlice[0]] = keyPairSlice[1]
|
||||
}
|
||||
return result, true, nil
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown type: %s", schema.Type))
|
||||
}
|
||||
|
|
|
@ -279,6 +279,53 @@ func TestFieldDataGet(t *testing.T) {
|
|||
"bar.baz-bay123",
|
||||
},
|
||||
|
||||
"keypair type, valid value map type": {
|
||||
map[string]*FieldSchema{
|
||||
"foo": &FieldSchema{Type: TypeKVPairs},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"foo": map[string]interface{}{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"key3": 1,
|
||||
},
|
||||
},
|
||||
"foo",
|
||||
map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"key3": "1",
|
||||
},
|
||||
},
|
||||
|
||||
"keypair type, list of equal sign delim key pairs type": {
|
||||
map[string]*FieldSchema{
|
||||
"foo": &FieldSchema{Type: TypeKVPairs},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"foo": []interface{}{"key1=value1", "key2=value2", "key3=1"},
|
||||
},
|
||||
"foo",
|
||||
map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"key3": "1",
|
||||
},
|
||||
},
|
||||
|
||||
"keypair type, single equal sign delim value": {
|
||||
map[string]*FieldSchema{
|
||||
"foo": &FieldSchema{Type: TypeKVPairs},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"foo": "key1=value1",
|
||||
},
|
||||
"foo",
|
||||
map[string]string{
|
||||
"key1": "value1",
|
||||
},
|
||||
},
|
||||
|
||||
"name string type, not supplied": {
|
||||
map[string]*FieldSchema{
|
||||
"foo": {Type: TypeNameString},
|
||||
|
@ -359,6 +406,15 @@ func TestFieldDataGet(t *testing.T) {
|
|||
"foo",
|
||||
[]string{},
|
||||
},
|
||||
|
||||
"type kv pair, not supplied": {
|
||||
map[string]*FieldSchema{
|
||||
"foo": {Type: TypeKVPairs},
|
||||
},
|
||||
map[string]interface{}{},
|
||||
"foo",
|
||||
map[string]string{},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
|
@ -422,6 +478,15 @@ func TestFieldDataGet_Error(t *testing.T) {
|
|||
},
|
||||
"foo",
|
||||
},
|
||||
"keypair type, csv version empty key name": {
|
||||
map[string]*FieldSchema{
|
||||
"foo": &FieldSchema{Type: TypeKVPairs},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"foo": []interface{}{"=value1", "key2=value2", "key3=1"},
|
||||
},
|
||||
"foo",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
|
|
@ -30,6 +30,10 @@ const (
|
|||
// rules. These rules include start and end with an alphanumeric
|
||||
// character and characters in the middle can be alphanumeric or . or -.
|
||||
TypeNameString
|
||||
|
||||
// TypeKVPairs allows you to represent the data as a map or a list of
|
||||
// equal sign delimited key pairs
|
||||
TypeKVPairs
|
||||
)
|
||||
|
||||
func (t FieldType) String() string {
|
||||
|
@ -44,6 +48,8 @@ func (t FieldType) String() string {
|
|||
return "bool"
|
||||
case TypeMap:
|
||||
return "map"
|
||||
case TypeKVPairs:
|
||||
return "keypair"
|
||||
case TypeDurationSecond:
|
||||
return "duration (sec)"
|
||||
case TypeSlice, TypeStringSlice, TypeCommaStringSlice:
|
||||
|
|
Loading…
Reference in New Issue