Bump kube-openapi dependency

pull/8/head
Haowei Cai 2018-05-01 17:33:27 -07:00
parent 62b58e625e
commit 212814a0c6
16 changed files with 279 additions and 123 deletions

16
Godeps/Godeps.json generated
View File

@ -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",

View File

@ -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",

View File

@ -180,7 +180,7 @@
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
}
]
}

View File

@ -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",

View File

@ -580,7 +580,7 @@
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
}
]
}

View File

@ -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"
}
]
}

View File

@ -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"
}
]
}

View File

@ -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"
}
]
}

View File

@ -916,7 +916,7 @@
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
"Rev": "f08db293d3ef80052d6513ece19792642a289fea"
}
]
}

View File

@ -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
}
}

View File

@ -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) {

View File

@ -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,

View File

@ -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",

128
vendor/k8s.io/kube-openapi/pkg/generators/extension.go generated vendored Normal file
View File

@ -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
}

View File

@ -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)

View File

@ -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)