openapi support for loading definitions from a file

This commit is contained in:
Phillip Wittrock
2020-02-13 15:01:37 -08:00
parent 0075d0a88c
commit b7bef5dc44
2 changed files with 104 additions and 40 deletions

View File

@@ -6,6 +6,7 @@ package openapi
import (
"encoding/json"
"fmt"
"io/ioutil"
"sync"
"github.com/go-openapi/spec"
@@ -44,6 +45,66 @@ func SchemaForResourceType(t yaml.TypeMeta) *ResourceSchema {
return &ResourceSchema{Schema: rs}
}
// SupplementaryOpenAPIFieldName is the conventional field name (JSON/YAML) containing
// supplementary OpenAPI definitions.
const SupplementaryOpenAPIFieldName = "openAPI"
// AddSchemaFromFile reads the file at path and parses the OpenAPI definitions
// from the field "openAPI"
func AddSchemaFromFile(path string) error {
return AddSchemaFromFileUsingField(path, SupplementaryOpenAPIFieldName)
}
// AddSchemaFromFileUsingField reads the file at path and parses the OpenAPI definitions
// from the specified field. If field is the empty string, use the whole document as
// OpenAPI.
func AddSchemaFromFileUsingField(path, field string) error {
b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
// parse the yaml file (json is a subset of yaml, so will also parse)
y, err := yaml.Parse(string(b))
if err != nil {
return err
}
if field != "" {
// get the field containing the openAPI
m := y.Field(field)
if yaml.IsFieldEmpty(m) {
// doesn't contain openAPI definitions
return nil
}
y = m.Value
}
oAPI, err := y.String()
if err != nil {
return err
}
// convert the yaml openAPI to a JSON string by unmarshalling it to an
// interface{} and the marshalling it to a string
var o interface{}
err = yaml.Unmarshal([]byte(oAPI), &o)
if err != nil {
return err
}
j, err := json.Marshal(o)
if err != nil {
return err
}
// add the json schema to the global schema
_, err = AddSchema(j)
if err != nil {
return err
}
return nil
}
// AddSchema parses s, and adds definitions from s to the global schema.
func AddSchema(s []byte) (*spec.Schema, error) {
return parse(s)
@@ -296,41 +357,6 @@ func resolve(root interface{}, ref *spec.Ref) (*spec.Schema, error) {
}
}
func PopulateDefsInOpenAPI(s string) error {
y, err := yaml.Parse(s)
if err != nil {
return err
}
// get the field containing the openAPI
f := y.Field("openAPI")
defs, err := f.Value.String()
if err != nil {
return err
}
// convert the yaml openAPI to an interface{}
// which can be marshalled into json
var o interface{}
err = yaml.Unmarshal([]byte(defs), &o)
if err != nil {
return err
}
// convert the interface{} into a json string
j, err := json.Marshal(o)
if err != nil {
return err
}
// add the json schema to the global schema
_, err = AddSchema(j)
if err != nil {
return err
}
return nil
}
func rootSchema() *spec.Schema {
initSchema()
return &globalSchema.schema

View File

@@ -5,6 +5,7 @@ package openapi
import (
"fmt"
"io/ioutil"
"testing"
"github.com/stretchr/testify/assert"
@@ -123,8 +124,8 @@ func TestSchemaForResourceType(t *testing.T) {
}
}
func TestPopulateDefsInOpenAPI_Setter(t *testing.T) {
globalSchema = openapiData{}
func TestAddSchemaFromFile(t *testing.T) {
ResetOpenAPI()
inputyaml := `
openAPI:
definitions:
@@ -134,8 +135,15 @@ openAPI:
name: image-name
value: "nginx"
`
err := PopulateDefsInOpenAPI(inputyaml)
f, err := ioutil.TempFile("", "openapi-")
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.NoError(t, ioutil.WriteFile(f.Name(), []byte(inputyaml), 0600)) {
t.FailNow()
}
err = AddSchemaFromFile(f.Name())
if !assert.NoError(t, err) {
t.FailNow()
}
@@ -153,7 +161,7 @@ openAPI:
}
func TestPopulateDefsInOpenAPI_Substitution(t *testing.T) {
globalSchema = openapiData{}
ResetOpenAPI()
inputyaml := `
openAPI:
definitions:
@@ -178,11 +186,18 @@ openAPI:
- marker: "IMAGE_TAG"
ref: "#/definitions/io.k8s.cli.setters.image-tag"
`
err := PopulateDefsInOpenAPI(inputyaml)
f, err := ioutil.TempFile("", "openapi-")
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.NoError(t, ioutil.WriteFile(f.Name(), []byte(inputyaml), 0600)) {
t.FailNow()
}
if !assert.NoError(t, AddSchemaFromFile(f.Name())) {
t.FailNow()
}
s, err := GetSchema(`{"$ref": "#/definitions/io.k8s.cli.substitutions.image"}`)
@@ -199,3 +214,26 @@ openAPI:
` map[marker:IMAGE_TAG ref:#/definitions/io.k8s.cli.setters.image-tag]]]]]`,
fmt.Sprintf("%v", s.Schema.Extensions))
}
func TestAddSchemaFromFile_empty(t *testing.T) {
ResetOpenAPI()
inputyaml := `
kind: Example
`
f, err := ioutil.TempFile("", "openapi-")
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.NoError(t, ioutil.WriteFile(f.Name(), []byte(inputyaml), 0600)) {
t.FailNow()
}
if !assert.NoError(t, AddSchemaFromFile(f.Name())) {
t.FailNow()
}
if !assert.Equal(t, len(globalSchema.schema.Definitions), 0) {
t.FailNow()
}
}