diff --git a/logical/framework/field_data.go b/logical/framework/field_data.go index 2ee529116d..ae4eefa7c3 100644 --- a/logical/framework/field_data.go +++ b/logical/framework/field_data.go @@ -63,8 +63,10 @@ func (d *FieldData) Get(k string) interface{} { panic(fmt.Sprintf("field %s not in the schema", k)) } + // If the value can't be decoded, use the zero or default value for the field + // type value, ok := d.GetOk(k) - if !ok { + if !ok || value == nil { value = schema.DefaultOrZero() } @@ -96,8 +98,10 @@ func (d *FieldData) GetFirst(k ...string) (interface{}, bool) { return nil, false } -// GetOk gets the value for the given field. The second return value -// will be false if the key is invalid or the key is not set at all. +// GetOk gets the value for the given field. The second return value will be +// false if the key is invalid or the key is not set at all. If the field k is +// set and the decoded value is nil, the default or zero value +// will be returned instead. func (d *FieldData) GetOk(k string) (interface{}, bool) { schema, ok := d.Schema[k] if !ok { @@ -147,49 +151,49 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo case TypeBool: var result bool if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err } return result, true, nil case TypeInt: var result int if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err } return result, true, nil case TypeString: var result string if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err } return result, true, nil case TypeLowerCaseString: var result string if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err } return strings.ToLower(result), true, nil case TypeNameString: var result string if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err } matched, err := regexp.MatchString("^\\w(([\\w-.]+)?\\w)?$", result) if err != nil { - return nil, true, err + return nil, false, err } if !matched { - return nil, true, errors.New("field does not match the formatting rules") + return nil, false, errors.New("field does not match the formatting rules") } return result, true, nil case TypeMap: var result map[string]interface{} if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err } return result, true, nil @@ -217,20 +221,20 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo case string: dur, err := parseutil.ParseDurationSecond(inp) if err != nil { - return nil, true, err + return nil, false, err } result = int(dur.Seconds()) case json.Number: valInt64, err := inp.Int64() if err != nil { - return nil, true, err + return nil, false, err } result = int(valInt64) default: return nil, false, fmt.Errorf("invalid input '%v'", raw) } if result < 0 { - return nil, true, fmt.Errorf("cannot provide negative value '%d'", result) + return nil, false, fmt.Errorf("cannot provide negative value '%d'", result) } return result, true, nil @@ -243,24 +247,33 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo } decoder, err := mapstructure.NewDecoder(config) if err != nil { - return nil, true, err + return nil, false, err } if err := decoder.Decode(raw); err != nil { - return nil, true, err + return nil, false, err + } + if len(result) == 0 { + return make([]int, 0), true, nil } return result, true, nil case TypeSlice: var result []interface{} if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err + } + if len(result) == 0 { + return make([]interface{}, 0), true, nil } return result, true, nil case TypeStringSlice: var result []string if err := mapstructure.WeakDecode(raw, &result); err != nil { - return nil, true, err + return nil, false, err + } + if len(result) == 0 { + return make([]string, 0), true, nil } return strutil.TrimStrings(result), true, nil @@ -281,7 +294,7 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo // 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 + return nil, false, err } result := make(map[string]string, len(listResult)) @@ -350,7 +363,7 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo if err := mapstructure.WeakDecode(raw, &resultMap); err == nil { result, err = toHeader(resultMap) if err != nil { - return nil, true, err + return nil, false, err } return result, true, nil } @@ -364,11 +377,11 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo headerBytes = []byte(headerStr) } if err := json.NewDecoder(bytes.NewReader(headerBytes)).Decode(&resultMap); err != nil { - return nil, true, err + return nil, false, err } result, err = toHeader(resultMap) if err != nil { - return nil, true, err + return nil, false, err } return result, true, nil } @@ -379,17 +392,17 @@ func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bo for _, keyPairIfc := range keyPairs { keyPair, ok := keyPairIfc.(string) if !ok { - return nil, true, fmt.Errorf("invalid key pair %q", keyPair) + return nil, false, fmt.Errorf("invalid key pair %q", keyPair) } keyPairSlice := strings.SplitN(keyPair, ":", 2) if len(keyPairSlice) != 2 || keyPairSlice[0] == "" { - return nil, true, fmt.Errorf("invalid key pair %q", keyPair) + return nil, false, fmt.Errorf("invalid key pair %q", keyPair) } result.Add(keyPairSlice[0], keyPairSlice[1]) } return result, true, nil } - return nil, true, fmt.Errorf("%s not provided an expected format", raw) + return nil, false, fmt.Errorf("%s not provided an expected format", raw) default: panic(fmt.Sprintf("Unknown type: %s", schema.Type))