mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
rebase: bump the golang-dependencies group with 1 update
Bumps the golang-dependencies group with 1 update: [golang.org/x/crypto](https://github.com/golang/crypto). Updates `golang.org/x/crypto` from 0.16.0 to 0.17.0 - [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-dependencies ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
mergify[bot]
parent
1ad79314f9
commit
e5d9b68d36
14
vendor/k8s.io/kube-openapi/pkg/builder3/openapi.go
generated
vendored
14
vendor/k8s.io/kube-openapi/pkg/builder3/openapi.go
generated
vendored
@ -156,7 +156,9 @@ func (o *openAPI) buildRequestBody(parameters []common.Parameter, consumes []str
|
||||
}
|
||||
r := &spec3.RequestBody{
|
||||
RequestBodyProps: spec3.RequestBodyProps{
|
||||
Content: map[string]*spec3.MediaType{},
|
||||
Content: map[string]*spec3.MediaType{},
|
||||
Description: param.Description(),
|
||||
Required: param.Required(),
|
||||
},
|
||||
}
|
||||
for _, consume := range consumes {
|
||||
@ -172,9 +174,9 @@ func (o *openAPI) buildRequestBody(parameters []common.Parameter, consumes []str
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func newOpenAPI(config *common.Config) openAPI {
|
||||
func newOpenAPI(config *common.OpenAPIV3Config) openAPI {
|
||||
o := openAPI{
|
||||
config: common.ConvertConfigToV3(config),
|
||||
config: config,
|
||||
spec: &spec3.OpenAPI{
|
||||
Version: "3.0.0",
|
||||
Info: config.Info,
|
||||
@ -313,12 +315,12 @@ func (o *openAPI) buildOpenAPISpec(webServices []common.RouteContainer) error {
|
||||
// BuildOpenAPISpec builds OpenAPI v3 spec given a list of route containers and common.Config to customize it.
|
||||
//
|
||||
// Deprecated: BuildOpenAPISpecFromRoutes should be used instead.
|
||||
func BuildOpenAPISpec(webServices []*restful.WebService, config *common.Config) (*spec3.OpenAPI, error) {
|
||||
func BuildOpenAPISpec(webServices []*restful.WebService, config *common.OpenAPIV3Config) (*spec3.OpenAPI, error) {
|
||||
return BuildOpenAPISpecFromRoutes(restfuladapter.AdaptWebServices(webServices), config)
|
||||
}
|
||||
|
||||
// BuildOpenAPISpecFromRoutes builds OpenAPI v3 spec given a list of route containers and common.Config to customize it.
|
||||
func BuildOpenAPISpecFromRoutes(webServices []common.RouteContainer, config *common.Config) (*spec3.OpenAPI, error) {
|
||||
func BuildOpenAPISpecFromRoutes(webServices []common.RouteContainer, config *common.OpenAPIV3Config) (*spec3.OpenAPI, error) {
|
||||
a := newOpenAPI(config)
|
||||
err := a.buildOpenAPISpec(webServices)
|
||||
if err != nil {
|
||||
@ -330,7 +332,7 @@ func BuildOpenAPISpecFromRoutes(webServices []common.RouteContainer, config *com
|
||||
// BuildOpenAPIDefinitionsForResource builds a partial OpenAPI spec given a sample object and common.Config to customize it.
|
||||
// BuildOpenAPIDefinitionsForResources returns the OpenAPI spec which includes the definitions for the
|
||||
// passed type names.
|
||||
func BuildOpenAPIDefinitionsForResources(config *common.Config, names ...string) (map[string]*spec.Schema, error) {
|
||||
func BuildOpenAPIDefinitionsForResources(config *common.OpenAPIV3Config, names ...string) (map[string]*spec.Schema, error) {
|
||||
o := newOpenAPI(config)
|
||||
// We can discard the return value of toSchema because all we care about is the side effect of calling it.
|
||||
// All the models created for this resource get added to o.swagger.Definitions
|
||||
|
266
vendor/k8s.io/kube-openapi/pkg/cached/cache.go
generated
vendored
266
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
vendor/k8s.io/kube-openapi/pkg/common/common.go
generated
vendored
38
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
|
||||
|
59
vendor/k8s.io/kube-openapi/pkg/handler/handler.go
generated
vendored
59
vendor/k8s.io/kube-openapi/pkg/handler/handler.go
generated
vendored
@ -30,6 +30,7 @@ import (
|
||||
openapi_v2 "github.com/google/gnostic-models/openapiv2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/munnerz/goautoneg"
|
||||
|
||||
klog "k8s.io/klog/v2"
|
||||
"k8s.io/kube-openapi/pkg/builder"
|
||||
"k8s.io/kube-openapi/pkg/cached"
|
||||
@ -59,52 +60,52 @@ type timedSpec struct {
|
||||
// OpenAPIService is the service responsible for serving OpenAPI spec. It has
|
||||
// the ability to safely change the spec while serving it.
|
||||
type OpenAPIService struct {
|
||||
specCache cached.Replaceable[*spec.Swagger]
|
||||
jsonCache cached.Data[timedSpec]
|
||||
protoCache cached.Data[timedSpec]
|
||||
specCache cached.LastSuccess[*spec.Swagger]
|
||||
jsonCache cached.Value[timedSpec]
|
||||
protoCache cached.Value[timedSpec]
|
||||
}
|
||||
|
||||
// NewOpenAPIService builds an OpenAPIService starting with the given spec.
|
||||
func NewOpenAPIService(swagger *spec.Swagger) *OpenAPIService {
|
||||
return NewOpenAPIServiceLazy(cached.NewResultOK(swagger, uuid.New().String()))
|
||||
return NewOpenAPIServiceLazy(cached.Static(swagger, uuid.New().String()))
|
||||
}
|
||||
|
||||
// NewOpenAPIServiceLazy builds an OpenAPIService from lazy spec.
|
||||
func NewOpenAPIServiceLazy(swagger cached.Data[*spec.Swagger]) *OpenAPIService {
|
||||
func NewOpenAPIServiceLazy(swagger cached.Value[*spec.Swagger]) *OpenAPIService {
|
||||
o := &OpenAPIService{}
|
||||
o.UpdateSpecLazy(swagger)
|
||||
|
||||
o.jsonCache = cached.NewTransformer[*spec.Swagger](func(result cached.Result[*spec.Swagger]) cached.Result[timedSpec] {
|
||||
if result.Err != nil {
|
||||
return cached.NewResultErr[timedSpec](result.Err)
|
||||
}
|
||||
json, err := result.Data.MarshalJSON()
|
||||
o.jsonCache = cached.Transform[*spec.Swagger](func(spec *spec.Swagger, 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 := spec.MarshalJSON()
|
||||
if err != nil {
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
return timedSpec{spec: json, lastModified: time.Now()}, computeETag(json), nil
|
||||
}, &o.specCache)
|
||||
o.protoCache = cached.NewTransformer(func(result cached.Result[timedSpec]) cached.Result[timedSpec] {
|
||||
if result.Err != nil {
|
||||
return cached.NewResultErr[timedSpec](result.Err)
|
||||
}
|
||||
proto, err := ToProtoBinary(result.Data.spec)
|
||||
o.protoCache = cached.Transform(func(ts timedSpec, etag string, err error) (timedSpec, string, error) {
|
||||
if err != nil {
|
||||
return cached.NewResultErr[timedSpec](err)
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
proto, err := ToProtoBinary(ts.spec)
|
||||
if err != nil {
|
||||
return timedSpec{}, "", err
|
||||
}
|
||||
// We can re-use the same etag as json because of the Vary header.
|
||||
return cached.NewResultOK(timedSpec{spec: proto, lastModified: result.Data.lastModified}, result.Etag)
|
||||
return timedSpec{spec: proto, lastModified: ts.lastModified}, etag, nil
|
||||
}, o.jsonCache)
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) UpdateSpec(swagger *spec.Swagger) error {
|
||||
o.UpdateSpecLazy(cached.NewResultOK(swagger, uuid.New().String()))
|
||||
o.UpdateSpecLazy(cached.Static(swagger, uuid.New().String()))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OpenAPIService) UpdateSpecLazy(swagger cached.Data[*spec.Swagger]) {
|
||||
o.specCache.Replace(swagger)
|
||||
func (o *OpenAPIService) UpdateSpecLazy(swagger cached.Value[*spec.Swagger]) {
|
||||
o.specCache.Store(swagger)
|
||||
}
|
||||
|
||||
func ToProtoBinary(json []byte) ([]byte, error) {
|
||||
@ -130,7 +131,7 @@ func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handl
|
||||
Type string
|
||||
SubType string
|
||||
ReturnedContentType string
|
||||
GetDataAndEtag cached.Data[timedSpec]
|
||||
GetDataAndEtag cached.Value[timedSpec]
|
||||
}{
|
||||
{"application", subTypeJSON, "application/" + subTypeJSON, o.jsonCache},
|
||||
{"application", subTypeProtobufDeprecated, "application/" + subTypeProtobuf, o.protoCache},
|
||||
@ -154,11 +155,11 @@ func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handl
|
||||
continue
|
||||
}
|
||||
// serve the first matching media type in the sorted clause list
|
||||
result := accepts.GetDataAndEtag.Get()
|
||||
if result.Err != nil {
|
||||
klog.Errorf("Error in OpenAPI handler: %s", result.Err)
|
||||
ts, etag, err := accepts.GetDataAndEtag.Get()
|
||||
if err != nil {
|
||||
klog.Errorf("Error in OpenAPI handler: %s", err)
|
||||
// only return a 503 if we have no older cache data to serve
|
||||
if result.Data.spec == nil {
|
||||
if ts.spec == nil {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
@ -167,9 +168,9 @@ func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handl
|
||||
w.Header().Set("Content-Type", accepts.ReturnedContentType)
|
||||
|
||||
// ETag must be enclosed in double quotes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
||||
w.Header().Set("Etag", strconv.Quote(result.Etag))
|
||||
w.Header().Set("Etag", strconv.Quote(etag))
|
||||
// ServeContent will take care of caching using eTag.
|
||||
http.ServeContent(w, r, servePath, result.Data.lastModified, bytes.NewReader(result.Data.spec))
|
||||
http.ServeContent(w, r, servePath, ts.lastModified, bytes.NewReader(ts.spec))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
81
vendor/k8s.io/kube-openapi/pkg/handler3/handler.go
generated
vendored
81
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
vendor/k8s.io/kube-openapi/pkg/internal/flags.go
generated
vendored
1
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
vendor/k8s.io/kube-openapi/pkg/openapiconv/convert.go
generated
vendored
322
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
|
||||
}
|
21
vendor/k8s.io/kube-openapi/pkg/spec3/encoding.go
generated
vendored
21
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
vendor/k8s.io/kube-openapi/pkg/spec3/example.go
generated
vendored
14
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
vendor/k8s.io/kube-openapi/pkg/spec3/external_documentation.go
generated
vendored
13
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
vendor/k8s.io/kube-openapi/pkg/spec3/fuzz.go
generated
vendored
27
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
vendor/k8s.io/kube-openapi/pkg/spec3/header.go
generated
vendored
31
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
vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go
generated
vendored
20
vendor/k8s.io/kube-openapi/pkg/spec3/media_type.go
generated
vendored
@ -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
vendor/k8s.io/kube-openapi/pkg/spec3/operation.go
generated
vendored
27
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
vendor/k8s.io/kube-openapi/pkg/spec3/parameter.go
generated
vendored
31
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
vendor/k8s.io/kube-openapi/pkg/spec3/path.go
generated
vendored
47
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
vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go
generated
vendored
21
vendor/k8s.io/kube-openapi/pkg/spec3/request_body.go
generated
vendored
@ -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
vendor/k8s.io/kube-openapi/pkg/spec3/response.go
generated
vendored
52
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
vendor/k8s.io/kube-openapi/pkg/spec3/security_scheme.go
generated
vendored
17
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
vendor/k8s.io/kube-openapi/pkg/spec3/server.go
generated
vendored
26
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
vendor/k8s.io/kube-openapi/pkg/spec3/spec.go
generated
vendored
25
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
vendor/k8s.io/kube-openapi/pkg/validation/spec/fuzz.go
generated
vendored
502
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