mirror of
https://github.com/rancher/steve.git
synced 2025-06-22 21:17:32 +00:00
430 lines
9.3 KiB
Go
430 lines
9.3 KiB
Go
package definitions
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
|
)
|
|
|
|
func TestCRDToDefinition(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
modelName string
|
|
// rawSchema is a JSON encoded OpenAPI V3 spec
|
|
// We use JSON instead of Go types because it's closer to what
|
|
// user are familiar with (JSON Schema in Go has some more fields
|
|
// like JSONSchemaPropsOrArray
|
|
rawSchema []byte
|
|
expectedSchemaDef schemaDefinition
|
|
wantError bool
|
|
}{
|
|
{
|
|
name: "primitives",
|
|
modelName: "my.group.v1.Test",
|
|
rawSchema: []byte(`
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"aStringWithoutDescription": {
|
|
"type": "string"
|
|
},
|
|
"aString": {
|
|
"type": "string",
|
|
"description": "description of aString"
|
|
},
|
|
"anInteger": {
|
|
"type": "integer",
|
|
"description": "description of anInteger"
|
|
},
|
|
"aNumber": {
|
|
"type": "number",
|
|
"description": "description of aNumber"
|
|
},
|
|
"aBoolean": {
|
|
"type": "boolean",
|
|
"description": "description of aBoolean"
|
|
}
|
|
}
|
|
}`),
|
|
expectedSchemaDef: schemaDefinition{
|
|
DefinitionType: "my.group.v1.Test",
|
|
Definitions: map[string]definition{
|
|
"my.group.v1.Test": {
|
|
Type: "my.group.v1.Test",
|
|
ResourceFields: map[string]definitionField{
|
|
"aStringWithoutDescription": {
|
|
Type: "string",
|
|
},
|
|
"aString": {
|
|
Type: "string",
|
|
Description: "description of aString",
|
|
},
|
|
"anInteger": {
|
|
Type: "int",
|
|
Description: "description of anInteger",
|
|
},
|
|
"aNumber": {
|
|
Type: "int",
|
|
Description: "description of aNumber",
|
|
},
|
|
"aBoolean": {
|
|
Type: "boolean",
|
|
Description: "description of aBoolean",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "arrays",
|
|
modelName: "my.group.v1.Test",
|
|
rawSchema: []byte(`
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"anArrayOfString": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"anArrayOfInteger": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"anArrayOfNumber": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"anArrayOfBoolean": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"anArrayOfObject": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"foo": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"anArrayOfMap": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"anArrayWithListOfItems": {
|
|
"type": "array",
|
|
"items": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "number"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}`),
|
|
expectedSchemaDef: schemaDefinition{
|
|
DefinitionType: "my.group.v1.Test",
|
|
Definitions: map[string]definition{
|
|
"my.group.v1.Test": {
|
|
Type: "my.group.v1.Test",
|
|
ResourceFields: map[string]definitionField{
|
|
"anArrayOfString": {
|
|
Type: "array",
|
|
SubType: "string",
|
|
},
|
|
"anArrayOfInteger": {
|
|
Type: "array",
|
|
SubType: "int",
|
|
},
|
|
"anArrayOfNumber": {
|
|
Type: "array",
|
|
SubType: "int",
|
|
},
|
|
"anArrayOfBoolean": {
|
|
Type: "array",
|
|
SubType: "boolean",
|
|
},
|
|
"anArrayOfObject": {
|
|
Type: "array",
|
|
SubType: "my.group.v1.Test.anArrayOfObject",
|
|
},
|
|
"anArrayOfMap": {
|
|
Type: "array",
|
|
SubType: "map",
|
|
},
|
|
"anArrayWithListOfItems": {
|
|
Type: "array",
|
|
SubType: "string",
|
|
},
|
|
},
|
|
},
|
|
"my.group.v1.Test.anArrayOfObject": {
|
|
Type: "my.group.v1.Test.anArrayOfObject",
|
|
ResourceFields: map[string]definitionField{
|
|
"foo": {
|
|
Type: "string",
|
|
},
|
|
},
|
|
},
|
|
// Currently not referenced in my.group.v1.Test due to lack of support for nested array
|
|
// but will be useful once we get this in
|
|
"my.group.v1.Test.anArrayOfMap": {
|
|
Type: "my.group.v1.Test.anArrayOfMap",
|
|
ResourceFields: map[string]definitionField{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "nested objects",
|
|
modelName: "my.group.v1.Test",
|
|
rawSchema: []byte(`
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"grandparent": {
|
|
"type": "object",
|
|
"properties": {
|
|
"parent": {
|
|
"type": "object",
|
|
"properties": {
|
|
"child": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`),
|
|
expectedSchemaDef: schemaDefinition{
|
|
DefinitionType: "my.group.v1.Test",
|
|
Definitions: map[string]definition{
|
|
"my.group.v1.Test": {
|
|
Type: "my.group.v1.Test",
|
|
ResourceFields: map[string]definitionField{
|
|
"grandparent": {
|
|
Type: "my.group.v1.Test.grandparent",
|
|
},
|
|
},
|
|
},
|
|
"my.group.v1.Test.grandparent": {
|
|
Type: "my.group.v1.Test.grandparent",
|
|
ResourceFields: map[string]definitionField{
|
|
"parent": {
|
|
Type: "my.group.v1.Test.grandparent.parent",
|
|
},
|
|
},
|
|
},
|
|
"my.group.v1.Test.grandparent.parent": {
|
|
Type: "my.group.v1.Test.grandparent.parent",
|
|
ResourceFields: map[string]definitionField{
|
|
"child": {
|
|
Type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "nested arrays",
|
|
modelName: "my.group.v1.Test",
|
|
rawSchema: []byte(`
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"anArrayOfArrayOfString": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`),
|
|
expectedSchemaDef: schemaDefinition{
|
|
DefinitionType: "my.group.v1.Test",
|
|
Definitions: map[string]definition{
|
|
"my.group.v1.Test": {
|
|
Type: "my.group.v1.Test",
|
|
ResourceFields: map[string]definitionField{
|
|
"anArrayOfArrayOfString": {
|
|
Type: "array",
|
|
SubType: "array",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "maps in object",
|
|
modelName: "my.group.v1.Test",
|
|
rawSchema: []byte(`
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"mapEmpty": {
|
|
"type": "object"
|
|
},
|
|
"mapAdditionalPropertiesObject": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"foo": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"mapAdditionalPropertiesPrimitive": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}`),
|
|
expectedSchemaDef: schemaDefinition{
|
|
DefinitionType: "my.group.v1.Test",
|
|
Definitions: map[string]definition{
|
|
"my.group.v1.Test": {
|
|
Type: "my.group.v1.Test",
|
|
ResourceFields: map[string]definitionField{
|
|
"mapEmpty": {
|
|
Type: "map",
|
|
SubType: "my.group.v1.Test.mapEmpty",
|
|
},
|
|
"mapAdditionalPropertiesObject": {
|
|
Type: "map",
|
|
SubType: "my.group.v1.Test.mapAdditionalPropertiesObject",
|
|
},
|
|
"mapAdditionalPropertiesPrimitive": {
|
|
Type: "map",
|
|
SubType: "string",
|
|
},
|
|
},
|
|
},
|
|
"my.group.v1.Test.mapEmpty": {
|
|
Type: "my.group.v1.Test.mapEmpty",
|
|
ResourceFields: map[string]definitionField{},
|
|
},
|
|
"my.group.v1.Test.mapAdditionalPropertiesObject": {
|
|
Type: "my.group.v1.Test.mapAdditionalPropertiesObject",
|
|
ResourceFields: map[string]definitionField{
|
|
"foo": {
|
|
Type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "required fields",
|
|
modelName: "my.group.v1.Test",
|
|
rawSchema: []byte(`
|
|
{
|
|
"type": "object",
|
|
"required": [
|
|
"topLevelRequired"
|
|
],
|
|
"properties": {
|
|
"topLevelRequired": {
|
|
"type": "string"
|
|
},
|
|
"child": {
|
|
"type": "object",
|
|
"required": [
|
|
"fieldIsRequired"
|
|
],
|
|
"properties": {
|
|
"fieldIsRequired": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`),
|
|
expectedSchemaDef: schemaDefinition{
|
|
DefinitionType: "my.group.v1.Test",
|
|
Definitions: map[string]definition{
|
|
"my.group.v1.Test": {
|
|
Type: "my.group.v1.Test",
|
|
ResourceFields: map[string]definitionField{
|
|
"topLevelRequired": {
|
|
Type: "string",
|
|
Required: true,
|
|
},
|
|
"child": {
|
|
Type: "my.group.v1.Test.child",
|
|
},
|
|
},
|
|
},
|
|
"my.group.v1.Test.child": {
|
|
Type: "my.group.v1.Test.child",
|
|
ResourceFields: map[string]definitionField{
|
|
"fieldIsRequired": {
|
|
Type: "string",
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "bad array",
|
|
modelName: "my.group.v1.Test",
|
|
rawSchema: []byte(`
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"badArray": {
|
|
"type": "array"
|
|
}
|
|
}
|
|
}`),
|
|
wantError: true,
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
var schema apiextv1.JSONSchemaProps
|
|
err := json.Unmarshal(test.rawSchema, &schema)
|
|
require.NoError(t, err)
|
|
|
|
schemaDef, err := crdToDefinition(&schema, test.modelName)
|
|
|
|
if test.wantError {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
require.Equal(t, test.expectedSchemaDef, schemaDef)
|
|
}
|
|
})
|
|
}
|
|
|
|
}
|