Update dependency go modules for k8s v1.27.0-rc.0
This commit is contained in:
264
vendor/k8s.io/kube-openapi/pkg/cached/cache.go
generated
vendored
Normal file
264
vendor/k8s.io/kube-openapi/pkg/cached/cache.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
Copyright 2022 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 cache provides a cache mechanism based on etags to lazily
|
||||
// build, and/or cache results from expensive operation such that those
|
||||
// operations are not repeated unnecessarily. The operations can be
|
||||
// created as a tree, and replaced dynamically as needed.
|
||||
//
|
||||
// # Dependencies and types of caches
|
||||
//
|
||||
// This package uses a source/transform/sink model of caches to build
|
||||
// the dependency tree, and can be used as follows:
|
||||
// - [NewSource]: A source cache that recomputes the content every time.
|
||||
// - [NewStaticSource]: A source cache that always produces the
|
||||
// same content, it is only called once.
|
||||
// - [NewTransformer]: A cache that transforms data from one format to
|
||||
// another. It's only refreshed when the source changes.
|
||||
// - [NewMerger]: A cache that aggregates multiple caches into one.
|
||||
// It's only refreshed when the source changes.
|
||||
// - [Replaceable]: A cache adapter that can be atomically
|
||||
// replaced with a new one, and saves the previous results in case an
|
||||
// error pops-up.
|
||||
//
|
||||
// # Atomicity
|
||||
//
|
||||
// Most of the operations are not atomic/thread-safe, except for
|
||||
// [Replaceable.Replace] which can be performed while the objects
|
||||
// are being read.
|
||||
//
|
||||
// # Etags
|
||||
//
|
||||
// Etags in this library is a cache version identifier. It doesn't
|
||||
// necessarily strictly match to the semantics of http `etags`, but are
|
||||
// somewhat inspired from it and function with the same principles.
|
||||
// Hashing the content is a good way to guarantee that your function is
|
||||
// never going to be called spuriously. In Kubernetes world, this could
|
||||
// be a `resourceVersion`, this can be an actual etag, a hash, a UUID
|
||||
// (if the cache always changes), or even a made-up string when the
|
||||
// content of the cache never changes.
|
||||
package cached
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Result is the content returned from a call to a cache. It can either
|
||||
// be created with [NewResultOK] if the call was a success, or
|
||||
// [NewResultErr] if the call resulted in an error.
|
||||
type Result[T any] struct {
|
||||
Data T
|
||||
Etag string
|
||||
Err error
|
||||
}
|
||||
|
||||
// NewResultOK creates a new [Result] for a successful operation.
|
||||
func NewResultOK[T any](data T, etag string) Result[T] {
|
||||
return Result[T]{
|
||||
Data: data,
|
||||
Etag: etag,
|
||||
}
|
||||
}
|
||||
|
||||
// NewResultErr creates a new [Result] when an error has happened.
|
||||
func NewResultErr[T any](err error) Result[T] {
|
||||
return Result[T]{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Result can be treated as a [Data] if necessary.
|
||||
func (r Result[T]) Get() Result[T] {
|
||||
return r
|
||||
}
|
||||
|
||||
// Data is a cache that performs an action whose result data will be
|
||||
// cached. It also returns an "etag" identifier to version the cache, so
|
||||
// that the caller can know if they have the most recent version of the
|
||||
// cache (and can decide to cache some operation based on that).
|
||||
//
|
||||
// The [NewMerger] and [NewTransformer] automatically handle
|
||||
// that for you by checking if the etag is updated before calling the
|
||||
// merging or transforming function.
|
||||
type Data[T any] interface {
|
||||
// Returns the cached data, as well as an "etag" to identify the
|
||||
// version of the cache, or an error if something happened.
|
||||
Get() Result[T]
|
||||
}
|
||||
|
||||
// T is the source type, V is the destination type.
|
||||
type merger[K comparable, T, V any] struct {
|
||||
mergeFn func(map[K]Result[T]) Result[V]
|
||||
caches map[K]Data[T]
|
||||
cacheResults map[K]Result[T]
|
||||
result Result[V]
|
||||
}
|
||||
|
||||
// NewMerger creates a new merge cache, a cache that merges the result
|
||||
// of other caches. The function only gets called if any of the
|
||||
// dependency has changed.
|
||||
//
|
||||
// If any of the dependency returned an error before, or any of the
|
||||
// dependency returned an error this time, or if the mergeFn failed
|
||||
// before, then the function is reran.
|
||||
//
|
||||
// The caches and results are mapped by K so that associated data can be
|
||||
// retrieved. The map of dependencies can not be modified after
|
||||
// creation, and a new merger should be created (and probably replaced
|
||||
// using a [Replaceable]).
|
||||
//
|
||||
// Note that this assumes there is no "partial" merge, the merge
|
||||
// function will remerge all the dependencies together everytime. Since
|
||||
// the list of dependencies is constant, there is no way to save some
|
||||
// partial merge information either.
|
||||
func NewMerger[K comparable, T, V any](mergeFn func(results map[K]Result[T]) Result[V], caches map[K]Data[T]) Data[V] {
|
||||
return &merger[K, T, V]{
|
||||
mergeFn: mergeFn,
|
||||
caches: caches,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *merger[K, T, V]) prepareResults() map[K]Result[T] {
|
||||
cacheResults := make(map[K]Result[T], len(c.caches))
|
||||
for key, cache := range c.caches {
|
||||
cacheResults[key] = cache.Get()
|
||||
}
|
||||
return cacheResults
|
||||
}
|
||||
|
||||
// Rerun if:
|
||||
// - The last run resulted in an error
|
||||
// - Any of the dependency previously returned an error
|
||||
// - Any of the dependency just returned an error
|
||||
// - Any of the dependency's etag changed
|
||||
func (c *merger[K, T, V]) needsRunning(results map[K]Result[T]) bool {
|
||||
if c.cacheResults == nil {
|
||||
return true
|
||||
}
|
||||
if c.result.Err != nil {
|
||||
return true
|
||||
}
|
||||
if len(results) != len(c.cacheResults) {
|
||||
panic(fmt.Errorf("invalid number of results: %v (expected %v)", len(results), len(c.cacheResults)))
|
||||
}
|
||||
for key, oldResult := range c.cacheResults {
|
||||
newResult, ok := results[key]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("unknown cache entry: %v", key))
|
||||
}
|
||||
|
||||
if newResult.Etag != oldResult.Etag || newResult.Err != nil || oldResult.Err != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *merger[K, T, V]) Get() Result[V] {
|
||||
cacheResults := c.prepareResults()
|
||||
if c.needsRunning(cacheResults) {
|
||||
c.cacheResults = cacheResults
|
||||
c.result = c.mergeFn(c.cacheResults)
|
||||
}
|
||||
return c.result
|
||||
}
|
||||
|
||||
type transformerCacheKeyType struct{}
|
||||
|
||||
// NewTransformer creates a new cache that transforms the result of
|
||||
// another cache. The transformFn will only be called if the source
|
||||
// cache has updated the output, otherwise, the cached result will be
|
||||
// returned.
|
||||
//
|
||||
// If the dependency returned an error before, or it returns an error
|
||||
// this time, or if the transformerFn failed before, the function is
|
||||
// reran.
|
||||
func NewTransformer[T, V any](transformerFn func(Result[T]) Result[V], source Data[T]) Data[V] {
|
||||
return NewMerger(func(caches map[transformerCacheKeyType]Result[T]) Result[V] {
|
||||
cache, ok := caches[transformerCacheKeyType{}]
|
||||
if len(caches) != 1 || !ok {
|
||||
panic(fmt.Errorf("invalid cache for transformer cache: %v", caches))
|
||||
}
|
||||
return transformerFn(cache)
|
||||
}, map[transformerCacheKeyType]Data[T]{
|
||||
{}: source,
|
||||
})
|
||||
}
|
||||
|
||||
// NewSource creates a new cache that generates some data. This
|
||||
// will always be called since we don't know the origin of the data and
|
||||
// if it needs to be updated or not.
|
||||
func NewSource[T any](sourceFn func() Result[T]) Data[T] {
|
||||
c := source[T](sourceFn)
|
||||
return &c
|
||||
}
|
||||
|
||||
type source[T any] func() Result[T]
|
||||
|
||||
func (c *source[T]) Get() Result[T] {
|
||||
return (*c)()
|
||||
}
|
||||
|
||||
// NewStaticSource creates a new cache that always generates the
|
||||
// same data. This will only be called once (lazily).
|
||||
func NewStaticSource[T any](staticFn func() Result[T]) Data[T] {
|
||||
return &static[T]{
|
||||
fn: staticFn,
|
||||
}
|
||||
}
|
||||
|
||||
type static[T any] struct {
|
||||
fn func() Result[T]
|
||||
result *Result[T]
|
||||
}
|
||||
|
||||
func (c *static[T]) Get() Result[T] {
|
||||
if c.result == nil {
|
||||
result := c.fn()
|
||||
c.result = &result
|
||||
}
|
||||
return *c.result
|
||||
}
|
||||
|
||||
// Replaceable is a cache that carries the result even when the
|
||||
// cache is replaced. The cache can be replaced atomically (without any
|
||||
// lock held). This is the type that should typically be stored in
|
||||
// structs.
|
||||
type Replaceable[T any] struct {
|
||||
cache atomic.Pointer[Data[T]]
|
||||
result *Result[T]
|
||||
}
|
||||
|
||||
// Get retrieves the data from the underlying source. [Replaceable]
|
||||
// implements the [Data] interface itself. This is a pass-through
|
||||
// that calls the most recent underlying cache. If the cache fails but
|
||||
// previously had returned a success, that success will be returned
|
||||
// instead. If the cache fails but we never returned a success, that
|
||||
// failure is returned.
|
||||
func (c *Replaceable[T]) Get() Result[T] {
|
||||
result := (*c.cache.Load()).Get()
|
||||
if result.Err != nil && c.result != nil && c.result.Err == nil {
|
||||
return *c.result
|
||||
}
|
||||
c.result = &result
|
||||
return *c.result
|
||||
}
|
||||
|
||||
// Replace changes the cache in a thread-safe way.
|
||||
func (c *Replaceable[T]) Replace(cache Data[T]) {
|
||||
c.cache.Swap(&cache)
|
||||
}
|
219
vendor/k8s.io/kube-openapi/pkg/handler3/handler.go
generated
vendored
219
vendor/k8s.io/kube-openapi/pkg/handler3/handler.go
generated
vendored
@@ -24,7 +24,6 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -32,11 +31,12 @@ import (
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
openapi_v3 "github.com/google/gnostic/openapiv3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/munnerz/goautoneg"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kube-openapi/pkg/cached"
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/internal/handler"
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -58,23 +58,63 @@ type OpenAPIV3DiscoveryGroupVersion struct {
|
||||
ServerRelativeURL string `json:"serverRelativeURL"`
|
||||
}
|
||||
|
||||
func ToV3ProtoBinary(json []byte) ([]byte, error) {
|
||||
document, err := openapi_v3.ParseDocument(json)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proto.Marshal(document)
|
||||
}
|
||||
|
||||
type timedSpec struct {
|
||||
spec []byte
|
||||
lastModified time.Time
|
||||
}
|
||||
|
||||
// This type is protected by the lock on OpenAPIService.
|
||||
type openAPIV3Group struct {
|
||||
specCache cached.Replaceable[*spec3.OpenAPI]
|
||||
pbCache cached.Data[timedSpec]
|
||||
jsonCache cached.Data[timedSpec]
|
||||
}
|
||||
|
||||
func newOpenAPIV3Group() *openAPIV3Group {
|
||||
o := &openAPIV3Group{}
|
||||
o.jsonCache = cached.NewTransformer[*spec3.OpenAPI](func(result cached.Result[*spec3.OpenAPI]) cached.Result[timedSpec] {
|
||||
if result.Err != nil {
|
||||
return cached.NewResultErr[timedSpec](result.Err)
|
||||
}
|
||||
json, err := json.Marshal(result.Data)
|
||||
if err != nil {
|
||||
return cached.NewResultErr[timedSpec](err)
|
||||
}
|
||||
return cached.NewResultOK(timedSpec{spec: json, lastModified: time.Now()}, computeETag(json))
|
||||
}, &o.specCache)
|
||||
o.pbCache = cached.NewTransformer(func(result cached.Result[timedSpec]) cached.Result[timedSpec] {
|
||||
if result.Err != nil {
|
||||
return cached.NewResultErr[timedSpec](result.Err)
|
||||
}
|
||||
proto, err := ToV3ProtoBinary(result.Data.spec)
|
||||
if err != nil {
|
||||
return cached.NewResultErr[timedSpec](err)
|
||||
}
|
||||
return cached.NewResultOK(timedSpec{spec: proto, lastModified: result.Data.lastModified}, result.Etag)
|
||||
}, o.jsonCache)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *openAPIV3Group) UpdateSpec(openapi cached.Data[*spec3.OpenAPI]) {
|
||||
o.specCache.Replace(openapi)
|
||||
}
|
||||
|
||||
// OpenAPIService is the service responsible for serving OpenAPI spec. It has
|
||||
// the ability to safely change the spec while serving it.
|
||||
type OpenAPIService struct {
|
||||
// rwMutex protects All members of this service.
|
||||
rwMutex sync.RWMutex
|
||||
lastModified time.Time
|
||||
v3Schema map[string]*OpenAPIV3Group
|
||||
}
|
||||
// Mutex protects the schema map.
|
||||
mutex sync.Mutex
|
||||
v3Schema map[string]*openAPIV3Group
|
||||
|
||||
type OpenAPIV3Group struct {
|
||||
rwMutex sync.RWMutex
|
||||
|
||||
lastModified time.Time
|
||||
|
||||
pbCache handler.HandlerCache
|
||||
jsonCache handler.HandlerCache
|
||||
etagCache handler.HandlerCache
|
||||
discoveryCache cached.Replaceable[timedSpec]
|
||||
}
|
||||
|
||||
func computeETag(data []byte) string {
|
||||
@@ -93,94 +133,90 @@ func constructServerRelativeURL(gvString, etag string) string {
|
||||
}
|
||||
|
||||
// NewOpenAPIService builds an OpenAPIService starting with the given spec.
|
||||
func NewOpenAPIService(spec *spec.Swagger) (*OpenAPIService, error) {
|
||||
func NewOpenAPIService() *OpenAPIService {
|
||||
o := &OpenAPIService{}
|
||||
o.v3Schema = make(map[string]*OpenAPIV3Group)
|
||||
return o, nil
|
||||
o.v3Schema = make(map[string]*openAPIV3Group)
|
||||
// We're not locked because we haven't shared the structure yet.
|
||||
o.discoveryCache.Replace(o.buildDiscoveryCacheLocked())
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) getGroupBytes() ([]byte, error) {
|
||||
o.rwMutex.RLock()
|
||||
defer o.rwMutex.RUnlock()
|
||||
keys := make([]string, len(o.v3Schema))
|
||||
i := 0
|
||||
for k := range o.v3Schema {
|
||||
keys[i] = k
|
||||
i++
|
||||
func (o *OpenAPIService) buildDiscoveryCacheLocked() cached.Data[timedSpec] {
|
||||
caches := make(map[string]cached.Data[timedSpec], len(o.v3Schema))
|
||||
for gvName, group := range o.v3Schema {
|
||||
caches[gvName] = group.jsonCache
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
discovery := &OpenAPIV3Discovery{Paths: make(map[string]OpenAPIV3DiscoveryGroupVersion)}
|
||||
for gvString, groupVersion := range o.v3Schema {
|
||||
etagBytes, err := groupVersion.etagCache.Get()
|
||||
return cached.NewMerger(func(results map[string]cached.Result[timedSpec]) cached.Result[timedSpec] {
|
||||
discovery := &OpenAPIV3Discovery{Paths: make(map[string]OpenAPIV3DiscoveryGroupVersion)}
|
||||
for gvName, result := range results {
|
||||
if result.Err != nil {
|
||||
return cached.NewResultErr[timedSpec](result.Err)
|
||||
}
|
||||
discovery.Paths[gvName] = OpenAPIV3DiscoveryGroupVersion{
|
||||
ServerRelativeURL: constructServerRelativeURL(gvName, result.Etag),
|
||||
}
|
||||
}
|
||||
j, err := json.Marshal(discovery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return cached.NewResultErr[timedSpec](err)
|
||||
}
|
||||
discovery.Paths[gvString] = OpenAPIV3DiscoveryGroupVersion{
|
||||
ServerRelativeURL: constructServerRelativeURL(gvString, string(etagBytes)),
|
||||
}
|
||||
}
|
||||
j, err := json.Marshal(discovery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return j, nil
|
||||
return cached.NewResultOK(timedSpec{spec: j, lastModified: time.Now()}, computeETag(j))
|
||||
}, caches)
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) getSingleGroupBytes(getType string, group string) ([]byte, string, time.Time, error) {
|
||||
o.rwMutex.RLock()
|
||||
defer o.rwMutex.RUnlock()
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
v, ok := o.v3Schema[group]
|
||||
if !ok {
|
||||
return nil, "", time.Now(), fmt.Errorf("Cannot find CRD group %s", group)
|
||||
}
|
||||
if getType == subTypeJSON {
|
||||
specBytes, err := v.jsonCache.Get()
|
||||
if err != nil {
|
||||
return nil, "", v.lastModified, err
|
||||
}
|
||||
etagBytes, err := v.etagCache.Get()
|
||||
return specBytes, string(etagBytes), v.lastModified, err
|
||||
} else if getType == subTypeProtobuf || getType == subTypeProtobufDeprecated {
|
||||
specPb, err := v.pbCache.Get()
|
||||
if err != nil {
|
||||
return nil, "", v.lastModified, err
|
||||
}
|
||||
etagBytes, err := v.etagCache.Get()
|
||||
return specPb, string(etagBytes), v.lastModified, err
|
||||
result := cached.Result[timedSpec]{}
|
||||
switch getType {
|
||||
case subTypeJSON:
|
||||
result = v.jsonCache.Get()
|
||||
case subTypeProtobuf, subTypeProtobufDeprecated:
|
||||
result = v.pbCache.Get()
|
||||
default:
|
||||
return nil, "", time.Now(), fmt.Errorf("Invalid accept clause %s", getType)
|
||||
}
|
||||
return nil, "", time.Now(), fmt.Errorf("Invalid accept clause %s", getType)
|
||||
return result.Data.spec, result.Etag, result.Data.lastModified, result.Err
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) UpdateGroupVersion(group string, openapi *spec3.OpenAPI) (err error) {
|
||||
o.rwMutex.Lock()
|
||||
defer o.rwMutex.Unlock()
|
||||
|
||||
// UpdateGroupVersionLazy adds or updates an existing group with the new cached.
|
||||
func (o *OpenAPIService) UpdateGroupVersionLazy(group string, openapi cached.Data[*spec3.OpenAPI]) {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
if _, ok := o.v3Schema[group]; !ok {
|
||||
o.v3Schema[group] = &OpenAPIV3Group{}
|
||||
o.v3Schema[group] = newOpenAPIV3Group()
|
||||
// Since there is a new item, we need to re-build the cache map.
|
||||
o.discoveryCache.Replace(o.buildDiscoveryCacheLocked())
|
||||
}
|
||||
return o.v3Schema[group].UpdateSpec(openapi)
|
||||
o.v3Schema[group].UpdateSpec(openapi)
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) UpdateGroupVersion(group string, openapi *spec3.OpenAPI) {
|
||||
o.UpdateGroupVersionLazy(group, cached.NewResultOK(openapi, uuid.New().String()))
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) DeleteGroupVersion(group string) {
|
||||
o.rwMutex.Lock()
|
||||
defer o.rwMutex.Unlock()
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
delete(o.v3Schema, group)
|
||||
}
|
||||
|
||||
func ToV3ProtoBinary(json []byte) ([]byte, error) {
|
||||
document, err := openapi_v3.ParseDocument(json)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proto.Marshal(document)
|
||||
// Rebuild the merge cache map since the items have changed.
|
||||
o.discoveryCache.Replace(o.buildDiscoveryCacheLocked())
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) HandleDiscovery(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ := o.getGroupBytes()
|
||||
w.Header().Set("Etag", strconv.Quote(computeETag(data)))
|
||||
result := o.discoveryCache.Get()
|
||||
if result.Err != nil {
|
||||
klog.Errorf("Error serving discovery: %s", result.Err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Etag", strconv.Quote(result.Etag))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
http.ServeContent(w, r, "/openapi/v3", time.Now(), bytes.NewReader(data))
|
||||
http.ServeContent(w, r, "/openapi/v3", result.Data.lastModified, bytes.NewReader(result.Data.spec))
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) HandleGroupVersion(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -256,30 +292,3 @@ func (o *OpenAPIService) RegisterOpenAPIV3VersionedService(servePath string, han
|
||||
handler.HandlePrefix(servePath+"/", http.HandlerFunc(o.HandleGroupVersion))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OpenAPIV3Group) UpdateSpec(openapi *spec3.OpenAPI) (err error) {
|
||||
o.rwMutex.Lock()
|
||||
defer o.rwMutex.Unlock()
|
||||
|
||||
o.jsonCache = o.jsonCache.New(func() ([]byte, error) {
|
||||
return json.Marshal(openapi)
|
||||
})
|
||||
o.pbCache = o.pbCache.New(func() ([]byte, error) {
|
||||
json, err := o.jsonCache.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToV3ProtoBinary(json)
|
||||
})
|
||||
// TODO: This forces a json marshal of corresponding group-versions.
|
||||
// We should look to replace this with a faster hashing mechanism.
|
||||
o.etagCache = o.etagCache.New(func() ([]byte, error) {
|
||||
json, err := o.jsonCache.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(computeETag(json)), nil
|
||||
})
|
||||
o.lastModified = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
2
vendor/k8s.io/kube-openapi/pkg/internal/flags.go
generated
vendored
2
vendor/k8s.io/kube-openapi/pkg/internal/flags.go
generated
vendored
@@ -18,7 +18,7 @@ package internal
|
||||
|
||||
// Used by tests to selectively disable experimental JSON unmarshaler
|
||||
var UseOptimizedJSONUnmarshaling bool = true
|
||||
var UseOptimizedJSONUnmarshalingV3 bool = false
|
||||
var UseOptimizedJSONUnmarshalingV3 bool = true
|
||||
|
||||
// Used by tests to selectively disable experimental JSON marshaler
|
||||
var UseOptimizedJSONMarshaling bool = true
|
||||
|
57
vendor/k8s.io/kube-openapi/pkg/internal/handler/handler_cache.go
generated
vendored
57
vendor/k8s.io/kube-openapi/pkg/internal/handler/handler_cache.go
generated
vendored
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
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 handler
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// HandlerCache represents a lazy cache for generating a byte array
|
||||
// It is used to lazily marshal OpenAPI v2/v3 and lazily generate the ETag
|
||||
type HandlerCache struct {
|
||||
BuildCache func() ([]byte, error)
|
||||
once sync.Once
|
||||
bytes []byte
|
||||
err error
|
||||
}
|
||||
|
||||
// Get either returns the cached value or calls BuildCache() once before caching and returning
|
||||
// its results. If BuildCache returns an error, the last valid value for the cache (from prior
|
||||
// calls to New()) is used instead if possible.
|
||||
func (c *HandlerCache) Get() ([]byte, 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
|
||||
}
|
||||
})
|
||||
return c.bytes, c.err
|
||||
}
|
||||
|
||||
// New creates a new HandlerCache for situations where a cache refresh is needed.
|
||||
// This function is not thread-safe and should not be called at the same time as Get().
|
||||
func (c *HandlerCache) New(cacheBuilder func() ([]byte, error)) HandlerCache {
|
||||
return HandlerCache{
|
||||
bytes: c.bytes,
|
||||
BuildCache: cacheBuilder,
|
||||
}
|
||||
}
|
20
vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go
generated
vendored
20
vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go
generated
vendored
@@ -18,7 +18,10 @@ package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -41,6 +44,9 @@ func (e *Encoding) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (e *Encoding) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
}
|
||||
if err := json.Unmarshal(data, &e.EncodingProps); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -50,6 +56,20 @@ func (e *Encoding) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoding) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
EncodingProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
e.EncodingProps = x.EncodingProps
|
||||
return nil
|
||||
}
|
||||
|
||||
type EncodingProps struct {
|
||||
// Content Type for encoding a specific property
|
||||
ContentType string `json:"contentType,omitempty"`
|
||||
|
23
vendor/k8s.io/kube-openapi/pkg/spec3/example.go
generated
vendored
23
vendor/k8s.io/kube-openapi/pkg/spec3/example.go
generated
vendored
@@ -20,6 +20,9 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -49,6 +52,9 @@ func (e *Example) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (e *Example) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
}
|
||||
if err := json.Unmarshal(data, &e.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -61,6 +67,23 @@ func (e *Example) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Example) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ExampleProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&e.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
e.ExampleProps = x.ExampleProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExampleProps struct {
|
||||
// Summary holds a short description of the example
|
||||
Summary string `json:"summary,omitempty"`
|
||||
|
19
vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go
generated
vendored
19
vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go
generated
vendored
@@ -18,7 +18,10 @@ package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -48,6 +51,9 @@ func (e *ExternalDocumentation) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (e *ExternalDocumentation) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
}
|
||||
if err := json.Unmarshal(data, &e.ExternalDocumentationProps); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,3 +62,16 @@ func (e *ExternalDocumentation) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ExternalDocumentation) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ExternalDocumentationProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
e.ExternalDocumentationProps = x.ExternalDocumentationProps
|
||||
return nil
|
||||
}
|
||||
|
132
vendor/k8s.io/kube-openapi/pkg/spec3/fuzz.go
generated
vendored
132
vendor/k8s.io/kube-openapi/pkg/spec3/fuzz.go
generated
vendored
@@ -1,10 +1,11 @@
|
||||
package spec3
|
||||
|
||||
import (
|
||||
fuzz "github.com/google/gofuzz"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -169,82 +170,85 @@ var OpenAPIV3FuzzFuncs []interface{} = []interface{}{
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
},
|
||||
func(v *spec.Extensions, c fuzz.Continue) {
|
||||
*v = spec.Extensions{}
|
||||
numChildren := c.Intn(5)
|
||||
if numChildren == 0 {
|
||||
*v = nil
|
||||
}
|
||||
for i := 0; i < numChildren; i++ {
|
||||
v.Add("x-"+randAlphanumString(), c.RandString()+"x")
|
||||
if *v == nil {
|
||||
*v = spec.Extensions{}
|
||||
}
|
||||
(*v)["x-"+c.RandString()] = c.RandString()
|
||||
}
|
||||
},
|
||||
func(v *spec.ExternalDocumentation, c fuzz.Continue) {
|
||||
c.Fuzz(&v.Description)
|
||||
v.URL = "https://" + randAlphanumString()
|
||||
},
|
||||
func(v *spec.SchemaURL, c fuzz.Continue) {
|
||||
*v = spec.SchemaURL("https://" + randAlphanumString())
|
||||
},
|
||||
func(v *spec.SchemaOrBool, c fuzz.Continue) {
|
||||
*v = spec.SchemaOrBool{}
|
||||
|
||||
if c.RandBool() {
|
||||
v.Allows = c.RandBool()
|
||||
} else {
|
||||
v.Schema = &spec.Schema{}
|
||||
v.Allows = true
|
||||
c.Fuzz(&v.Schema)
|
||||
}
|
||||
},
|
||||
func(v *spec.SchemaOrArray, c fuzz.Continue) {
|
||||
*v = spec.SchemaOrArray{}
|
||||
if c.RandBool() {
|
||||
schema := spec.Schema{}
|
||||
c.Fuzz(&schema)
|
||||
v.Schema = &schema
|
||||
} else {
|
||||
v.Schemas = []spec.Schema{}
|
||||
numChildren := c.Intn(5)
|
||||
for i := 0; i < numChildren; i++ {
|
||||
schema := spec.Schema{}
|
||||
c.Fuzz(&schema)
|
||||
v.Schemas = append(v.Schemas, schema)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
func(v *spec.SchemaOrStringArray, c fuzz.Continue) {
|
||||
if c.RandBool() {
|
||||
*v = spec.SchemaOrStringArray{}
|
||||
if c.RandBool() {
|
||||
c.Fuzz(&v.Property)
|
||||
} else {
|
||||
c.Fuzz(&v.Schema)
|
||||
}
|
||||
}
|
||||
},
|
||||
func(v *spec.Schema, c fuzz.Continue) {
|
||||
if c.Intn(refChance) == 0 {
|
||||
c.Fuzz(&v.Ref)
|
||||
return
|
||||
}
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
c.Fuzz(&v.Description)
|
||||
c.Fuzz(&v.Nullable)
|
||||
c.Fuzz(&v.Title)
|
||||
c.Fuzz(&v.Required)
|
||||
c.Fuzz(&v.ExternalDocs)
|
||||
n := c.Intn(8)
|
||||
switch n {
|
||||
case 0:
|
||||
// To prevent exponential growth from recursively generating properties, only allow the schema to be an object with low frequency
|
||||
if c.Intn(5) == 0 {
|
||||
c.Fuzz(&v.Properties)
|
||||
c.Fuzz(&v.MinProperties)
|
||||
c.Fuzz(&v.MaxProperties)
|
||||
} else {
|
||||
v.Type = spec.StringOrArray{"integer"}
|
||||
switch c.Intn(3) {
|
||||
case 0:
|
||||
v.Format = "int32"
|
||||
case 1:
|
||||
v.Format = "int64"
|
||||
}
|
||||
c.Fuzz(&v.MultipleOf)
|
||||
c.Fuzz(&v.Minimum)
|
||||
c.Fuzz(&v.Maximum)
|
||||
c.Fuzz(&v.ExclusiveMaximum)
|
||||
c.Fuzz(&v.ExclusiveMinimum)
|
||||
}
|
||||
case 1:
|
||||
v.Type = spec.StringOrArray{"number"}
|
||||
switch c.Intn(3) {
|
||||
case 0:
|
||||
v.Format = "float"
|
||||
case 1:
|
||||
v.Format = "double"
|
||||
}
|
||||
c.Fuzz(&v.MultipleOf)
|
||||
c.Fuzz(&v.ExclusiveMaximum)
|
||||
c.Fuzz(&v.ExclusiveMinimum)
|
||||
c.Fuzz(&v.Minimum)
|
||||
c.Fuzz(&v.Maximum)
|
||||
case 2:
|
||||
v.Type = spec.StringOrArray{"string"}
|
||||
c.Fuzz(&v.MinLength)
|
||||
c.Fuzz(&v.MaxLength)
|
||||
case 3:
|
||||
v.Type = spec.StringOrArray{"boolean"}
|
||||
case 4:
|
||||
v.Type = spec.StringOrArray{"array"}
|
||||
s := spec.Schema{}
|
||||
c.Fuzz(&s)
|
||||
v.Items = &spec.SchemaOrArray{Schema: &s}
|
||||
case 5:
|
||||
c.Fuzz(&v.AnyOf)
|
||||
case 6:
|
||||
c.Fuzz(&v.AllOf)
|
||||
case 7:
|
||||
c.Fuzz(&v.OneOf)
|
||||
if c.RandBool() {
|
||||
// file schema
|
||||
c.Fuzz(&v.Default)
|
||||
c.Fuzz(&v.Description)
|
||||
c.Fuzz(&v.Example)
|
||||
c.Fuzz(&v.ExternalDocs)
|
||||
|
||||
c.Fuzz(&v.Format)
|
||||
c.Fuzz(&v.ReadOnly)
|
||||
c.Fuzz(&v.Required)
|
||||
c.Fuzz(&v.Title)
|
||||
v.Type = spec.StringOrArray{"file"}
|
||||
|
||||
} else {
|
||||
// normal schema
|
||||
c.Fuzz(&v.SchemaProps)
|
||||
c.Fuzz(&v.SwaggerSchemaProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
c.Fuzz(&v.ExtraProps)
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
21
vendor/k8s.io/kube-openapi/pkg/spec3/header.go
generated
vendored
21
vendor/k8s.io/kube-openapi/pkg/spec3/header.go
generated
vendored
@@ -20,6 +20,8 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -50,6 +52,9 @@ func (h *Header) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (h *Header) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, h)
|
||||
}
|
||||
if err := json.Unmarshal(data, &h.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -63,6 +68,22 @@ func (h *Header) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Header) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
HeaderProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&h.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
h.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
h.HeaderProps = x.HeaderProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// HeaderProps a struct that describes a header object
|
||||
type HeaderProps struct {
|
||||
// Description holds a brief description of the parameter
|
||||
|
20
vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go
generated
vendored
20
vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go
generated
vendored
@@ -18,7 +18,10 @@ package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -44,6 +47,9 @@ func (m *MediaType) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (m *MediaType) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, m)
|
||||
}
|
||||
if err := json.Unmarshal(data, &m.MediaTypeProps); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -53,6 +59,20 @@ func (m *MediaType) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MediaType) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
MediaTypeProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
m.MediaTypeProps = x.MediaTypeProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MediaTypeProps a struct that allows you to specify content format, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#mediaTypeObject
|
||||
type MediaTypeProps struct {
|
||||
// Schema holds the schema defining the type used for the media type
|
||||
|
18
vendor/k8s.io/kube-openapi/pkg/spec3/operation.go
generated
vendored
18
vendor/k8s.io/kube-openapi/pkg/spec3/operation.go
generated
vendored
@@ -20,6 +20,8 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -46,12 +48,28 @@ func (o *Operation) MarshalJSON() ([]byte, error) {
|
||||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
func (o *Operation) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, o)
|
||||
}
|
||||
if err := json.Unmarshal(data, &o.OperationProps); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, &o.VendorExtensible)
|
||||
}
|
||||
|
||||
func (o *Operation) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
OperationProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
o.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
o.OperationProps = x.OperationProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// OperationProps describes a single API operation on a path, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#operationObject
|
||||
type OperationProps struct {
|
||||
// Tags holds a list of tags for API documentation control
|
||||
|
22
vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go
generated
vendored
22
vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go
generated
vendored
@@ -20,6 +20,8 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -50,6 +52,10 @@ func (p *Parameter) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (p *Parameter) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &p.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -63,6 +69,22 @@ func (p *Parameter) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parameter) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ParameterProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&p.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
p.ParameterProps = x.ParameterProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParameterProps a struct that describes a single operation parameter, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#parameterObject
|
||||
type ParameterProps struct {
|
||||
// Name holds the name of the parameter
|
||||
|
80
vendor/k8s.io/kube-openapi/pkg/spec3/path.go
generated
vendored
80
vendor/k8s.io/kube-openapi/pkg/spec3/path.go
generated
vendored
@@ -18,9 +18,12 @@ package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -45,6 +48,9 @@ func (p *Paths) MarshalJSON() ([]byte, error) {
|
||||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
func (p *Paths) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
}
|
||||
var res map[string]json.RawMessage
|
||||
if err := json.Unmarshal(data, &res); err != nil {
|
||||
return err
|
||||
@@ -74,6 +80,59 @@ func (p *Paths) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch k := tok.Kind(); k {
|
||||
case 'n':
|
||||
*p = Paths{}
|
||||
return nil
|
||||
case '{':
|
||||
for {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tok.Kind() == '}' {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch k := tok.String(); {
|
||||
case internal.IsExtensionKey(k):
|
||||
var ext any
|
||||
if err := opts.UnmarshalNext(dec, &ext); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Extensions == nil {
|
||||
p.Extensions = make(map[string]any)
|
||||
}
|
||||
p.Extensions[k] = ext
|
||||
case len(k) > 0 && k[0] == '/':
|
||||
pi := Path{}
|
||||
if err := opts.UnmarshalNext(dec, &pi); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Paths == nil {
|
||||
p.Paths = make(map[string]*Path)
|
||||
}
|
||||
p.Paths[k] = &pi
|
||||
default:
|
||||
_, err := dec.ReadValue() // skip value
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown JSON kind: %v", k)
|
||||
}
|
||||
}
|
||||
|
||||
// Path describes the operations available on a single path, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#pathItemObject
|
||||
//
|
||||
// Note that this struct is actually a thin wrapper around PathProps to make it referable and extensible
|
||||
@@ -101,6 +160,9 @@ func (p *Path) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (p *Path) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
}
|
||||
if err := json.Unmarshal(data, &p.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -113,6 +175,24 @@ func (p *Path) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Path) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
PathProps
|
||||
}
|
||||
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&p.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
p.PathProps = x.PathProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PathProps describes the operations available on a single path, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#pathItemObject
|
||||
type PathProps struct {
|
||||
// Summary holds a summary for all operations in this path
|
||||
|
21
vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go
generated
vendored
21
vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go
generated
vendored
@@ -20,6 +20,8 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -50,6 +52,9 @@ func (r *RequestBody) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (r *RequestBody) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -71,3 +76,19 @@ type RequestBodyProps struct {
|
||||
// Required determines if the request body is required in the request
|
||||
Required bool `json:"required,omitempty"`
|
||||
}
|
||||
|
||||
func (r *RequestBody) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
RequestBodyProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&r.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
r.RequestBodyProps = x.RequestBodyProps
|
||||
return nil
|
||||
}
|
||||
|
101
vendor/k8s.io/kube-openapi/pkg/spec3/response.go
generated
vendored
101
vendor/k8s.io/kube-openapi/pkg/spec3/response.go
generated
vendored
@@ -18,9 +18,12 @@ package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -46,13 +49,15 @@ func (r *Responses) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (r *Responses) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.ResponsesProps); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.VendorExtensible); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -78,6 +83,9 @@ func (r ResponsesProps) MarshalJSON() ([]byte, error) {
|
||||
|
||||
// UnmarshalJSON unmarshals responses from JSON
|
||||
func (r *ResponsesProps) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
var res map[string]json.RawMessage
|
||||
if err := json.Unmarshal(data, &res); err != nil {
|
||||
return err
|
||||
@@ -106,6 +114,60 @@ func (r *ResponsesProps) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) (err error) {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch k := tok.Kind(); k {
|
||||
case 'n':
|
||||
*r = Responses{}
|
||||
return nil
|
||||
case '{':
|
||||
for {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tok.Kind() == '}' {
|
||||
return nil
|
||||
}
|
||||
switch k := tok.String(); {
|
||||
case internal.IsExtensionKey(k):
|
||||
var ext any
|
||||
if err := opts.UnmarshalNext(dec, &ext); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Extensions == nil {
|
||||
r.Extensions = make(map[string]any)
|
||||
}
|
||||
r.Extensions[k] = ext
|
||||
case k == "default":
|
||||
resp := Response{}
|
||||
if err := opts.UnmarshalNext(dec, &resp); err != nil {
|
||||
return err
|
||||
}
|
||||
r.ResponsesProps.Default = &resp
|
||||
default:
|
||||
if nk, err := strconv.Atoi(k); err == nil {
|
||||
resp := Response{}
|
||||
if err := opts.UnmarshalNext(dec, &resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.StatusCodeResponses == nil {
|
||||
r.StatusCodeResponses = map[int]*Response{}
|
||||
}
|
||||
r.StatusCodeResponses[nk] = &resp
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown JSON kind: %v", k)
|
||||
}
|
||||
}
|
||||
|
||||
// Response describes a single response from an API Operation, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responseObject
|
||||
//
|
||||
// Note that this struct is actually a thin wrapper around ResponseProps to make it referable and extensible
|
||||
@@ -133,6 +195,9 @@ func (r *Response) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (r *Response) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -142,7 +207,22 @@ func (r *Response) UnmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, &r.VendorExtensible); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Response) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ResponseProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&r.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
r.ResponseProps = x.ResponseProps
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -183,6 +263,9 @@ func (r *Link) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (r *Link) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -196,6 +279,22 @@ func (r *Link) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Link) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
LinkProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&l.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
l.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
l.LinkProps = x.LinkProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkProps describes a single response from an API Operation, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responseObject
|
||||
type LinkProps struct {
|
||||
// OperationId is the name of an existing, resolvable OAS operation
|
||||
|
38
vendor/k8s.io/kube-openapi/pkg/spec3/server.go
generated
vendored
38
vendor/k8s.io/kube-openapi/pkg/spec3/server.go
generated
vendored
@@ -18,7 +18,10 @@ package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -50,6 +53,10 @@ func (s *Server) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (s *Server) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, s)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &s.ServerProps); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -59,6 +66,20 @@ func (s *Server) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ServerProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.ServerProps = x.ServerProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerVariable struct {
|
||||
ServerVariableProps
|
||||
spec.VendorExtensible
|
||||
@@ -87,6 +108,9 @@ func (s *ServerVariable) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (s *ServerVariable) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, s)
|
||||
}
|
||||
if err := json.Unmarshal(data, &s.ServerVariableProps); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -95,3 +119,17 @@ func (s *ServerVariable) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ServerVariable) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ServerVariableProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.ServerVariableProps = x.ServerVariableProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
13
vendor/k8s.io/kube-openapi/pkg/spec3/spec.go
generated
vendored
13
vendor/k8s.io/kube-openapi/pkg/spec3/spec.go
generated
vendored
@@ -17,6 +17,10 @@ limitations under the License.
|
||||
package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
@@ -35,3 +39,12 @@ type OpenAPI struct {
|
||||
// ExternalDocs holds additional external documentation
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
func (o *OpenAPI) UnmarshalJSON(data []byte) error {
|
||||
type OpenAPIWithNoFunctions OpenAPI
|
||||
p := (*OpenAPIWithNoFunctions)(o)
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, &p)
|
||||
}
|
||||
return json.Unmarshal(data, &p)
|
||||
}
|
||||
|
4
vendor/k8s.io/kube-openapi/pkg/validation/spec/schema.go
generated
vendored
4
vendor/k8s.io/kube-openapi/pkg/validation/spec/schema.go
generated
vendored
@@ -523,6 +523,7 @@ func (s Schema) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder)
|
||||
ArbitraryKeys
|
||||
SchemaProps schemaPropsOmitZero `json:",inline"`
|
||||
SwaggerSchemaProps swaggerSchemaPropsOmitZero `json:",inline"`
|
||||
Schema string `json:"$schema,omitempty"`
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
}
|
||||
x.ArbitraryKeys = make(map[string]any, len(s.Extensions)+len(s.ExtraProps))
|
||||
@@ -537,6 +538,7 @@ func (s Schema) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder)
|
||||
x.SchemaProps = schemaPropsOmitZero(s.SchemaProps)
|
||||
x.SwaggerSchemaProps = swaggerSchemaPropsOmitZero(s.SwaggerSchemaProps)
|
||||
x.Ref = s.Ref.String()
|
||||
x.Schema = string(s.Schema)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
@@ -622,7 +624,7 @@ func (s *Schema) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Dec
|
||||
}
|
||||
|
||||
s.ExtraProps = x.Extensions.sanitizeWithExtra()
|
||||
s.VendorExtensible.Extensions = x.Extensions
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.SchemaProps = x.SchemaProps
|
||||
s.SwaggerSchemaProps = x.SwaggerSchemaProps
|
||||
return nil
|
||||
|
20
vendor/k8s.io/kube-openapi/pkg/validation/spec/swagger.go
generated
vendored
20
vendor/k8s.io/kube-openapi/pkg/validation/spec/swagger.go
generated
vendored
@@ -164,15 +164,15 @@ func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
var nw SchemaOrBool
|
||||
if len(data) >= 4 {
|
||||
if data[0] == '{' {
|
||||
var sch Schema
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Schema = &sch
|
||||
if len(data) > 0 && data[0] == '{' {
|
||||
var sch Schema
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Allows = !(data[0] == 'f' && data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e')
|
||||
nw.Schema = &sch
|
||||
nw.Allows = true
|
||||
} else {
|
||||
json.Unmarshal(data, &nw.Allows)
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
@@ -385,7 +385,7 @@ func (s SchemaOrArray) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
if len(s.Schemas) > 0 {
|
||||
if s.Schemas != nil {
|
||||
return json.Marshal(s.Schemas)
|
||||
}
|
||||
return json.Marshal(s.Schema)
|
||||
@@ -393,7 +393,7 @@ func (s SchemaOrArray) MarshalJSON() ([]byte, error) {
|
||||
|
||||
// MarshalJSON converts this schema object or array into JSON structure
|
||||
func (s SchemaOrArray) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
if len(s.Schemas) > 0 {
|
||||
if s.Schemas != nil {
|
||||
return opts.MarshalNext(enc, s.Schemas)
|
||||
}
|
||||
return opts.MarshalNext(enc, s.Schema)
|
||||
|
Reference in New Issue
Block a user