Merge pull request #106181 from ulucinar/aru/consume-kube-openapi
Bump k8s.io/kube-openapi to commit ee342a809c29
This commit is contained in:
152
vendor/k8s.io/kube-openapi/pkg/generators/enum.go
generated
vendored
Normal file
152
vendor/k8s.io/kube-openapi/pkg/generators/enum.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
Copyright 2021 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"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
const tagEnumType = "enum"
|
||||
const enumTypeDescriptionHeader = "Possible enum values:"
|
||||
|
||||
type enumValue struct {
|
||||
Name string
|
||||
Value string
|
||||
Comment string
|
||||
}
|
||||
|
||||
type enumType struct {
|
||||
Name types.Name
|
||||
Values []*enumValue
|
||||
}
|
||||
|
||||
// enumMap is a map from the name to the matching enum type.
|
||||
type enumMap map[types.Name]*enumType
|
||||
|
||||
type enumContext struct {
|
||||
enumTypes enumMap
|
||||
}
|
||||
|
||||
func newEnumContext(c *generator.Context) *enumContext {
|
||||
return &enumContext{enumTypes: parseEnums(c)}
|
||||
}
|
||||
|
||||
// EnumType checks and finds the enumType for a given type.
|
||||
// If the given type is a known enum type, returns the enumType, true
|
||||
// Otherwise, returns nil, false
|
||||
func (ec *enumContext) EnumType(t *types.Type) (enum *enumType, isEnum bool) {
|
||||
enum, ok := ec.enumTypes[t.Name]
|
||||
return enum, ok
|
||||
}
|
||||
|
||||
// ValueStrings returns all possible values of the enum type as strings
|
||||
// the results are sorted and quoted as Go literals.
|
||||
func (et *enumType) ValueStrings() []string {
|
||||
var values []string
|
||||
for _, value := range et.Values {
|
||||
// use "%q" format to generate a Go literal of the string const value
|
||||
values = append(values, fmt.Sprintf("%q", value.Value))
|
||||
}
|
||||
sort.Strings(values)
|
||||
return values
|
||||
}
|
||||
|
||||
// DescriptionLines returns a description of the enum in this format:
|
||||
//
|
||||
// Possible enum values:
|
||||
// - `value1`: description 1
|
||||
// - `value2`: description 2
|
||||
func (et *enumType) DescriptionLines() []string {
|
||||
var lines []string
|
||||
for _, value := range et.Values {
|
||||
lines = append(lines, value.Description())
|
||||
}
|
||||
sort.Strings(lines)
|
||||
// Prepend a empty string to initiate a new paragraph.
|
||||
return append([]string{"", enumTypeDescriptionHeader}, lines...)
|
||||
}
|
||||
|
||||
func parseEnums(c *generator.Context) enumMap {
|
||||
// First, find the builtin "string" type
|
||||
stringType := c.Universe.Type(types.Name{Name: "string"})
|
||||
|
||||
enumTypes := make(enumMap)
|
||||
for _, p := range c.Universe {
|
||||
// find all enum types.
|
||||
for _, t := range p.Types {
|
||||
if isEnumType(stringType, t) {
|
||||
if _, ok := enumTypes[t.Name]; !ok {
|
||||
enumTypes[t.Name] = &enumType{
|
||||
Name: t.Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// find all enum values from constants, and try to match each with its type.
|
||||
for _, c := range p.Constants {
|
||||
enumType := c.Underlying
|
||||
if _, ok := enumTypes[enumType.Name]; ok {
|
||||
value := &enumValue{
|
||||
Name: c.Name.Name,
|
||||
Value: *c.ConstValue,
|
||||
Comment: strings.Join(c.CommentLines, " "),
|
||||
}
|
||||
enumTypes[enumType.Name].appendValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return enumTypes
|
||||
}
|
||||
|
||||
func (et *enumType) appendValue(value *enumValue) {
|
||||
et.Values = append(et.Values, value)
|
||||
}
|
||||
|
||||
// Description returns the description line for the enumValue
|
||||
// with the format:
|
||||
// - `FooValue`: is the Foo value
|
||||
func (ev *enumValue) Description() string {
|
||||
comment := strings.TrimSpace(ev.Comment)
|
||||
// The comment should starts with the type name, trim it first.
|
||||
comment = strings.TrimPrefix(comment, ev.Name)
|
||||
// Trim the possible space after previous step.
|
||||
comment = strings.TrimSpace(comment)
|
||||
// The comment may be multiline, cascade all consecutive whitespaces.
|
||||
comment = whitespaceRegex.ReplaceAllString(comment, " ")
|
||||
return fmt.Sprintf(" - `%s`: %s", ev.Value, comment)
|
||||
}
|
||||
|
||||
// isEnumType checks if a given type is an enum by the definition
|
||||
// An enum type should be an alias of string and has tag '+enum' in its comment.
|
||||
// Additionally, pass the type of builtin 'string' to check against.
|
||||
func isEnumType(stringType *types.Type, t *types.Type) bool {
|
||||
return t.Kind == types.Alias && t.Underlying == stringType && hasEnumTag(t)
|
||||
}
|
||||
|
||||
func hasEnumTag(t *types.Type) bool {
|
||||
return types.ExtractCommentTags("+", t.CommentLines)[tagEnumType] != nil
|
||||
}
|
||||
|
||||
// whitespaceRegex is the regex for consecutive whitespaces.
|
||||
var whitespaceRegex = regexp.MustCompile(`\s+`)
|
4
vendor/k8s.io/kube-openapi/pkg/generators/extension.go
generated
vendored
4
vendor/k8s.io/kube-openapi/pkg/generators/extension.go
generated
vendored
@@ -66,6 +66,10 @@ var tagToExtension = map[string]extensionAttributes{
|
||||
kind: types.Struct,
|
||||
allowedValues: sets.NewString("atomic", "granular"),
|
||||
},
|
||||
"validations": {
|
||||
xName: "x-kubernetes-validations",
|
||||
kind: types.Slice,
|
||||
},
|
||||
}
|
||||
|
||||
// Extension encapsulates information necessary to generate an OpenAPI extension.
|
||||
|
12
vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
generated
vendored
12
vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
generated
vendored
@@ -225,6 +225,7 @@ type openAPITypeWriter struct {
|
||||
*generator.SnippetWriter
|
||||
context *generator.Context
|
||||
refTypes map[string]*types.Type
|
||||
enumContext *enumContext
|
||||
GetDefinitionInterface *types.Type
|
||||
}
|
||||
|
||||
@@ -233,6 +234,7 @@ func newOpenAPITypeWriter(sw *generator.SnippetWriter, c *generator.Context) ope
|
||||
SnippetWriter: sw,
|
||||
context: c,
|
||||
refTypes: map[string]*types.Type{},
|
||||
enumContext: newEnumContext(c),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,7 +627,11 @@ func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type)
|
||||
return err
|
||||
}
|
||||
g.Do("SchemaProps: spec.SchemaProps{\n", nil)
|
||||
g.generateDescription(m.CommentLines)
|
||||
var extraComments []string
|
||||
if enumType, isEnum := g.enumContext.EnumType(m.Type); isEnum {
|
||||
extraComments = enumType.DescriptionLines()
|
||||
}
|
||||
g.generateDescription(append(m.CommentLines, extraComments...))
|
||||
jsonTags := getJsonTags(m)
|
||||
if len(jsonTags) > 1 && jsonTags[1] == "string" {
|
||||
g.generateSimpleProperty("string", "")
|
||||
@@ -641,6 +647,10 @@ func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type)
|
||||
typeString, format := openapi.OpenAPITypeFormat(t.String())
|
||||
if typeString != "" {
|
||||
g.generateSimpleProperty(typeString, format)
|
||||
if enumType, isEnum := g.enumContext.EnumType(m.Type); isEnum {
|
||||
// original type is an enum, add "Enum: " and the values
|
||||
g.Do("Enum: []interface{}{$.$}", strings.Join(enumType.ValueStrings(), ", "))
|
||||
}
|
||||
g.Do("},\n},\n", nil)
|
||||
return nil
|
||||
}
|
||||
|
114
vendor/k8s.io/kube-openapi/pkg/handler/handler.go
generated
vendored
114
vendor/k8s.io/kube-openapi/pkg/handler/handler.go
generated
vendored
@@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha512"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
@@ -30,9 +31,9 @@ import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/protobuf/proto"
|
||||
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/munnerz/goautoneg"
|
||||
"gopkg.in/yaml.v2"
|
||||
klog "k8s.io/klog/v2"
|
||||
"k8s.io/kube-openapi/pkg/builder"
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
@@ -55,13 +56,40 @@ type OpenAPIService struct {
|
||||
|
||||
lastModified time.Time
|
||||
|
||||
specBytes []byte
|
||||
specPb []byte
|
||||
specPbGz []byte
|
||||
jsonCache cache
|
||||
protoCache cache
|
||||
}
|
||||
|
||||
specBytesETag string
|
||||
specPbETag string
|
||||
specPbGzETag string
|
||||
type cache struct {
|
||||
BuildCache func() ([]byte, error)
|
||||
once sync.Once
|
||||
bytes []byte
|
||||
etag string
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *cache) Get() ([]byte, string, error) {
|
||||
c.once.Do(func() {
|
||||
bytes, err := c.BuildCache()
|
||||
// if there is an error updating the cache, there can be situations where
|
||||
// c.bytes contains a valid value (carried over from the previous update)
|
||||
// but c.err is also not nil; the cache user is expected to check for this
|
||||
c.err = err
|
||||
if c.err == nil {
|
||||
// don't override previous spec if we had an error
|
||||
c.bytes = bytes
|
||||
c.etag = computeETag(c.bytes)
|
||||
}
|
||||
})
|
||||
return c.bytes, c.etag, c.err
|
||||
}
|
||||
|
||||
func (c *cache) New(cacheBuilder func() ([]byte, error)) cache {
|
||||
return cache{
|
||||
bytes: c.bytes,
|
||||
etag: c.etag,
|
||||
BuildCache: cacheBuilder,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -71,6 +99,9 @@ func init() {
|
||||
}
|
||||
|
||||
func computeETag(data []byte) string {
|
||||
if data == nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("\"%X\"", sha512.Sum512(data))
|
||||
}
|
||||
|
||||
@@ -83,51 +114,40 @@ func NewOpenAPIService(spec *spec.Swagger) (*OpenAPIService, error) {
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) getSwaggerBytes() ([]byte, string, time.Time) {
|
||||
func (o *OpenAPIService) getSwaggerBytes() ([]byte, string, time.Time, error) {
|
||||
o.rwMutex.RLock()
|
||||
defer o.rwMutex.RUnlock()
|
||||
return o.specBytes, o.specBytesETag, o.lastModified
|
||||
specBytes, etag, err := o.jsonCache.Get()
|
||||
if err != nil {
|
||||
return nil, "", time.Time{}, err
|
||||
}
|
||||
return specBytes, etag, o.lastModified, nil
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) getSwaggerPbBytes() ([]byte, string, time.Time) {
|
||||
func (o *OpenAPIService) getSwaggerPbBytes() ([]byte, string, time.Time, error) {
|
||||
o.rwMutex.RLock()
|
||||
defer o.rwMutex.RUnlock()
|
||||
return o.specPb, o.specPbETag, o.lastModified
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) getSwaggerPbGzBytes() ([]byte, string, time.Time) {
|
||||
o.rwMutex.RLock()
|
||||
defer o.rwMutex.RUnlock()
|
||||
return o.specPbGz, o.specPbGzETag, o.lastModified
|
||||
specPb, etag, err := o.protoCache.Get()
|
||||
if err != nil {
|
||||
return nil, "", time.Time{}, err
|
||||
}
|
||||
return specPb, etag, o.lastModified, nil
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) {
|
||||
specBytes, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(openapiSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
specPb, err := ToProtoBinary(specBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
specPbGz := toGzip(specPb)
|
||||
|
||||
specBytesETag := computeETag(specBytes)
|
||||
specPbETag := computeETag(specPb)
|
||||
specPbGzETag := computeETag(specPbGz)
|
||||
|
||||
lastModified := time.Now()
|
||||
|
||||
o.rwMutex.Lock()
|
||||
defer o.rwMutex.Unlock()
|
||||
|
||||
o.specBytes = specBytes
|
||||
o.specPb = specPb
|
||||
o.specPbGz = specPbGz
|
||||
o.specBytesETag = specBytesETag
|
||||
o.specPbETag = specPbETag
|
||||
o.specPbGzETag = specPbGzETag
|
||||
o.lastModified = lastModified
|
||||
o.jsonCache = o.jsonCache.New(func() ([]byte, error) {
|
||||
return json.Marshal(openapiSpec)
|
||||
})
|
||||
o.protoCache = o.protoCache.New(func() ([]byte, error) {
|
||||
json, _, err := o.jsonCache.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToProtoBinary(json)
|
||||
})
|
||||
o.lastModified = time.Now()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -206,7 +226,7 @@ func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handl
|
||||
accepted := []struct {
|
||||
Type string
|
||||
SubType string
|
||||
GetDataAndETag func() ([]byte, string, time.Time)
|
||||
GetDataAndETag func() ([]byte, string, time.Time, error)
|
||||
}{
|
||||
{"application", "json", o.getSwaggerBytes},
|
||||
{"application", "com.github.proto-openapi.spec.v2@v1.0+protobuf", o.getSwaggerPbBytes},
|
||||
@@ -230,7 +250,15 @@ func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handl
|
||||
}
|
||||
|
||||
// serve the first matching media type in the sorted clause list
|
||||
data, etag, lastModified := accepts.GetDataAndETag()
|
||||
data, etag, lastModified, err := accepts.GetDataAndETag()
|
||||
if err != nil {
|
||||
klog.Errorf("Error in OpenAPI handler: %s", err)
|
||||
// only return a 503 if we have no older cache data to serve
|
||||
if data == nil {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.Header().Set("Etag", etag)
|
||||
// ServeContent will take care of caching using eTag.
|
||||
http.ServeContent(w, r, servePath, lastModified, bytes.NewReader(data))
|
||||
|
19
vendor/k8s.io/kube-openapi/pkg/validation/spec/info.go
generated
vendored
19
vendor/k8s.io/kube-openapi/pkg/validation/spec/info.go
generated
vendored
@@ -68,6 +68,25 @@ func (e Extensions) GetStringSlice(key string) ([]string, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// GetObject gets the object value from the extensions.
|
||||
// out must be a json serializable type; the json go struct
|
||||
// tags of out are used to populate it.
|
||||
func (e Extensions) GetObject(key string, out interface{}) error {
|
||||
// This json serialization/deserialization could be replaced with
|
||||
// an approach using reflection if the optimization becomes justified.
|
||||
if v, ok := e[strings.ToLower(key)]; ok {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(b, out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// VendorExtensible composition block.
|
||||
type VendorExtensible struct {
|
||||
Extensions Extensions
|
||||
|
2
vendor/k8s.io/kube-openapi/pkg/validation/validate/schema.go
generated
vendored
2
vendor/k8s.io/kube-openapi/pkg/validation/validate/schema.go
generated
vendored
@@ -91,7 +91,7 @@ func NewSchemaValidator(schema *spec.Schema, rootSchema interface{}, root string
|
||||
return &s
|
||||
}
|
||||
|
||||
// SetPath sets the path for this schema valdiator
|
||||
// SetPath sets the path for this schema validator
|
||||
func (s *SchemaValidator) SetPath(path string) {
|
||||
s.Path = path
|
||||
}
|
||||
|
1
vendor/k8s.io/kube-openapi/pkg/validation/validate/schema_option.go
generated
vendored
1
vendor/k8s.io/kube-openapi/pkg/validation/validate/schema_option.go
generated
vendored
@@ -16,6 +16,7 @@ package validate
|
||||
|
||||
// SchemaValidatorOptions defines optional rules for schema validation
|
||||
type SchemaValidatorOptions struct {
|
||||
validationRulesEnabled bool
|
||||
}
|
||||
|
||||
// Option sets optional rules for schema validation
|
||||
|
16
vendor/k8s.io/kube-openapi/pkg/validation/validate/validator.go
generated
vendored
16
vendor/k8s.io/kube-openapi/pkg/validation/validate/validator.go
generated
vendored
@@ -21,15 +21,17 @@ import (
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// An EntityValidator is an interface for things that can validate entities
|
||||
type EntityValidator interface {
|
||||
Validate(interface{}) *Result
|
||||
}
|
||||
|
||||
// valueValidator validates the values it applies to.
|
||||
type valueValidator interface {
|
||||
// SetPath sets the exact path of the validator prior to calling Validate.
|
||||
// The exact path contains the map keys and array indices to locate the
|
||||
// value to be validated from the root data element.
|
||||
SetPath(path string)
|
||||
Applies(interface{}, reflect.Kind) bool
|
||||
Validate(interface{}) *Result
|
||||
// Applies returns true if the validator applies to the valueKind
|
||||
// from source. Validate will be called if and only if Applies returns true.
|
||||
Applies(source interface{}, valueKind reflect.Kind) bool
|
||||
// Validate validates the value.
|
||||
Validate(value interface{}) *Result
|
||||
}
|
||||
|
||||
type basicCommonValidator struct {
|
||||
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -2059,7 +2059,7 @@ k8s.io/kube-aggregator/pkg/registry/apiservice/rest
|
||||
# k8s.io/kube-controller-manager v0.0.0 => ./staging/src/k8s.io/kube-controller-manager
|
||||
## explicit
|
||||
k8s.io/kube-controller-manager/config/v1alpha1
|
||||
# k8s.io/kube-openapi v0.0.0-20210817084001-7fbd8d59e5b8 => k8s.io/kube-openapi v0.0.0-20210817084001-7fbd8d59e5b8
|
||||
# k8s.io/kube-openapi v0.0.0-20211105084753-ee342a809c29 => k8s.io/kube-openapi v0.0.0-20211105084753-ee342a809c29
|
||||
## explicit
|
||||
k8s.io/kube-openapi/cmd/openapi-gen
|
||||
k8s.io/kube-openapi/cmd/openapi-gen/args
|
||||
@@ -2772,7 +2772,7 @@ sigs.k8s.io/yaml
|
||||
# k8s.io/klog/v2 => k8s.io/klog/v2 v2.30.0
|
||||
# k8s.io/kube-aggregator => ./staging/src/k8s.io/kube-aggregator
|
||||
# k8s.io/kube-controller-manager => ./staging/src/k8s.io/kube-controller-manager
|
||||
# k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20210817084001-7fbd8d59e5b8
|
||||
# k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20211105084753-ee342a809c29
|
||||
# k8s.io/kube-proxy => ./staging/src/k8s.io/kube-proxy
|
||||
# k8s.io/kube-scheduler => ./staging/src/k8s.io/kube-scheduler
|
||||
# k8s.io/kubectl => ./staging/src/k8s.io/kubectl
|
||||
|
Reference in New Issue
Block a user