mirror of https://github.com/k3s-io/k3s
Bump kube-openapi dependency
parent
62b58e625e
commit
212814a0c6
|
@ -3299,35 +3299,35 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/aggregator",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/builder",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/common",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/generators",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/handler",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto/validation",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/utils/clock",
|
||||
|
|
|
@ -2008,23 +2008,23 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/builder",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/common",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/handler",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
|
||||
|
|
|
@ -180,7 +180,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1736,23 +1736,23 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/builder",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/common",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/handler",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/discovery",
|
||||
|
|
|
@ -580,7 +580,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -260,11 +260,11 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/common",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/generators",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1652,27 +1652,27 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/aggregator",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/builder",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/common",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/handler",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1616,23 +1616,23 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/builder",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/common",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/handler",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -916,7 +916,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ func (s *referenceWalker) Start() {
|
|||
}
|
||||
}
|
||||
|
||||
// usedDefinitionForSpec returns a map with all used definition in the provided spec as keys and true as values.
|
||||
// usedDefinitionForSpec returns a map with all used definitions in the provided spec as keys and true as values.
|
||||
func usedDefinitionForSpec(sp *spec.Swagger) map[string]bool {
|
||||
usedDefinitions := map[string]bool{}
|
||||
walkOnAllReferences(func(ref spec.Ref) spec.Ref {
|
||||
|
@ -172,7 +172,7 @@ func usedDefinitionForSpec(sp *spec.Swagger) map[string]bool {
|
|||
}
|
||||
|
||||
// FilterSpecByPaths removes unnecessary paths and definitions used by those paths.
|
||||
// i.e. if a Path removed by this function, all definition used by it and not used
|
||||
// i.e. if a Path removed by this function, all definitions used by it and not used
|
||||
// anywhere else will also be removed.
|
||||
func FilterSpecByPaths(sp *spec.Swagger, keepPathPrefixes []string) {
|
||||
// Walk all references to find all used definitions. This function
|
||||
|
@ -335,6 +335,9 @@ func mergeSpecs(dest, source *spec.Swagger, renameModelConflicts, ignorePathConf
|
|||
}
|
||||
for k, v := range source.Definitions {
|
||||
if _, found := dest.Definitions[k]; !found {
|
||||
if dest.Definitions == nil {
|
||||
dest.Definitions = spec.Definitions{}
|
||||
}
|
||||
dest.Definitions[k] = v
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ func (o *openAPI) buildDefinitionRecursively(name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// buildDefinitionForType build a definition for a given type and return a referable name to it's definition.
|
||||
// buildDefinitionForType build a definition for a given type and return a referable name to its definition.
|
||||
// This is the main function that keep track of definitions used in this spec and is depend on code generated
|
||||
// by k8s.io/kubernetes/cmd/libs/go2idl/openapi-gen.
|
||||
func (o *openAPI) buildDefinitionForType(sample interface{}) (string, error) {
|
||||
|
|
|
@ -32,7 +32,7 @@ type OpenAPIDefinition struct {
|
|||
|
||||
type ReferenceCallback func(path string) spec.Ref
|
||||
|
||||
// OpenAPIDefinitions is collection of all definitions.
|
||||
// GetOpenAPIDefinitions is collection of all definitions.
|
||||
type GetOpenAPIDefinitions func(ReferenceCallback) map[string]OpenAPIDefinition
|
||||
|
||||
// OpenAPIDefinitionGetter gets openAPI definitions for a given type. If a type implements this interface,
|
||||
|
|
|
@ -2,12 +2,16 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["openapi.go"],
|
||||
srcs = [
|
||||
"extension.go",
|
||||
"openapi.go",
|
||||
],
|
||||
importpath = "k8s.io/kube-openapi/pkg/generators",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/gengo/args:go_default_library",
|
||||
"//vendor/k8s.io/gengo/examples/set-gen/sets:go_default_library",
|
||||
"//vendor/k8s.io/gengo/generator:go_default_library",
|
||||
"//vendor/k8s.io/gengo/namer:go_default_library",
|
||||
"//vendor/k8s.io/gengo/types:go_default_library",
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
Copyright 2018 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 generators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/gengo/examples/set-gen/sets"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
const extensionPrefix = "x-kubernetes-"
|
||||
|
||||
// Extension tag to openapi extension
|
||||
var tagToExtension = map[string]string{
|
||||
"patchMergeKey": "x-kubernetes-patch-merge-key",
|
||||
"patchStrategy": "x-kubernetes-patch-strategy",
|
||||
"listType": "x-kubernetes-list-type",
|
||||
"listMapKey": "x-kubernetes-list-map-keys",
|
||||
}
|
||||
|
||||
// Enum values per extension
|
||||
var allowedExtensionValues = map[string]sets.String{
|
||||
"x-kubernetes-patch-strategy": sets.NewString("merge", "retainKeys"),
|
||||
"x-kubernetes-list-type": sets.NewString("atomic", "set", "map"),
|
||||
}
|
||||
|
||||
// Extension encapsulates information necessary to generate an OpenAPI extension.
|
||||
type extension struct {
|
||||
idlTag string // Example: listType
|
||||
xName string // Example: x-kubernetes-list-type
|
||||
values []string // Example: [atomic]
|
||||
}
|
||||
|
||||
func (e extension) validateAllowedValues() error {
|
||||
// allowedValues not set means no restrictions on values.
|
||||
allowedValues, exists := allowedExtensionValues[e.xName]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
// Check for missing value.
|
||||
if len(e.values) == 0 {
|
||||
return fmt.Errorf("%s needs a value, none given.", e.idlTag)
|
||||
}
|
||||
// For each extension value, validate that it is allowed.
|
||||
if !allowedValues.HasAll(e.values...) {
|
||||
return fmt.Errorf("%v not allowed for %s. Allowed values: %v",
|
||||
e.values, e.idlTag, allowedValues.List())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e extension) hasMultipleValues() bool {
|
||||
return len(e.values) > 1
|
||||
}
|
||||
|
||||
// Returns sorted list of map keys. Needed for deterministic testing.
|
||||
func sortedMapKeys(m map[string][]string) []string {
|
||||
keys := make([]string, len(m))
|
||||
i := 0
|
||||
for k := range m {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// Parses comments to return openapi extensions.
|
||||
// NOTE: Non-empty errors does not mean extensions is empty.
|
||||
func parseExtensions(comments []string) ([]extension, []error) {
|
||||
extensions := []extension{}
|
||||
errors := []error{}
|
||||
// First, generate extensions from "+k8s:openapi-gen=x-kubernetes-*" annotations.
|
||||
values := getOpenAPITagValue(comments)
|
||||
for _, val := range values {
|
||||
// Example: x-kubernetes-member-tag:member_test
|
||||
if strings.HasPrefix(val, extensionPrefix) {
|
||||
parts := strings.SplitN(val, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
errors = append(errors, fmt.Errorf("invalid extension value: %v", val))
|
||||
continue
|
||||
}
|
||||
e := extension{
|
||||
idlTag: tagName, // Example: k8s:openapi-gen
|
||||
xName: parts[0], // Example: x-kubernetes-member-tag
|
||||
values: []string{parts[1]}, // Example: member_test
|
||||
}
|
||||
extensions = append(extensions, e)
|
||||
}
|
||||
}
|
||||
// Next, generate extensions from "idlTags" (e.g. +listType)
|
||||
tagValues := types.ExtractCommentTags("+", comments)
|
||||
for _, idlTag := range sortedMapKeys(tagValues) {
|
||||
xName, exists := tagToExtension[idlTag]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
values := tagValues[idlTag]
|
||||
e := extension{
|
||||
idlTag: idlTag, // listType
|
||||
xName: xName, // x-kubernetes-list-type
|
||||
values: values, // [atomic]
|
||||
}
|
||||
if err := e.validateAllowedValues(); err != nil {
|
||||
// For now, only log the extension validation errors.
|
||||
errors = append(errors, err)
|
||||
}
|
||||
extensions = append(extensions, e)
|
||||
}
|
||||
return extensions, errors
|
||||
}
|
|
@ -40,15 +40,17 @@ const tagOptional = "optional"
|
|||
|
||||
// Known values for the tag.
|
||||
const (
|
||||
tagValueTrue = "true"
|
||||
tagValueFalse = "false"
|
||||
tagExtensionPrefix = "x-kubernetes-"
|
||||
tagPatchStrategy = "patchStrategy"
|
||||
tagPatchMergeKey = "patchMergeKey"
|
||||
patchStrategyExtensionName = "patch-strategy"
|
||||
patchMergeKeyExtensionName = "patch-merge-key"
|
||||
tagValueTrue = "true"
|
||||
tagValueFalse = "false"
|
||||
)
|
||||
|
||||
// Used for temporary validation of patch struct tags.
|
||||
// TODO: Remove patch struct tag validation because they we are now consuming OpenAPI on server.
|
||||
var tempPatchTags = [...]string{
|
||||
"patchMergeKey",
|
||||
"patchStrategy",
|
||||
}
|
||||
|
||||
func getOpenAPITagValue(comments []string) []string {
|
||||
return types.ExtractCommentTags("+", comments)[tagName]
|
||||
}
|
||||
|
@ -155,6 +157,7 @@ type openAPIGen struct {
|
|||
// TargetPackage is the package that will get GetOpenAPIDefinitions function returns all open API definitions.
|
||||
targetPackage string
|
||||
imports namer.ImportTracker
|
||||
types []*types.Type
|
||||
context *generator.Context
|
||||
}
|
||||
|
||||
|
@ -169,10 +172,18 @@ func NewOpenAPIGen(sanitizedName string, targetPackage string, context *generato
|
|||
}
|
||||
}
|
||||
|
||||
const nameTmpl = "schema_$.type|private$"
|
||||
|
||||
func (g *openAPIGen) Namers(c *generator.Context) namer.NameSystems {
|
||||
// Have the raw namer for this file track what it imports.
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.targetPackage, g.imports),
|
||||
"private": &namer.NameStrategy{
|
||||
Join: func(pre string, in []string, post string) string {
|
||||
return strings.Join(in, "_")
|
||||
},
|
||||
PrependPackageNames: 4, // enough to fully qualify from k8s.io/api/...
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,6 +192,7 @@ func (g *openAPIGen) Filter(c *generator.Context, t *types.Type) bool {
|
|||
if strings.HasPrefix(t.Name.Name, "codecSelfer") {
|
||||
return false
|
||||
}
|
||||
g.types = append(g.types, t)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -215,13 +227,17 @@ func (g *openAPIGen) Init(c *generator.Context, w io.Writer) error {
|
|||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
sw.Do("func GetOpenAPIDefinitions(ref $.ReferenceCallback|raw$) map[string]$.OpenAPIDefinition|raw$ {\n", argsFromType(nil))
|
||||
sw.Do("return map[string]$.OpenAPIDefinition|raw${\n", argsFromType(nil))
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
func (g *openAPIGen) Finalize(c *generator.Context, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
sw.Do("}\n", nil)
|
||||
for _, t := range g.types {
|
||||
err := newOpenAPITypeWriter(sw).generateCall(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
sw.Do("}\n", nil)
|
||||
sw.Do("}\n\n", nil)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
|
@ -243,10 +259,6 @@ func getJsonTags(m *types.Member) []string {
|
|||
return strings.Split(jsonTag, ",")
|
||||
}
|
||||
|
||||
func getPatchTags(m *types.Member) (string, string) {
|
||||
return reflect.StructTag(m.Tags).Get(tagPatchMergeKey), reflect.StructTag(m.Tags).Get(tagPatchStrategy)
|
||||
}
|
||||
|
||||
func getReferableName(m *types.Member) string {
|
||||
jsonTags := getJsonTags(m)
|
||||
if len(jsonTags) > 0 {
|
||||
|
@ -342,7 +354,7 @@ func (g openAPITypeWriter) generateMembers(t *types.Type, required []string) ([]
|
|||
return required, nil
|
||||
}
|
||||
|
||||
func (g openAPITypeWriter) generate(t *types.Type) error {
|
||||
func (g openAPITypeWriter) generateCall(t *types.Type) error {
|
||||
// Only generate for struct type and ignore the rest
|
||||
switch t.Kind {
|
||||
case types.Struct:
|
||||
|
@ -350,31 +362,36 @@ func (g openAPITypeWriter) generate(t *types.Type) error {
|
|||
g.Do("\"$.$\": ", t.Name)
|
||||
if hasOpenAPIDefinitionMethod(t) {
|
||||
g.Do("$.type|raw${}.OpenAPIDefinition(),\n", args)
|
||||
} else {
|
||||
g.Do(nameTmpl+"(ref),\n", args)
|
||||
}
|
||||
}
|
||||
return g.Error()
|
||||
}
|
||||
|
||||
func (g openAPITypeWriter) generate(t *types.Type) error {
|
||||
// Only generate for struct type and ignore the rest
|
||||
switch t.Kind {
|
||||
case types.Struct:
|
||||
if hasOpenAPIDefinitionMethod(t) {
|
||||
// already invoked directly
|
||||
return nil
|
||||
}
|
||||
|
||||
args := argsFromType(t)
|
||||
g.Do("func "+nameTmpl+"(ref $.ReferenceCallback|raw$) $.OpenAPIDefinition|raw$ {\n", args)
|
||||
if hasOpenAPIDefinitionMethods(t) {
|
||||
// Since this generated snippet is part of a map:
|
||||
//
|
||||
// map[string]common.OpenAPIDefinition: {
|
||||
// "TYPE_NAME": {
|
||||
// Schema: spec.Schema{ ... },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// For compliance with gofmt -s it's important we elide the
|
||||
// struct type. The type is implied by the map and will be
|
||||
// removed otherwise.
|
||||
g.Do("{\n"+
|
||||
g.Do("return $.OpenAPIDefinition|raw${\n"+
|
||||
"Schema: spec.Schema{\n"+
|
||||
"SchemaProps: spec.SchemaProps{\n"+
|
||||
"Type:$.type|raw${}.OpenAPISchemaType(),\n"+
|
||||
"Format:$.type|raw${}.OpenAPISchemaFormat(),\n"+
|
||||
"},\n"+
|
||||
"},\n"+
|
||||
"},\n", args)
|
||||
"}\n}\n\n", args)
|
||||
return nil
|
||||
}
|
||||
g.Do("{\nSchema: spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
|
||||
g.Do("return $.OpenAPIDefinition|raw${\nSchema: spec.Schema{\nSchemaProps: spec.SchemaProps{\n", args)
|
||||
g.generateDescription(t.CommentLines)
|
||||
g.Do("Properties: map[string]$.SpecSchemaType|raw${\n", args)
|
||||
required, err := g.generateMembers(t, []string{})
|
||||
|
@ -386,7 +403,7 @@ func (g openAPITypeWriter) generate(t *types.Type) error {
|
|||
g.Do("Required: []string{\"$.$\"},\n", strings.Join(required, "\",\""))
|
||||
}
|
||||
g.Do("},\n", nil)
|
||||
if err := g.generateExtensions(t.CommentLines); err != nil {
|
||||
if err := g.generateStructExtensions(t); err != nil {
|
||||
return err
|
||||
}
|
||||
g.Do("},\n", nil)
|
||||
|
@ -406,70 +423,74 @@ func (g openAPITypeWriter) generate(t *types.Type) error {
|
|||
}
|
||||
g.Do("\"$.$\",", k)
|
||||
}
|
||||
g.Do("},\n},\n", nil)
|
||||
g.Do("},\n}\n}\n\n", nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g openAPITypeWriter) generateExtensions(CommentLines []string) error {
|
||||
tagValues := getOpenAPITagValue(CommentLines)
|
||||
type NameValue struct {
|
||||
Name, Value string
|
||||
}
|
||||
extensions := []NameValue{}
|
||||
for _, val := range tagValues {
|
||||
if strings.HasPrefix(val, tagExtensionPrefix) {
|
||||
parts := strings.SplitN(val, ":", 2)
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("invalid extension value: %v", val)
|
||||
}
|
||||
extensions = append(extensions, NameValue{parts[0], parts[1]})
|
||||
func (g openAPITypeWriter) generateStructExtensions(t *types.Type) error {
|
||||
extensions, errors := parseExtensions(t.CommentLines)
|
||||
// Initially, we will only log struct extension errors.
|
||||
if len(errors) > 0 {
|
||||
for e := range errors {
|
||||
glog.V(2).Infof("[%s]: %s\n", t.String(), e)
|
||||
}
|
||||
}
|
||||
patchMergeKeyTag, err := getSingleTagsValue(CommentLines, tagPatchMergeKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(patchMergeKeyTag) > 0 {
|
||||
extensions = append(extensions, NameValue{tagExtensionPrefix + patchMergeKeyExtensionName, patchMergeKeyTag})
|
||||
}
|
||||
patchStrategyTag, err := getSingleTagsValue(CommentLines, tagPatchStrategy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(patchStrategyTag) > 0 {
|
||||
extensions = append(extensions, NameValue{tagExtensionPrefix + patchStrategyExtensionName, patchStrategyTag})
|
||||
// TODO(seans3): Validate struct extensions here.
|
||||
g.emitExtensions(extensions)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g openAPITypeWriter) generateMemberExtensions(m *types.Member, parent *types.Type) error {
|
||||
extensions, errors := parseExtensions(m.CommentLines)
|
||||
// Initially, we will only log member extension errors.
|
||||
if len(errors) > 0 {
|
||||
errorPrefix := fmt.Sprintf("[%s] %s:", parent.String(), m.String())
|
||||
for e := range errors {
|
||||
glog.V(2).Infof("%s %s\n", errorPrefix, e)
|
||||
}
|
||||
}
|
||||
// TODO(seans3): Validate member extensions here.
|
||||
// Example: listType extension is only on a Slice.
|
||||
// Example: cross-extension validation - listMapKey only makes sense with listType=map
|
||||
g.emitExtensions(extensions)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g openAPITypeWriter) emitExtensions(extensions []extension) {
|
||||
// If any extensions exist, then emit code to create them.
|
||||
if len(extensions) == 0 {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
g.Do("VendorExtensible: spec.VendorExtensible{\nExtensions: spec.Extensions{\n", nil)
|
||||
for _, extension := range extensions {
|
||||
g.Do("\"$.$\": ", extension.Name)
|
||||
g.Do("\"$.$\",\n", extension.Value)
|
||||
g.Do("\"$.$\": ", extension.xName)
|
||||
if extension.hasMultipleValues() {
|
||||
g.Do("[]string{\n", nil)
|
||||
}
|
||||
for _, value := range extension.values {
|
||||
g.Do("\"$.$\",\n", value)
|
||||
}
|
||||
if extension.hasMultipleValues() {
|
||||
g.Do("},\n", nil)
|
||||
}
|
||||
}
|
||||
g.Do("},\n},\n", nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(#44005): Move this validation outside of this generator (probably to policy verifier)
|
||||
func (g openAPITypeWriter) validatePatchTags(m *types.Member, parent *types.Type) error {
|
||||
patchMergeKeyStructTag, patchStrategyStructTag := getPatchTags(m)
|
||||
patchMergeKeyCommentTag, err := getSingleTagsValue(m.CommentLines, tagPatchMergeKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
patchStrategyCommentTag, err := getSingleTagsValue(m.CommentLines, tagPatchStrategy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if patchMergeKeyStructTag != patchMergeKeyCommentTag {
|
||||
return fmt.Errorf("patchMergeKey in comment and struct tags should match for member (%s) of (%s)",
|
||||
m.Name, parent.Name.String())
|
||||
}
|
||||
if patchStrategyStructTag != patchStrategyCommentTag {
|
||||
return fmt.Errorf("patchStrategy in comment and struct tags should match for member (%s) of (%s)",
|
||||
m.Name, parent.Name.String())
|
||||
// TODO: Remove patch struct tag validation because they we are now consuming OpenAPI on server.
|
||||
for _, tagKey := range tempPatchTags {
|
||||
structTagValue := reflect.StructTag(m.Tags).Get(tagKey)
|
||||
commentTagValue, err := getSingleTagsValue(m.CommentLines, tagKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if structTagValue != commentTagValue {
|
||||
return fmt.Errorf("Tags in comment and struct should match for member (%s) of (%s)",
|
||||
m.Name, parent.Name.String())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -526,7 +547,7 @@ func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type)
|
|||
return err
|
||||
}
|
||||
g.Do("\"$.$\": {\n", name)
|
||||
if err := g.generateExtensions(m.CommentLines); err != nil {
|
||||
if err := g.generateMemberExtensions(m, parent); err != nil {
|
||||
return err
|
||||
}
|
||||
g.Do("SchemaProps: spec.SchemaProps{\n", nil)
|
||||
|
|
|
@ -84,7 +84,7 @@ func computeETag(data []byte) string {
|
|||
// 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 provides access to it.
|
||||
// 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)
|
||||
|
@ -98,7 +98,7 @@ func BuildAndRegisterOpenAPIService(servePath string, webServices []*restful.Web
|
|||
// 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 provides access to provided swagger spec.
|
||||
// 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) {
|
||||
|
@ -214,7 +214,7 @@ func toGzip(data []byte) []byte {
|
|||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// RegisterOpenAPIVersionedService registers a handler to provides access to provided swagger spec.
|
||||
// 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 {
|
||||
|
@ -264,7 +264,7 @@ func RegisterOpenAPIVersionedService(openapiSpec *spec.Swagger, servePath string
|
|||
return &o, nil
|
||||
}
|
||||
|
||||
// BuildAndRegisterOpenAPIVersionedService builds the spec and registers a handler to provides access to it.
|
||||
// BuildAndRegisterOpenAPIVersionedService 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 RegisterOpenAPIVersionedService.
|
||||
func BuildAndRegisterOpenAPIVersionedService(servePath string, webServices []*restful.WebService, config *common.Config, handler common.PathHandler) (*OpenAPIService, error) {
|
||||
spec, err := builder.BuildOpenAPISpec(webServices, config)
|
||||
|
|
Loading…
Reference in New Issue