mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 01:38:10 +00:00
vendor dependencies
This commit is contained in:
parent
604208ef4f
commit
72abf135d6
1156 changed files with 78178 additions and 105799 deletions
23
vendor/k8s.io/kube-openapi/pkg/builder/openapi.go
generated
vendored
23
vendor/k8s.io/kube-openapi/pkg/builder/openapi.go
generated
vendored
|
|
@ -20,7 +20,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
restful "github.com/emicklei/go-restful"
|
||||
|
|
@ -58,7 +57,7 @@ func BuildOpenAPIDefinitionsForResource(model interface{}, config *common.Config
|
|||
o := newOpenAPI(config)
|
||||
// We can discard the return value of toSchema because all we care about is the side effect of calling it.
|
||||
// All the models created for this resource get added to o.swagger.Definitions
|
||||
_, err := o.toSchema(getCanonicalTypeName(model))
|
||||
_, err := o.toSchema(util.GetCanonicalTypeName(model))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -92,6 +91,7 @@ func newOpenAPI(config *common.Config) openAPI {
|
|||
SwaggerProps: spec.SwaggerProps{
|
||||
Swagger: OpenAPIVersion,
|
||||
Definitions: spec.Definitions{},
|
||||
Responses: config.ResponseDefinitions,
|
||||
Paths: &spec.Paths{Paths: map[string]spec.PathItem{}},
|
||||
Info: config.Info,
|
||||
},
|
||||
|
|
@ -135,21 +135,6 @@ func (o *openAPI) finalizeSwagger() (*spec.Swagger, error) {
|
|||
return o.swagger, nil
|
||||
}
|
||||
|
||||
func getCanonicalTypeName(model interface{}) string {
|
||||
t := reflect.TypeOf(model)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.PkgPath() == "" {
|
||||
return t.Name()
|
||||
}
|
||||
path := t.PkgPath()
|
||||
if strings.Contains(path, "/vendor/") {
|
||||
path = path[strings.Index(path, "/vendor/")+len("/vendor/"):]
|
||||
}
|
||||
return path + "." + t.Name()
|
||||
}
|
||||
|
||||
func (o *openAPI) buildDefinitionRecursively(name string) error {
|
||||
uniqueName, extensions := o.config.GetDefinitionName(name)
|
||||
if _, ok := o.swagger.Definitions[uniqueName]; ok {
|
||||
|
|
@ -335,7 +320,7 @@ func (o *openAPI) buildOperations(route restful.Route, inPathCommonParamsMap map
|
|||
}
|
||||
|
||||
func (o *openAPI) buildResponse(model interface{}, description string) (spec.Response, error) {
|
||||
schema, err := o.toSchema(getCanonicalTypeName(model))
|
||||
schema, err := o.toSchema(util.GetCanonicalTypeName(model))
|
||||
if err != nil {
|
||||
return spec.Response{}, err
|
||||
}
|
||||
|
|
@ -413,7 +398,7 @@ func (o *openAPI) buildParameter(restParam restful.ParameterData, bodySample int
|
|||
case restful.BodyParameterKind:
|
||||
if bodySample != nil {
|
||||
ret.In = "body"
|
||||
ret.Schema, err = o.toSchema(getCanonicalTypeName(bodySample))
|
||||
ret.Schema, err = o.toSchema(util.GetCanonicalTypeName(bodySample))
|
||||
return ret, err
|
||||
} else {
|
||||
// There is not enough information in the body parameter to build the definition.
|
||||
|
|
|
|||
6
vendor/k8s.io/kube-openapi/pkg/common/common.go
generated
vendored
6
vendor/k8s.io/kube-openapi/pkg/common/common.go
generated
vendored
|
|
@ -59,6 +59,12 @@ type Config struct {
|
|||
// will show up as ... "responses" : {"default" : $DefaultResponse} in the spec.
|
||||
DefaultResponse *spec.Response
|
||||
|
||||
// ResponseDefinitions will be added to "responses" under the top-level swagger object. This is an object
|
||||
// that holds responses definitions that can be used across operations. This property does not define
|
||||
// global responses for all operations. For more info please refer:
|
||||
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields
|
||||
ResponseDefinitions map[string]spec.Response
|
||||
|
||||
// CommonResponses will be added as a response to all operation specs. This is a good place to add common
|
||||
// responses such as authorization failed.
|
||||
CommonResponses map[int]spec.Response
|
||||
|
|
|
|||
153
vendor/k8s.io/kube-openapi/pkg/handler/handler.go
generated
vendored
153
vendor/k8s.io/kube-openapi/pkg/handler/handler.go
generated
vendored
|
|
@ -20,24 +20,21 @@ import (
|
|||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha512"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/ww/goautoneg"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/NYTimes/gziphandler"
|
||||
restful "github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/golang/protobuf/proto"
|
||||
openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
|
||||
"github.com/googleapis/gnostic/OpenAPIv2"
|
||||
"github.com/googleapis/gnostic/compiler"
|
||||
"github.com/json-iterator/go"
|
||||
"github.com/munnerz/goautoneg"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/builder"
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
|
|
@ -79,66 +76,13 @@ func computeETag(data []byte) string {
|
|||
return fmt.Sprintf("\"%X\"", sha512.Sum512(data))
|
||||
}
|
||||
|
||||
// NOTE: [DEPRECATION] We will announce deprecation for format-separated endpoints for OpenAPI spec,
|
||||
// and switch to a single /openapi/v2 endpoint in Kubernetes 1.10. The design doc and deprecation process
|
||||
// are tracked at: https://docs.google.com/document/d/19lEqE9lc4yHJ3WJAJxS_G7TcORIJXGHyq3wpwcH28nU.
|
||||
//
|
||||
// BuildAndRegisterOpenAPIService builds the spec and registers a handler to provide access to it.
|
||||
// Use this method if your OpenAPI spec is static. If you want to update the spec, use BuildOpenAPISpec then RegisterOpenAPIService.
|
||||
func BuildAndRegisterOpenAPIService(servePath string, webServices []*restful.WebService, config *common.Config, handler common.PathHandler) (*OpenAPIService, error) {
|
||||
spec, err := builder.BuildOpenAPISpec(webServices, config)
|
||||
if err != nil {
|
||||
// NewOpenAPIService builds an OpenAPIService starting with the given spec.
|
||||
func NewOpenAPIService(spec *spec.Swagger) (*OpenAPIService, error) {
|
||||
o := &OpenAPIService{}
|
||||
if err := o.UpdateSpec(spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return RegisterOpenAPIService(spec, servePath, handler)
|
||||
}
|
||||
|
||||
// NOTE: [DEPRECATION] We will announce deprecation for format-separated endpoints for OpenAPI spec,
|
||||
// and switch to a single /openapi/v2 endpoint in Kubernetes 1.10. The design doc and deprecation process
|
||||
// are tracked at: https://docs.google.com/document/d/19lEqE9lc4yHJ3WJAJxS_G7TcORIJXGHyq3wpwcH28nU.
|
||||
//
|
||||
// RegisterOpenAPIService registers a handler to provide access to provided swagger spec.
|
||||
// Note: servePath should end with ".json" as the RegisterOpenAPIService assume it is serving a
|
||||
// json file and will also serve .pb and .gz files.
|
||||
func RegisterOpenAPIService(openapiSpec *spec.Swagger, servePath string, handler common.PathHandler) (*OpenAPIService, error) {
|
||||
if !strings.HasSuffix(servePath, jsonExt) {
|
||||
return nil, fmt.Errorf("serving path must end with \"%s\"", jsonExt)
|
||||
}
|
||||
|
||||
servePathBase := strings.TrimSuffix(servePath, jsonExt)
|
||||
|
||||
o := OpenAPIService{}
|
||||
if err := o.UpdateSpec(openapiSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type fileInfo struct {
|
||||
ext string
|
||||
getDataAndETag func() ([]byte, string, time.Time)
|
||||
}
|
||||
|
||||
files := []fileInfo{
|
||||
{".json", o.getSwaggerBytes},
|
||||
{"-2.0.0.json", o.getSwaggerBytes},
|
||||
{"-2.0.0.pb-v1", o.getSwaggerPbBytes},
|
||||
{"-2.0.0.pb-v1.gz", o.getSwaggerPbGzBytes},
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
path := servePathBase + file.ext
|
||||
getDataAndETag := file.getDataAndETag
|
||||
handler.Handle(path, gziphandler.GzipHandler(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
data, etag, lastModified := getDataAndETag()
|
||||
w.Header().Set("Etag", etag)
|
||||
|
||||
// ServeContent will take care of caching using eTag.
|
||||
http.ServeContent(w, r, path, lastModified, bytes.NewReader(data))
|
||||
}),
|
||||
))
|
||||
}
|
||||
|
||||
return &o, nil
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) getSwaggerBytes() ([]byte, string, time.Time) {
|
||||
|
|
@ -160,11 +104,15 @@ func (o *OpenAPIService) getSwaggerPbGzBytes() ([]byte, string, time.Time) {
|
|||
}
|
||||
|
||||
func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) {
|
||||
specBytes, err := json.MarshalIndent(openapiSpec, " ", " ")
|
||||
specBytes, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(openapiSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
specPb, err := toProtoBinary(specBytes)
|
||||
var json map[string]interface{}
|
||||
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(specBytes, &json); err != nil {
|
||||
return err
|
||||
}
|
||||
specPb, err := ToProtoBinary(json)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -190,13 +138,50 @@ func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func toProtoBinary(spec []byte) ([]byte, error) {
|
||||
var info yaml.MapSlice
|
||||
err := yaml.Unmarshal(spec, &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func jsonToYAML(j map[string]interface{}) yaml.MapSlice {
|
||||
if j == nil {
|
||||
return nil
|
||||
}
|
||||
document, err := openapi_v2.NewDocument(info, compiler.NewContext("$root", nil))
|
||||
ret := make(yaml.MapSlice, 0, len(j))
|
||||
for k, v := range j {
|
||||
ret = append(ret, yaml.MapItem{k, jsonToYAMLValue(v)})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func jsonToYAMLValue(j interface{}) interface{} {
|
||||
switch j := j.(type) {
|
||||
case map[string]interface{}:
|
||||
return jsonToYAML(j)
|
||||
case []interface{}:
|
||||
ret := make([]interface{}, len(j))
|
||||
for i := range j {
|
||||
ret[i] = jsonToYAMLValue(j[i])
|
||||
}
|
||||
return ret
|
||||
case float64:
|
||||
// replicate the logic in https://github.com/go-yaml/yaml/blob/51d6538a90f86fe93ac480b35f37b2be17fef232/resolve.go#L151
|
||||
if i64 := int64(j); j == float64(i64) {
|
||||
if i := int(i64); i64 == int64(i) {
|
||||
return i
|
||||
}
|
||||
return i64
|
||||
}
|
||||
if ui64 := uint64(j); j == float64(ui64) {
|
||||
return ui64
|
||||
}
|
||||
return j
|
||||
case int64:
|
||||
if i := int(j); j == int64(i) {
|
||||
return i
|
||||
}
|
||||
return j
|
||||
}
|
||||
return j
|
||||
}
|
||||
|
||||
func ToProtoBinary(json map[string]interface{}) ([]byte, error) {
|
||||
document, err := openapi_v2.NewDocument(jsonToYAML(json), compiler.NewContext("$root", nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -212,12 +197,18 @@ func toGzip(data []byte) []byte {
|
|||
}
|
||||
|
||||
// RegisterOpenAPIVersionedService registers a handler to provide access to provided swagger spec.
|
||||
func RegisterOpenAPIVersionedService(openapiSpec *spec.Swagger, servePath string, handler common.PathHandler) (*OpenAPIService, error) {
|
||||
o := OpenAPIService{}
|
||||
if err := o.UpdateSpec(openapiSpec); err != nil {
|
||||
//
|
||||
// Deprecated: use OpenAPIService.RegisterOpenAPIVersionedService instead.
|
||||
func RegisterOpenAPIVersionedService(spec *spec.Swagger, servePath string, handler common.PathHandler) (*OpenAPIService, error) {
|
||||
o, err := NewOpenAPIService(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return o, o.RegisterOpenAPIVersionedService(servePath, handler)
|
||||
}
|
||||
|
||||
// RegisterOpenAPIVersionedService registers a handler to provide access to provided swagger spec.
|
||||
func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handler common.PathHandler) error {
|
||||
accepted := []struct {
|
||||
Type string
|
||||
SubType string
|
||||
|
|
@ -258,7 +249,7 @@ func RegisterOpenAPIVersionedService(openapiSpec *spec.Swagger, servePath string
|
|||
}),
|
||||
))
|
||||
|
||||
return &o, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// BuildAndRegisterOpenAPIVersionedService builds the spec and registers a handler to provide access to it.
|
||||
|
|
@ -268,5 +259,9 @@ func BuildAndRegisterOpenAPIVersionedService(servePath string, webServices []*re
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return RegisterOpenAPIVersionedService(spec, servePath, handler)
|
||||
o, err := NewOpenAPIService(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return o, o.RegisterOpenAPIVersionedService(servePath, handler)
|
||||
}
|
||||
|
|
|
|||
249
vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go
generated
vendored
Normal file
249
vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package schemaconv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
"sigs.k8s.io/structured-merge-diff/schema"
|
||||
)
|
||||
|
||||
// ToSchema converts openapi definitions into a schema suitable for structured
|
||||
// merge (i.e. kubectl apply v2).
|
||||
func ToSchema(models proto.Models) (*schema.Schema, error) {
|
||||
c := convert{
|
||||
input: models,
|
||||
output: &schema.Schema{},
|
||||
}
|
||||
if err := c.convertAll(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.output, nil
|
||||
}
|
||||
|
||||
type convert struct {
|
||||
input proto.Models
|
||||
output *schema.Schema
|
||||
|
||||
currentName string
|
||||
current *schema.Atom
|
||||
errorMessages []string
|
||||
}
|
||||
|
||||
func (c *convert) push(name string, a *schema.Atom) *convert {
|
||||
return &convert{
|
||||
input: c.input,
|
||||
output: c.output,
|
||||
currentName: name,
|
||||
current: a,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) top() *schema.Atom { return c.current }
|
||||
|
||||
func (c *convert) pop(c2 *convert) {
|
||||
c.errorMessages = append(c.errorMessages, c2.errorMessages...)
|
||||
}
|
||||
|
||||
func (c *convert) convertAll() error {
|
||||
for _, name := range c.input.ListModels() {
|
||||
model := c.input.LookupModel(name)
|
||||
c.insertTypeDef(name, model)
|
||||
}
|
||||
if len(c.errorMessages) > 0 {
|
||||
return errors.New(strings.Join(c.errorMessages, "\n"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *convert) reportError(format string, args ...interface{}) {
|
||||
c.errorMessages = append(c.errorMessages,
|
||||
c.currentName+": "+fmt.Sprintf(format, args...),
|
||||
)
|
||||
}
|
||||
|
||||
func (c *convert) insertTypeDef(name string, model proto.Schema) {
|
||||
def := schema.TypeDef{
|
||||
Name: name,
|
||||
}
|
||||
c2 := c.push(name, &def.Atom)
|
||||
model.Accept(c2)
|
||||
c.pop(c2)
|
||||
if def.Atom == (schema.Atom{}) {
|
||||
// This could happen if there were a top-level reference.
|
||||
return
|
||||
}
|
||||
c.output.Types = append(c.output.Types, def)
|
||||
}
|
||||
|
||||
func (c *convert) makeRef(model proto.Schema) schema.TypeRef {
|
||||
var tr schema.TypeRef
|
||||
if r, ok := model.(*proto.Ref); ok {
|
||||
if r.Reference() == "io.k8s.apimachinery.pkg.runtime.RawExtension" {
|
||||
return schema.TypeRef{
|
||||
Inlined: schema.Atom{
|
||||
Untyped: &schema.Untyped{},
|
||||
},
|
||||
}
|
||||
}
|
||||
// reference a named type
|
||||
_, n := path.Split(r.Reference())
|
||||
tr.NamedType = &n
|
||||
} else {
|
||||
// compute the type inline
|
||||
c2 := c.push("inlined in "+c.currentName, &tr.Inlined)
|
||||
model.Accept(c2)
|
||||
c.pop(c2)
|
||||
|
||||
if tr == (schema.TypeRef{}) {
|
||||
// emit warning?
|
||||
tr.Inlined.Untyped = &schema.Untyped{}
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (c *convert) VisitKind(k *proto.Kind) {
|
||||
a := c.top()
|
||||
a.Struct = &schema.Struct{}
|
||||
for _, name := range k.FieldOrder {
|
||||
member := k.Fields[name]
|
||||
tr := c.makeRef(member)
|
||||
a.Struct.Fields = append(a.Struct.Fields, schema.StructField{
|
||||
Name: name,
|
||||
Type: tr,
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Get element relationship when we start adding it to the spec.
|
||||
}
|
||||
|
||||
func toStringSlice(o interface{}) (out []string, ok bool) {
|
||||
switch t := o.(type) {
|
||||
case []interface{}:
|
||||
for _, v := range t {
|
||||
switch vt := v.(type) {
|
||||
case string:
|
||||
out = append(out, vt)
|
||||
}
|
||||
}
|
||||
return out, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (c *convert) VisitArray(a *proto.Array) {
|
||||
atom := c.top()
|
||||
atom.List = &schema.List{
|
||||
ElementRelationship: schema.Atomic,
|
||||
}
|
||||
l := atom.List
|
||||
l.ElementType = c.makeRef(a.SubType)
|
||||
|
||||
ext := a.GetExtensions()
|
||||
|
||||
if val, ok := ext["x-kubernetes-list-type"]; ok {
|
||||
if val == "atomic" {
|
||||
l.ElementRelationship = schema.Atomic
|
||||
} else if val == "set" {
|
||||
l.ElementRelationship = schema.Associative
|
||||
} else if val == "map" {
|
||||
l.ElementRelationship = schema.Associative
|
||||
if keys, ok := ext["x-kubernetes-list-map-keys"]; ok {
|
||||
if keyNames, ok := toStringSlice(keys); ok {
|
||||
l.Keys = keyNames
|
||||
} else {
|
||||
c.reportError("uninterpreted map keys: %#v", keys)
|
||||
}
|
||||
} else {
|
||||
c.reportError("missing map keys")
|
||||
}
|
||||
} else {
|
||||
c.reportError("unknown list type %v", val)
|
||||
l.ElementRelationship = schema.Atomic
|
||||
}
|
||||
} else if val, ok := ext["x-kubernetes-patch-strategy"]; ok {
|
||||
if val == "merge" || val == "merge,retainKeys" {
|
||||
l.ElementRelationship = schema.Associative
|
||||
if key, ok := ext["x-kubernetes-patch-merge-key"]; ok {
|
||||
if keyName, ok := key.(string); ok {
|
||||
l.Keys = []string{keyName}
|
||||
} else {
|
||||
c.reportError("uninterpreted merge key: %#v", key)
|
||||
}
|
||||
} else {
|
||||
// It's not an error for this to be absent, it
|
||||
// means it's a set.
|
||||
}
|
||||
} else if val == "retainKeys" {
|
||||
} else {
|
||||
c.reportError("unknown patch strategy %v", val)
|
||||
l.ElementRelationship = schema.Atomic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitMap(m *proto.Map) {
|
||||
a := c.top()
|
||||
a.Map = &schema.Map{}
|
||||
a.Map.ElementType = c.makeRef(m.SubType)
|
||||
|
||||
// TODO: Get element relationship when we start putting it into the
|
||||
// spec.
|
||||
}
|
||||
|
||||
func (c *convert) VisitPrimitive(p *proto.Primitive) {
|
||||
a := c.top()
|
||||
ptr := func(s schema.Scalar) *schema.Scalar { return &s }
|
||||
switch p.Type {
|
||||
case proto.Integer:
|
||||
a.Scalar = ptr(schema.Numeric)
|
||||
case proto.Number:
|
||||
a.Scalar = ptr(schema.Numeric)
|
||||
case proto.String:
|
||||
switch p.Format {
|
||||
case "":
|
||||
a.Scalar = ptr(schema.String)
|
||||
case "byte":
|
||||
// byte really means []byte and is encoded as a string.
|
||||
a.Scalar = ptr(schema.String)
|
||||
case "int-or-string":
|
||||
a.Untyped = &schema.Untyped{}
|
||||
case "date-time":
|
||||
a.Untyped = &schema.Untyped{}
|
||||
default:
|
||||
a.Untyped = &schema.Untyped{}
|
||||
}
|
||||
case proto.Boolean:
|
||||
a.Scalar = ptr(schema.Boolean)
|
||||
default:
|
||||
a.Untyped = &schema.Untyped{}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitArbitrary(a *proto.Arbitrary) {
|
||||
c.top().Untyped = &schema.Untyped{}
|
||||
}
|
||||
|
||||
func (c *convert) VisitReference(proto.Reference) {
|
||||
// Do nothing, we handle references specially
|
||||
}
|
||||
2
vendor/k8s.io/kube-openapi/pkg/util/proto/OWNERS
generated
vendored
Normal file
2
vendor/k8s.io/kube-openapi/pkg/util/proto/OWNERS
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
approvers:
|
||||
- apelisse
|
||||
25
vendor/k8s.io/kube-openapi/pkg/util/proto/document.go
generated
vendored
25
vendor/k8s.io/kube-openapi/pkg/util/proto/document.go
generated
vendored
|
|
@ -92,13 +92,16 @@ func NewOpenAPIData(doc *openapi_v2.Document) (Models, error) {
|
|||
// We believe the schema is a reference, verify that and returns a new
|
||||
// Schema
|
||||
func (d *Definitions) parseReference(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
||||
// TODO(wrong): a schema with a $ref can have properties. We can ignore them (would be incomplete), but we cannot return an error.
|
||||
if len(s.GetProperties().GetAdditionalProperties()) > 0 {
|
||||
return nil, newSchemaError(path, "unallowed embedded type definition")
|
||||
}
|
||||
// TODO(wrong): a schema with a $ref can have a type. We can ignore it (would be incomplete), but we cannot return an error.
|
||||
if len(s.GetType().GetValue()) > 0 {
|
||||
return nil, newSchemaError(path, "definition reference can't have a type")
|
||||
}
|
||||
|
||||
// TODO(wrong): $refs outside of the definitions are completely valid. We can ignore them (would be incomplete), but we cannot return an error.
|
||||
if !strings.HasPrefix(s.GetXRef(), "#/definitions/") {
|
||||
return nil, newSchemaError(path, "unallowed reference to non-definition %q", s.GetXRef())
|
||||
}
|
||||
|
|
@ -127,6 +130,7 @@ func (d *Definitions) parseMap(s *openapi_v2.Schema, path *Path) (Schema, error)
|
|||
return nil, newSchemaError(path, "invalid object type")
|
||||
}
|
||||
var sub Schema
|
||||
// TODO(incomplete): this misses the boolean case as AdditionalProperties is a bool+schema sum type.
|
||||
if s.GetAdditionalProperties().GetSchema() == nil {
|
||||
sub = &Arbitrary{
|
||||
BaseSchema: d.parseBaseSchema(s, path),
|
||||
|
|
@ -157,6 +161,7 @@ func (d *Definitions) parsePrimitive(s *openapi_v2.Schema, path *Path) (Schema,
|
|||
case Number: // do nothing
|
||||
case Integer: // do nothing
|
||||
case Boolean: // do nothing
|
||||
// TODO(wrong): this misses "null". Would skip the null case (would be incomplete), but we cannot return an error.
|
||||
default:
|
||||
return nil, newSchemaError(path, "Unknown primitive type: %q", t)
|
||||
}
|
||||
|
|
@ -175,6 +180,8 @@ func (d *Definitions) parseArray(s *openapi_v2.Schema, path *Path) (Schema, erro
|
|||
return nil, newSchemaError(path, `array should have type "array"`)
|
||||
}
|
||||
if len(s.GetItems().GetSchema()) != 1 {
|
||||
// TODO(wrong): Items can have multiple elements. We can ignore Items then (would be incomplete), but we cannot return an error.
|
||||
// TODO(wrong): "type: array" witohut any items at all is completely valid.
|
||||
return nil, newSchemaError(path, "array should have exactly one sub-item")
|
||||
}
|
||||
sub, err := d.ParseSchema(s.GetItems().GetSchema()[0], path)
|
||||
|
|
@ -196,20 +203,24 @@ func (d *Definitions) parseKind(s *openapi_v2.Schema, path *Path) (Schema, error
|
|||
}
|
||||
|
||||
fields := map[string]Schema{}
|
||||
fieldOrder := []string{}
|
||||
|
||||
for _, namedSchema := range s.GetProperties().GetAdditionalProperties() {
|
||||
var err error
|
||||
path := path.FieldPath(namedSchema.GetName())
|
||||
fields[namedSchema.GetName()], err = d.ParseSchema(namedSchema.GetValue(), &path)
|
||||
name := namedSchema.GetName()
|
||||
path := path.FieldPath(name)
|
||||
fields[name], err = d.ParseSchema(namedSchema.GetValue(), &path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldOrder = append(fieldOrder, name)
|
||||
}
|
||||
|
||||
return &Kind{
|
||||
BaseSchema: d.parseBaseSchema(s, path),
|
||||
RequiredFields: s.GetRequired(),
|
||||
Fields: fields,
|
||||
FieldOrder: fieldOrder,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -223,6 +234,8 @@ func (d *Definitions) parseArbitrary(s *openapi_v2.Schema, path *Path) (Schema,
|
|||
// this function is public, it doesn't leak through the interface.
|
||||
func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, error) {
|
||||
if s.GetXRef() != "" {
|
||||
// TODO(incomplete): ignoring the rest of s is wrong. As long as there are no conflict, everything from s must be considered
|
||||
// Reference: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#path-item-object
|
||||
return d.parseReference(s, path)
|
||||
}
|
||||
objectTypes := s.GetType().GetValue()
|
||||
|
|
@ -230,11 +243,15 @@ func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, err
|
|||
case 0:
|
||||
// in the OpenAPI schema served by older k8s versions, object definitions created from structs did not include
|
||||
// the type:object property (they only included the "properties" property), so we need to handle this case
|
||||
// TODO: validate that we ever published empty, non-nil properties. JSON roundtripping nils them.
|
||||
if s.GetProperties() != nil {
|
||||
// TODO(wrong): when verifying a non-object later against this, it will be rejected as invalid type.
|
||||
// TODO(CRD validation schema publishing): we have to filter properties (empty or not) if type=object is not given
|
||||
return d.parseKind(s, path)
|
||||
} else {
|
||||
// Definition has no type and no properties. Treat it as an arbitrary value
|
||||
// TODO: what if it has additionalProperties or patternProperties?
|
||||
// TODO(incomplete): what if it has additionalProperties=false or patternProperties?
|
||||
// ANSWER: parseArbitrary is less strict than it has to be with patternProperties (which is ignored). So this is correct (of course not complete).
|
||||
return d.parseArbitrary(s, path)
|
||||
}
|
||||
case 1:
|
||||
|
|
@ -252,6 +269,8 @@ func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, err
|
|||
return d.parsePrimitive(s, path)
|
||||
default:
|
||||
// the OpenAPI generator never generates (nor it ever did in the past) OpenAPI type definitions with multiple types
|
||||
// TODO(wrong): this is rejecting a completely valid OpenAPI spec
|
||||
// TODO(CRD validation schema publishing): filter these out
|
||||
return nil, newSchemaError(path, "definitions with multiple types aren't supported")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go
generated
vendored
2
vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go
generated
vendored
|
|
@ -173,6 +173,8 @@ type Kind struct {
|
|||
RequiredFields []string
|
||||
// Maps field names to types.
|
||||
Fields map[string]Schema
|
||||
// FieldOrder reports the canonical order for the fields.
|
||||
FieldOrder []string
|
||||
}
|
||||
|
||||
var _ Schema = &Kind{}
|
||||
|
|
|
|||
72
vendor/k8s.io/kube-openapi/pkg/util/util.go
generated
vendored
72
vendor/k8s.io/kube-openapi/pkg/util/util.go
generated
vendored
|
|
@ -16,16 +16,44 @@ limitations under the License.
|
|||
|
||||
package util
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ToCanonicalName converts Golang package/type name into canonical OpenAPI name.
|
||||
// Examples:
|
||||
// [DEPRECATED] ToCanonicalName converts Golang package/type canonical name into REST friendly OpenAPI name.
|
||||
// This method is deprecated because it has a misleading name. Please use ToRESTFriendlyName
|
||||
// instead
|
||||
//
|
||||
// NOTE: actually the "canonical name" in this method should be named "REST friendly OpenAPI name",
|
||||
// which is different from "canonical name" defined in GetCanonicalTypeName. The "canonical name" defined
|
||||
// in GetCanonicalTypeName means Go type names with full package path.
|
||||
//
|
||||
// Examples of REST friendly OpenAPI name:
|
||||
// Input: k8s.io/api/core/v1.Pod
|
||||
// Output: io.k8s.api.core.v1.Pod
|
||||
//
|
||||
// Input: k8s.io/api/core/v1
|
||||
// Output: io.k8s.api.core.v1
|
||||
//
|
||||
// Input: csi.storage.k8s.io/v1alpha1.CSINodeInfo
|
||||
// Output: io.k8s.storage.csi.v1alpha1.CSINodeInfo
|
||||
func ToCanonicalName(name string) string {
|
||||
return ToRESTFriendlyName(name)
|
||||
}
|
||||
|
||||
// ToRESTFriendlyName converts Golang package/type canonical name into REST friendly OpenAPI name.
|
||||
//
|
||||
// Examples of REST friendly OpenAPI name:
|
||||
// Input: k8s.io/api/core/v1.Pod
|
||||
// Output: io.k8s.api.core.v1.Pod
|
||||
//
|
||||
// Input: k8s.io/api/core/v1
|
||||
// Output: io.k8s.api.core.v1
|
||||
//
|
||||
// Input: csi.storage.k8s.io/v1alpha1.CSINodeInfo
|
||||
// Output: io.k8s.storage.csi.v1alpha1.CSINodeInfo
|
||||
func ToRESTFriendlyName(name string) string {
|
||||
nameParts := strings.Split(name, "/")
|
||||
// Reverse first part. e.g., io.k8s... instead of k8s.io...
|
||||
if len(nameParts) > 0 && strings.Contains(nameParts[0], ".") {
|
||||
|
|
@ -37,3 +65,41 @@ func ToCanonicalName(name string) string {
|
|||
}
|
||||
return strings.Join(nameParts, ".")
|
||||
}
|
||||
|
||||
// OpenAPICanonicalTypeNamer is an interface for models without Go type to seed model name.
|
||||
//
|
||||
// OpenAPI canonical names are Go type names with full package path, for uniquely indentifying
|
||||
// a model / Go type. If a Go type is vendored from another package, only the path after "/vendor/"
|
||||
// should be used. For custom resource definition (CRD), the canonical name is expected to be
|
||||
// group/version.kind
|
||||
//
|
||||
// Examples of canonical name:
|
||||
// Go type: k8s.io/kubernetes/pkg/apis/core.Pod
|
||||
// CRD: csi.storage.k8s.io/v1alpha1.CSINodeInfo
|
||||
//
|
||||
// Example for vendored Go type:
|
||||
// Original full path: k8s.io/kubernetes/vendor/k8s.io/api/core/v1.Pod
|
||||
// Canonical name: k8s.io/api/core/v1.Pod
|
||||
type OpenAPICanonicalTypeNamer interface {
|
||||
OpenAPICanonicalTypeName() string
|
||||
}
|
||||
|
||||
// GetCanonicalTypeName will find the canonical type name of a sample object, removing
|
||||
// the "vendor" part of the path
|
||||
func GetCanonicalTypeName(model interface{}) string {
|
||||
if namer, ok := model.(OpenAPICanonicalTypeNamer); ok {
|
||||
return namer.OpenAPICanonicalTypeName()
|
||||
}
|
||||
t := reflect.TypeOf(model)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.PkgPath() == "" {
|
||||
return t.Name()
|
||||
}
|
||||
path := t.PkgPath()
|
||||
if strings.Contains(path, "/vendor/") {
|
||||
path = path[strings.Index(path, "/vendor/")+len("/vendor/"):]
|
||||
}
|
||||
return path + "." + t.Name()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue