Skip to content

Commit

Permalink
feat: removes custom schema types in favor of a user provided json sc…
Browse files Browse the repository at this point in the history
…hema

Signed-off-by: Jennifer Power <[email protected]>
  • Loading branch information
jpower432 committed Jan 12, 2023
1 parent fb73d05 commit 78e586a
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 255 deletions.
11 changes: 2 additions & 9 deletions api/client/v1alpha1/schema_types.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package v1alpha1

import (
"github.com/uor-framework/uor-client-go/schema"
)

// SchemaConfigurationKind object kind of SchemaConfiguration
const SchemaConfigurationKind = "SchemaConfiguration"

Expand All @@ -19,9 +15,6 @@ type SchemaConfigurationSpec struct {
// the schema
ID string `json:"id"`
Description string `json:"description"`
// SchemaPath defines that path to a JSON schema. If set, the AttributeTypes fields
// will be ignored.
SchemaPath string
// AttributeTypes is a collection of attribute type definitions.
AttributeTypes schema.Types `json:"attributeTypes,omitempty"`
// SchemaPath defines that path to a JSON schema.
SchemaPath string `json:"schemaPath"`
}
22 changes: 7 additions & 15 deletions cmd/client/commands/build_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,13 @@ func (o *BuildSchemaOptions) Run(ctx context.Context) error {
}
}()

var userSchema schema.Loader
if config.Schema.SchemaPath != "" {
schemaBytes, err := ioutil.ReadFile(config.Schema.SchemaPath)
if err != nil {
return err
}
userSchema, err = schema.FromBytes(schemaBytes)
if err != nil {
return err
}
} else {
userSchema, err = schema.FromTypes(config.Schema.AttributeTypes)
if err != nil {
return err
}
schemaBytes, err := ioutil.ReadFile(config.Schema.SchemaPath)
if err != nil {
return err
}
userSchema, err := schema.FromBytes(schemaBytes)
if err != nil {
return err
}

schemaAnnotations := map[string]string{}
Expand Down
20 changes: 19 additions & 1 deletion cmd/client/commands/build_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func TestBuildSchemaRun(t *testing.T) {

cases := []spec{
{
name: "Success/FlatWorkspace",
name: "Success/ValidateSchemaConfig",
opts: &BuildSchemaOptions{
BuildOptions: &BuildOptions{
Destination: fmt.Sprintf("%s/client-flat-test:latest", u.Host),
Expand All @@ -127,6 +127,24 @@ func TestBuildSchemaRun(t *testing.T) {
SchemaConfig: "testdata/configs/schema-config.yaml",
},
},
{
name: "Failure/NoSchemaPath",
opts: &BuildSchemaOptions{
BuildOptions: &BuildOptions{
Destination: fmt.Sprintf("%s/client-flat-test:latest", u.Host),
Common: &options.Common{
IOStreams: genericclioptions.IOStreams{
Out: os.Stdout,
In: os.Stdin,
ErrOut: os.Stderr,
},
Logger: testlogr,
},
},
SchemaConfig: "testdata/configs/schema-config-nopath.yaml",
},
expError: "no schema path provided in schema config",
},
}

for _, c := range cases {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kind: SchemaConfiguration
apiVersion: client.uor-framework.io/v1alpha1
schema:
id: "myid"
3 changes: 1 addition & 2 deletions cmd/client/commands/testdata/configs/schema-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
kind: SchemaConfiguration
apiVersion: client.uor-framework.io/v1alpha1
schema:
attributeTypes:
"test": "string"
schemaPath: "testdata/configs/test.json"
12 changes: 12 additions & 0 deletions cmd/client/commands/testdata/configs/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"test": {
"type": "string"
}
},
"required": [
"test"
]
}
5 changes: 5 additions & 0 deletions config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"path/filepath"
Expand Down Expand Up @@ -65,6 +66,10 @@ func LoadSchemaConfig(data []byte) (configuration v1alpha1.SchemaConfiguration,
if err = dec.Decode(&configuration); err != nil {
return configuration, err
}

if configuration.Schema.SchemaPath == "" {
return configuration, errors.New("no schema path provided in schema config")
}
return configuration, err
}

Expand Down
13 changes: 8 additions & 5 deletions config/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
uorspec "github.com/uor-framework/collection-spec/specs-go/v1alpha1"

"github.com/uor-framework/uor-client-go/api/client/v1alpha1"
"github.com/uor-framework/uor-client-go/schema"
)

func TestReadAttributeQuery(t *testing.T) {
Expand Down Expand Up @@ -122,14 +121,18 @@ func TestReadSchemaConfiguration(t *testing.T) {
APIVersion: v1alpha1.GroupVersion,
},
Schema: v1alpha1.SchemaConfigurationSpec{
AttributeTypes: map[string]schema.Type{
"test": schema.TypeString,
},
ID: "myschema",
SchemaPath: "mypath",
},
},
},
{
name: "Failure/InvalidConfig",
name: "Failure/InvalidConfigNoPath",
path: "testdata/invalid-schema.yaml",
expError: "no schema path provided in schema config",
},
{
name: "Failure/InvalidConfigWrongType",
path: "testdata/valid-attr.yaml",
expError: "config kind AttributeQuery, does not match expected SchemaConfiguration",
},
Expand Down
4 changes: 4 additions & 0 deletions config/testdata/invalid-schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kind: SchemaConfiguration
apiVersion: client.uor-framework.io/v1alpha1
schema:
id: "myschema"
4 changes: 2 additions & 2 deletions config/testdata/valid-schema.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
kind: SchemaConfiguration
apiVersion: client.uor-framework.io/v1alpha1
schema:
attributeTypes:
"test": "string"
id: "myschema"
schemaPath: "mypath"
42 changes: 0 additions & 42 deletions schema/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package schema

import (
"encoding/json"
"sort"

"github.com/xeipuuv/gojsonschema"
)
Expand All @@ -17,47 +16,6 @@ func (l Loader) Export() json.RawMessage {
return l.raw
}

// FromTypes builds a JSON Schema from a key with an associated type.
// All keys provided will be considered required types in the schema when
// comparing sets of attributes.
func FromTypes(types Types) (Loader, error) {
if err := types.Validate(); err != nil {
return Loader{}, err
}

// Build an object in json from the provided types
type jsonSchema struct {
Type string `json:"type"`
Properties map[string]map[string]string `json:"properties"`
Required []string `json:"required"`
}

// Fill in properties and required keys. At this point
// we consider all keys as required.
properties := map[string]map[string]string{}
var required []string
for key, value := range types {
properties[key] = map[string]string{"type": value.String()}
required = append(required, key)
}

// Make the required slice order deterministic
sort.Slice(required, func(i, j int) bool {
return required[i] < required[j]
})

tmp := jsonSchema{
Type: "object",
Properties: properties,
Required: required,
}
b, err := json.Marshal(tmp)
if err != nil {
return Loader{}, err
}
return FromBytes(b)
}

// FromGo loads a Go struct into a JSON schema that
// can be used for attribute validation.
func FromGo(source interface{}) (Loader, error) {
Expand Down
49 changes: 0 additions & 49 deletions schema/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,6 @@ import (
"github.com/stretchr/testify/require"
)

func TestFromTypes(t *testing.T) {
type spec struct {
name string
types map[string]Type
expSchema string
expError string
}

cases := []spec{
{
name: "Success/ValidConfiguration",
types: map[string]Type{
"test": TypeString,
"size": TypeNumber,
},
expSchema: "{\"type\":\"object\",\"properties\":" + "" +
"{\"size\":{\"type\":\"number\"},\"test\":{\"type\":\"string\"}},\"required\":[\"size\",\"test\"]}",
},
{
name: "Failure/InvalidType",
types: map[string]Type{
"test": TypeString,
"size": TypeInvalid,
},
expError: "must set schema type",
},
{
name: "Failure/UnknownType",
types: map[string]Type{
"test": TypeString,
"size": 20,
},
expError: "unknown schema type",
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
schema, err := FromTypes(c.types)
if c.expError != "" {
require.EqualError(t, err, c.expError)
} else {
require.NoError(t, err)
require.Equal(t, c.expSchema, string(schema.Export()))
}
})
}
}

func TestFromBytes(t *testing.T) {
type spec struct {
name string
Expand Down
64 changes: 52 additions & 12 deletions schema/schema_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package schema

import (
"encoding/json"
"sort"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -11,18 +13,20 @@ import (

func TestSchema_Validate(t *testing.T) {
type spec struct {
name string
schemaTypes Types
doc model.AttributeSet
expRes bool
expError string
name string
properties map[string]map[string]string
doc model.AttributeSet
expRes bool
expError string
}

cases := []spec{
{
name: "Success/ValidAttributes",
schemaTypes: map[string]Type{
"size": TypeNumber,
properties: map[string]map[string]string{
"size": {
"type": "number",
},
},
doc: attributes.Attributes{
"size": attributes.NewFloat("size", 1.0),
Expand All @@ -31,8 +35,10 @@ func TestSchema_Validate(t *testing.T) {
},
{
name: "Failure/IncompatibleType",
schemaTypes: map[string]Type{
"size": TypeBool,
properties: map[string]map[string]string{
"size": {
"type": "boolean",
},
},
doc: attributes.Attributes{
"size": attributes.NewFloat("size", 1.0),
Expand All @@ -42,8 +48,10 @@ func TestSchema_Validate(t *testing.T) {
},
{
name: "Failure/MissingKey",
schemaTypes: map[string]Type{
"size": TypeString,
properties: map[string]map[string]string{
"size": {
"type": "number",
},
},
doc: attributes.Attributes{
"name": attributes.NewString("name", "test"),
Expand All @@ -55,7 +63,7 @@ func TestSchema_Validate(t *testing.T) {

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
loader, err := FromTypes(c.schemaTypes)
loader, err := fromProperties(c.properties)
require.NoError(t, err)

schema, err := New(loader)
Expand All @@ -71,3 +79,35 @@ func TestSchema_Validate(t *testing.T) {
})
}
}

func fromProperties(properties map[string]map[string]string) (Loader, error) {
// Build an object in json from the provided types
type jsonSchema struct {
Type string `json:"type"`
Properties map[string]map[string]string `json:"properties"`
Required []string `json:"required"`
}

// Fill in properties and required keys. At this point
// we consider all keys as required.
var required []string
for key := range properties {
required = append(required, key)
}

// Make the required slice order deterministic
sort.Slice(required, func(i, j int) bool {
return required[i] < required[j]
})

tmp := jsonSchema{
Type: "object",
Properties: properties,
Required: required,
}
b, err := json.Marshal(tmp)
if err != nil {
return Loader{}, err
}
return FromBytes(b)
}
Loading

0 comments on commit 78e586a

Please sign in to comment.