Skip to content

Commit

Permalink
feat: removes viper for config loading and uses JSON standard library
Browse files Browse the repository at this point in the history
Due to inconsistencies between the way viper and the JSON standard library unmarshals
number values between float/int, removing in favor of sticking to the standard lib to have
consistent attribute sets.

Signed-off-by: Jennifer Power <barnabei.jennifer@gmail.com>
  • Loading branch information
jpower432 committed Aug 16, 2022
1 parent 2bfe139 commit c6525fd
Show file tree
Hide file tree
Showing 22 changed files with 101 additions and 143 deletions.
2 changes: 1 addition & 1 deletion attributes/bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (a boolAttribute) AsFloat() (float64, error) {

// AsInt returns the value as an int value errors and if that is not
// the underlying type.
func (a boolAttribute) AsInt() (int, error) {
func (a boolAttribute) AsInt() (int64, error) {
return 0, ErrWrongKind
}

Expand Down
2 changes: 1 addition & 1 deletion attributes/bool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestBoolAttribute_AsInt(t *testing.T) {
test := NewBool("test", false)
b, err := test.AsInt()
require.ErrorIs(t, ErrWrongKind, err)
require.Equal(t, 0, b)
require.Equal(t, int64(0), b)
}

func TestBoolAttribute_AsString(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion attributes/float.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (a floatAttribute) AsFloat() (float64, error) {

// AsInt returns the value as a number value and errors if that is not
// the underlying type.
func (a floatAttribute) AsInt() (int, error) {
func (a floatAttribute) AsInt() (int64, error) {
return 0, ErrWrongKind
}

Expand Down
2 changes: 1 addition & 1 deletion attributes/float_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestFloatAttribute_AsInt(t *testing.T) {
test := NewFloat("test", 1)
n, err := test.AsInt()
require.ErrorIs(t, ErrWrongKind, err)
require.Equal(t, 0, n)
require.Equal(t, int64(0), n)
}

func TestFloatAttribute_AsString(t *testing.T) {
Expand Down
6 changes: 3 additions & 3 deletions attributes/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import "github.com/uor-framework/uor-client-go/model"

type intAttribute struct {
key string
value int
value int64
}

var _ model.Attribute = intAttribute{}

// NewInt returns an int attribute.
func NewInt(key string, value int) model.Attribute {
func NewInt(key string, value int64) model.Attribute {
return intAttribute{key: key, value: value}
}

Expand Down Expand Up @@ -49,7 +49,7 @@ func (a intAttribute) AsFloat() (float64, error) {

// AsInt returns the value as an int value errors and if that is not
// the underlying type.
func (a intAttribute) AsInt() (int, error) {
func (a intAttribute) AsInt() (int64, error) {
return a.value, nil
}

Expand Down
2 changes: 1 addition & 1 deletion attributes/int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestIntAttribute_AsInt(t *testing.T) {
test := NewInt("test", 1)
n, err := test.AsInt()
require.NoError(t, err)
require.Equal(t, 1, n)
require.Equal(t, int64(1), n)
}

func TestIntAttribute_AsFloat(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion attributes/null.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (a nullAttribute) AsFloat() (float64, error) {

// AsInt returns the value as an int value errors if that is not
// the underlying type.
func (a nullAttribute) AsInt() (int, error) {
func (a nullAttribute) AsInt() (int64, error) {
return 0, ErrWrongKind
}

Expand Down
2 changes: 1 addition & 1 deletion attributes/null_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestNullAttribute_AsInt(t *testing.T) {
test := NewNull("test")
n, err := test.AsInt()
require.ErrorIs(t, ErrWrongKind, err)
require.Equal(t, 0, n)
require.Equal(t, int64(0), n)
}

func TestNullAttribute_AsFloat(t *testing.T) {
Expand Down
17 changes: 16 additions & 1 deletion attributes/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package attributes
import (
"errors"
"github.com/uor-framework/uor-client-go/model"
"reflect"
)

// ErrInvalidAttribute defines the error thrown when an attribute has an invalid
Expand All @@ -11,17 +12,31 @@ var ErrInvalidAttribute = errors.New("invalid attribute type")

// Reflect will create a model.Attribute type from a Go type.
func Reflect(key string, value interface{}) (model.Attribute, error) {
// Try type switch first
switch typVal := value.(type) {
case string:
return NewString(key, typVal), nil
case float64:
return NewFloat(key, typVal), nil
case int:
case int64:
return NewInt(key, typVal), nil
case nil:
return NewNull(key), nil
case bool:
return NewBool(key, typVal), nil
}

// To catch more types try reflection
reflectVal := reflect.ValueOf(value)
switch reflectVal.Kind() {
case reflect.Bool:
return NewBool(key, reflectVal.Bool()), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return NewInt(key, reflectVal.Int()), nil
case reflect.Float32, reflect.Float64:
return NewFloat(key, reflectVal.Float()), nil
case reflect.String:
return NewString(key, reflectVal.String()), nil
default:
return nil, ErrInvalidAttribute
}
Expand Down
2 changes: 1 addition & 1 deletion attributes/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (a stringAttribute) AsFloat() (float64, error) {

// AsInt returns the value as an int value errors and if that is not
// the underlying type.
func (a stringAttribute) AsInt() (int, error) {
func (a stringAttribute) AsInt() (int64, error) {
return 0, ErrWrongKind
}

Expand Down
2 changes: 1 addition & 1 deletion attributes/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestStringAttribute_AsInt(t *testing.T) {
test := NewBool("test", false)
s, err := test.AsInt()
require.ErrorIs(t, ErrWrongKind, err)
require.Equal(t, 0, s)
require.Equal(t, int64(0), s)
}

func TestStringAttribute_AsString(t *testing.T) {
Expand Down
5 changes: 2 additions & 3 deletions builder/api/v1alpha1/attribute_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ const AttributeQueryKind = "AttributeQuery"

// AttributeQuery configures an attribute query.
type AttributeQuery struct {
Kind string `mapstructure:"kind"`
APIVersion string `mapstructure:"apiVersion"`
TypeMeta `json:",inline"`
// Attributes list the configuration for Attribute types.
Attributes Attributes `mapstructure:"attributes"`
Attributes Attributes `json:"attributes"`
}
23 changes: 15 additions & 8 deletions builder/api/v1alpha1/config_types.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
package v1alpha1

// TypeMeta contains type metadata.
type TypeMeta struct {
Kind string `json:"kind,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
}

// DataSetConfigurationKind object kind of DataSetConfiguration.
const DataSetConfigurationKind = "DataSetConfiguration"

// DataSetConfiguration configures a dataset
type DataSetConfiguration struct {
Kind string `mapstructure:"kind,omitempty"`
APIVersion string `mapstructure:"apiVersion,omitempty"`
TypeMeta `json:",inline"`
// Collection configuration spec.
Collection Collection `mapstructure:"collection,omitempty"`
Collection Collection `json:"collection,omitempty"`
// LinkedCollections are the remote addresses of collection that are
// linked to the collection.
LinkedCollections []string `mapstructure:"linkedCollections,omitempty"`
LinkedCollections []string `json:"linkedCollections,omitempty"`
}

type Collection struct {
// Files defines custom attributes to add the files in the
// workspaces when publishing content/
Files []File `mapstructure:"files,omitempty"`
Files []File `json:"files,omitempty"`
// SchemaAddress is the address of the schema to associated
// to the Collection.
SchemaAddress string `mapstructure:"schemaAddress,omitempty"`
SchemaAddress string `json:"schemaAddress,omitempty"`
}

// File associates attributes with file names.
type File struct {
// File is a string that can be compiled into a regular expression
// for grouping attributes.
File string `mapstructure:"file,omitempty"`
File string `json:"file,omitempty"`
// Attributes is the lists of to associate to the file.
Attributes Attributes `mapstructure:"attributes,omitempty"`
Attributes Attributes `json:"attributes,omitempty"`
}

// Attributes is a map structure that holds all
// attribute information.
type Attributes map[string]interface{}
62 changes: 39 additions & 23 deletions builder/config/load.go
Original file line number Diff line number Diff line change
@@ -1,56 +1,72 @@
package config

import (
"bytes"
"encoding/json"
"fmt"
"github.com/spf13/viper"
"path/filepath"

"github.com/uor-framework/uor-client-go/builder/api/v1alpha1"
"io/ioutil"
"path/filepath"
"sigs.k8s.io/yaml"
)

// ReadCollectionConfig read the specified config into a CollectionConfiguration type.
func ReadCollectionConfig(configPath string) (v1alpha1.DataSetConfiguration, error) {
var configuration v1alpha1.DataSetConfiguration
cfg, err := readInConfig(configPath, configuration)
data, err := readInConfig(configPath, v1alpha1.DataSetConfigurationKind)
if err != nil {
return configuration, err
}
dsConfig := cfg.(v1alpha1.DataSetConfiguration)
if dsConfig.Kind != v1alpha1.DataSetConfigurationKind {
return v1alpha1.DataSetConfiguration{}, fmt.Errorf("config kind not recognized: %s", dsConfig.Kind)

dec := json.NewDecoder(bytes.NewBuffer(data))
dec.DisallowUnknownFields()
if err := dec.Decode(&configuration); err != nil {
return configuration, err
}
return dsConfig, nil

return configuration, nil
}

// ReadAttributeQuery read the specified config into a AttributeQuery type.
func ReadAttributeQuery(configPath string) (v1alpha1.AttributeQuery, error) {
var configuration v1alpha1.AttributeQuery
cfg, err := readInConfig(configPath, configuration)
data, err := readInConfig(configPath, v1alpha1.AttributeQueryKind)
if err != nil {
return configuration, err
}

queryConfig := cfg.(v1alpha1.AttributeQuery)
if queryConfig.Kind != v1alpha1.AttributeQueryKind {
return v1alpha1.AttributeQuery{}, fmt.Errorf("config kind not recognized: %s", queryConfig.Kind)
dec := json.NewDecoder(bytes.NewBuffer(data))
dec.DisallowUnknownFields()
if err := dec.Decode(&configuration); err != nil {
return configuration, err
}
return queryConfig, nil
}

func readInConfig(configPath string, object interface{}) (interface{}, error) {
base := filepath.Base(configPath)
dir := filepath.Dir(configPath)
viper.SetConfigName(base)
viper.AddConfigPath(filepath.Clean(dir))
viper.SetConfigType("yaml")
return configuration, nil
}

err := viper.ReadInConfig()
func readInConfig(configPath, kind string) ([]byte, error) {
data, err := ioutil.ReadFile(filepath.Clean(configPath))
if err != nil {
return nil, err
}
err = viper.Unmarshal(&object)

if data, err = yaml.YAMLToJSON(data); err != nil {
return nil, err
}

typeMeta, err := getTypeMeta(data)
if err != nil {
return nil, err
}
return object, nil
if typeMeta.Kind != kind {
return nil, fmt.Errorf("config kind %s, does not match expected %s", typeMeta.Kind, kind)
}
return data, nil
}

func getTypeMeta(data []byte) (typeMeta v1alpha1.TypeMeta, err error) {
if err := json.Unmarshal(data, &typeMeta); err != nil {
return typeMeta, fmt.Errorf("get type meta: %v", err)
}
return typeMeta, nil
}
16 changes: 10 additions & 6 deletions builder/config/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ func TestReadAttributeQuery(t *testing.T) {
name: "Success/ValidConfig",
path: "testdata/valid-attr.yaml",
exp: v1alpha1.AttributeQuery{
Kind: v1alpha1.AttributeQueryKind,
APIVersion: v1alpha1.GroupVersion,
TypeMeta: v1alpha1.TypeMeta{
Kind: v1alpha1.AttributeQueryKind,
APIVersion: v1alpha1.GroupVersion,
},
Attributes: map[string]interface{}{
"size": "small",
},
Expand All @@ -29,7 +31,7 @@ func TestReadAttributeQuery(t *testing.T) {
{
name: "Failure/InvalidConfig",
path: "testdata/valid-ds.yaml",
expError: "config kind not recognized: DataSetConfiguration",
expError: "config kind DataSetConfiguration, does not match expected AttributeQuery",
},
}

Expand Down Expand Up @@ -59,8 +61,10 @@ func TestReadCollectionConfig(t *testing.T) {
name: "Success/ValidConfig",
path: "testdata/valid-ds.yaml",
exp: v1alpha1.DataSetConfiguration{
Kind: v1alpha1.DataSetConfigurationKind,
APIVersion: v1alpha1.GroupVersion,
TypeMeta: v1alpha1.TypeMeta{
Kind: v1alpha1.DataSetConfigurationKind,
APIVersion: v1alpha1.GroupVersion,
},
Collection: v1alpha1.Collection{
SchemaAddress: "localhost:5001/schema:latest",
Files: []v1alpha1.File{
Expand All @@ -77,7 +81,7 @@ func TestReadCollectionConfig(t *testing.T) {
{
name: "Failure/InvalidConfig",
path: "testdata/valid-attr.yaml",
expError: "config kind not recognized: AttributeQuery",
expError: "config kind AttributeQuery, does not match expected DataSetConfiguration",
},
}

Expand Down
2 changes: 1 addition & 1 deletion cli/testdata/configs/link.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
kind: AttributeQuery
apiVersion: client.uor-framework.io/v1alpha1
attributes:
- "test": "linkedannotation"
"test": "linkedannotation"
2 changes: 1 addition & 1 deletion cli/testdata/configs/match.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
kind: AttributeQuery
apiVersion: client.uor-framework.io/v1alpha1
attributes:
- "test": "annotation"
"test": "annotation"
2 changes: 1 addition & 1 deletion cli/testdata/configs/nomatch.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
kind: AttributeQuery
apiVersion: client.uor-framework.io/v1alpha1
attributes:
- "test2": annotation"
"test2": annotation"
2 changes: 1 addition & 1 deletion examples/attributes.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
kind: AttributeQuery
apiVersion: client.uor-framework.io/v1alpha1
attributes:
size: "small"
size: 2
Loading

0 comments on commit c6525fd

Please sign in to comment.