Add field type TypeNameString (#3028)

This commit is contained in:
Chris Hoffman
2017-07-17 11:39:58 -07:00
committed by GitHub
parent 41fefd49bd
commit 508183a1b3
3 changed files with 103 additions and 1 deletions

View File

@@ -2,7 +2,9 @@ package framework
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"regexp"
"github.com/hashicorp/vault/helper/parseutil" "github.com/hashicorp/vault/helper/parseutil"
"github.com/hashicorp/vault/helper/strutil" "github.com/hashicorp/vault/helper/strutil"
@@ -108,7 +110,7 @@ func (d *FieldData) GetOkErr(k string) (interface{}, bool, error) {
switch schema.Type { switch schema.Type {
case TypeBool, TypeInt, TypeMap, TypeDurationSecond, TypeString, case TypeBool, TypeInt, TypeMap, TypeDurationSecond, TypeString,
TypeSlice, TypeStringSlice, TypeCommaStringSlice: TypeNameString, TypeSlice, TypeStringSlice, TypeCommaStringSlice:
return d.getPrimitive(k, schema) return d.getPrimitive(k, schema)
default: default:
return nil, false, return nil, false,
@@ -145,6 +147,20 @@ func (d *FieldData) getPrimitive(
} }
return result, true, nil return result, true, nil
case TypeNameString:
var result string
if err := mapstructure.WeakDecode(raw, &result); err != nil {
return nil, true, err
}
matched, err := regexp.MatchString("^\\w(([\\w-.]+)?\\w)?$", result)
if err != nil {
return nil, true, err
}
if !matched {
return nil, true, errors.New("field does not match the formatting rules")
}
return result, true, nil
case TypeMap: case TypeMap:
var result map[string]interface{} var result map[string]interface{}
if err := mapstructure.WeakDecode(raw, &result); err != nil { if err := mapstructure.WeakDecode(raw, &result); err != nil {

View File

@@ -256,6 +256,28 @@ func TestFieldDataGet(t *testing.T) {
"foo", "foo",
[]string{}, []string{},
}, },
"name string type, valid string": {
map[string]*FieldSchema{
"foo": &FieldSchema{Type: TypeNameString},
},
map[string]interface{}{
"foo": "bar",
},
"foo",
"bar",
},
"name string type, valid value with special characters": {
map[string]*FieldSchema{
"foo": &FieldSchema{Type: TypeNameString},
},
map[string]interface{}{
"foo": "bar.baz-bay123",
},
"foo",
"bar.baz-bay123",
},
} }
for name, tc := range cases { for name, tc := range cases {
@@ -272,3 +294,60 @@ func TestFieldDataGet(t *testing.T) {
} }
} }
} }
func TestFieldDataGet_Error(t *testing.T) {
cases := map[string]struct {
Schema map[string]*FieldSchema
Raw map[string]interface{}
Key string
}{
"name string type, invalid value with invalid characters": {
map[string]*FieldSchema{
"foo": &FieldSchema{Type: TypeNameString},
},
map[string]interface{}{
"foo": "bar baz",
},
"foo",
},
"name string type, invalid value with special characters at beginning": {
map[string]*FieldSchema{
"foo": &FieldSchema{Type: TypeNameString},
},
map[string]interface{}{
"foo": ".barbaz",
},
"foo",
},
"name string type, invalid value with special characters at end": {
map[string]*FieldSchema{
"foo": &FieldSchema{Type: TypeNameString},
},
map[string]interface{}{
"foo": "barbaz-",
},
"foo",
},
"name string type, empty string": {
map[string]*FieldSchema{
"foo": &FieldSchema{Type: TypeNameString},
},
map[string]interface{}{
"foo": "",
},
"foo",
},
}
for _, tc := range cases {
data := &FieldData{
Raw: tc.Raw,
Schema: tc.Schema,
}
_, _, err := data.GetOkErr(tc.Key)
if err == nil {
t.Fatalf("error expected, none received")
}
}
}

View File

@@ -23,12 +23,19 @@ const (
// slice of strings and also supports parsing a comma-separated list in // slice of strings and also supports parsing a comma-separated list in
// a string field // a string field
TypeCommaStringSlice TypeCommaStringSlice
// TypeNameString represents a name that is URI safe and follows specific
// rules. These rules include start and end with an alphanumeric
// character and characters in the middle can be alphanumeric or . or -.
TypeNameString
) )
func (t FieldType) String() string { func (t FieldType) String() string {
switch t { switch t {
case TypeString: case TypeString:
return "string" return "string"
case TypeNameString:
return "name string"
case TypeInt: case TypeInt:
return "int" return "int"
case TypeBool: case TypeBool: