vendor: Update vendor logic

This commit is contained in:
Clayton Coleman 2020-04-08 14:34:43 -04:00
parent c6ac5cbc87
commit 4ca64b85f0
No known key found for this signature in database
GPG key ID: 3D16906B4F1C5CB3
1540 changed files with 265304 additions and 91616 deletions

View file

@ -31,8 +31,6 @@ import (
const (
OpenAPIVersion = "2.0"
// TODO: Make this configurable.
extensionPrefix = "x-kubernetes-"
)
type openAPI struct {
@ -154,6 +152,11 @@ func (o *openAPI) buildDefinitionRecursively(name string) error {
schema.Extensions[k] = v
}
}
if v, ok := item.Schema.Extensions[common.ExtensionV2Schema]; ok {
if v2Schema, isOpenAPISchema := v.(spec.Schema); isOpenAPISchema {
schema = v2Schema
}
}
o.swagger.Definitions[uniqueName] = schema
for _, v := range item.Dependencies {
if err := o.buildDefinitionRecursively(v); err != nil {
@ -270,7 +273,7 @@ func (o *openAPI) buildOperations(route restful.Route, inPathCommonParamsMap map
},
}
for k, v := range route.Metadata {
if strings.HasPrefix(k, extensionPrefix) {
if strings.HasPrefix(k, common.ExtensionPrefix) {
if ret.Extensions == nil {
ret.Extensions = spec.Extensions{}
}

View file

@ -24,6 +24,12 @@ import (
"github.com/go-openapi/spec"
)
const (
// TODO: Make this configurable.
ExtensionPrefix = "x-kubernetes-"
ExtensionV2Schema = ExtensionPrefix + "v2-schema"
)
// OpenAPIDefinition describes single type. Normally these definitions are auto-generated using gen-openapi.
type OpenAPIDefinition struct {
Schema spec.Schema
@ -43,6 +49,10 @@ type OpenAPIDefinitionGetter interface {
OpenAPIDefinition() *OpenAPIDefinition
}
type OpenAPIV3DefinitionGetter interface {
OpenAPIV3Definition() *OpenAPIDefinition
}
type PathHandler interface {
Handle(path string, handler http.Handler)
}
@ -172,3 +182,11 @@ func EscapeJsonPointer(p string) string {
p = strings.Replace(p, "/", "~1", -1)
return p
}
func EmbedOpenAPIDefinitionIntoV2Extension(main OpenAPIDefinition, embedded OpenAPIDefinition) OpenAPIDefinition {
if main.Schema.Extensions == nil {
main.Schema.Extensions = make(map[string]interface{})
}
main.Schema.Extensions[ExtensionV2Schema] = embedded.Schema
return main
}

View file

@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"path"
"sort"
"strings"
"k8s.io/kube-openapi/pkg/util/proto"
@ -29,20 +30,28 @@ import (
// ToSchema converts openapi definitions into a schema suitable for structured
// merge (i.e. kubectl apply v2).
func ToSchema(models proto.Models) (*schema.Schema, error) {
return ToSchemaWithPreserveUnknownFields(models, false)
}
// ToSchemaWithPreserveUnknownFields converts openapi definitions into a schema suitable for structured
// merge (i.e. kubectl apply v2), it will preserve unknown fields if specified.
func ToSchemaWithPreserveUnknownFields(models proto.Models, preserveUnknownFields bool) (*schema.Schema, error) {
c := convert{
input: models,
output: &schema.Schema{},
input: models,
preserveUnknownFields: preserveUnknownFields,
output: &schema.Schema{},
}
if err := c.convertAll(); err != nil {
return nil, err
}
c.addCommonTypes()
return c.output, nil
}
type convert struct {
input proto.Models
output *schema.Schema
input proto.Models
preserveUnknownFields bool
output *schema.Schema
currentName string
current *schema.Atom
@ -51,10 +60,11 @@ type convert struct {
func (c *convert) push(name string, a *schema.Atom) *convert {
return &convert{
input: c.input,
output: c.output,
currentName: name,
current: a,
input: c.input,
preserveUnknownFields: c.preserveUnknownFields,
output: c.output,
currentName: name,
current: a,
}
}
@ -95,14 +105,59 @@ func (c *convert) insertTypeDef(name string, model proto.Schema) {
c.output.Types = append(c.output.Types, def)
}
func (c *convert) makeRef(model proto.Schema) schema.TypeRef {
func (c *convert) addCommonTypes() {
c.output.Types = append(c.output.Types, untypedDef)
c.output.Types = append(c.output.Types, deducedDef)
}
var untypedName string = "__untyped_atomic_"
var untypedDef schema.TypeDef = schema.TypeDef{
Name: untypedName,
Atom: schema.Atom{
Scalar: ptr(schema.Scalar("untyped")),
List: &schema.List{
ElementType: schema.TypeRef{
NamedType: &untypedName,
},
ElementRelationship: schema.Atomic,
},
Map: &schema.Map{
ElementType: schema.TypeRef{
NamedType: &untypedName,
},
ElementRelationship: schema.Atomic,
},
},
}
var deducedName string = "__untyped_deduced_"
var deducedDef schema.TypeDef = schema.TypeDef{
Name: deducedName,
Atom: schema.Atom{
Scalar: ptr(schema.Scalar("untyped")),
List: &schema.List{
ElementType: schema.TypeRef{
NamedType: &untypedName,
},
ElementRelationship: schema.Atomic,
},
Map: &schema.Map{
ElementType: schema.TypeRef{
NamedType: &deducedName,
},
ElementRelationship: schema.Separable,
},
},
}
func (c *convert) makeRef(model proto.Schema, preserveUnknownFields bool) 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{},
},
NamedType: &untypedName,
}
}
// reference a named type
@ -111,30 +166,152 @@ func (c *convert) makeRef(model proto.Schema) schema.TypeRef {
} else {
// compute the type inline
c2 := c.push("inlined in "+c.currentName, &tr.Inlined)
c2.preserveUnknownFields = preserveUnknownFields
model.Accept(c2)
c.pop(c2)
if tr == (schema.TypeRef{}) {
// emit warning?
tr.Inlined.Untyped = &schema.Untyped{}
tr.NamedType = &untypedName
}
}
return tr
}
func makeUnions(extensions map[string]interface{}) ([]schema.Union, error) {
schemaUnions := []schema.Union{}
if iunions, ok := extensions["x-kubernetes-unions"]; ok {
unions, ok := iunions.([]interface{})
if !ok {
return nil, fmt.Errorf(`"x-kubernetes-unions" should be a list, got %#v`, unions)
}
for _, iunion := range unions {
union, ok := iunion.(map[interface{}]interface{})
if !ok {
return nil, fmt.Errorf(`"x-kubernetes-unions" items should be a map of string to unions, got %#v`, iunion)
}
unionMap := map[string]interface{}{}
for k, v := range union {
key, ok := k.(string)
if !ok {
return nil, fmt.Errorf(`"x-kubernetes-unions" has non-string key: %#v`, k)
}
unionMap[key] = v
}
schemaUnion, err := makeUnion(unionMap)
if err != nil {
return nil, err
}
schemaUnions = append(schemaUnions, schemaUnion)
}
}
// Make sure we have no overlap between unions
fs := map[string]struct{}{}
for _, u := range schemaUnions {
if u.Discriminator != nil {
if _, ok := fs[*u.Discriminator]; ok {
return nil, fmt.Errorf("%v field appears multiple times in unions", *u.Discriminator)
}
fs[*u.Discriminator] = struct{}{}
}
for _, f := range u.Fields {
if _, ok := fs[f.FieldName]; ok {
return nil, fmt.Errorf("%v field appears multiple times in unions", f.FieldName)
}
fs[f.FieldName] = struct{}{}
}
}
return schemaUnions, nil
}
func makeUnion(extensions map[string]interface{}) (schema.Union, error) {
union := schema.Union{
Fields: []schema.UnionField{},
}
if idiscriminator, ok := extensions["discriminator"]; ok {
discriminator, ok := idiscriminator.(string)
if !ok {
return schema.Union{}, fmt.Errorf(`"discriminator" must be a string, got: %#v`, idiscriminator)
}
union.Discriminator = &discriminator
}
if ifields, ok := extensions["fields-to-discriminateBy"]; ok {
fields, ok := ifields.(map[interface{}]interface{})
if !ok {
return schema.Union{}, fmt.Errorf(`"fields-to-discriminateBy" must be a map[string]string, got: %#v`, ifields)
}
// Needs sorted keys by field.
keys := []string{}
for ifield := range fields {
field, ok := ifield.(string)
if !ok {
return schema.Union{}, fmt.Errorf(`"fields-to-discriminateBy": field must be a string, got: %#v`, ifield)
}
keys = append(keys, field)
}
sort.Strings(keys)
reverseMap := map[string]struct{}{}
for _, field := range keys {
value := fields[field]
discriminated, ok := value.(string)
if !ok {
return schema.Union{}, fmt.Errorf(`"fields-to-discriminateBy"/%v: value must be a string, got: %#v`, field, value)
}
union.Fields = append(union.Fields, schema.UnionField{
FieldName: field,
DiscriminatorValue: discriminated,
})
// Check that we don't have the same discriminateBy multiple times.
if _, ok := reverseMap[discriminated]; ok {
return schema.Union{}, fmt.Errorf("Multiple fields have the same discriminated name: %v", discriminated)
}
reverseMap[discriminated] = struct{}{}
}
}
if union.Discriminator != nil && len(union.Fields) == 0 {
return schema.Union{}, fmt.Errorf("discriminator set to %v, but no fields in union", *union.Discriminator)
}
return union, nil
}
func (c *convert) VisitKind(k *proto.Kind) {
preserveUnknownFields := c.preserveUnknownFields
if p, ok := k.GetExtensions()["x-kubernetes-preserve-unknown-fields"]; ok && p == true {
preserveUnknownFields = true
}
a := c.top()
a.Struct = &schema.Struct{}
a.Map = &schema.Map{}
for _, name := range k.FieldOrder {
member := k.Fields[name]
tr := c.makeRef(member)
a.Struct.Fields = append(a.Struct.Fields, schema.StructField{
tr := c.makeRef(member, preserveUnknownFields)
a.Map.Fields = append(a.Map.Fields, schema.StructField{
Name: name,
Type: tr,
})
}
// TODO: Get element relationship when we start adding it to the spec.
unions, err := makeUnions(k.GetExtensions())
if err != nil {
c.reportError(err.Error())
return
}
// TODO: We should check that the fields and discriminator
// specified in the union are actual fields in the struct.
a.Map.Unions = unions
if preserveUnknownFields {
a.Map.ElementType = schema.TypeRef{
NamedType: &deducedName,
}
}
}
func toStringSlice(o interface{}) (out []string, ok bool) {
@ -157,7 +334,7 @@ func (c *convert) VisitArray(a *proto.Array) {
ElementRelationship: schema.Atomic,
}
l := atom.List
l.ElementType = c.makeRef(a.SubType)
l.ElementType = c.makeRef(a.SubType, c.preserveUnknownFields)
ext := a.GetExtensions()
@ -205,15 +382,16 @@ func (c *convert) VisitArray(a *proto.Array) {
func (c *convert) VisitMap(m *proto.Map) {
a := c.top()
a.Map = &schema.Map{}
a.Map.ElementType = c.makeRef(m.SubType)
a.Map.ElementType = c.makeRef(m.SubType, c.preserveUnknownFields)
// TODO: Get element relationship when we start putting it into the
// spec.
}
func ptr(s schema.Scalar) *schema.Scalar { return &s }
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)
@ -227,21 +405,24 @@ func (c *convert) VisitPrimitive(p *proto.Primitive) {
// byte really means []byte and is encoded as a string.
a.Scalar = ptr(schema.String)
case "int-or-string":
a.Untyped = &schema.Untyped{}
a.Scalar = ptr(schema.Scalar("untyped"))
case "date-time":
a.Untyped = &schema.Untyped{}
a.Scalar = ptr(schema.Scalar("untyped"))
default:
a.Untyped = &schema.Untyped{}
a.Scalar = ptr(schema.Scalar("untyped"))
}
case proto.Boolean:
a.Scalar = ptr(schema.Boolean)
default:
a.Untyped = &schema.Untyped{}
a.Scalar = ptr(schema.Scalar("untyped"))
}
}
func (c *convert) VisitArbitrary(a *proto.Arbitrary) {
c.top().Untyped = &schema.Untyped{}
*c.top() = untypedDef.Atom
if c.preserveUnknownFields {
*c.top() = deducedDef.Atom
}
}
func (c *convert) VisitReference(proto.Reference) {