remove unused helper/fields package (#17197)

Has been unused since we switched task drivers to plugins and used
hclschema for config in #4936 (v0.9.0-beta1)
This commit is contained in:
Michael Schurter
2023-05-15 12:10:11 -07:00
committed by GitHub
parent a430abedf0
commit fea29c57a4
6 changed files with 0 additions and 456 deletions

View File

@@ -1,172 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fields
import (
"fmt"
multierror "github.com/hashicorp/go-multierror"
"github.com/mitchellh/mapstructure"
)
// FieldData contains the raw data and the schema that the data should adhere to
type FieldData struct {
Raw map[string]interface{}
Schema map[string]*FieldSchema
}
// Validate cycles through the raw data and validates conversions in the schema.
// It also checks for the existence and value of required fields.
func (d *FieldData) Validate() error {
var result *multierror.Error
// Scan for missing required fields
for field, schema := range d.Schema {
if schema.Required {
_, ok := d.Raw[field]
if !ok {
result = multierror.Append(result, fmt.Errorf(
"field %q is required", field))
}
}
}
// Validate field type and value
for field, value := range d.Raw {
schema, ok := d.Schema[field]
if !ok {
result = multierror.Append(result, fmt.Errorf(
"%q is an invalid field", field))
continue
}
switch schema.Type {
case TypeBool, TypeInt, TypeMap, TypeArray, TypeString:
val, _, err := d.getPrimitive(field, schema)
if err != nil {
result = multierror.Append(result, fmt.Errorf(
"field %q with input %q doesn't seem to be of type %s",
field, value, schema.Type))
}
// Check that we don't have an empty value for required fields
if schema.Required && val == schema.Type.Zero() {
result = multierror.Append(result, fmt.Errorf(
"field %q is required, but no value was found", field))
}
default:
result = multierror.Append(result, fmt.Errorf(
"unknown field type %s for field %s", schema.Type, field))
}
}
return result.ErrorOrNil()
}
// Get gets the value for the given field. If the key is an invalid field,
// FieldData will panic. If you want a safer version of this method, use
// GetOk. If the field k is not set, the default value (if set) will be
// returned, otherwise the zero value will be returned.
func (d *FieldData) Get(k string) interface{} {
schema, ok := d.Schema[k]
if !ok {
panic(fmt.Sprintf("field %s not in the schema", k))
}
value, ok := d.GetOk(k)
if !ok {
value = schema.DefaultOrZero()
}
return value
}
// 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.
func (d *FieldData) GetOk(k string) (interface{}, bool) {
schema, ok := d.Schema[k]
if !ok {
return nil, false
}
result, ok, err := d.GetOkErr(k)
if err != nil {
panic(fmt.Sprintf("error reading %s: %s", k, err))
}
if ok && result == nil {
result = schema.DefaultOrZero()
}
return result, ok
}
// GetOkErr is the most conservative of all the Get methods. It returns
// whether key is set or not, but also an error value. The error value is
// non-nil if the field doesn't exist or there was an error parsing the
// field value.
func (d *FieldData) GetOkErr(k string) (interface{}, bool, error) {
schema, ok := d.Schema[k]
if !ok {
return nil, false, fmt.Errorf("unknown field: %s", k)
}
switch schema.Type {
case TypeBool, TypeInt, TypeMap, TypeArray, TypeString:
return d.getPrimitive(k, schema)
default:
return nil, false,
fmt.Errorf("unknown field type %s for field %s", schema.Type, k)
}
}
// getPrimitive tries to convert the raw value of a field to its data type as
// defined in the schema. It does strict type checking, so the value will need
// to be able to convert to the appropriate type directly.
func (d *FieldData) getPrimitive(
k string, schema *FieldSchema) (interface{}, bool, error) {
raw, ok := d.Raw[k]
if !ok {
return nil, false, nil
}
switch schema.Type {
case TypeBool:
var result bool
if err := mapstructure.Decode(raw, &result); err != nil {
return nil, true, err
}
return result, true, nil
case TypeInt:
var result int
if err := mapstructure.Decode(raw, &result); err != nil {
return nil, true, err
}
return result, true, nil
case TypeString:
var result string
if err := mapstructure.Decode(raw, &result); err != nil {
return nil, true, err
}
return result, true, nil
case TypeMap:
var result map[string]interface{}
if err := mapstructure.Decode(raw, &result); err != nil {
return nil, true, err
}
return result, true, nil
case TypeArray:
var result []interface{}
if err := mapstructure.Decode(raw, &result); err != nil {
return nil, true, err
}
return result, true, nil
default:
panic(fmt.Sprintf("Unknown type: %s", schema.Type))
}
}

View File

@@ -1,123 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fields
import (
"reflect"
"testing"
)
func TestFieldDataGet(t *testing.T) {
cases := map[string]struct {
Schema map[string]*FieldSchema
Raw map[string]interface{}
Key string
Value interface{}
}{
"string type, string value": {
map[string]*FieldSchema{
"foo": {Type: TypeString},
},
map[string]interface{}{
"foo": "bar",
},
"foo",
"bar",
},
"string type, int value": {
map[string]*FieldSchema{
"foo": {Type: TypeInt},
},
map[string]interface{}{
"foo": 42,
},
"foo",
42,
},
"string type, unset value": {
map[string]*FieldSchema{
"foo": {Type: TypeString},
},
map[string]interface{}{},
"foo",
"",
},
"string type, unset value with default": {
map[string]*FieldSchema{
"foo": {
Type: TypeString,
Default: "bar",
},
},
map[string]interface{}{},
"foo",
"bar",
},
"int type, int value": {
map[string]*FieldSchema{
"foo": {Type: TypeInt},
},
map[string]interface{}{
"foo": 42,
},
"foo",
42,
},
"bool type, bool value": {
map[string]*FieldSchema{
"foo": {Type: TypeBool},
},
map[string]interface{}{
"foo": false,
},
"foo",
false,
},
"map type, map value": {
map[string]*FieldSchema{
"foo": {Type: TypeMap},
},
map[string]interface{}{
"foo": map[string]interface{}{
"child": true,
},
},
"foo",
map[string]interface{}{
"child": true,
},
},
"array type, array value": {
map[string]*FieldSchema{
"foo": {Type: TypeArray},
},
map[string]interface{}{
"foo": []interface{}{},
},
"foo",
[]interface{}{},
},
}
for name, tc := range cases {
data := &FieldData{
Raw: tc.Raw,
Schema: tc.Schema,
}
actual := data.Get(tc.Key)
if !reflect.DeepEqual(actual, tc.Value) {
t.Fatalf(
"bad: %s\n\nExpected: %#v\nGot: %#v",
name, tc.Value, actual)
}
}
}

View File

@@ -1,22 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fields
// FieldSchema is a basic schema to describe the format of a configuration field
type FieldSchema struct {
Type FieldType
Default interface{}
Description string
Required bool
}
// DefaultOrZero returns the default value if it is set, or otherwise
// the zero value of the type.
func (s *FieldSchema) DefaultOrZero() interface{} {
if s.Default != nil {
return s.Default
}
return s.Type.Zero()
}

View File

@@ -1,25 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fields
import "testing"
func TestFieldSchemaDefaultOrZero(t *testing.T) {
fs := &FieldSchema{
Type: TypeString,
Default: "default",
}
if d := fs.DefaultOrZero(); d != "default" {
t.Fatalf("bad: Expected: default Got: %s", d)
}
fs = &FieldSchema{
Type: TypeString,
}
if d := fs.DefaultOrZero(); d != "" {
t.Fatalf("bad: Expected: \"\" Got: %s", d)
}
}

View File

@@ -1,50 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fields
// FieldType is the enum of types that a field can be.
type FieldType uint
const (
TypeInvalid FieldType = 0
TypeString FieldType = iota
TypeInt
TypeBool
TypeMap
TypeArray
)
func (t FieldType) String() string {
switch t {
case TypeString:
return "string"
case TypeInt:
return "integer"
case TypeBool:
return "boolean"
case TypeMap:
return "map"
case TypeArray:
return "array"
default:
return "unknown type"
}
}
func (t FieldType) Zero() interface{} {
switch t {
case TypeString:
return ""
case TypeInt:
return 0
case TypeBool:
return false
case TypeMap:
return map[string]interface{}{}
case TypeArray:
return []interface{}{}
default:
panic("unknown type: " + t.String())
}
}

View File

@@ -1,64 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fields
import "testing"
func TestFieldTypeString(t *testing.T) {
if s := TypeString.String(); s != "string" {
t.Fatalf("bad: expected 'string' got: %s", s)
}
if s := TypeInt.String(); s != "integer" {
t.Fatalf("bad: expected 'integer' got: %s", s)
}
if s := TypeBool.String(); s != "boolean" {
t.Fatalf("bad: expected 'boolean' got: %s", s)
}
if s := TypeMap.String(); s != "map" {
t.Fatalf("bad: expected 'map' got: %v", s)
}
if s := TypeArray.String(); s != "array" {
t.Fatalf("bad: expected 'array' got: %v", s)
}
if s := TypeInvalid.String(); s != "unknown type" {
t.Fatalf("bad: expected 'unknown type' got: %v", s)
}
}
func TestFieldTypeZero(t *testing.T) {
if z := TypeString.Zero(); z != "" {
t.Fatalf("bad: expected \"\" got: %v", z)
}
if z := TypeInt.Zero(); z != 0 {
t.Fatalf("bad: expected 0 got: %v", z)
}
if z := TypeBool.Zero(); z != false {
t.Fatalf("bad: expected false got: %v", z)
}
z := TypeMap.Zero()
if _, ok := z.(map[string]interface{}); !ok {
t.Fatalf("bad: expected map[string]interface{} got: %v", z)
}
z = TypeArray.Zero()
if _, ok := z.([]interface{}); !ok {
t.Fatalf("bad: expected []interface{} got: %v", z)
}
defer func() {
if r := recover(); r == nil {
t.Errorf("The code did not panic")
}
}()
TypeInvalid.Zero()
}