update modules kustomize add helm
Signed-off-by: LiHui <andrewli@yunify.com>
This commit is contained in:
607
vendor/sigs.k8s.io/kustomize/kyaml/openapi/openapi.go
generated
vendored
Normal file
607
vendor/sigs.k8s.io/kustomize/kyaml/openapi/openapi.go
generated
vendored
Normal file
@@ -0,0 +1,607 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package openapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi/kubernetesapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi/kustomizationapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
// globalSchema contains global state information about the openapi
|
||||
var globalSchema openapiData
|
||||
|
||||
// kubernetesOpenAPIVersion specifies which builtin kubernetes schema to use
|
||||
var kubernetesOpenAPIVersion string
|
||||
|
||||
// customSchemaFile stores the custom OpenApi schema if it is provided
|
||||
var customSchema []byte
|
||||
|
||||
// openapiData contains the parsed openapi state. this is in a struct rather than
|
||||
// a list of vars so that it can be reset from tests.
|
||||
type openapiData struct {
|
||||
// schema holds the OpenAPI schema data
|
||||
schema spec.Schema
|
||||
|
||||
// schemaForResourceType is a map of Resource types to their schemas
|
||||
schemaByResourceType map[yaml.TypeMeta]*spec.Schema
|
||||
|
||||
// namespaceabilityByResourceType stores whether a given Resource type
|
||||
// is namespaceable or not
|
||||
namespaceabilityByResourceType map[yaml.TypeMeta]bool
|
||||
|
||||
// noUseBuiltInSchema stores whether we want to prevent using the built-n
|
||||
// Kubernetes schema as part of the global schema
|
||||
noUseBuiltInSchema bool
|
||||
|
||||
// schemaInit stores whether or not we've parsed the schema already,
|
||||
// so that we only reparse the when necessary (to speed up performance)
|
||||
schemaInit bool
|
||||
}
|
||||
|
||||
// ResourceSchema wraps the OpenAPI Schema.
|
||||
type ResourceSchema struct {
|
||||
// Schema is the OpenAPI schema for a Resource or field
|
||||
Schema *spec.Schema
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the ResourceSchema is empty
|
||||
func (rs *ResourceSchema) IsMissingOrNull() bool {
|
||||
if rs == nil || rs.Schema == nil {
|
||||
return true
|
||||
}
|
||||
return reflect.DeepEqual(*rs.Schema, spec.Schema{})
|
||||
}
|
||||
|
||||
// SchemaForResourceType returns the Schema for the given Resource
|
||||
// TODO(pwittrock): create a version of this function that will return a schema
|
||||
// which can be used for duck-typed Resources -- e.g. contains common fields such
|
||||
// as metadata, replicas and spec.template.spec
|
||||
func SchemaForResourceType(t yaml.TypeMeta) *ResourceSchema {
|
||||
initSchema()
|
||||
rs, found := globalSchema.schemaByResourceType[t]
|
||||
if !found {
|
||||
return nil
|
||||
}
|
||||
return &ResourceSchema{Schema: rs}
|
||||
}
|
||||
|
||||
// SupplementaryOpenAPIFieldName is the conventional field name (JSON/YAML) containing
|
||||
// supplementary OpenAPI definitions.
|
||||
const SupplementaryOpenAPIFieldName = "openAPI"
|
||||
|
||||
const Definitions = "definitions"
|
||||
|
||||
// AddSchemaFromFile reads the file at path and parses the OpenAPI definitions
|
||||
// from the field "openAPI", also returns a function to clean the added definitions
|
||||
// The returned clean function is a no-op on error, or else it's a function
|
||||
// that the caller should use to remove the added openAPI definitions from
|
||||
// global schema
|
||||
func SchemaFromFile(path string) (*spec.Schema, error) {
|
||||
object, err := parseOpenAPI(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return schemaUsingField(object, SupplementaryOpenAPIFieldName)
|
||||
}
|
||||
|
||||
// DefinitionRefs returns the list of openAPI definition references present in the
|
||||
// input openAPIPath
|
||||
func DefinitionRefs(openAPIPath string) ([]string, error) {
|
||||
object, err := parseOpenAPI(openAPIPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return definitionRefsFromRNode(object)
|
||||
}
|
||||
|
||||
// definitionRefsFromRNode returns the list of openAPI definitions keys from input
|
||||
// yaml RNode
|
||||
func definitionRefsFromRNode(object *yaml.RNode) ([]string, error) {
|
||||
definitions, err := object.Pipe(yaml.Lookup(SupplementaryOpenAPIFieldName, Definitions))
|
||||
if definitions == nil {
|
||||
return nil, err
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return definitions.Fields()
|
||||
}
|
||||
|
||||
// parseOpenAPI reads openAPIPath yaml and converts it to RNode
|
||||
func parseOpenAPI(openAPIPath string) (*yaml.RNode, error) {
|
||||
b, err := ioutil.ReadFile(openAPIPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
object, err := yaml.Parse(string(b))
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("invalid file %q: %v", openAPIPath, err)
|
||||
}
|
||||
return object, nil
|
||||
}
|
||||
|
||||
// addSchemaUsingField parses the OpenAPI definitions from the specified field.
|
||||
// If field is the empty string, use the whole document as OpenAPI.
|
||||
func schemaUsingField(object *yaml.RNode, field string) (*spec.Schema, error) {
|
||||
if field != "" {
|
||||
// get the field containing the openAPI
|
||||
m := object.Field(field)
|
||||
if m.IsNilOrEmpty() {
|
||||
// doesn't contain openAPI definitions
|
||||
return nil, nil
|
||||
}
|
||||
object = m.Value
|
||||
}
|
||||
|
||||
oAPI, err := object.String()
|
||||
if err != nil {
|
||||
return nil, 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 nil, err
|
||||
}
|
||||
j, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sc spec.Schema
|
||||
err = sc.UnmarshalJSON(j)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sc, nil
|
||||
}
|
||||
|
||||
// AddSchema parses s, and adds definitions from s to the global schema.
|
||||
func AddSchema(s []byte) error {
|
||||
return parse(s)
|
||||
}
|
||||
|
||||
// ResetOpenAPI resets the openapi data to empty
|
||||
func ResetOpenAPI() {
|
||||
globalSchema = openapiData{}
|
||||
}
|
||||
|
||||
// AddDefinitions adds the definitions to the global schema.
|
||||
func AddDefinitions(definitions spec.Definitions) {
|
||||
// initialize values if they have not yet been set
|
||||
if globalSchema.schemaByResourceType == nil {
|
||||
globalSchema.schemaByResourceType = map[yaml.TypeMeta]*spec.Schema{}
|
||||
}
|
||||
if globalSchema.schema.Definitions == nil {
|
||||
globalSchema.schema.Definitions = spec.Definitions{}
|
||||
}
|
||||
|
||||
// index the schema definitions so we can lookup them up for Resources
|
||||
for k := range definitions {
|
||||
// index by GVK, if no GVK is found then it is the schema for a subfield
|
||||
// of a Resource
|
||||
d := definitions[k]
|
||||
|
||||
// copy definitions to the schema
|
||||
globalSchema.schema.Definitions[k] = d
|
||||
gvk, found := d.VendorExtensible.Extensions[kubernetesGVKExtensionKey]
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
// cast the extension to a []map[string]string
|
||||
exts, ok := gvk.([]interface{})
|
||||
if !ok || len(exts) != 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
typeMeta, ok := toTypeMeta(exts[0])
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
globalSchema.schemaByResourceType[typeMeta] = &d
|
||||
}
|
||||
}
|
||||
|
||||
func toTypeMeta(ext interface{}) (yaml.TypeMeta, bool) {
|
||||
m, ok := ext.(map[string]interface{})
|
||||
if !ok {
|
||||
return yaml.TypeMeta{}, false
|
||||
}
|
||||
|
||||
g := m[groupKey].(string)
|
||||
apiVersion := m[versionKey].(string)
|
||||
if g != "" {
|
||||
apiVersion = g + "/" + apiVersion
|
||||
}
|
||||
return yaml.TypeMeta{Kind: m[kindKey].(string), APIVersion: apiVersion}, true
|
||||
}
|
||||
|
||||
// Resolve resolves the reference against the global schema
|
||||
func Resolve(ref *spec.Ref, schema *spec.Schema) (*spec.Schema, error) {
|
||||
return resolve(schema, ref)
|
||||
}
|
||||
|
||||
// Schema returns the global schema
|
||||
func Schema() *spec.Schema {
|
||||
return rootSchema()
|
||||
}
|
||||
|
||||
// GetSchema parses s into a ResourceSchema, resolving References within the
|
||||
// global schema.
|
||||
func GetSchema(s string, schema *spec.Schema) (*ResourceSchema, error) {
|
||||
var sc spec.Schema
|
||||
if err := sc.UnmarshalJSON([]byte(s)); err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
if sc.Ref.String() != "" {
|
||||
r, err := Resolve(&sc.Ref, schema)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
sc = *r
|
||||
}
|
||||
|
||||
return &ResourceSchema{Schema: &sc}, nil
|
||||
}
|
||||
|
||||
// IsNamespaceScoped determines whether a resource is namespace or
|
||||
// cluster-scoped by looking at the information in the openapi schema.
|
||||
// The second return value tells whether the provided type could be found
|
||||
// in the openapi schema. If the value is false here, the scope of the
|
||||
// resource is not known. If the type if found, the first return value will
|
||||
// be true if the resource is namespace-scoped, and false if the type is
|
||||
// cluster-scoped.
|
||||
func IsNamespaceScoped(typeMeta yaml.TypeMeta) (bool, bool) {
|
||||
initSchema()
|
||||
isNamespaceScoped, found := globalSchema.namespaceabilityByResourceType[typeMeta]
|
||||
return isNamespaceScoped, found
|
||||
}
|
||||
|
||||
// SuppressBuiltInSchemaUse can be called to prevent using the built-in Kubernetes
|
||||
// schema as part of the global schema.
|
||||
// Must be called before the schema is used.
|
||||
func SuppressBuiltInSchemaUse() {
|
||||
globalSchema.noUseBuiltInSchema = true
|
||||
}
|
||||
|
||||
// Elements returns the Schema for the elements of an array.
|
||||
func (rs *ResourceSchema) Elements() *ResourceSchema {
|
||||
// load the schema from swagger.json
|
||||
initSchema()
|
||||
|
||||
if len(rs.Schema.Type) != 1 || rs.Schema.Type[0] != "array" {
|
||||
// either not an array, or array has multiple types
|
||||
return nil
|
||||
}
|
||||
if rs == nil || rs.Schema == nil || rs.Schema.Items == nil {
|
||||
// no-scheme for the items
|
||||
return nil
|
||||
}
|
||||
s := *rs.Schema.Items.Schema
|
||||
for s.Ref.String() != "" {
|
||||
sc, e := Resolve(&s.Ref, Schema())
|
||||
if e != nil {
|
||||
return nil
|
||||
}
|
||||
s = *sc
|
||||
}
|
||||
return &ResourceSchema{Schema: &s}
|
||||
}
|
||||
|
||||
const Elements = "[]"
|
||||
|
||||
// Lookup calls either Field or Elements for each item in the path.
|
||||
// If the path item is "[]", then Elements is called, otherwise
|
||||
// Field is called.
|
||||
// If any Field or Elements call returns nil, then Lookup returns
|
||||
// nil immediately.
|
||||
func (rs *ResourceSchema) Lookup(path ...string) *ResourceSchema {
|
||||
s := rs
|
||||
for _, p := range path {
|
||||
if s == nil {
|
||||
break
|
||||
}
|
||||
if p == Elements {
|
||||
s = s.Elements()
|
||||
continue
|
||||
}
|
||||
s = s.Field(p)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Field returns the Schema for a field.
|
||||
func (rs *ResourceSchema) Field(field string) *ResourceSchema {
|
||||
// load the schema from swagger.json
|
||||
initSchema()
|
||||
|
||||
// locate the Schema
|
||||
s, found := rs.Schema.Properties[field]
|
||||
switch {
|
||||
case found:
|
||||
// no-op, continue with s as the schema
|
||||
case rs.Schema.AdditionalProperties != nil && rs.Schema.AdditionalProperties.Schema != nil:
|
||||
// map field type -- use Schema of the value
|
||||
// (the key doesn't matter, they all have the same value type)
|
||||
s = *rs.Schema.AdditionalProperties.Schema
|
||||
default:
|
||||
// no Schema found from either swagger.json or line comments
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolve the reference to the Schema if the Schema has one
|
||||
for s.Ref.String() != "" {
|
||||
sc, e := Resolve(&s.Ref, Schema())
|
||||
if e != nil {
|
||||
return nil
|
||||
}
|
||||
s = *sc
|
||||
}
|
||||
|
||||
// return the merged Schema
|
||||
return &ResourceSchema{Schema: &s}
|
||||
}
|
||||
|
||||
// PatchStrategyAndKeyList returns the patch strategy and complete merge key list
|
||||
func (rs *ResourceSchema) PatchStrategyAndKeyList() (string, []string) {
|
||||
ps, found := rs.Schema.Extensions[kubernetesPatchStrategyExtensionKey]
|
||||
if !found {
|
||||
// empty patch strategy
|
||||
return "", []string{}
|
||||
}
|
||||
mkList, found := rs.Schema.Extensions[kubernetesMergeKeyMapList]
|
||||
if found {
|
||||
// mkList is []interface, convert to []string
|
||||
mkListStr := make([]string, len(mkList.([]interface{})))
|
||||
for i, v := range mkList.([]interface{}) {
|
||||
mkListStr[i] = v.(string)
|
||||
}
|
||||
return ps.(string), mkListStr
|
||||
}
|
||||
mk, found := rs.Schema.Extensions[kubernetesMergeKeyExtensionKey]
|
||||
if !found {
|
||||
// no mergeKey -- may be a primitive associative list (e.g. finalizers)
|
||||
return ps.(string), []string{}
|
||||
}
|
||||
return ps.(string), []string{mk.(string)}
|
||||
}
|
||||
|
||||
// PatchStrategyAndKey returns the patch strategy and merge key extensions
|
||||
func (rs *ResourceSchema) PatchStrategyAndKey() (string, string) {
|
||||
ps, found := rs.Schema.Extensions[kubernetesPatchStrategyExtensionKey]
|
||||
if !found {
|
||||
// empty patch strategy
|
||||
return "", ""
|
||||
}
|
||||
|
||||
mk, found := rs.Schema.Extensions[kubernetesMergeKeyExtensionKey]
|
||||
if !found {
|
||||
// no mergeKey -- may be a primitive associative list (e.g. finalizers)
|
||||
mk = ""
|
||||
}
|
||||
return ps.(string), mk.(string)
|
||||
}
|
||||
|
||||
const (
|
||||
// kubernetesOpenAPIDefaultVersion is the latest version number of the statically compiled in
|
||||
// OpenAPI schema for kubernetes built-in types
|
||||
kubernetesOpenAPIDefaultVersion = kubernetesapi.DefaultOpenAPI
|
||||
|
||||
// kustomizationAPIAssetName is the name of the asset containing the statically compiled in
|
||||
// OpenAPI definitions for Kustomization built-in types
|
||||
kustomizationAPIAssetName = "kustomizationapi/swagger.json"
|
||||
|
||||
// kubernetesGVKExtensionKey is the key to lookup the kubernetes group version kind extension
|
||||
// -- the extension is an array of objects containing a gvk
|
||||
kubernetesGVKExtensionKey = "x-kubernetes-group-version-kind"
|
||||
|
||||
// kubernetesMergeKeyExtensionKey is the key to lookup the kubernetes merge key extension
|
||||
// -- the extension is a string
|
||||
kubernetesMergeKeyExtensionKey = "x-kubernetes-patch-merge-key"
|
||||
|
||||
// kubernetesPatchStrategyExtensionKey is the key to lookup the kubernetes patch strategy
|
||||
// extension -- the extension is a string
|
||||
kubernetesPatchStrategyExtensionKey = "x-kubernetes-patch-strategy"
|
||||
|
||||
// kubernetesMergeKeyMapList is the list of merge keys when there needs to be multiple
|
||||
// -- the extension is an array of strings
|
||||
kubernetesMergeKeyMapList = "x-kubernetes-list-map-keys"
|
||||
|
||||
// groupKey is the key to lookup the group from the GVK extension
|
||||
groupKey = "group"
|
||||
// versionKey is the key to lookup the version from the GVK extension
|
||||
versionKey = "version"
|
||||
// kindKey is the the to lookup the kind from the GVK extension
|
||||
kindKey = "kind"
|
||||
)
|
||||
|
||||
// SetSchema sets the kubernetes OpenAPI schema version to use
|
||||
func SetSchema(openAPIField map[string]string, schema []byte, reset bool) error {
|
||||
// this should only be set once
|
||||
schemaIsSet := (kubernetesOpenAPIVersion != "") || customSchema != nil
|
||||
if schemaIsSet && !reset {
|
||||
return nil
|
||||
}
|
||||
|
||||
version, exists := openAPIField["version"]
|
||||
if exists && schema != nil {
|
||||
return fmt.Errorf("builtin version and custom schema provided, cannot use both")
|
||||
}
|
||||
|
||||
if schema != nil { // use custom schema
|
||||
customSchema = schema
|
||||
kubernetesOpenAPIVersion = "custom"
|
||||
return nil
|
||||
}
|
||||
|
||||
// use builtin version
|
||||
kubernetesOpenAPIVersion = strings.ReplaceAll(version, ".", "")
|
||||
if kubernetesOpenAPIVersion == "" {
|
||||
return nil
|
||||
}
|
||||
if _, ok := kubernetesapi.OpenAPIMustAsset[kubernetesOpenAPIVersion]; !ok {
|
||||
return fmt.Errorf("the specified OpenAPI version is not built in")
|
||||
}
|
||||
customSchema = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSchemaVersion returns what kubernetes OpenAPI version is being used
|
||||
func GetSchemaVersion() string {
|
||||
switch {
|
||||
case kubernetesOpenAPIVersion == "" && customSchema == nil:
|
||||
return kubernetesOpenAPIDefaultVersion
|
||||
case customSchema != nil:
|
||||
return "using custom schema from file provided"
|
||||
default:
|
||||
return kubernetesOpenAPIVersion
|
||||
}
|
||||
}
|
||||
|
||||
// initSchema parses the json schema
|
||||
func initSchema() {
|
||||
if globalSchema.schemaInit {
|
||||
return
|
||||
}
|
||||
globalSchema.schemaInit = true
|
||||
|
||||
if customSchema != nil {
|
||||
err := parse(customSchema)
|
||||
if err != nil {
|
||||
panic("invalid schema file")
|
||||
}
|
||||
if err = parse(kustomizationapi.MustAsset(kustomizationAPIAssetName)); err != nil {
|
||||
// this should never happen
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if kubernetesOpenAPIVersion == "" {
|
||||
parseBuiltinSchema(kubernetesOpenAPIDefaultVersion)
|
||||
} else {
|
||||
parseBuiltinSchema(kubernetesOpenAPIVersion)
|
||||
}
|
||||
}
|
||||
|
||||
// parseBuiltinSchema calls parse to parse the json schemas
|
||||
func parseBuiltinSchema(version string) {
|
||||
if globalSchema.noUseBuiltInSchema {
|
||||
// don't parse the built in schema
|
||||
return
|
||||
}
|
||||
|
||||
// parse the swagger, this should never fail
|
||||
assetName := filepath.Join(
|
||||
"kubernetesapi",
|
||||
version,
|
||||
"swagger.json")
|
||||
|
||||
if err := parse(kubernetesapi.OpenAPIMustAsset[version](assetName)); err != nil {
|
||||
// this should never happen
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := parse(kustomizationapi.MustAsset(kustomizationAPIAssetName)); err != nil {
|
||||
// this should never happen
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// parse parses and indexes a single json schema
|
||||
func parse(b []byte) error {
|
||||
var swagger spec.Swagger
|
||||
|
||||
if err := swagger.UnmarshalJSON(b); err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
AddDefinitions(swagger.Definitions)
|
||||
findNamespaceability(swagger.Paths)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// findNamespaceability looks at the api paths for the resource to determine
|
||||
// if it is cluster-scoped or namespace-scoped. The gvk of the resource
|
||||
// for each path is found by looking at the x-kubernetes-group-version-kind
|
||||
// extension. If a path exists for the resource that contains a namespace path
|
||||
// parameter, the resource is namespace-scoped.
|
||||
func findNamespaceability(paths *spec.Paths) {
|
||||
if globalSchema.namespaceabilityByResourceType == nil {
|
||||
globalSchema.namespaceabilityByResourceType = make(map[yaml.TypeMeta]bool)
|
||||
}
|
||||
|
||||
if paths == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for path, pathInfo := range paths.Paths {
|
||||
if pathInfo.Get == nil {
|
||||
continue
|
||||
}
|
||||
gvk, found := pathInfo.Get.VendorExtensible.Extensions[kubernetesGVKExtensionKey]
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
typeMeta, found := toTypeMeta(gvk)
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(path, "namespaces/{namespace}") {
|
||||
// if we find a namespace path parameter, we just update the map
|
||||
// directly
|
||||
globalSchema.namespaceabilityByResourceType[typeMeta] = true
|
||||
} else if _, found := globalSchema.namespaceabilityByResourceType[typeMeta]; !found {
|
||||
// if the resource doesn't have the namespace path parameter, we
|
||||
// only add it to the map if it doesn't already exist.
|
||||
globalSchema.namespaceabilityByResourceType[typeMeta] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func resolve(root interface{}, ref *spec.Ref) (*spec.Schema, error) {
|
||||
res, _, err := ref.GetPointer().Get(root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
switch sch := res.(type) {
|
||||
case spec.Schema:
|
||||
return &sch, nil
|
||||
case *spec.Schema:
|
||||
return sch, nil
|
||||
case map[string]interface{}:
|
||||
b, err := json.Marshal(sch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newSch := new(spec.Schema)
|
||||
if err = json.Unmarshal(b, newSch); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newSch, nil
|
||||
default:
|
||||
return nil, errors.Wrap(fmt.Errorf("unknown type for the resolved reference"))
|
||||
}
|
||||
}
|
||||
|
||||
func rootSchema() *spec.Schema {
|
||||
initSchema()
|
||||
return &globalSchema.schema
|
||||
}
|
||||
Reference in New Issue
Block a user