Update dependencies for k8s v1.29.0
This commit is contained in:
51
client/vendor/k8s.io/kube-openapi/pkg/builder3/util/util.go
generated
vendored
51
client/vendor/k8s.io/kube-openapi/pkg/builder3/util/util.go
generated
vendored
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/schemamutation"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// wrapRefs wraps OpenAPI V3 Schema refs that contain sibling elements.
|
||||
// AllOf is used to wrap the Ref to prevent references from having sibling elements
|
||||
// Please see https://github.com/kubernetes/kubernetes/issues/106387#issuecomment-967640388
|
||||
func WrapRefs(schema *spec.Schema) *spec.Schema {
|
||||
walker := schemamutation.Walker{
|
||||
SchemaCallback: func(schema *spec.Schema) *spec.Schema {
|
||||
orig := schema
|
||||
clone := func() {
|
||||
if orig == schema {
|
||||
schema = new(spec.Schema)
|
||||
*schema = *orig
|
||||
}
|
||||
}
|
||||
if schema.Ref.String() != "" && !reflect.DeepEqual(*schema, spec.Schema{SchemaProps: spec.SchemaProps{Ref: schema.Ref}}) {
|
||||
clone()
|
||||
refSchema := new(spec.Schema)
|
||||
refSchema.Ref = schema.Ref
|
||||
schema.Ref = spec.Ref{}
|
||||
schema.AllOf = []spec.Schema{*refSchema}
|
||||
}
|
||||
return schema
|
||||
},
|
||||
RefCallback: schemamutation.RefCallbackNoop,
|
||||
}
|
||||
return walker.WalkSchema(schema)
|
||||
}
|
266
client/vendor/k8s.io/kube-openapi/pkg/cached/cache.go
generated
vendored
266
client/vendor/k8s.io/kube-openapi/pkg/cached/cache.go
generated
vendored
@@ -14,7 +14,7 @@ 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
|
||||
// Package cached 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.
|
||||
@@ -25,16 +25,18 @@ limitations under the License.
|
||||
//
|
||||
// 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
|
||||
// - [Func]: A source cache that recomputes the content every time.
|
||||
// - [Once]: A source cache that always produces the
|
||||
// same content, it is only called once.
|
||||
// - [NewTransformer]: A cache that transforms data from one format to
|
||||
// - [Transform]: 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.
|
||||
// - [Merge]: A cache that aggregates multiple caches in a map 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.
|
||||
// - [MergeList]: A cache that aggregates multiple caches in a list into one.
|
||||
// It's only refreshed when the source changes.
|
||||
// - [Atomic]: A cache adapter that atomically replaces the source with a new one.
|
||||
// - [LastSuccess]: A cache adapter that caches the last successful and returns
|
||||
// it if the next call fails. It extends [Atomic].
|
||||
//
|
||||
// # Etags
|
||||
//
|
||||
@@ -54,61 +56,45 @@ import (
|
||||
"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.
|
||||
// Value is wrapping a value behind a getter for lazy evaluation.
|
||||
type Value[T any] interface {
|
||||
Get() (value T, etag string, err error)
|
||||
}
|
||||
|
||||
// Result is wrapping T and error into a struct for cases where a tuple is more
|
||||
// convenient or necessary in Golang.
|
||||
type Result[T any] struct {
|
||||
Data T
|
||||
Etag string
|
||||
Err error
|
||||
Value 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,
|
||||
}
|
||||
func (r Result[T]) Get() (T, string, error) {
|
||||
return r.Value, r.Etag, r.Err
|
||||
}
|
||||
|
||||
// NewResultErr creates a new [Result] when an error has happened.
|
||||
func NewResultErr[T any](err error) Result[T] {
|
||||
return Result[T]{
|
||||
Err: err,
|
||||
}
|
||||
// Func wraps a (thread-safe) function as a Value[T].
|
||||
func Func[T any](fn func() (T, string, error)) Value[T] {
|
||||
return valueFunc[T](fn)
|
||||
}
|
||||
|
||||
// Result can be treated as a [Data] if necessary.
|
||||
func (r Result[T]) Get() Result[T] {
|
||||
return r
|
||||
type valueFunc[T any] func() (T, string, error)
|
||||
|
||||
func (c valueFunc[T]) Get() (T, string, error) {
|
||||
return c()
|
||||
}
|
||||
|
||||
// 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]
|
||||
// Static returns constant values.
|
||||
func Static[T any](value T, etag string) Value[T] {
|
||||
return Result[T]{Value: value, Etag: etag}
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Merge merges a of cached values. The merge 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]).
|
||||
// before, then the function is run again.
|
||||
//
|
||||
// Note that this assumes there is no "partial" merge, the merge
|
||||
// function will remerge all the dependencies together everytime. Since
|
||||
@@ -118,18 +104,19 @@ type Data[T any] interface {
|
||||
// Also note that Golang map iteration is not stable. If the mergeFn
|
||||
// depends on the order iteration to be stable, it will need to
|
||||
// implement its own sorting or iteration order.
|
||||
func NewMerger[K comparable, T, V any](mergeFn func(results map[K]Result[T]) Result[V], caches map[K]Data[T]) Data[V] {
|
||||
listCaches := make([]Data[T], 0, len(caches))
|
||||
// maps from index to key
|
||||
func Merge[K comparable, T, V any](mergeFn func(results map[K]Result[T]) (V, string, error), caches map[K]Value[T]) Value[V] {
|
||||
list := make([]Value[T], 0, len(caches))
|
||||
|
||||
// map from index to key
|
||||
indexes := make(map[int]K, len(caches))
|
||||
i := 0
|
||||
for k := range caches {
|
||||
listCaches = append(listCaches, caches[k])
|
||||
list = append(list, caches[k])
|
||||
indexes[i] = k
|
||||
i++
|
||||
}
|
||||
|
||||
return NewListMerger(func(results []Result[T]) Result[V] {
|
||||
return MergeList(func(results []Result[T]) (V, string, error) {
|
||||
if len(results) != len(indexes) {
|
||||
panic(fmt.Errorf("invalid result length %d, expected %d", len(results), len(indexes)))
|
||||
}
|
||||
@@ -138,20 +125,11 @@ func NewMerger[K comparable, T, V any](mergeFn func(results map[K]Result[T]) Res
|
||||
m[indexes[i]] = results[i]
|
||||
}
|
||||
return mergeFn(m)
|
||||
}, listCaches)
|
||||
}, list)
|
||||
}
|
||||
|
||||
type listMerger[T, V any] struct {
|
||||
lock sync.Mutex
|
||||
mergeFn func([]Result[T]) Result[V]
|
||||
caches []Data[T]
|
||||
cacheResults []Result[T]
|
||||
result Result[V]
|
||||
}
|
||||
|
||||
// NewListMerger creates a new merge cache that merges the results of
|
||||
// other caches in list form. The function only gets called if any of
|
||||
// the dependency has changed.
|
||||
// MergeList merges a list of cached values. The function only gets called if
|
||||
// any of the dependency has changed.
|
||||
//
|
||||
// The benefit of ListMerger over the basic Merger is that caches are
|
||||
// stored in an ordered list so the order of the cache will be
|
||||
@@ -165,31 +143,37 @@ type listMerger[T, V any] struct {
|
||||
// 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 NewListMerger[T, V any](mergeFn func(results []Result[T]) Result[V], caches []Data[T]) Data[V] {
|
||||
func MergeList[T, V any](mergeFn func(results []Result[T]) (V, string, error), delegates []Value[T]) Value[V] {
|
||||
return &listMerger[T, V]{
|
||||
mergeFn: mergeFn,
|
||||
caches: caches,
|
||||
mergeFn: mergeFn,
|
||||
delegates: delegates,
|
||||
}
|
||||
}
|
||||
|
||||
type listMerger[T, V any] struct {
|
||||
lock sync.Mutex
|
||||
mergeFn func([]Result[T]) (V, string, error)
|
||||
delegates []Value[T]
|
||||
cache []Result[T]
|
||||
result Result[V]
|
||||
}
|
||||
|
||||
func (c *listMerger[T, V]) prepareResultsLocked() []Result[T] {
|
||||
cacheResults := make([]Result[T], len(c.caches))
|
||||
cacheResults := make([]Result[T], len(c.delegates))
|
||||
ch := make(chan struct {
|
||||
int
|
||||
Result[T]
|
||||
}, len(c.caches))
|
||||
for i := range c.caches {
|
||||
}, len(c.delegates))
|
||||
for i := range c.delegates {
|
||||
go func(index int) {
|
||||
value, etag, err := c.delegates[index].Get()
|
||||
ch <- struct {
|
||||
int
|
||||
Result[T]
|
||||
}{
|
||||
index,
|
||||
c.caches[index].Get(),
|
||||
}
|
||||
}{index, Result[T]{Value: value, Etag: etag, Err: err}}
|
||||
}(i)
|
||||
}
|
||||
for i := 0; i < len(c.caches); i++ {
|
||||
for i := 0; i < len(c.delegates); i++ {
|
||||
res := <-ch
|
||||
cacheResults[res.int] = res.Result
|
||||
}
|
||||
@@ -197,16 +181,16 @@ func (c *listMerger[T, V]) prepareResultsLocked() []Result[T] {
|
||||
}
|
||||
|
||||
func (c *listMerger[T, V]) needsRunningLocked(results []Result[T]) bool {
|
||||
if c.cacheResults == nil {
|
||||
if c.cache == 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)))
|
||||
if len(results) != len(c.cache) {
|
||||
panic(fmt.Errorf("invalid number of results: %v (expected %v)", len(results), len(c.cache)))
|
||||
}
|
||||
for i, oldResult := range c.cacheResults {
|
||||
for i, oldResult := range c.cache {
|
||||
newResult := results[i]
|
||||
if newResult.Etag != oldResult.Etag || newResult.Err != nil || oldResult.Err != nil {
|
||||
return true
|
||||
@@ -215,98 +199,92 @@ func (c *listMerger[T, V]) needsRunningLocked(results []Result[T]) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *listMerger[T, V]) Get() Result[V] {
|
||||
func (c *listMerger[T, V]) Get() (V, string, error) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
cacheResults := c.prepareResultsLocked()
|
||||
if c.needsRunningLocked(cacheResults) {
|
||||
c.cacheResults = cacheResults
|
||||
c.result = c.mergeFn(c.cacheResults)
|
||||
c.cache = cacheResults
|
||||
c.result.Value, c.result.Etag, c.result.Err = c.mergeFn(c.cache)
|
||||
}
|
||||
return c.result
|
||||
return c.result.Value, c.result.Etag, c.result.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Transform the result of another cached value. The transformFn will only be called
|
||||
// if the source has updated, otherwise, the 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 NewListMerger(func(caches []Result[T]) Result[V] {
|
||||
if len(caches) != 1 {
|
||||
panic(fmt.Errorf("invalid cache for transformer cache: %v", caches))
|
||||
func Transform[T, V any](transformerFn func(T, string, error) (V, string, error), source Value[T]) Value[V] {
|
||||
return MergeList(func(delegates []Result[T]) (V, string, error) {
|
||||
if len(delegates) != 1 {
|
||||
panic(fmt.Errorf("invalid cache for transformer cache: %v", delegates))
|
||||
}
|
||||
return transformerFn(caches[0])
|
||||
}, []Data[T]{source})
|
||||
return transformerFn(delegates[0].Value, delegates[0].Etag, delegates[0].Err)
|
||||
}, []Value[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. sourceFn MUST be thread-safe.
|
||||
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,
|
||||
// Once calls Value[T].Get() lazily and only once, even in case of an error result.
|
||||
func Once[T any](d Value[T]) Value[T] {
|
||||
return &once[T]{
|
||||
data: d,
|
||||
}
|
||||
}
|
||||
|
||||
type static[T any] struct {
|
||||
type once[T any] struct {
|
||||
once sync.Once
|
||||
fn func() Result[T]
|
||||
data Value[T]
|
||||
result Result[T]
|
||||
}
|
||||
|
||||
func (c *static[T]) Get() Result[T] {
|
||||
func (c *once[T]) Get() (T, string, error) {
|
||||
c.once.Do(func() {
|
||||
c.result = c.fn()
|
||||
c.result.Value, c.result.Etag, c.result.Err = c.data.Get()
|
||||
})
|
||||
return c.result
|
||||
return c.result.Value, c.result.Etag, c.result.Err
|
||||
}
|
||||
|
||||
// Replaceable is a cache that carries the result even when the cache is
|
||||
// replaced. This is the type that should typically be stored in
|
||||
// structs.
|
||||
type Replaceable[T any] struct {
|
||||
cache atomic.Pointer[Data[T]]
|
||||
result atomic.Pointer[Result[T]]
|
||||
// Replaceable extends the Value[T] interface with the ability to change the
|
||||
// underlying Value[T] after construction.
|
||||
type Replaceable[T any] interface {
|
||||
Value[T]
|
||||
Store(Value[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()
|
||||
// Atomic wraps a Value[T] as an atomic value that can be replaced. It implements
|
||||
// Replaceable[T].
|
||||
type Atomic[T any] struct {
|
||||
value atomic.Pointer[Value[T]]
|
||||
}
|
||||
|
||||
for {
|
||||
cResult := c.result.Load()
|
||||
if result.Err != nil && cResult != nil && cResult.Err == nil {
|
||||
return *cResult
|
||||
}
|
||||
if c.result.CompareAndSwap(cResult, &result) {
|
||||
return result
|
||||
var _ Replaceable[[]byte] = &Atomic[[]byte]{}
|
||||
|
||||
func (x *Atomic[T]) Store(val Value[T]) { x.value.Store(&val) }
|
||||
func (x *Atomic[T]) Get() (T, string, error) { return (*x.value.Load()).Get() }
|
||||
|
||||
// LastSuccess calls Value[T].Get(), but hides errors by returning the last
|
||||
// success if there has been any.
|
||||
type LastSuccess[T any] struct {
|
||||
Atomic[T]
|
||||
success atomic.Pointer[Result[T]]
|
||||
}
|
||||
|
||||
var _ Replaceable[[]byte] = &LastSuccess[[]byte]{}
|
||||
|
||||
func (c *LastSuccess[T]) Get() (T, string, error) {
|
||||
success := c.success.Load()
|
||||
value, etag, err := c.Atomic.Get()
|
||||
if err == nil {
|
||||
if success == nil {
|
||||
c.success.CompareAndSwap(nil, &Result[T]{Value: value, Etag: etag, Err: err})
|
||||
}
|
||||
return value, etag, err
|
||||
}
|
||||
}
|
||||
|
||||
// Replace changes the cache.
|
||||
func (c *Replaceable[T]) Replace(cache Data[T]) {
|
||||
c.cache.Swap(&cache)
|
||||
if success != nil {
|
||||
return success.Value, success.Etag, success.Err
|
||||
}
|
||||
|
||||
return value, etag, err
|
||||
}
|
||||
|
38
client/vendor/k8s.io/kube-openapi/pkg/common/common.go
generated
vendored
38
client/vendor/k8s.io/kube-openapi/pkg/common/common.go
generated
vendored
@@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/openapiconv"
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
@@ -172,43 +171,6 @@ type OpenAPIV3Config struct {
|
||||
DefaultSecurity []map[string][]string
|
||||
}
|
||||
|
||||
// ConvertConfigToV3 converts a Config object to an OpenAPIV3Config object
|
||||
func ConvertConfigToV3(config *Config) *OpenAPIV3Config {
|
||||
if config == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
v3Config := &OpenAPIV3Config{
|
||||
Info: config.Info,
|
||||
IgnorePrefixes: config.IgnorePrefixes,
|
||||
GetDefinitions: config.GetDefinitions,
|
||||
GetOperationIDAndTags: config.GetOperationIDAndTags,
|
||||
GetOperationIDAndTagsFromRoute: config.GetOperationIDAndTagsFromRoute,
|
||||
GetDefinitionName: config.GetDefinitionName,
|
||||
Definitions: config.Definitions,
|
||||
SecuritySchemes: make(spec3.SecuritySchemes),
|
||||
DefaultSecurity: config.DefaultSecurity,
|
||||
DefaultResponse: openapiconv.ConvertResponse(config.DefaultResponse, []string{"application/json"}),
|
||||
|
||||
CommonResponses: make(map[int]*spec3.Response),
|
||||
ResponseDefinitions: make(map[string]*spec3.Response),
|
||||
}
|
||||
|
||||
if config.SecurityDefinitions != nil {
|
||||
for s, securityScheme := range *config.SecurityDefinitions {
|
||||
v3Config.SecuritySchemes[s] = openapiconv.ConvertSecurityScheme(securityScheme)
|
||||
}
|
||||
}
|
||||
for k, commonResponse := range config.CommonResponses {
|
||||
v3Config.CommonResponses[k] = openapiconv.ConvertResponse(&commonResponse, []string{"application/json"})
|
||||
}
|
||||
|
||||
for k, responseDefinition := range config.ResponseDefinitions {
|
||||
v3Config.ResponseDefinitions[k] = openapiconv.ConvertResponse(&responseDefinition, []string{"application/json"})
|
||||
}
|
||||
return v3Config
|
||||
}
|
||||
|
||||
type typeInfo struct {
|
||||
name string
|
||||
format string
|
||||
|
104
client/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
generated
vendored
104
client/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
generated
vendored
@@ -26,6 +26,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
defaultergen "k8s.io/gengo/examples/defaulter-gen/generators"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
@@ -120,7 +121,7 @@ func newOpenAPIGen(sanitizedName string, targetPackage string) generator.Generat
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: sanitizedName,
|
||||
},
|
||||
imports: generator.NewImportTracker(),
|
||||
imports: generator.NewImportTrackerForPackage(targetPackage),
|
||||
targetPackage: targetPackage,
|
||||
}
|
||||
}
|
||||
@@ -553,23 +554,83 @@ func (g openAPITypeWriter) validatePatchTags(m *types.Member, parent *types.Type
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultFromComments(comments []string) (interface{}, error) {
|
||||
tag, err := getSingleTagsValue(comments, tagDefault)
|
||||
func defaultFromComments(comments []string, commentPath string, t *types.Type) (interface{}, *types.Name, error) {
|
||||
var tag string
|
||||
|
||||
for {
|
||||
var err error
|
||||
tag, err = getSingleTagsValue(comments, tagDefault)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if t == nil || len(tag) > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
comments = t.CommentLines
|
||||
commentPath = t.Name.Package
|
||||
switch t.Kind {
|
||||
case types.Pointer:
|
||||
t = t.Elem
|
||||
case types.Alias:
|
||||
t = t.Underlying
|
||||
default:
|
||||
t = nil
|
||||
}
|
||||
}
|
||||
|
||||
if tag == "" {
|
||||
return nil, err
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
var i interface{}
|
||||
if err := json.Unmarshal([]byte(tag), &i); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal default: %v", err)
|
||||
if id, ok := defaultergen.ParseSymbolReference(tag, commentPath); ok {
|
||||
klog.Errorf("%v, %v", id, commentPath)
|
||||
return nil, &id, nil
|
||||
} else if err := json.Unmarshal([]byte(tag), &i); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to unmarshal default: %v", err)
|
||||
}
|
||||
return i, nil, nil
|
||||
}
|
||||
|
||||
func implementsCustomUnmarshalling(t *types.Type) bool {
|
||||
switch t.Kind {
|
||||
case types.Pointer:
|
||||
unmarshaller, isUnmarshaller := t.Elem.Methods["UnmarshalJSON"]
|
||||
return isUnmarshaller && unmarshaller.Signature.Receiver.Kind == types.Pointer
|
||||
case types.Struct:
|
||||
_, isUnmarshaller := t.Methods["UnmarshalJSON"]
|
||||
return isUnmarshaller
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func mustEnforceDefault(t *types.Type, omitEmpty bool) (interface{}, error) {
|
||||
// Treat types with custom unmarshalling as a value
|
||||
// (Can be alias, struct, or pointer)
|
||||
if implementsCustomUnmarshalling(t) {
|
||||
// Since Go JSON deserializer always feeds `null` when present
|
||||
// to structs with custom UnmarshalJSON, the zero value for
|
||||
// these structs is also null.
|
||||
//
|
||||
// In general, Kubernetes API types with custom marshalling should
|
||||
// marshal their empty values to `null`.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
switch t.Kind {
|
||||
case types.Alias:
|
||||
return mustEnforceDefault(t.Underlying, omitEmpty)
|
||||
case types.Pointer, types.Map, types.Slice, types.Array, types.Interface:
|
||||
return nil, nil
|
||||
case types.Struct:
|
||||
if len(t.Members) == 1 && t.Members[0].Embedded {
|
||||
// Treat a struct with a single embedded member the same as an alias
|
||||
return mustEnforceDefault(t.Members[0].Type, omitEmpty)
|
||||
}
|
||||
|
||||
return map[string]interface{}{}, nil
|
||||
case types.Builtin:
|
||||
if !omitEmpty {
|
||||
@@ -585,9 +646,8 @@ func mustEnforceDefault(t *types.Type, omitEmpty bool) (interface{}, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (g openAPITypeWriter) generateDefault(comments []string, t *types.Type, omitEmpty bool) error {
|
||||
t = resolveAliasAndEmbeddedType(t)
|
||||
def, err := defaultFromComments(comments)
|
||||
func (g openAPITypeWriter) generateDefault(comments []string, t *types.Type, omitEmpty bool, commentOwningType *types.Type) error {
|
||||
def, ref, err := defaultFromComments(comments, commentOwningType.Name.Package, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -603,6 +663,8 @@ func (g openAPITypeWriter) generateDefault(comments []string, t *types.Type, omi
|
||||
}
|
||||
if def != nil {
|
||||
g.Do("Default: $.$,\n", fmt.Sprintf("%#v", def))
|
||||
} else if ref != nil {
|
||||
g.Do("Default: $.|raw$,\n", &types.Type{Name: *ref})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -676,7 +738,7 @@ func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type)
|
||||
return nil
|
||||
}
|
||||
omitEmpty := strings.Contains(reflect.StructTag(m.Tags).Get("json"), "omitempty")
|
||||
if err := g.generateDefault(m.CommentLines, m.Type, omitEmpty); err != nil {
|
||||
if err := g.generateDefault(m.CommentLines, m.Type, omitEmpty, parent); err != nil {
|
||||
return fmt.Errorf("failed to generate default in %v: %v: %v", parent, m.Name, err)
|
||||
}
|
||||
t := resolveAliasAndPtrType(m.Type)
|
||||
@@ -721,22 +783,6 @@ func (g openAPITypeWriter) generateReferenceProperty(t *types.Type) {
|
||||
g.Do("Ref: ref(\"$.$\"),\n", t.Name.String())
|
||||
}
|
||||
|
||||
func resolveAliasAndEmbeddedType(t *types.Type) *types.Type {
|
||||
var prev *types.Type
|
||||
for prev != t {
|
||||
prev = t
|
||||
if t.Kind == types.Alias {
|
||||
t = t.Underlying
|
||||
}
|
||||
if t.Kind == types.Struct {
|
||||
if len(t.Members) == 1 && t.Members[0].Embedded {
|
||||
t = t.Members[0].Type
|
||||
}
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func resolveAliasAndPtrType(t *types.Type) *types.Type {
|
||||
var prev *types.Type
|
||||
for prev != t {
|
||||
@@ -762,7 +808,7 @@ func (g openAPITypeWriter) generateMapProperty(t *types.Type) error {
|
||||
|
||||
g.Do("Type: []string{\"object\"},\n", nil)
|
||||
g.Do("AdditionalProperties: &spec.SchemaOrBool{\nAllows: true,\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
|
||||
if err := g.generateDefault(t.Elem.CommentLines, t.Elem, false); err != nil {
|
||||
if err := g.generateDefault(t.Elem.CommentLines, t.Elem, false, t.Elem); err != nil {
|
||||
return err
|
||||
}
|
||||
typeString, format := openapi.OpenAPITypeFormat(elemType.String())
|
||||
@@ -795,7 +841,7 @@ func (g openAPITypeWriter) generateSliceProperty(t *types.Type) error {
|
||||
elemType := resolveAliasAndPtrType(t.Elem)
|
||||
g.Do("Type: []string{\"array\"},\n", nil)
|
||||
g.Do("Items: &spec.SchemaOrArray{\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
|
||||
if err := g.generateDefault(t.Elem.CommentLines, t.Elem, false); err != nil {
|
||||
if err := g.generateDefault(t.Elem.CommentLines, t.Elem, false, t.Elem); err != nil {
|
||||
return err
|
||||
}
|
||||
typeString, format := openapi.OpenAPITypeFormat(elemType.String())
|
||||
|
81
client/vendor/k8s.io/kube-openapi/pkg/handler3/handler.go
generated
vendored
81
client/vendor/k8s.io/kube-openapi/pkg/handler3/handler.go
generated
vendored
@@ -33,6 +33,7 @@ import (
|
||||
openapi_v3 "github.com/google/gnostic-models/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"
|
||||
@@ -73,38 +74,38 @@ type timedSpec struct {
|
||||
|
||||
// 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]
|
||||
specCache cached.LastSuccess[*spec3.OpenAPI]
|
||||
pbCache cached.Value[timedSpec]
|
||||
jsonCache cached.Value[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)
|
||||
o.jsonCache = cached.Transform[*spec3.OpenAPI](func(spec *spec3.OpenAPI, etag string, err error) (timedSpec, string, error) {
|
||||
if err != nil {
|
||||
return cached.NewResultErr[timedSpec](err)
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
return cached.NewResultOK(timedSpec{spec: json, lastModified: time.Now()}, computeETag(json))
|
||||
json, err := json.Marshal(spec)
|
||||
if err != nil {
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
return timedSpec{spec: json, lastModified: time.Now()}, computeETag(json), nil
|
||||
}, &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)
|
||||
o.pbCache = cached.Transform(func(ts timedSpec, etag string, err error) (timedSpec, string, error) {
|
||||
if err != nil {
|
||||
return cached.NewResultErr[timedSpec](err)
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
return cached.NewResultOK(timedSpec{spec: proto, lastModified: result.Data.lastModified}, result.Etag)
|
||||
proto, err := ToV3ProtoBinary(ts.spec)
|
||||
if err != nil {
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
return timedSpec{spec: proto, lastModified: ts.lastModified}, etag, nil
|
||||
}, o.jsonCache)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *openAPIV3Group) UpdateSpec(openapi cached.Data[*spec3.OpenAPI]) {
|
||||
o.specCache.Replace(openapi)
|
||||
func (o *openAPIV3Group) UpdateSpec(openapi cached.Value[*spec3.OpenAPI]) {
|
||||
o.specCache.Store(openapi)
|
||||
}
|
||||
|
||||
// OpenAPIService is the service responsible for serving OpenAPI spec. It has
|
||||
@@ -114,7 +115,7 @@ type OpenAPIService struct {
|
||||
mutex sync.Mutex
|
||||
v3Schema map[string]*openAPIV3Group
|
||||
|
||||
discoveryCache cached.Replaceable[timedSpec]
|
||||
discoveryCache cached.LastSuccess[timedSpec]
|
||||
}
|
||||
|
||||
func computeETag(data []byte) string {
|
||||
@@ -137,20 +138,20 @@ func NewOpenAPIService() *OpenAPIService {
|
||||
o := &OpenAPIService{}
|
||||
o.v3Schema = make(map[string]*openAPIV3Group)
|
||||
// We're not locked because we haven't shared the structure yet.
|
||||
o.discoveryCache.Replace(o.buildDiscoveryCacheLocked())
|
||||
o.discoveryCache.Store(o.buildDiscoveryCacheLocked())
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) buildDiscoveryCacheLocked() cached.Data[timedSpec] {
|
||||
caches := make(map[string]cached.Data[timedSpec], len(o.v3Schema))
|
||||
func (o *OpenAPIService) buildDiscoveryCacheLocked() cached.Value[timedSpec] {
|
||||
caches := make(map[string]cached.Value[timedSpec], len(o.v3Schema))
|
||||
for gvName, group := range o.v3Schema {
|
||||
caches[gvName] = group.jsonCache
|
||||
}
|
||||
return cached.NewMerger(func(results map[string]cached.Result[timedSpec]) cached.Result[timedSpec] {
|
||||
return cached.Merge(func(results map[string]cached.Result[timedSpec]) (timedSpec, string, error) {
|
||||
discovery := &OpenAPIV3Discovery{Paths: make(map[string]OpenAPIV3DiscoveryGroupVersion)}
|
||||
for gvName, result := range results {
|
||||
if result.Err != nil {
|
||||
return cached.NewResultErr[timedSpec](result.Err)
|
||||
return timedSpec{}, "", result.Err
|
||||
}
|
||||
discovery.Paths[gvName] = OpenAPIV3DiscoveryGroupVersion{
|
||||
ServerRelativeURL: constructServerRelativeURL(gvName, result.Etag),
|
||||
@@ -158,9 +159,9 @@ func (o *OpenAPIService) buildDiscoveryCacheLocked() cached.Data[timedSpec] {
|
||||
}
|
||||
j, err := json.Marshal(discovery)
|
||||
if err != nil {
|
||||
return cached.NewResultErr[timedSpec](err)
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
return cached.NewResultOK(timedSpec{spec: j, lastModified: time.Now()}, computeETag(j))
|
||||
return timedSpec{spec: j, lastModified: time.Now()}, computeETag(j), nil
|
||||
}, caches)
|
||||
}
|
||||
|
||||
@@ -171,32 +172,32 @@ func (o *OpenAPIService) getSingleGroupBytes(getType string, group string) ([]by
|
||||
if !ok {
|
||||
return nil, "", time.Now(), fmt.Errorf("Cannot find CRD group %s", group)
|
||||
}
|
||||
result := cached.Result[timedSpec]{}
|
||||
switch getType {
|
||||
case subTypeJSON:
|
||||
result = v.jsonCache.Get()
|
||||
ts, etag, err := v.jsonCache.Get()
|
||||
return ts.spec, etag, ts.lastModified, err
|
||||
case subTypeProtobuf, subTypeProtobufDeprecated:
|
||||
result = v.pbCache.Get()
|
||||
ts, etag, err := v.pbCache.Get()
|
||||
return ts.spec, etag, ts.lastModified, err
|
||||
default:
|
||||
return nil, "", time.Now(), fmt.Errorf("Invalid accept clause %s", getType)
|
||||
}
|
||||
return result.Data.spec, result.Etag, result.Data.lastModified, result.Err
|
||||
}
|
||||
|
||||
// UpdateGroupVersionLazy adds or updates an existing group with the new cached.
|
||||
func (o *OpenAPIService) UpdateGroupVersionLazy(group string, openapi cached.Data[*spec3.OpenAPI]) {
|
||||
func (o *OpenAPIService) UpdateGroupVersionLazy(group string, openapi cached.Value[*spec3.OpenAPI]) {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
if _, ok := o.v3Schema[group]; !ok {
|
||||
o.v3Schema[group] = newOpenAPIV3Group()
|
||||
// Since there is a new item, we need to re-build the cache map.
|
||||
o.discoveryCache.Replace(o.buildDiscoveryCacheLocked())
|
||||
o.discoveryCache.Store(o.buildDiscoveryCacheLocked())
|
||||
}
|
||||
o.v3Schema[group].UpdateSpec(openapi)
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) UpdateGroupVersion(group string, openapi *spec3.OpenAPI) {
|
||||
o.UpdateGroupVersionLazy(group, cached.NewResultOK(openapi, uuid.New().String()))
|
||||
o.UpdateGroupVersionLazy(group, cached.Static(openapi, uuid.New().String()))
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) DeleteGroupVersion(group string) {
|
||||
@@ -204,19 +205,19 @@ func (o *OpenAPIService) DeleteGroupVersion(group string) {
|
||||
defer o.mutex.Unlock()
|
||||
delete(o.v3Schema, group)
|
||||
// Rebuild the merge cache map since the items have changed.
|
||||
o.discoveryCache.Replace(o.buildDiscoveryCacheLocked())
|
||||
o.discoveryCache.Store(o.buildDiscoveryCacheLocked())
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) HandleDiscovery(w http.ResponseWriter, r *http.Request) {
|
||||
result := o.discoveryCache.Get()
|
||||
if result.Err != nil {
|
||||
klog.Errorf("Error serving discovery: %s", result.Err)
|
||||
ts, etag, err := o.discoveryCache.Get()
|
||||
if err != nil {
|
||||
klog.Errorf("Error serving discovery: %s", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Etag", strconv.Quote(result.Etag))
|
||||
w.Header().Set("Etag", strconv.Quote(etag))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
http.ServeContent(w, r, "/openapi/v3", result.Data.lastModified, bytes.NewReader(result.Data.spec))
|
||||
http.ServeContent(w, r, "/openapi/v3", ts.lastModified, bytes.NewReader(ts.spec))
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) HandleGroupVersion(w http.ResponseWriter, r *http.Request) {
|
||||
|
1
client/vendor/k8s.io/kube-openapi/pkg/internal/flags.go
generated
vendored
1
client/vendor/k8s.io/kube-openapi/pkg/internal/flags.go
generated
vendored
@@ -22,3 +22,4 @@ var UseOptimizedJSONUnmarshalingV3 bool = true
|
||||
|
||||
// Used by tests to selectively disable experimental JSON marshaler
|
||||
var UseOptimizedJSONMarshaling bool = true
|
||||
var UseOptimizedJSONMarshalingV3 bool = true
|
||||
|
322
client/vendor/k8s.io/kube-openapi/pkg/openapiconv/convert.go
generated
vendored
322
client/vendor/k8s.io/kube-openapi/pkg/openapiconv/convert.go
generated
vendored
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
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 openapiconv
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
klog "k8s.io/klog/v2"
|
||||
builderutil "k8s.io/kube-openapi/pkg/builder3/util"
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
var OpenAPIV2DefPrefix = "#/definitions/"
|
||||
var OpenAPIV3DefPrefix = "#/components/schemas/"
|
||||
|
||||
// ConvertV2ToV3 converts an OpenAPI V2 object into V3.
|
||||
// Certain references may be shared between the V2 and V3 objects in the conversion.
|
||||
func ConvertV2ToV3(v2Spec *spec.Swagger) *spec3.OpenAPI {
|
||||
v3Spec := &spec3.OpenAPI{
|
||||
Version: "3.0.0",
|
||||
Info: v2Spec.Info,
|
||||
ExternalDocs: ConvertExternalDocumentation(v2Spec.ExternalDocs),
|
||||
Paths: ConvertPaths(v2Spec.Paths),
|
||||
Components: ConvertComponents(v2Spec.SecurityDefinitions, v2Spec.Definitions, v2Spec.Responses, v2Spec.Produces),
|
||||
}
|
||||
|
||||
return v3Spec
|
||||
}
|
||||
|
||||
func ConvertExternalDocumentation(v2ED *spec.ExternalDocumentation) *spec3.ExternalDocumentation {
|
||||
if v2ED == nil {
|
||||
return nil
|
||||
}
|
||||
return &spec3.ExternalDocumentation{
|
||||
ExternalDocumentationProps: spec3.ExternalDocumentationProps{
|
||||
Description: v2ED.Description,
|
||||
URL: v2ED.URL,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertComponents(v2SecurityDefinitions spec.SecurityDefinitions, v2Definitions spec.Definitions, v2Responses map[string]spec.Response, produces []string) *spec3.Components {
|
||||
components := &spec3.Components{}
|
||||
|
||||
if v2Definitions != nil {
|
||||
components.Schemas = make(map[string]*spec.Schema)
|
||||
}
|
||||
for s, schema := range v2Definitions {
|
||||
components.Schemas[s] = ConvertSchema(&schema)
|
||||
}
|
||||
if v2SecurityDefinitions != nil {
|
||||
components.SecuritySchemes = make(spec3.SecuritySchemes)
|
||||
}
|
||||
for s, securityScheme := range v2SecurityDefinitions {
|
||||
components.SecuritySchemes[s] = ConvertSecurityScheme(securityScheme)
|
||||
}
|
||||
if v2Responses != nil {
|
||||
components.Responses = make(map[string]*spec3.Response)
|
||||
}
|
||||
for r, response := range v2Responses {
|
||||
components.Responses[r] = ConvertResponse(&response, produces)
|
||||
}
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
func ConvertSchema(v2Schema *spec.Schema) *spec.Schema {
|
||||
if v2Schema == nil {
|
||||
return nil
|
||||
}
|
||||
v3Schema := spec.Schema{
|
||||
VendorExtensible: v2Schema.VendorExtensible,
|
||||
SchemaProps: v2Schema.SchemaProps,
|
||||
SwaggerSchemaProps: v2Schema.SwaggerSchemaProps,
|
||||
ExtraProps: v2Schema.ExtraProps,
|
||||
}
|
||||
|
||||
if refString := v2Schema.Ref.String(); refString != "" {
|
||||
if idx := strings.Index(refString, OpenAPIV2DefPrefix); idx != -1 {
|
||||
v3Schema.Ref = spec.MustCreateRef(OpenAPIV3DefPrefix + refString[idx+len(OpenAPIV2DefPrefix):])
|
||||
} else {
|
||||
klog.Errorf("Error: Swagger V2 Ref %s does not contain #/definitions\n", refString)
|
||||
}
|
||||
}
|
||||
|
||||
if v2Schema.Properties != nil {
|
||||
v3Schema.Properties = make(map[string]spec.Schema)
|
||||
for key, property := range v2Schema.Properties {
|
||||
v3Schema.Properties[key] = *ConvertSchema(&property)
|
||||
}
|
||||
}
|
||||
if v2Schema.Items != nil {
|
||||
v3Schema.Items = &spec.SchemaOrArray{
|
||||
Schema: ConvertSchema(v2Schema.Items.Schema),
|
||||
Schemas: ConvertSchemaList(v2Schema.Items.Schemas),
|
||||
}
|
||||
}
|
||||
|
||||
if v2Schema.AdditionalProperties != nil {
|
||||
v3Schema.AdditionalProperties = &spec.SchemaOrBool{
|
||||
Schema: ConvertSchema(v2Schema.AdditionalProperties.Schema),
|
||||
Allows: v2Schema.AdditionalProperties.Allows,
|
||||
}
|
||||
}
|
||||
if v2Schema.AdditionalItems != nil {
|
||||
v3Schema.AdditionalItems = &spec.SchemaOrBool{
|
||||
Schema: ConvertSchema(v2Schema.AdditionalItems.Schema),
|
||||
Allows: v2Schema.AdditionalItems.Allows,
|
||||
}
|
||||
}
|
||||
|
||||
return builderutil.WrapRefs(&v3Schema)
|
||||
}
|
||||
|
||||
func ConvertSchemaList(v2SchemaList []spec.Schema) []spec.Schema {
|
||||
if v2SchemaList == nil {
|
||||
return nil
|
||||
}
|
||||
v3SchemaList := []spec.Schema{}
|
||||
for _, s := range v2SchemaList {
|
||||
v3SchemaList = append(v3SchemaList, *ConvertSchema(&s))
|
||||
}
|
||||
return v3SchemaList
|
||||
}
|
||||
|
||||
func ConvertSecurityScheme(v2securityScheme *spec.SecurityScheme) *spec3.SecurityScheme {
|
||||
if v2securityScheme == nil {
|
||||
return nil
|
||||
}
|
||||
securityScheme := &spec3.SecurityScheme{
|
||||
VendorExtensible: v2securityScheme.VendorExtensible,
|
||||
SecuritySchemeProps: spec3.SecuritySchemeProps{
|
||||
Description: v2securityScheme.Description,
|
||||
Type: v2securityScheme.Type,
|
||||
Name: v2securityScheme.Name,
|
||||
In: v2securityScheme.In,
|
||||
},
|
||||
}
|
||||
|
||||
if v2securityScheme.Flow != "" {
|
||||
securityScheme.Flows = make(map[string]*spec3.OAuthFlow)
|
||||
securityScheme.Flows[v2securityScheme.Flow] = &spec3.OAuthFlow{
|
||||
OAuthFlowProps: spec3.OAuthFlowProps{
|
||||
AuthorizationUrl: v2securityScheme.AuthorizationURL,
|
||||
TokenUrl: v2securityScheme.TokenURL,
|
||||
Scopes: v2securityScheme.Scopes,
|
||||
},
|
||||
}
|
||||
}
|
||||
return securityScheme
|
||||
}
|
||||
|
||||
func ConvertPaths(v2Paths *spec.Paths) *spec3.Paths {
|
||||
if v2Paths == nil {
|
||||
return nil
|
||||
}
|
||||
paths := &spec3.Paths{
|
||||
VendorExtensible: v2Paths.VendorExtensible,
|
||||
}
|
||||
|
||||
if v2Paths.Paths != nil {
|
||||
paths.Paths = make(map[string]*spec3.Path)
|
||||
}
|
||||
for k, v := range v2Paths.Paths {
|
||||
paths.Paths[k] = ConvertPathItem(v)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func ConvertPathItem(v2pathItem spec.PathItem) *spec3.Path {
|
||||
path := &spec3.Path{
|
||||
Refable: v2pathItem.Refable,
|
||||
PathProps: spec3.PathProps{
|
||||
Get: ConvertOperation(v2pathItem.Get),
|
||||
Put: ConvertOperation(v2pathItem.Put),
|
||||
Post: ConvertOperation(v2pathItem.Post),
|
||||
Delete: ConvertOperation(v2pathItem.Delete),
|
||||
Options: ConvertOperation(v2pathItem.Options),
|
||||
Head: ConvertOperation(v2pathItem.Head),
|
||||
Patch: ConvertOperation(v2pathItem.Patch),
|
||||
},
|
||||
VendorExtensible: v2pathItem.VendorExtensible,
|
||||
}
|
||||
for _, param := range v2pathItem.Parameters {
|
||||
path.Parameters = append(path.Parameters, ConvertParameter(param))
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func ConvertOperation(v2Operation *spec.Operation) *spec3.Operation {
|
||||
if v2Operation == nil {
|
||||
return nil
|
||||
}
|
||||
operation := &spec3.Operation{
|
||||
VendorExtensible: v2Operation.VendorExtensible,
|
||||
OperationProps: spec3.OperationProps{
|
||||
Description: v2Operation.Description,
|
||||
ExternalDocs: ConvertExternalDocumentation(v2Operation.OperationProps.ExternalDocs),
|
||||
Tags: v2Operation.Tags,
|
||||
Summary: v2Operation.Summary,
|
||||
Deprecated: v2Operation.Deprecated,
|
||||
OperationId: v2Operation.ID,
|
||||
},
|
||||
}
|
||||
|
||||
for _, param := range v2Operation.Parameters {
|
||||
if param.ParamProps.Name == "body" && param.ParamProps.Schema != nil {
|
||||
operation.OperationProps.RequestBody = &spec3.RequestBody{
|
||||
RequestBodyProps: spec3.RequestBodyProps{},
|
||||
}
|
||||
if v2Operation.Consumes != nil {
|
||||
operation.RequestBody.Content = make(map[string]*spec3.MediaType)
|
||||
}
|
||||
for _, consumer := range v2Operation.Consumes {
|
||||
operation.RequestBody.Content[consumer] = &spec3.MediaType{
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: ConvertSchema(param.ParamProps.Schema),
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
operation.Parameters = append(operation.Parameters, ConvertParameter(param))
|
||||
}
|
||||
}
|
||||
|
||||
operation.Responses = &spec3.Responses{ResponsesProps: spec3.ResponsesProps{
|
||||
Default: ConvertResponse(v2Operation.Responses.Default, v2Operation.Produces),
|
||||
},
|
||||
VendorExtensible: v2Operation.Responses.VendorExtensible,
|
||||
}
|
||||
|
||||
if v2Operation.Responses.StatusCodeResponses != nil {
|
||||
operation.Responses.StatusCodeResponses = make(map[int]*spec3.Response)
|
||||
}
|
||||
for k, v := range v2Operation.Responses.StatusCodeResponses {
|
||||
operation.Responses.StatusCodeResponses[k] = ConvertResponse(&v, v2Operation.Produces)
|
||||
}
|
||||
return operation
|
||||
}
|
||||
|
||||
func ConvertResponse(v2Response *spec.Response, produces []string) *spec3.Response {
|
||||
if v2Response == nil {
|
||||
return nil
|
||||
}
|
||||
response := &spec3.Response{
|
||||
Refable: ConvertRefableResponse(v2Response.Refable),
|
||||
VendorExtensible: v2Response.VendorExtensible,
|
||||
ResponseProps: spec3.ResponseProps{
|
||||
Description: v2Response.Description,
|
||||
},
|
||||
}
|
||||
|
||||
if v2Response.Schema != nil {
|
||||
if produces != nil {
|
||||
response.Content = make(map[string]*spec3.MediaType)
|
||||
}
|
||||
for _, producer := range produces {
|
||||
response.ResponseProps.Content[producer] = &spec3.MediaType{
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: ConvertSchema(v2Response.Schema),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
func ConvertParameter(v2Param spec.Parameter) *spec3.Parameter {
|
||||
param := &spec3.Parameter{
|
||||
Refable: ConvertRefableParameter(v2Param.Refable),
|
||||
VendorExtensible: v2Param.VendorExtensible,
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: v2Param.Name,
|
||||
Description: v2Param.Description,
|
||||
In: v2Param.In,
|
||||
Required: v2Param.Required,
|
||||
Schema: ConvertSchema(v2Param.Schema),
|
||||
AllowEmptyValue: v2Param.AllowEmptyValue,
|
||||
},
|
||||
}
|
||||
// Convert SimpleSchema into Schema
|
||||
if param.Schema == nil {
|
||||
param.Schema = &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{v2Param.Type},
|
||||
Format: v2Param.Format,
|
||||
UniqueItems: v2Param.UniqueItems,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return param
|
||||
}
|
||||
|
||||
func ConvertRefableParameter(refable spec.Refable) spec.Refable {
|
||||
if refable.Ref.String() != "" {
|
||||
return spec.Refable{Ref: spec.MustCreateRef(strings.Replace(refable.Ref.String(), "#/parameters/", "#/components/parameters/", 1))}
|
||||
}
|
||||
return refable
|
||||
}
|
||||
|
||||
func ConvertRefableResponse(refable spec.Refable) spec.Refable {
|
||||
if refable.Ref.String() != "" {
|
||||
return spec.Refable{Ref: spec.MustCreateRef(strings.Replace(refable.Ref.String(), "#/responses/", "#/components/responses/", 1))}
|
||||
}
|
||||
return refable
|
||||
}
|
519
client/vendor/k8s.io/kube-openapi/pkg/schemamutation/walker.go
generated
vendored
519
client/vendor/k8s.io/kube-openapi/pkg/schemamutation/walker.go
generated
vendored
@@ -1,519 +0,0 @@
|
||||
/*
|
||||
Copyright 2017 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 schemamutation
|
||||
|
||||
import (
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// Walker runs callback functions on all references of an OpenAPI spec,
|
||||
// replacing the values when visiting corresponding types.
|
||||
type Walker struct {
|
||||
// SchemaCallback will be called on each schema, taking the original schema,
|
||||
// and before any other callbacks of the Walker.
|
||||
// If the schema needs to be mutated, DO NOT mutate it in-place,
|
||||
// always create a copy, mutate, and return it.
|
||||
SchemaCallback func(schema *spec.Schema) *spec.Schema
|
||||
|
||||
// RefCallback will be called on each ref.
|
||||
// If the ref needs to be mutated, DO NOT mutate it in-place,
|
||||
// always create a copy, mutate, and return it.
|
||||
RefCallback func(ref *spec.Ref) *spec.Ref
|
||||
}
|
||||
|
||||
type SchemaCallbackFunc func(schema *spec.Schema) *spec.Schema
|
||||
type RefCallbackFunc func(ref *spec.Ref) *spec.Ref
|
||||
|
||||
var SchemaCallBackNoop SchemaCallbackFunc = func(schema *spec.Schema) *spec.Schema {
|
||||
return schema
|
||||
}
|
||||
var RefCallbackNoop RefCallbackFunc = func(ref *spec.Ref) *spec.Ref {
|
||||
return ref
|
||||
}
|
||||
|
||||
// ReplaceReferences rewrites the references without mutating the input.
|
||||
// The output might share data with the input.
|
||||
func ReplaceReferences(walkRef func(ref *spec.Ref) *spec.Ref, sp *spec.Swagger) *spec.Swagger {
|
||||
walker := &Walker{RefCallback: walkRef, SchemaCallback: SchemaCallBackNoop}
|
||||
return walker.WalkRoot(sp)
|
||||
}
|
||||
|
||||
func (w *Walker) WalkSchema(schema *spec.Schema) *spec.Schema {
|
||||
if schema == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := schema
|
||||
clone := func() {
|
||||
if orig == schema {
|
||||
schema = &spec.Schema{}
|
||||
*schema = *orig
|
||||
}
|
||||
}
|
||||
|
||||
// Always run callback on the whole schema first
|
||||
// so that SchemaCallback can take the original schema as input.
|
||||
schema = w.SchemaCallback(schema)
|
||||
|
||||
if r := w.RefCallback(&schema.Ref); r != &schema.Ref {
|
||||
clone()
|
||||
schema.Ref = *r
|
||||
}
|
||||
|
||||
definitionsCloned := false
|
||||
for k, v := range schema.Definitions {
|
||||
if s := w.WalkSchema(&v); s != &v {
|
||||
if !definitionsCloned {
|
||||
definitionsCloned = true
|
||||
clone()
|
||||
schema.Definitions = make(spec.Definitions, len(orig.Definitions))
|
||||
for k2, v2 := range orig.Definitions {
|
||||
schema.Definitions[k2] = v2
|
||||
}
|
||||
}
|
||||
schema.Definitions[k] = *s
|
||||
}
|
||||
}
|
||||
|
||||
propertiesCloned := false
|
||||
for k, v := range schema.Properties {
|
||||
if s := w.WalkSchema(&v); s != &v {
|
||||
if !propertiesCloned {
|
||||
propertiesCloned = true
|
||||
clone()
|
||||
schema.Properties = make(map[string]spec.Schema, len(orig.Properties))
|
||||
for k2, v2 := range orig.Properties {
|
||||
schema.Properties[k2] = v2
|
||||
}
|
||||
}
|
||||
schema.Properties[k] = *s
|
||||
}
|
||||
}
|
||||
|
||||
patternPropertiesCloned := false
|
||||
for k, v := range schema.PatternProperties {
|
||||
if s := w.WalkSchema(&v); s != &v {
|
||||
if !patternPropertiesCloned {
|
||||
patternPropertiesCloned = true
|
||||
clone()
|
||||
schema.PatternProperties = make(map[string]spec.Schema, len(orig.PatternProperties))
|
||||
for k2, v2 := range orig.PatternProperties {
|
||||
schema.PatternProperties[k2] = v2
|
||||
}
|
||||
}
|
||||
schema.PatternProperties[k] = *s
|
||||
}
|
||||
}
|
||||
|
||||
allOfCloned := false
|
||||
for i := range schema.AllOf {
|
||||
if s := w.WalkSchema(&schema.AllOf[i]); s != &schema.AllOf[i] {
|
||||
if !allOfCloned {
|
||||
allOfCloned = true
|
||||
clone()
|
||||
schema.AllOf = make([]spec.Schema, len(orig.AllOf))
|
||||
copy(schema.AllOf, orig.AllOf)
|
||||
}
|
||||
schema.AllOf[i] = *s
|
||||
}
|
||||
}
|
||||
|
||||
anyOfCloned := false
|
||||
for i := range schema.AnyOf {
|
||||
if s := w.WalkSchema(&schema.AnyOf[i]); s != &schema.AnyOf[i] {
|
||||
if !anyOfCloned {
|
||||
anyOfCloned = true
|
||||
clone()
|
||||
schema.AnyOf = make([]spec.Schema, len(orig.AnyOf))
|
||||
copy(schema.AnyOf, orig.AnyOf)
|
||||
}
|
||||
schema.AnyOf[i] = *s
|
||||
}
|
||||
}
|
||||
|
||||
oneOfCloned := false
|
||||
for i := range schema.OneOf {
|
||||
if s := w.WalkSchema(&schema.OneOf[i]); s != &schema.OneOf[i] {
|
||||
if !oneOfCloned {
|
||||
oneOfCloned = true
|
||||
clone()
|
||||
schema.OneOf = make([]spec.Schema, len(orig.OneOf))
|
||||
copy(schema.OneOf, orig.OneOf)
|
||||
}
|
||||
schema.OneOf[i] = *s
|
||||
}
|
||||
}
|
||||
|
||||
if schema.Not != nil {
|
||||
if s := w.WalkSchema(schema.Not); s != schema.Not {
|
||||
clone()
|
||||
schema.Not = s
|
||||
}
|
||||
}
|
||||
|
||||
if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
|
||||
if s := w.WalkSchema(schema.AdditionalProperties.Schema); s != schema.AdditionalProperties.Schema {
|
||||
clone()
|
||||
schema.AdditionalProperties = &spec.SchemaOrBool{Schema: s, Allows: schema.AdditionalProperties.Allows}
|
||||
}
|
||||
}
|
||||
|
||||
if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
|
||||
if s := w.WalkSchema(schema.AdditionalItems.Schema); s != schema.AdditionalItems.Schema {
|
||||
clone()
|
||||
schema.AdditionalItems = &spec.SchemaOrBool{Schema: s, Allows: schema.AdditionalItems.Allows}
|
||||
}
|
||||
}
|
||||
|
||||
if schema.Items != nil {
|
||||
if schema.Items.Schema != nil {
|
||||
if s := w.WalkSchema(schema.Items.Schema); s != schema.Items.Schema {
|
||||
clone()
|
||||
schema.Items = &spec.SchemaOrArray{Schema: s}
|
||||
}
|
||||
} else {
|
||||
itemsCloned := false
|
||||
for i := range schema.Items.Schemas {
|
||||
if s := w.WalkSchema(&schema.Items.Schemas[i]); s != &schema.Items.Schemas[i] {
|
||||
if !itemsCloned {
|
||||
clone()
|
||||
schema.Items = &spec.SchemaOrArray{
|
||||
Schemas: make([]spec.Schema, len(orig.Items.Schemas)),
|
||||
}
|
||||
itemsCloned = true
|
||||
copy(schema.Items.Schemas, orig.Items.Schemas)
|
||||
}
|
||||
schema.Items.Schemas[i] = *s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
func (w *Walker) walkParameter(param *spec.Parameter) *spec.Parameter {
|
||||
if param == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := param
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
param = &spec.Parameter{}
|
||||
*param = *orig
|
||||
}
|
||||
}
|
||||
|
||||
if r := w.RefCallback(¶m.Ref); r != ¶m.Ref {
|
||||
clone()
|
||||
param.Ref = *r
|
||||
}
|
||||
if s := w.WalkSchema(param.Schema); s != param.Schema {
|
||||
clone()
|
||||
param.Schema = s
|
||||
}
|
||||
if param.Items != nil {
|
||||
if r := w.RefCallback(¶m.Items.Ref); r != ¶m.Items.Ref {
|
||||
param.Items.Ref = *r
|
||||
}
|
||||
}
|
||||
|
||||
return param
|
||||
}
|
||||
|
||||
func (w *Walker) walkParameters(params []spec.Parameter) ([]spec.Parameter, bool) {
|
||||
if params == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
orig := params
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
params = make([]spec.Parameter, len(params))
|
||||
copy(params, orig)
|
||||
}
|
||||
}
|
||||
|
||||
for i := range params {
|
||||
if s := w.walkParameter(¶ms[i]); s != ¶ms[i] {
|
||||
clone()
|
||||
params[i] = *s
|
||||
}
|
||||
}
|
||||
|
||||
return params, cloned
|
||||
}
|
||||
|
||||
func (w *Walker) walkResponse(resp *spec.Response) *spec.Response {
|
||||
if resp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := resp
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
resp = &spec.Response{}
|
||||
*resp = *orig
|
||||
}
|
||||
}
|
||||
|
||||
if r := w.RefCallback(&resp.Ref); r != &resp.Ref {
|
||||
clone()
|
||||
resp.Ref = *r
|
||||
}
|
||||
if s := w.WalkSchema(resp.Schema); s != resp.Schema {
|
||||
clone()
|
||||
resp.Schema = s
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func (w *Walker) walkResponses(resps *spec.Responses) *spec.Responses {
|
||||
if resps == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := resps
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
resps = &spec.Responses{}
|
||||
*resps = *orig
|
||||
}
|
||||
}
|
||||
|
||||
if r := w.walkResponse(resps.ResponsesProps.Default); r != resps.ResponsesProps.Default {
|
||||
clone()
|
||||
resps.Default = r
|
||||
}
|
||||
|
||||
responsesCloned := false
|
||||
for k, v := range resps.ResponsesProps.StatusCodeResponses {
|
||||
if r := w.walkResponse(&v); r != &v {
|
||||
if !responsesCloned {
|
||||
responsesCloned = true
|
||||
clone()
|
||||
resps.ResponsesProps.StatusCodeResponses = make(map[int]spec.Response, len(orig.StatusCodeResponses))
|
||||
for k2, v2 := range orig.StatusCodeResponses {
|
||||
resps.ResponsesProps.StatusCodeResponses[k2] = v2
|
||||
}
|
||||
}
|
||||
resps.ResponsesProps.StatusCodeResponses[k] = *r
|
||||
}
|
||||
}
|
||||
|
||||
return resps
|
||||
}
|
||||
|
||||
func (w *Walker) walkOperation(op *spec.Operation) *spec.Operation {
|
||||
if op == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := op
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
op = &spec.Operation{}
|
||||
*op = *orig
|
||||
}
|
||||
}
|
||||
|
||||
parametersCloned := false
|
||||
for i := range op.Parameters {
|
||||
if s := w.walkParameter(&op.Parameters[i]); s != &op.Parameters[i] {
|
||||
if !parametersCloned {
|
||||
parametersCloned = true
|
||||
clone()
|
||||
op.Parameters = make([]spec.Parameter, len(orig.Parameters))
|
||||
copy(op.Parameters, orig.Parameters)
|
||||
}
|
||||
op.Parameters[i] = *s
|
||||
}
|
||||
}
|
||||
|
||||
if r := w.walkResponses(op.Responses); r != op.Responses {
|
||||
clone()
|
||||
op.Responses = r
|
||||
}
|
||||
|
||||
return op
|
||||
}
|
||||
|
||||
func (w *Walker) walkPathItem(pathItem *spec.PathItem) *spec.PathItem {
|
||||
if pathItem == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := pathItem
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
pathItem = &spec.PathItem{}
|
||||
*pathItem = *orig
|
||||
}
|
||||
}
|
||||
|
||||
if p, changed := w.walkParameters(pathItem.Parameters); changed {
|
||||
clone()
|
||||
pathItem.Parameters = p
|
||||
}
|
||||
if op := w.walkOperation(pathItem.Get); op != pathItem.Get {
|
||||
clone()
|
||||
pathItem.Get = op
|
||||
}
|
||||
if op := w.walkOperation(pathItem.Head); op != pathItem.Head {
|
||||
clone()
|
||||
pathItem.Head = op
|
||||
}
|
||||
if op := w.walkOperation(pathItem.Delete); op != pathItem.Delete {
|
||||
clone()
|
||||
pathItem.Delete = op
|
||||
}
|
||||
if op := w.walkOperation(pathItem.Options); op != pathItem.Options {
|
||||
clone()
|
||||
pathItem.Options = op
|
||||
}
|
||||
if op := w.walkOperation(pathItem.Patch); op != pathItem.Patch {
|
||||
clone()
|
||||
pathItem.Patch = op
|
||||
}
|
||||
if op := w.walkOperation(pathItem.Post); op != pathItem.Post {
|
||||
clone()
|
||||
pathItem.Post = op
|
||||
}
|
||||
if op := w.walkOperation(pathItem.Put); op != pathItem.Put {
|
||||
clone()
|
||||
pathItem.Put = op
|
||||
}
|
||||
|
||||
return pathItem
|
||||
}
|
||||
|
||||
func (w *Walker) walkPaths(paths *spec.Paths) *spec.Paths {
|
||||
if paths == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := paths
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
paths = &spec.Paths{}
|
||||
*paths = *orig
|
||||
}
|
||||
}
|
||||
|
||||
pathsCloned := false
|
||||
for k, v := range paths.Paths {
|
||||
if p := w.walkPathItem(&v); p != &v {
|
||||
if !pathsCloned {
|
||||
pathsCloned = true
|
||||
clone()
|
||||
paths.Paths = make(map[string]spec.PathItem, len(orig.Paths))
|
||||
for k2, v2 := range orig.Paths {
|
||||
paths.Paths[k2] = v2
|
||||
}
|
||||
}
|
||||
paths.Paths[k] = *p
|
||||
}
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
func (w *Walker) WalkRoot(swagger *spec.Swagger) *spec.Swagger {
|
||||
if swagger == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
orig := swagger
|
||||
cloned := false
|
||||
clone := func() {
|
||||
if !cloned {
|
||||
cloned = true
|
||||
swagger = &spec.Swagger{}
|
||||
*swagger = *orig
|
||||
}
|
||||
}
|
||||
|
||||
parametersCloned := false
|
||||
for k, v := range swagger.Parameters {
|
||||
if p := w.walkParameter(&v); p != &v {
|
||||
if !parametersCloned {
|
||||
parametersCloned = true
|
||||
clone()
|
||||
swagger.Parameters = make(map[string]spec.Parameter, len(orig.Parameters))
|
||||
for k2, v2 := range orig.Parameters {
|
||||
swagger.Parameters[k2] = v2
|
||||
}
|
||||
}
|
||||
swagger.Parameters[k] = *p
|
||||
}
|
||||
}
|
||||
|
||||
responsesCloned := false
|
||||
for k, v := range swagger.Responses {
|
||||
if r := w.walkResponse(&v); r != &v {
|
||||
if !responsesCloned {
|
||||
responsesCloned = true
|
||||
clone()
|
||||
swagger.Responses = make(map[string]spec.Response, len(orig.Responses))
|
||||
for k2, v2 := range orig.Responses {
|
||||
swagger.Responses[k2] = v2
|
||||
}
|
||||
}
|
||||
swagger.Responses[k] = *r
|
||||
}
|
||||
}
|
||||
|
||||
definitionsCloned := false
|
||||
for k, v := range swagger.Definitions {
|
||||
if s := w.WalkSchema(&v); s != &v {
|
||||
if !definitionsCloned {
|
||||
definitionsCloned = true
|
||||
clone()
|
||||
swagger.Definitions = make(spec.Definitions, len(orig.Definitions))
|
||||
for k2, v2 := range orig.Definitions {
|
||||
swagger.Definitions[k2] = v2
|
||||
}
|
||||
}
|
||||
swagger.Definitions[k] = *s
|
||||
}
|
||||
}
|
||||
|
||||
if swagger.Paths != nil {
|
||||
if p := w.walkPaths(swagger.Paths); p != swagger.Paths {
|
||||
clone()
|
||||
swagger.Paths = p
|
||||
}
|
||||
}
|
||||
|
||||
return swagger
|
||||
}
|
21
client/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go
generated
vendored
21
client/vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go
generated
vendored
@@ -32,6 +32,9 @@ type Encoding struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Encoding as JSON
|
||||
func (e *Encoding) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(e)
|
||||
}
|
||||
b1, err := json.Marshal(e.EncodingProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -43,6 +46,16 @@ func (e *Encoding) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (e *Encoding) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
EncodingProps encodingPropsOmitZero `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(e.Extensions)
|
||||
x.EncodingProps = encodingPropsOmitZero(e.EncodingProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (e *Encoding) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
@@ -82,3 +95,11 @@ type EncodingProps struct {
|
||||
// AllowReserved determines whether the parameter value SHOULD allow reserved characters, as defined by RFC3986
|
||||
AllowReserved bool `json:"allowReserved,omitempty"`
|
||||
}
|
||||
|
||||
type encodingPropsOmitZero struct {
|
||||
ContentType string `json:"contentType,omitempty"`
|
||||
Headers map[string]*Header `json:"headers,omitempty"`
|
||||
Style string `json:"style,omitempty"`
|
||||
Explode bool `json:"explode,omitzero"`
|
||||
AllowReserved bool `json:"allowReserved,omitzero"`
|
||||
}
|
||||
|
14
client/vendor/k8s.io/kube-openapi/pkg/spec3/example.go
generated
vendored
14
client/vendor/k8s.io/kube-openapi/pkg/spec3/example.go
generated
vendored
@@ -36,6 +36,9 @@ type Example struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode RequestBody as JSON
|
||||
func (e *Example) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(e)
|
||||
}
|
||||
b1, err := json.Marshal(e.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -50,6 +53,17 @@ func (e *Example) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
func (e *Example) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
ExampleProps `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Ref = e.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(e.Extensions)
|
||||
x.ExampleProps = e.ExampleProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (e *Example) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
|
13
client/vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go
generated
vendored
13
client/vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go
generated
vendored
@@ -39,6 +39,9 @@ type ExternalDocumentationProps struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Responses as JSON
|
||||
func (e *ExternalDocumentation) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(e)
|
||||
}
|
||||
b1, err := json.Marshal(e.ExternalDocumentationProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -50,6 +53,16 @@ func (e *ExternalDocumentation) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (e *ExternalDocumentation) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
ExternalDocumentationProps `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(e.Extensions)
|
||||
x.ExternalDocumentationProps = e.ExternalDocumentationProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (e *ExternalDocumentation) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
|
27
client/vendor/k8s.io/kube-openapi/pkg/spec3/fuzz.go
generated
vendored
27
client/vendor/k8s.io/kube-openapi/pkg/spec3/fuzz.go
generated
vendored
@@ -35,6 +35,18 @@ var OpenAPIV3FuzzFuncs []interface{} = []interface{}{
|
||||
func(o *OpenAPI, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(o)
|
||||
o.Version = "3.0.0"
|
||||
for i, val := range o.SecurityRequirement {
|
||||
if val == nil {
|
||||
o.SecurityRequirement[i] = make(map[string][]string)
|
||||
}
|
||||
|
||||
for k, v := range val {
|
||||
if v == nil {
|
||||
val[k] = make([]string, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
func(r *interface{}, c fuzz.Continue) {
|
||||
switch c.Intn(3) {
|
||||
@@ -169,6 +181,21 @@ var OpenAPIV3FuzzFuncs []interface{} = []interface{}{
|
||||
c.Fuzz(&v.ResponseProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
},
|
||||
func(v *Operation, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(v)
|
||||
// Do not fuzz null values into the array.
|
||||
for i, val := range v.SecurityRequirement {
|
||||
if val == nil {
|
||||
v.SecurityRequirement[i] = make(map[string][]string)
|
||||
}
|
||||
|
||||
for k, v := range val {
|
||||
if v == nil {
|
||||
val[k] = make([]string, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
func(v *spec.Extensions, c fuzz.Continue) {
|
||||
numChildren := c.Intn(5)
|
||||
for i := 0; i < numChildren; i++ {
|
||||
|
31
client/vendor/k8s.io/kube-openapi/pkg/spec3/header.go
generated
vendored
31
client/vendor/k8s.io/kube-openapi/pkg/spec3/header.go
generated
vendored
@@ -36,6 +36,9 @@ type Header struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Header as JSON
|
||||
func (h *Header) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(h)
|
||||
}
|
||||
b1, err := json.Marshal(h.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -51,6 +54,18 @@ func (h *Header) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (h *Header) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
HeaderProps headerPropsOmitZero `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Ref = h.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(h.Extensions)
|
||||
x.HeaderProps = headerPropsOmitZero(h.HeaderProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (h *Header) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, h)
|
||||
@@ -109,3 +124,19 @@ type HeaderProps struct {
|
||||
// Examples of the header
|
||||
Examples map[string]*Example `json:"examples,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type headerPropsOmitZero struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
Required bool `json:"required,omitzero"`
|
||||
Deprecated bool `json:"deprecated,omitzero"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitzero"`
|
||||
Style string `json:"style,omitempty"`
|
||||
Explode bool `json:"explode,omitzero"`
|
||||
AllowReserved bool `json:"allowReserved,omitzero"`
|
||||
Schema *spec.Schema `json:"schema,omitzero"`
|
||||
Content map[string]*MediaType `json:"content,omitempty"`
|
||||
Example interface{} `json:"example,omitempty"`
|
||||
Examples map[string]*Example `json:"examples,omitempty"`
|
||||
}
|
||||
|
20
client/vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go
generated
vendored
20
client/vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go
generated
vendored
@@ -35,6 +35,9 @@ type MediaType struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode MediaType as JSON
|
||||
func (m *MediaType) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(m)
|
||||
}
|
||||
b1, err := json.Marshal(m.MediaTypeProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -46,6 +49,16 @@ func (m *MediaType) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (e *MediaType) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
MediaTypeProps mediaTypePropsOmitZero `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(e.Extensions)
|
||||
x.MediaTypeProps = mediaTypePropsOmitZero(e.MediaTypeProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (m *MediaType) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, m)
|
||||
@@ -84,3 +97,10 @@ type MediaTypeProps struct {
|
||||
// A map between a property name and its encoding information. The key, being the property name, MUST exist in the schema as a property. The encoding object SHALL only apply to requestBody objects when the media type is multipart or application/x-www-form-urlencoded
|
||||
Encoding map[string]*Encoding `json:"encoding,omitempty"`
|
||||
}
|
||||
|
||||
type mediaTypePropsOmitZero struct {
|
||||
Schema *spec.Schema `json:"schema,omitzero"`
|
||||
Example interface{} `json:"example,omitempty"`
|
||||
Examples map[string]*Example `json:"examples,omitempty"`
|
||||
Encoding map[string]*Encoding `json:"encoding,omitempty"`
|
||||
}
|
||||
|
27
client/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go
generated
vendored
27
client/vendor/k8s.io/kube-openapi/pkg/spec3/operation.go
generated
vendored
@@ -35,6 +35,9 @@ type Operation struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Operation as JSON
|
||||
func (o *Operation) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(o)
|
||||
}
|
||||
b1, err := json.Marshal(o.OperationProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -46,6 +49,16 @@ func (o *Operation) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (o *Operation) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
OperationProps operationPropsOmitZero `json:",inline"`
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(o.Extensions)
|
||||
x.OperationProps = operationPropsOmitZero(o.OperationProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
func (o *Operation) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
@@ -95,3 +108,17 @@ type OperationProps struct {
|
||||
// Servers contains an alternative server array to service this operation
|
||||
Servers []*Server `json:"servers,omitempty"`
|
||||
}
|
||||
|
||||
type operationPropsOmitZero struct {
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Summary string `json:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitzero"`
|
||||
OperationId string `json:"operationId,omitempty"`
|
||||
Parameters []*Parameter `json:"parameters,omitempty"`
|
||||
RequestBody *RequestBody `json:"requestBody,omitzero"`
|
||||
Responses *Responses `json:"responses,omitzero"`
|
||||
Deprecated bool `json:"deprecated,omitzero"`
|
||||
SecurityRequirement []map[string][]string `json:"security,omitempty"`
|
||||
Servers []*Server `json:"servers,omitempty"`
|
||||
}
|
||||
|
31
client/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go
generated
vendored
31
client/vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go
generated
vendored
@@ -36,6 +36,9 @@ type Parameter struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Parameter as JSON
|
||||
func (p *Parameter) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(p)
|
||||
}
|
||||
b1, err := json.Marshal(p.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -51,6 +54,18 @@ func (p *Parameter) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (p *Parameter) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
ParameterProps parameterPropsOmitZero `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Ref = p.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(p.Extensions)
|
||||
x.ParameterProps = parameterPropsOmitZero(p.ParameterProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (p *Parameter) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
@@ -114,3 +129,19 @@ type ParameterProps struct {
|
||||
// Examples of the parameter's potential value. Each example SHOULD contain a value in the correct format as specified in the parameter encoding
|
||||
Examples map[string]*Example `json:"examples,omitempty"`
|
||||
}
|
||||
|
||||
type parameterPropsOmitZero struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
In string `json:"in,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Required bool `json:"required,omitzero"`
|
||||
Deprecated bool `json:"deprecated,omitzero"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitzero"`
|
||||
Style string `json:"style,omitempty"`
|
||||
Explode bool `json:"explode,omitzero"`
|
||||
AllowReserved bool `json:"allowReserved,omitzero"`
|
||||
Schema *spec.Schema `json:"schema,omitzero"`
|
||||
Content map[string]*MediaType `json:"content,omitempty"`
|
||||
Example interface{} `json:"example,omitempty"`
|
||||
Examples map[string]*Example `json:"examples,omitempty"`
|
||||
}
|
||||
|
47
client/vendor/k8s.io/kube-openapi/pkg/spec3/path.go
generated
vendored
47
client/vendor/k8s.io/kube-openapi/pkg/spec3/path.go
generated
vendored
@@ -35,15 +35,41 @@ type Paths struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Paths as JSON
|
||||
func (p *Paths) MarshalJSON() ([]byte, error) {
|
||||
b1, err := json.Marshal(p.Paths)
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(p)
|
||||
}
|
||||
b1, err := json.Marshal(p.VendorExtensible)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b2, err := json.Marshal(p.VendorExtensible)
|
||||
|
||||
pths := make(map[string]*Path)
|
||||
for k, v := range p.Paths {
|
||||
if strings.HasPrefix(k, "/") {
|
||||
pths[k] = v
|
||||
}
|
||||
}
|
||||
b2, err := json.Marshal(pths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
concated := swag.ConcatJSON(b1, b2)
|
||||
return concated, nil
|
||||
}
|
||||
|
||||
func (p *Paths) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
m := make(map[string]any, len(p.Extensions)+len(p.Paths))
|
||||
for k, v := range p.Extensions {
|
||||
if internal.IsExtensionKey(k) {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
for k, v := range p.Paths {
|
||||
if strings.HasPrefix(k, "/") {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
return opts.MarshalNext(enc, m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
@@ -144,6 +170,9 @@ type Path struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Path as JSON
|
||||
func (p *Path) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(p)
|
||||
}
|
||||
b1, err := json.Marshal(p.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -159,6 +188,18 @@ func (p *Path) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (p *Path) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
spec.Extensions
|
||||
PathProps
|
||||
}
|
||||
x.Ref = p.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(p.Extensions)
|
||||
x.PathProps = p.PathProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (p *Path) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
|
21
client/vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go
generated
vendored
21
client/vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go
generated
vendored
@@ -36,6 +36,9 @@ type RequestBody struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode RequestBody as JSON
|
||||
func (r *RequestBody) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(r)
|
||||
}
|
||||
b1, err := json.Marshal(r.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -51,6 +54,18 @@ func (r *RequestBody) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (r *RequestBody) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
RequestBodyProps requestBodyPropsOmitZero `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Ref = r.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(r.Extensions)
|
||||
x.RequestBodyProps = requestBodyPropsOmitZero(r.RequestBodyProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (r *RequestBody) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
@@ -77,6 +92,12 @@ type RequestBodyProps struct {
|
||||
Required bool `json:"required,omitempty"`
|
||||
}
|
||||
|
||||
type requestBodyPropsOmitZero struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
Content map[string]*MediaType `json:"content,omitempty"`
|
||||
Required bool `json:"required,omitzero"`
|
||||
}
|
||||
|
||||
func (r *RequestBody) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
|
52
client/vendor/k8s.io/kube-openapi/pkg/spec3/response.go
generated
vendored
52
client/vendor/k8s.io/kube-openapi/pkg/spec3/response.go
generated
vendored
@@ -37,6 +37,9 @@ type Responses struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Responses as JSON
|
||||
func (r *Responses) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(r)
|
||||
}
|
||||
b1, err := json.Marshal(r.ResponsesProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -48,6 +51,25 @@ func (r *Responses) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (r Responses) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
type ArbitraryKeys map[string]interface{}
|
||||
var x struct {
|
||||
ArbitraryKeys
|
||||
Default *Response `json:"default,omitzero"`
|
||||
}
|
||||
x.ArbitraryKeys = make(map[string]any, len(r.Extensions)+len(r.StatusCodeResponses))
|
||||
for k, v := range r.Extensions {
|
||||
if internal.IsExtensionKey(k) {
|
||||
x.ArbitraryKeys[k] = v
|
||||
}
|
||||
}
|
||||
for k, v := range r.StatusCodeResponses {
|
||||
x.ArbitraryKeys[strconv.Itoa(k)] = v
|
||||
}
|
||||
x.Default = r.Default
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (r *Responses) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
@@ -179,6 +201,9 @@ type Response struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Response as JSON
|
||||
func (r *Response) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(r)
|
||||
}
|
||||
b1, err := json.Marshal(r.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -194,6 +219,18 @@ func (r *Response) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (r Response) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
spec.Extensions
|
||||
ResponseProps `json:",inline"`
|
||||
}
|
||||
x.Ref = r.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(r.Extensions)
|
||||
x.ResponseProps = r.ResponseProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (r *Response) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
@@ -247,6 +284,9 @@ type Link struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Link as JSON
|
||||
func (r *Link) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(r)
|
||||
}
|
||||
b1, err := json.Marshal(r.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -262,6 +302,18 @@ func (r *Link) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (r *Link) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
spec.Extensions
|
||||
LinkProps `json:",inline"`
|
||||
}
|
||||
x.Ref = r.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(r.Extensions)
|
||||
x.LinkProps = r.LinkProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (r *Link) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
|
17
client/vendor/k8s.io/kube-openapi/pkg/spec3/security_scheme.go
generated
vendored
17
client/vendor/k8s.io/kube-openapi/pkg/spec3/security_scheme.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"
|
||||
)
|
||||
|
||||
@@ -32,6 +34,9 @@ type SecurityScheme struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode SecurityScheme as JSON
|
||||
func (s *SecurityScheme) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
b1, err := json.Marshal(s.SecuritySchemeProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -47,6 +52,18 @@ func (s *SecurityScheme) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (s *SecurityScheme) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
SecuritySchemeProps `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Ref = s.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(s.Extensions)
|
||||
x.SecuritySchemeProps = s.SecuritySchemeProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
func (s *SecurityScheme) UnmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, &s.SecuritySchemeProps); err != nil {
|
||||
|
26
client/vendor/k8s.io/kube-openapi/pkg/spec3/server.go
generated
vendored
26
client/vendor/k8s.io/kube-openapi/pkg/spec3/server.go
generated
vendored
@@ -41,6 +41,9 @@ type ServerProps struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Responses as JSON
|
||||
func (s *Server) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
b1, err := json.Marshal(s.ServerProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -52,6 +55,16 @@ func (s *Server) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (s *Server) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
ServerProps `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(s.Extensions)
|
||||
x.ServerProps = s.ServerProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (s *Server) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, s)
|
||||
@@ -96,6 +109,9 @@ type ServerVariableProps struct {
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode Responses as JSON
|
||||
func (s *ServerVariable) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
b1, err := json.Marshal(s.ServerVariableProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -107,6 +123,16 @@ func (s *ServerVariable) MarshalJSON() ([]byte, error) {
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (s *ServerVariable) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
ServerVariableProps `json:",inline"`
|
||||
spec.Extensions
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(s.Extensions)
|
||||
x.ServerVariableProps = s.ServerVariableProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
func (s *ServerVariable) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, s)
|
||||
|
25
client/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go
generated
vendored
25
client/vendor/k8s.io/kube-openapi/pkg/spec3/spec.go
generated
vendored
@@ -36,6 +36,8 @@ type OpenAPI struct {
|
||||
Servers []*Server `json:"servers,omitempty"`
|
||||
// Components hold various schemas for the specification
|
||||
Components *Components `json:"components,omitempty"`
|
||||
// SecurityRequirement holds a declaration of which security mechanisms can be used across the API
|
||||
SecurityRequirement []map[string][]string `json:"security,omitempty"`
|
||||
// ExternalDocs holds additional external documentation
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
|
||||
}
|
||||
@@ -48,3 +50,26 @@ func (o *OpenAPI) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
return json.Unmarshal(data, &p)
|
||||
}
|
||||
|
||||
func (o *OpenAPI) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshalingV3 {
|
||||
return internal.DeterministicMarshal(o)
|
||||
}
|
||||
type OpenAPIWithNoFunctions OpenAPI
|
||||
p := (*OpenAPIWithNoFunctions)(o)
|
||||
return json.Marshal(&p)
|
||||
}
|
||||
|
||||
func (o *OpenAPI) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
type OpenAPIOmitZero struct {
|
||||
Version string `json:"openapi"`
|
||||
Info *spec.Info `json:"info"`
|
||||
Paths *Paths `json:"paths,omitzero"`
|
||||
Servers []*Server `json:"servers,omitempty"`
|
||||
Components *Components `json:"components,omitzero"`
|
||||
SecurityRequirement []map[string][]string `json:"security,omitempty"`
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitzero"`
|
||||
}
|
||||
x := (*OpenAPIOmitZero)(o)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
502
client/vendor/k8s.io/kube-openapi/pkg/validation/spec/fuzz.go
generated
vendored
502
client/vendor/k8s.io/kube-openapi/pkg/validation/spec/fuzz.go
generated
vendored
@@ -1,502 +0,0 @@
|
||||
/*
|
||||
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 spec
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/jsonreference"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
fuzz "github.com/google/gofuzz"
|
||||
)
|
||||
|
||||
var SwaggerFuzzFuncs []interface{} = []interface{}{
|
||||
func(v *Responses, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(v)
|
||||
if v.Default != nil {
|
||||
// Check if we hit maxDepth and left an incomplete value
|
||||
if v.Default.Description == "" {
|
||||
v.Default = nil
|
||||
v.StatusCodeResponses = nil
|
||||
}
|
||||
}
|
||||
|
||||
// conversion has no way to discern empty statusCodeResponses from
|
||||
// nil, since "default" is always included in the map.
|
||||
// So avoid empty responses list
|
||||
if len(v.StatusCodeResponses) == 0 {
|
||||
v.StatusCodeResponses = nil
|
||||
}
|
||||
},
|
||||
func(v *Operation, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(v)
|
||||
|
||||
if v != nil {
|
||||
// force non-nil
|
||||
v.Responses = &Responses{}
|
||||
c.Fuzz(v.Responses)
|
||||
|
||||
v.Schemes = nil
|
||||
if c.RandBool() {
|
||||
v.Schemes = append(v.Schemes, "http")
|
||||
}
|
||||
|
||||
if c.RandBool() {
|
||||
v.Schemes = append(v.Schemes, "https")
|
||||
}
|
||||
|
||||
if c.RandBool() {
|
||||
v.Schemes = append(v.Schemes, "ws")
|
||||
}
|
||||
|
||||
if c.RandBool() {
|
||||
v.Schemes = append(v.Schemes, "wss")
|
||||
}
|
||||
|
||||
// Gnostic unconditionally makes security values non-null
|
||||
// So do not fuzz null values into the array.
|
||||
for i, val := range v.Security {
|
||||
if val == nil {
|
||||
v.Security[i] = make(map[string][]string)
|
||||
}
|
||||
|
||||
for k, v := range val {
|
||||
if v == nil {
|
||||
val[k] = make([]string, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
func(v map[int]Response, c fuzz.Continue) {
|
||||
n := 0
|
||||
c.Fuzz(&n)
|
||||
if n == 0 {
|
||||
// Test that fuzzer is not at maxDepth so we do not
|
||||
// end up with empty elements
|
||||
return
|
||||
}
|
||||
|
||||
// Prevent negative numbers
|
||||
num := c.Intn(4)
|
||||
for i := 0; i < num+2; i++ {
|
||||
val := Response{}
|
||||
c.Fuzz(&val)
|
||||
|
||||
val.Description = c.RandString() + "x"
|
||||
v[100*(i+1)+c.Intn(100)] = val
|
||||
}
|
||||
},
|
||||
func(v map[string]PathItem, c fuzz.Continue) {
|
||||
n := 0
|
||||
c.Fuzz(&n)
|
||||
if n == 0 {
|
||||
// Test that fuzzer is not at maxDepth so we do not
|
||||
// end up with empty elements
|
||||
return
|
||||
}
|
||||
|
||||
num := c.Intn(5)
|
||||
for i := 0; i < num+2; i++ {
|
||||
val := PathItem{}
|
||||
c.Fuzz(&val)
|
||||
|
||||
// Ref params are only allowed in certain locations, so
|
||||
// possibly add a few to PathItems
|
||||
numRefsToAdd := c.Intn(5)
|
||||
for i := 0; i < numRefsToAdd; i++ {
|
||||
theRef := Parameter{}
|
||||
c.Fuzz(&theRef.Refable)
|
||||
|
||||
val.Parameters = append(val.Parameters, theRef)
|
||||
}
|
||||
|
||||
v["/"+c.RandString()] = val
|
||||
}
|
||||
},
|
||||
func(v *SchemaOrArray, c fuzz.Continue) {
|
||||
*v = SchemaOrArray{}
|
||||
// gnostic parser just doesn't support more
|
||||
// than one Schema here
|
||||
v.Schema = &Schema{}
|
||||
c.Fuzz(&v.Schema)
|
||||
|
||||
},
|
||||
func(v *SchemaOrBool, c fuzz.Continue) {
|
||||
*v = SchemaOrBool{}
|
||||
|
||||
if c.RandBool() {
|
||||
v.Allows = c.RandBool()
|
||||
} else {
|
||||
v.Schema = &Schema{}
|
||||
v.Allows = true
|
||||
c.Fuzz(&v.Schema)
|
||||
}
|
||||
},
|
||||
func(v map[string]Response, c fuzz.Continue) {
|
||||
n := 0
|
||||
c.Fuzz(&n)
|
||||
if n == 0 {
|
||||
// Test that fuzzer is not at maxDepth so we do not
|
||||
// end up with empty elements
|
||||
return
|
||||
}
|
||||
|
||||
// Response definitions are not allowed to
|
||||
// be refs
|
||||
for i := 0; i < c.Intn(5)+1; i++ {
|
||||
resp := &Response{}
|
||||
|
||||
c.Fuzz(resp)
|
||||
resp.Ref = Ref{}
|
||||
resp.Description = c.RandString() + "x"
|
||||
|
||||
// Response refs are not vendor extensible by gnostic
|
||||
resp.VendorExtensible.Extensions = nil
|
||||
v[c.RandString()+"x"] = *resp
|
||||
}
|
||||
},
|
||||
func(v *Header, c fuzz.Continue) {
|
||||
if v != nil {
|
||||
c.FuzzNoCustom(v)
|
||||
|
||||
// descendant Items of Header may not be refs
|
||||
cur := v.Items
|
||||
for cur != nil {
|
||||
cur.Ref = Ref{}
|
||||
cur = cur.Items
|
||||
}
|
||||
}
|
||||
},
|
||||
func(v *Ref, c fuzz.Continue) {
|
||||
*v = Ref{}
|
||||
v.Ref, _ = jsonreference.New("http://asd.com/" + c.RandString())
|
||||
},
|
||||
func(v *Response, c fuzz.Continue) {
|
||||
*v = Response{}
|
||||
if c.RandBool() {
|
||||
v.Ref = Ref{}
|
||||
v.Ref.Ref, _ = jsonreference.New("http://asd.com/" + c.RandString())
|
||||
} else {
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
c.Fuzz(&v.Schema)
|
||||
c.Fuzz(&v.ResponseProps)
|
||||
|
||||
v.Headers = nil
|
||||
v.Ref = Ref{}
|
||||
|
||||
n := 0
|
||||
c.Fuzz(&n)
|
||||
if n != 0 {
|
||||
// Test that fuzzer is not at maxDepth so we do not
|
||||
// end up with empty elements
|
||||
num := c.Intn(4)
|
||||
for i := 0; i < num; i++ {
|
||||
if v.Headers == nil {
|
||||
v.Headers = make(map[string]Header)
|
||||
}
|
||||
hdr := Header{}
|
||||
c.Fuzz(&hdr)
|
||||
if hdr.Type == "" {
|
||||
// hit maxDepth, just abort trying to make haders
|
||||
v.Headers = nil
|
||||
break
|
||||
}
|
||||
v.Headers[c.RandString()+"x"] = hdr
|
||||
}
|
||||
} else {
|
||||
v.Headers = nil
|
||||
}
|
||||
}
|
||||
|
||||
v.Description = c.RandString() + "x"
|
||||
|
||||
// Gnostic parses empty as nil, so to keep avoid putting empty
|
||||
if len(v.Headers) == 0 {
|
||||
v.Headers = nil
|
||||
}
|
||||
},
|
||||
func(v **Info, c fuzz.Continue) {
|
||||
// Info is never nil
|
||||
*v = &Info{}
|
||||
c.FuzzNoCustom(*v)
|
||||
|
||||
(*v).Title = c.RandString() + "x"
|
||||
},
|
||||
func(v *Extensions, c fuzz.Continue) {
|
||||
// gnostic parser only picks up x- vendor extensions
|
||||
numChildren := c.Intn(5)
|
||||
for i := 0; i < numChildren; i++ {
|
||||
if *v == nil {
|
||||
*v = Extensions{}
|
||||
}
|
||||
(*v)["x-"+c.RandString()] = c.RandString()
|
||||
}
|
||||
},
|
||||
func(v *Swagger, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(v)
|
||||
|
||||
if v.Paths == nil {
|
||||
// Force paths non-nil since it does not have omitempty in json tag.
|
||||
// This means a perfect roundtrip (via json) is impossible,
|
||||
// since we can't tell the difference between empty/unspecified paths
|
||||
v.Paths = &Paths{}
|
||||
c.Fuzz(v.Paths)
|
||||
}
|
||||
|
||||
v.Swagger = "2.0"
|
||||
|
||||
// Gnostic support serializing ID at all
|
||||
// unavoidable data loss
|
||||
v.ID = ""
|
||||
|
||||
v.Schemes = nil
|
||||
if c.RandUint64()%2 == 1 {
|
||||
v.Schemes = append(v.Schemes, "http")
|
||||
}
|
||||
|
||||
if c.RandUint64()%2 == 1 {
|
||||
v.Schemes = append(v.Schemes, "https")
|
||||
}
|
||||
|
||||
if c.RandUint64()%2 == 1 {
|
||||
v.Schemes = append(v.Schemes, "ws")
|
||||
}
|
||||
|
||||
if c.RandUint64()%2 == 1 {
|
||||
v.Schemes = append(v.Schemes, "wss")
|
||||
}
|
||||
|
||||
// Gnostic unconditionally makes security values non-null
|
||||
// So do not fuzz null values into the array.
|
||||
for i, val := range v.Security {
|
||||
if val == nil {
|
||||
v.Security[i] = make(map[string][]string)
|
||||
}
|
||||
|
||||
for k, v := range val {
|
||||
if v == nil {
|
||||
val[k] = make([]string, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
func(v *SecurityScheme, c fuzz.Continue) {
|
||||
v.Description = c.RandString() + "x"
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
|
||||
switch c.Intn(3) {
|
||||
case 0:
|
||||
v.Type = "basic"
|
||||
case 1:
|
||||
v.Type = "apiKey"
|
||||
switch c.Intn(2) {
|
||||
case 0:
|
||||
v.In = "header"
|
||||
case 1:
|
||||
v.In = "query"
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
v.Name = "x" + c.RandString()
|
||||
case 2:
|
||||
v.Type = "oauth2"
|
||||
|
||||
switch c.Intn(4) {
|
||||
case 0:
|
||||
v.Flow = "accessCode"
|
||||
v.TokenURL = "https://" + c.RandString()
|
||||
v.AuthorizationURL = "https://" + c.RandString()
|
||||
case 1:
|
||||
v.Flow = "application"
|
||||
v.TokenURL = "https://" + c.RandString()
|
||||
case 2:
|
||||
v.Flow = "implicit"
|
||||
v.AuthorizationURL = "https://" + c.RandString()
|
||||
case 3:
|
||||
v.Flow = "password"
|
||||
v.TokenURL = "https://" + c.RandString()
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
c.Fuzz(&v.Scopes)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
},
|
||||
func(v *interface{}, c fuzz.Continue) {
|
||||
*v = c.RandString() + "x"
|
||||
},
|
||||
func(v *string, c fuzz.Continue) {
|
||||
*v = c.RandString() + "x"
|
||||
},
|
||||
func(v *ExternalDocumentation, c fuzz.Continue) {
|
||||
v.Description = c.RandString() + "x"
|
||||
v.URL = c.RandString() + "x"
|
||||
},
|
||||
func(v *SimpleSchema, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(v)
|
||||
|
||||
switch c.Intn(5) {
|
||||
case 0:
|
||||
v.Type = "string"
|
||||
case 1:
|
||||
v.Type = "number"
|
||||
case 2:
|
||||
v.Type = "boolean"
|
||||
case 3:
|
||||
v.Type = "integer"
|
||||
case 4:
|
||||
v.Type = "array"
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
switch c.Intn(5) {
|
||||
case 0:
|
||||
v.CollectionFormat = "csv"
|
||||
case 1:
|
||||
v.CollectionFormat = "ssv"
|
||||
case 2:
|
||||
v.CollectionFormat = "tsv"
|
||||
case 3:
|
||||
v.CollectionFormat = "pipes"
|
||||
case 4:
|
||||
v.CollectionFormat = ""
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// None of the types which include SimpleSchema in our definitions
|
||||
// actually support "example" in the official spec
|
||||
v.Example = nil
|
||||
|
||||
// unsupported by openapi
|
||||
v.Nullable = false
|
||||
},
|
||||
func(v *int64, c fuzz.Continue) {
|
||||
c.Fuzz(v)
|
||||
|
||||
// Gnostic does not differentiate between 0 and non-specified
|
||||
// so avoid using 0 for fuzzer
|
||||
if *v == 0 {
|
||||
*v = 1
|
||||
}
|
||||
},
|
||||
func(v *float64, c fuzz.Continue) {
|
||||
c.Fuzz(v)
|
||||
|
||||
// Gnostic does not differentiate between 0 and non-specified
|
||||
// so avoid using 0 for fuzzer
|
||||
if *v == 0.0 {
|
||||
*v = 1.0
|
||||
}
|
||||
},
|
||||
func(v *Parameter, c fuzz.Continue) {
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
if c.RandBool() {
|
||||
// body param
|
||||
v.Description = c.RandString() + "x"
|
||||
v.Name = c.RandString() + "x"
|
||||
v.In = "body"
|
||||
c.Fuzz(&v.Description)
|
||||
c.Fuzz(&v.Required)
|
||||
|
||||
v.Schema = &Schema{}
|
||||
c.Fuzz(&v.Schema)
|
||||
|
||||
} else {
|
||||
c.Fuzz(&v.SimpleSchema)
|
||||
c.Fuzz(&v.CommonValidations)
|
||||
v.AllowEmptyValue = false
|
||||
v.Description = c.RandString() + "x"
|
||||
v.Name = c.RandString() + "x"
|
||||
|
||||
switch c.Intn(4) {
|
||||
case 0:
|
||||
// Header param
|
||||
v.In = "header"
|
||||
case 1:
|
||||
// Form data param
|
||||
v.In = "formData"
|
||||
v.AllowEmptyValue = c.RandBool()
|
||||
case 2:
|
||||
// Query param
|
||||
v.In = "query"
|
||||
v.AllowEmptyValue = c.RandBool()
|
||||
case 3:
|
||||
// Path param
|
||||
v.In = "path"
|
||||
v.Required = true
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// descendant Items of Parameter may not be refs
|
||||
cur := v.Items
|
||||
for cur != nil {
|
||||
cur.Ref = Ref{}
|
||||
cur = cur.Items
|
||||
}
|
||||
}
|
||||
},
|
||||
func(v *Schema, c fuzz.Continue) {
|
||||
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 = StringOrArray{"file"}
|
||||
|
||||
} else {
|
||||
// normal schema
|
||||
c.Fuzz(&v.SchemaProps)
|
||||
c.Fuzz(&v.SwaggerSchemaProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
// c.Fuzz(&v.ExtraProps)
|
||||
// ExtraProps will not roundtrip - gnostic throws out
|
||||
// unrecognized keys
|
||||
}
|
||||
|
||||
// Not supported by official openapi v2 spec
|
||||
// and stripped by k8s apiserver
|
||||
v.ID = ""
|
||||
v.AnyOf = nil
|
||||
v.OneOf = nil
|
||||
v.Not = nil
|
||||
v.Nullable = false
|
||||
v.AdditionalItems = nil
|
||||
v.Schema = ""
|
||||
v.PatternProperties = nil
|
||||
v.Definitions = nil
|
||||
v.Dependencies = nil
|
||||
},
|
||||
}
|
||||
|
||||
var SwaggerDiffOptions = []cmp.Option{
|
||||
// cmp.Diff panics on Ref since jsonreference.Ref uses unexported fields
|
||||
cmp.Comparer(func(a Ref, b Ref) bool {
|
||||
return a.String() == b.String()
|
||||
}),
|
||||
}
|
Reference in New Issue
Block a user