Fix v3 spec

Kubernetes-commit: b30c6bdff817cec28b3d88b3bb3e12f1e86488d0
This commit is contained in:
Jefftree 2023-10-04 12:55:49 -04:00 committed by Kubernetes Publisher
parent e6bba9e4ab
commit 2e1024671d
3 changed files with 64 additions and 8 deletions

View File

@ -78,6 +78,7 @@ import (
"k8s.io/component-base/tracing" "k8s.io/component-base/tracing"
"k8s.io/klog/v2" "k8s.io/klog/v2"
openapicommon "k8s.io/kube-openapi/pkg/common" openapicommon "k8s.io/kube-openapi/pkg/common"
"k8s.io/kube-openapi/pkg/spec3"
"k8s.io/kube-openapi/pkg/validation/spec" "k8s.io/kube-openapi/pkg/validation/spec"
"k8s.io/utils/clock" "k8s.io/utils/clock"
utilsnet "k8s.io/utils/net" utilsnet "k8s.io/utils/net"
@ -194,7 +195,7 @@ type Config struct {
// OpenAPIConfig will be used in generating OpenAPI spec. This is nil by default. Use DefaultOpenAPIConfig for "working" defaults. // OpenAPIConfig will be used in generating OpenAPI spec. This is nil by default. Use DefaultOpenAPIConfig for "working" defaults.
OpenAPIConfig *openapicommon.Config OpenAPIConfig *openapicommon.Config
// OpenAPIV3Config will be used in generating OpenAPI V3 spec. This is nil by default. Use DefaultOpenAPIV3Config for "working" defaults. // OpenAPIV3Config will be used in generating OpenAPI V3 spec. This is nil by default. Use DefaultOpenAPIV3Config for "working" defaults.
OpenAPIV3Config *openapicommon.Config OpenAPIV3Config *openapicommon.OpenAPIV3Config
// SkipOpenAPIInstallation avoids installing the OpenAPI handler if set to true. // SkipOpenAPIInstallation avoids installing the OpenAPI handler if set to true.
SkipOpenAPIInstallation bool SkipOpenAPIInstallation bool
@ -482,8 +483,23 @@ func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, de
} }
// DefaultOpenAPIV3Config provides the default OpenAPIV3Config used to build the OpenAPI V3 spec // DefaultOpenAPIV3Config provides the default OpenAPIV3Config used to build the OpenAPI V3 spec
func DefaultOpenAPIV3Config(getDefinitions openapicommon.GetOpenAPIDefinitions, defNamer *apiopenapi.DefinitionNamer) *openapicommon.Config { func DefaultOpenAPIV3Config(getDefinitions openapicommon.GetOpenAPIDefinitions, defNamer *apiopenapi.DefinitionNamer) *openapicommon.OpenAPIV3Config {
defaultConfig := DefaultOpenAPIConfig(getDefinitions, defNamer) defaultConfig := &openapicommon.OpenAPIV3Config{
IgnorePrefixes: []string{},
Info: &spec.Info{
InfoProps: spec.InfoProps{
Title: "Generic API Server",
},
},
DefaultResponse: &spec3.Response{
ResponseProps: spec3.ResponseProps{
Description: "Default Response.",
},
},
GetOperationIDAndTags: apiopenapi.GetOperationIDAndTags,
GetDefinitionName: defNamer.GetDefinitionName,
GetDefinitions: getDefinitions,
}
defaultConfig.Definitions = getDefinitions(func(name string) spec.Ref { defaultConfig.Definitions = getDefinitions(func(name string) spec.Ref {
defName, _ := defaultConfig.GetDefinitionName(name) defName, _ := defaultConfig.GetDefinitionName(name)
return spec.MustCreateRef("#/components/schemas/" + openapicommon.EscapeJsonPointer(defName)) return spec.MustCreateRef("#/components/schemas/" + openapicommon.EscapeJsonPointer(defName))
@ -608,6 +624,45 @@ func completeOpenAPI(config *openapicommon.Config, version *version.Info) {
} }
} }
func completeOpenAPIV3(config *openapicommon.OpenAPIV3Config, version *version.Info) {
if config == nil {
return
}
if config.SecuritySchemes != nil {
// Setup OpenAPI security: all APIs will have the same authentication for now.
config.DefaultSecurity = []map[string][]string{}
keys := []string{}
for k := range config.SecuritySchemes {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
config.DefaultSecurity = append(config.DefaultSecurity, map[string][]string{k: {}})
}
if config.CommonResponses == nil {
config.CommonResponses = map[int]*spec3.Response{}
}
if _, exists := config.CommonResponses[http.StatusUnauthorized]; !exists {
config.CommonResponses[http.StatusUnauthorized] = &spec3.Response{
ResponseProps: spec3.ResponseProps{
Description: "Unauthorized",
},
}
}
}
// make sure we populate info, and info.version, if not manually set
if config.Info == nil {
config.Info = &spec.Info{}
}
if config.Info.Version == "" {
if version != nil {
config.Info.Version = strings.Split(version.String(), "-")[0]
} else {
config.Info.Version = "unversioned"
}
}
}
// DrainedNotify returns a lifecycle signal of genericapiserver already drained while shutting down. // DrainedNotify returns a lifecycle signal of genericapiserver already drained while shutting down.
func (c *Config) DrainedNotify() <-chan struct{} { func (c *Config) DrainedNotify() <-chan struct{} {
return c.lifecycleSignals.InFlightRequestsDrained.Signaled() return c.lifecycleSignals.InFlightRequestsDrained.Signaled()
@ -633,7 +688,7 @@ func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedCo
} }
completeOpenAPI(c.OpenAPIConfig, c.Version) completeOpenAPI(c.OpenAPIConfig, c.Version)
completeOpenAPI(c.OpenAPIV3Config, c.Version) completeOpenAPIV3(c.OpenAPIV3Config, c.Version)
if c.DiscoveryAddresses == nil { if c.DiscoveryAddresses == nil {
c.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: c.ExternalAddress} c.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: c.ExternalAddress}

View File

@ -158,7 +158,7 @@ type GenericAPIServer struct {
openAPIConfig *openapicommon.Config openAPIConfig *openapicommon.Config
// Enable swagger and/or OpenAPI V3 if these configs are non-nil. // Enable swagger and/or OpenAPI V3 if these configs are non-nil.
openAPIV3Config *openapicommon.Config openAPIV3Config *openapicommon.OpenAPIV3Config
// SkipOpenAPIInstallation indicates not to install the OpenAPI handler // SkipOpenAPIInstallation indicates not to install the OpenAPI handler
// during PrepareRun. // during PrepareRun.
@ -432,7 +432,7 @@ func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer {
if s.openAPIV3Config != nil && !s.skipOpenAPIInstallation { if s.openAPIV3Config != nil && !s.skipOpenAPIInstallation {
if utilfeature.DefaultFeatureGate.Enabled(features.OpenAPIV3) { if utilfeature.DefaultFeatureGate.Enabled(features.OpenAPIV3) {
s.OpenAPIV3VersionedService = routes.OpenAPI{ s.OpenAPIV3VersionedService = routes.OpenAPI{
Config: s.openAPIV3Config, V3Config: s.openAPIV3Config,
}.InstallV3(s.Handler.GoRestfulContainer, s.Handler.NonGoRestfulMux) }.InstallV3(s.Handler.GoRestfulContainer, s.Handler.NonGoRestfulMux)
} }
} }

View File

@ -33,6 +33,7 @@ import (
// OpenAPI installs spec endpoints for each web service. // OpenAPI installs spec endpoints for each web service.
type OpenAPI struct { type OpenAPI struct {
Config *common.Config Config *common.Config
V3Config *common.OpenAPIV3Config
} }
// Install adds the SwaggerUI webservice to the given mux. // Install adds the SwaggerUI webservice to the given mux.
@ -65,7 +66,7 @@ func (oa OpenAPI) InstallV3(c *restful.Container, mux *mux.PathRecorderMux) *han
} }
for gv, ws := range grouped { for gv, ws := range grouped {
spec, err := builder3.BuildOpenAPISpecFromRoutes(restfuladapter.AdaptWebServices(ws), oa.Config) spec, err := builder3.BuildOpenAPISpecFromRoutes(restfuladapter.AdaptWebServices(ws), oa.V3Config)
if err != nil { if err != nil {
klog.Errorf("Failed to build OpenAPI v3 for group %s, %q", gv, err) klog.Errorf("Failed to build OpenAPI v3 for group %s, %q", gv, err)