mirror of https://github.com/k3s-io/k3s
Merge pull request #40124 from mbohlool/separation
Automatic merge from submit-queue Use full package path for definition name in OpenAPI spec We were using short package name (last part of package name) plus type name for OpenAPI spec definition name. That can result in duplicate names and make the spec invalid. To be sure we will always have unique names, we are going to use full package name as definition name. Also "x-kubernetes-tag" custom field is added to definitions to list Group/Version/Kind for the definitions that has it. This will help clients to discover definitions easier. Lastly, we've added a reference from old definition names to the new ones to keep backward compatibilities. The list of old definitions will not be updated. **Release note**: - Rename OpenAPI definition names to type's full package names to prevent duplicates - Create OpenAPI extension "x-kubernetes-group-version-kind" for definitions to store Group/Version/Kind - Deprecate old definition names and create a reference to the new definitions. Old definitions will be removed in the next release.pull/6/head
commit
c523476d6f
File diff suppressed because it is too large
Load Diff
|
@ -295,7 +295,7 @@ func Run(s *options.ServerRunOptions) error {
|
|||
genericConfig.Authenticator = apiAuthenticator
|
||||
genericConfig.Authorizer = apiAuthorizer
|
||||
genericConfig.AdmissionControl = admissionController
|
||||
genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(generatedopenapi.OpenAPIDefinitions)
|
||||
genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(generatedopenapi.GetOpenAPIDefinitions)
|
||||
genericConfig.OpenAPIConfig.SecurityDefinitions = securityDefinitions
|
||||
genericConfig.OpenAPIConfig.Info.Title = "Kubernetes"
|
||||
genericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig()
|
||||
|
|
|
@ -133,7 +133,7 @@ const (
|
|||
// openApiGen produces a file with auto-generated OpenAPI functions.
|
||||
type openAPIGen struct {
|
||||
generator.DefaultGen
|
||||
// TargetPackage is the package that will get OpenAPIDefinitions variable contains all open API definitions.
|
||||
// TargetPackage is the package that will get GetOpenAPIDefinitions function returns all open API definitions.
|
||||
targetPackage *types.Package
|
||||
imports namer.ImportTracker
|
||||
context *generator.Context
|
||||
|
@ -185,23 +185,24 @@ func (g *openAPIGen) Imports(c *generator.Context) []string {
|
|||
|
||||
func argsFromType(t *types.Type) generator.Args {
|
||||
return generator.Args{
|
||||
"type": t,
|
||||
"OpenAPIDefinitions": types.Ref(openAPICommonPackagePath, "OpenAPIDefinitions"),
|
||||
"OpenAPIDefinition": types.Ref(openAPICommonPackagePath, "OpenAPIDefinition"),
|
||||
"SpecSchemaType": types.Ref(specPackagePath, "Schema"),
|
||||
"type": t,
|
||||
"ReferenceCallback": types.Ref(openAPICommonPackagePath, "ReferenceCallback"),
|
||||
"OpenAPIDefinition": types.Ref(openAPICommonPackagePath, "OpenAPIDefinition"),
|
||||
"SpecSchemaType": types.Ref(specPackagePath, "Schema"),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *openAPIGen) Init(c *generator.Context, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
sw.Do("var OpenAPIDefinitions *$.OpenAPIDefinitions|raw$ = ", argsFromType(nil))
|
||||
sw.Do("&$.OpenAPIDefinitions|raw${\n", argsFromType(nil))
|
||||
sw.Do("func GetOpenAPIDefinitions(ref $.ReferenceCallback|raw$) map[string]$.OpenAPIDefinition|raw$ {\n", argsFromType(nil))
|
||||
sw.Do("return map[string]$.OpenAPIDefinition|raw${\n", argsFromType(nil))
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
func (g *openAPIGen) Finalize(c *generator.Context, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
sw.Do("}\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
|
@ -308,9 +309,9 @@ func (g openAPITypeWriter) generate(t *types.Type) error {
|
|||
switch t.Kind {
|
||||
case types.Struct:
|
||||
args := argsFromType(t)
|
||||
g.Do("\"$.$\": ", typeShortName(t))
|
||||
g.Do("\"$.$\": ", t.Name)
|
||||
if hasOpenAPIDefinitionMethod(t) {
|
||||
g.Do("$.type|raw${}.OpenAPIDefinition(),", args)
|
||||
g.Do("$.type|raw${}.OpenAPIDefinition(),\n", args)
|
||||
return nil
|
||||
}
|
||||
g.Do("{\nSchema: spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
|
||||
|
@ -437,14 +438,8 @@ func (g openAPITypeWriter) generateSimpleProperty(typeString, format string) {
|
|||
}
|
||||
|
||||
func (g openAPITypeWriter) generateReferenceProperty(t *types.Type) {
|
||||
var name string
|
||||
if t.Name.Package == "" {
|
||||
name = t.Name.Name
|
||||
} else {
|
||||
name = filepath.Base(t.Name.Package) + "." + t.Name.Name
|
||||
}
|
||||
g.refTypes[name] = t
|
||||
g.Do("Ref: spec.MustCreateRef(\"#/definitions/$.$\"),\n", name)
|
||||
g.refTypes[t.Name.String()] = t
|
||||
g.Do("Ref: ref(\"$.$\"),\n", t.Name.String())
|
||||
}
|
||||
|
||||
func resolveAliasAndPtrType(t *types.Type) *types.Type {
|
||||
|
|
|
@ -112,7 +112,7 @@ type Blah struct {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(`"foo.Blah": {
|
||||
assert.Equal(`"base/foo.Blah": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Blah is a test.",
|
||||
|
@ -280,7 +280,7 @@ type Blah struct {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(`"foo.Blah": {
|
||||
assert.Equal(`"base/foo.Blah": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "PointerSample demonstrate pointer's properties",
|
||||
|
@ -295,7 +295,7 @@ Format: "",
|
|||
"StructPointer": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A struct pointer",
|
||||
Ref: spec.MustCreateRef("#/definitions/foo.Blah"),
|
||||
Ref: ref("base/foo.Blah"),
|
||||
},
|
||||
},
|
||||
"SlicePointer": {
|
||||
|
@ -331,7 +331,7 @@ Required: []string{"StringPointer","StructPointer","SlicePointer","MapPointer"},
|
|||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"foo.Blah",},
|
||||
"base/foo.Blah",},
|
||||
},
|
||||
`, buffer.String())
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -175,7 +175,7 @@ func Run(s *options.ServerRunOptions) error {
|
|||
genericConfig.Authenticator = apiAuthenticator
|
||||
genericConfig.Authorizer = apiAuthorizer
|
||||
genericConfig.AdmissionControl = admissionController
|
||||
genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.OpenAPIDefinitions)
|
||||
genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions)
|
||||
genericConfig.OpenAPIConfig.SecurityDefinitions = securityDefinitions
|
||||
genericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig()
|
||||
genericConfig.LongRunningFunc = filters.BasicLongRunningRequestCheck(
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,6 +5,7 @@ licenses(["notice"])
|
|||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
|
@ -13,6 +14,11 @@ go_library(
|
|||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/openapi",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apiserver/pkg/util/trie",
|
||||
],
|
||||
)
|
||||
|
@ -29,3 +35,16 @@ filegroup(
|
|||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["openapi_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -19,16 +19,27 @@ package openapi
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/go-openapi/spec"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/openapi"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/util/trie"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var verbs = trie.New([]string{"get", "log", "read", "replace", "patch", "delete", "deletecollection", "watch", "connect", "proxy", "list", "create", "patch"})
|
||||
|
||||
const (
|
||||
extensionGVK = "x-kubernetes-group-version-kind"
|
||||
)
|
||||
|
||||
// ToValidOperationID makes an string a valid op ID (e.g. removing punctuations and whitespaces and make it camel case)
|
||||
func ToValidOperationID(s string, capitalizeFirstLetter bool) string {
|
||||
var buffer bytes.Buffer
|
||||
|
@ -85,3 +96,382 @@ func GetOperationIDAndTags(servePath string, r *restful.Route) (string, []string
|
|||
return op, tags, nil
|
||||
}
|
||||
}
|
||||
|
||||
type groupVersionKinds []v1.GroupVersionKind
|
||||
|
||||
func (s groupVersionKinds) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s groupVersionKinds) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s groupVersionKinds) Less(i, j int) bool {
|
||||
if s[i].Group == s[j].Group {
|
||||
if s[i].Version == s[j].Version {
|
||||
return s[i].Kind < s[j].Kind
|
||||
}
|
||||
return s[i].Version < s[j].Version
|
||||
}
|
||||
return s[i].Group < s[j].Group
|
||||
}
|
||||
|
||||
// DefinitionNamer is the type to customize OpenAPI definition name.
|
||||
type DefinitionNamer struct {
|
||||
typeGroupVersionKinds map[string]groupVersionKinds
|
||||
}
|
||||
|
||||
func gvkConvert(gvk schema.GroupVersionKind) v1.GroupVersionKind {
|
||||
return v1.GroupVersionKind{
|
||||
Group: gvk.Group,
|
||||
Version: gvk.Version,
|
||||
Kind: gvk.Kind,
|
||||
}
|
||||
}
|
||||
|
||||
func friendlyName(name string) string {
|
||||
nameParts := strings.Split(name, "/")
|
||||
// Reverse first part. e.g., io.k8s... instead of k8s.io...
|
||||
if len(nameParts) > 0 && strings.Contains(nameParts[0], ".") {
|
||||
parts := strings.Split(nameParts[0], ".")
|
||||
for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 {
|
||||
parts[i], parts[j] = parts[j], parts[i]
|
||||
}
|
||||
nameParts[0] = strings.Join(parts, ".")
|
||||
}
|
||||
return strings.Join(nameParts, ".")
|
||||
}
|
||||
|
||||
func typeName(t reflect.Type) string {
|
||||
return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
|
||||
}
|
||||
|
||||
// NewDefinitionNamer constructs a new DefinitionNamer to be used to customize OpenAPI spec.
|
||||
func NewDefinitionNamer(s *runtime.Scheme) DefinitionNamer {
|
||||
ret := DefinitionNamer{
|
||||
typeGroupVersionKinds: map[string]groupVersionKinds{},
|
||||
}
|
||||
for gvk, rtype := range s.AllKnownTypes() {
|
||||
ret.typeGroupVersionKinds[typeName(rtype)] = append(ret.typeGroupVersionKinds[typeName(rtype)], gvkConvert(gvk))
|
||||
}
|
||||
for _, gvk := range ret.typeGroupVersionKinds {
|
||||
sort.Sort(gvk)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetDefinitionName returns the name and tags for a given definition
|
||||
func (d *DefinitionNamer) GetDefinitionName(servePath string, name string) (string, spec.Extensions) {
|
||||
if groupVersionKinds, ok := d.typeGroupVersionKinds[name]; ok {
|
||||
return friendlyName(name), spec.Extensions{
|
||||
extensionGVK: []v1.GroupVersionKind(groupVersionKinds),
|
||||
}
|
||||
}
|
||||
return friendlyName(name), nil
|
||||
}
|
||||
|
||||
// PostProcessSpec finalize OpenAPI spec and add removed definition for backward compatibility
|
||||
func PostProcessSpec(s *spec.Swagger) (*spec.Swagger, error) {
|
||||
compatibilityMap := map[string]string{
|
||||
"v1beta1.DeploymentStatus": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DeploymentStatus",
|
||||
"v1beta1.ReplicaSetList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ReplicaSetList",
|
||||
"v1beta1.Eviction": "k8s.io/kubernetes/pkg/apis/policy/v1beta1.Eviction",
|
||||
"v1beta1.StatefulSetList": "k8s.io/kubernetes/pkg/apis/apps/v1beta1.StatefulSetList",
|
||||
"v1beta1.RoleBinding": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.RoleBinding",
|
||||
"v1beta1.PodSecurityPolicyList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.PodSecurityPolicyList",
|
||||
"v1.NodeSpec": "k8s.io/kubernetes/pkg/api/v1.NodeSpec",
|
||||
"v1.FlockerVolumeSource": "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource",
|
||||
"v1.ContainerState": "k8s.io/kubernetes/pkg/api/v1.ContainerState",
|
||||
"v1beta1.ClusterRole": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.ClusterRole",
|
||||
"v1beta1.StorageClass": "k8s.io/kubernetes/pkg/apis/storage/v1beta1.StorageClass",
|
||||
"v1.FlexVolumeSource": "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource",
|
||||
"v1.SecretKeySelector": "k8s.io/kubernetes/pkg/api/v1.SecretKeySelector",
|
||||
"v1.DeleteOptions": "k8s.io/kubernetes/pkg/api/v1.DeleteOptions",
|
||||
"v1.PodStatus": "k8s.io/kubernetes/pkg/api/v1.PodStatus",
|
||||
"v1.NodeStatus": "k8s.io/kubernetes/pkg/api/v1.NodeStatus",
|
||||
"v1.ServiceSpec": "k8s.io/kubernetes/pkg/api/v1.ServiceSpec",
|
||||
"v1.AttachedVolume": "k8s.io/kubernetes/pkg/api/v1.AttachedVolume",
|
||||
"v1.PersistentVolume": "k8s.io/kubernetes/pkg/api/v1.PersistentVolume",
|
||||
"v1.LimitRangeList": "k8s.io/kubernetes/pkg/api/v1.LimitRangeList",
|
||||
"v1alpha1.Role": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.Role",
|
||||
"v1.Affinity": "k8s.io/kubernetes/pkg/api/v1.Affinity",
|
||||
"v1beta1.PodDisruptionBudget": "k8s.io/kubernetes/pkg/apis/policy/v1beta1.PodDisruptionBudget",
|
||||
"v1alpha1.RoleBindingList": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.RoleBindingList",
|
||||
"v1.PodAffinity": "k8s.io/kubernetes/pkg/api/v1.PodAffinity",
|
||||
"v1beta1.SELinuxStrategyOptions": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.SELinuxStrategyOptions",
|
||||
"v1.ResourceQuotaList": "k8s.io/kubernetes/pkg/api/v1.ResourceQuotaList",
|
||||
"v1.PodList": "k8s.io/kubernetes/pkg/api/v1.PodList",
|
||||
"v1.EnvVarSource": "k8s.io/kubernetes/pkg/api/v1.EnvVarSource",
|
||||
"v1beta1.TokenReviewStatus": "k8s.io/kubernetes/pkg/apis/authentication/v1beta1.TokenReviewStatus",
|
||||
"v1.PersistentVolumeClaimList": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimList",
|
||||
"v1beta1.RoleList": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.RoleList",
|
||||
"v1.ListMeta": "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta",
|
||||
"v1.ObjectMeta": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta",
|
||||
"v1.APIGroupList": "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroupList",
|
||||
"v2alpha1.Job": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.Job",
|
||||
"v1.EnvFromSource": "k8s.io/kubernetes/pkg/api/v1.EnvFromSource",
|
||||
"v1beta1.IngressStatus": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.IngressStatus",
|
||||
"v1.Service": "k8s.io/kubernetes/pkg/api/v1.Service",
|
||||
"v1beta1.DaemonSetStatus": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSetStatus",
|
||||
"v1alpha1.Subject": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.Subject",
|
||||
"v1.HorizontalPodAutoscaler": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.HorizontalPodAutoscaler",
|
||||
"v1.StatusCause": "k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause",
|
||||
"v1.NodeSelectorRequirement": "k8s.io/kubernetes/pkg/api/v1.NodeSelectorRequirement",
|
||||
"v1beta1.NetworkPolicyIngressRule": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.NetworkPolicyIngressRule",
|
||||
"v1beta1.ThirdPartyResource": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ThirdPartyResource",
|
||||
"v1beta1.PodSecurityPolicy": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.PodSecurityPolicy",
|
||||
"v1beta1.StatefulSet": "k8s.io/kubernetes/pkg/apis/apps/v1beta1.StatefulSet",
|
||||
"v1.LabelSelector": "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector",
|
||||
"v1.ScaleSpec": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.ScaleSpec",
|
||||
"v1.DownwardAPIVolumeFile": "k8s.io/kubernetes/pkg/api/v1.DownwardAPIVolumeFile",
|
||||
"v1beta1.HorizontalPodAutoscaler": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.HorizontalPodAutoscaler",
|
||||
"v1.AWSElasticBlockStoreVolumeSource": "k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource",
|
||||
"v1.ComponentStatus": "k8s.io/kubernetes/pkg/api/v1.ComponentStatus",
|
||||
"v2alpha1.JobSpec": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.JobSpec",
|
||||
"v1.ContainerImage": "k8s.io/kubernetes/pkg/api/v1.ContainerImage",
|
||||
"v1.ReplicationControllerStatus": "k8s.io/kubernetes/pkg/api/v1.ReplicationControllerStatus",
|
||||
"v1.ResourceQuota": "k8s.io/kubernetes/pkg/api/v1.ResourceQuota",
|
||||
"v1beta1.NetworkPolicyList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.NetworkPolicyList",
|
||||
"v1beta1.NonResourceAttributes": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.NonResourceAttributes",
|
||||
"v1.JobCondition": "k8s.io/kubernetes/pkg/apis/batch/v1.JobCondition",
|
||||
"v1.LabelSelectorRequirement": "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement",
|
||||
"v1beta1.Deployment": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.Deployment",
|
||||
"v1.LoadBalancerIngress": "k8s.io/kubernetes/pkg/api/v1.LoadBalancerIngress",
|
||||
"v1.SecretList": "k8s.io/kubernetes/pkg/api/v1.SecretList",
|
||||
"v1beta1.ReplicaSetSpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ReplicaSetSpec",
|
||||
"v1beta1.RoleBindingList": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.RoleBindingList",
|
||||
"v1.ServicePort": "k8s.io/kubernetes/pkg/api/v1.ServicePort",
|
||||
"v1.Namespace": "k8s.io/kubernetes/pkg/api/v1.Namespace",
|
||||
"v1beta1.NetworkPolicyPeer": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.NetworkPolicyPeer",
|
||||
"v1.ReplicationControllerList": "k8s.io/kubernetes/pkg/api/v1.ReplicationControllerList",
|
||||
"v1beta1.ReplicaSetCondition": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ReplicaSetCondition",
|
||||
"v1.ReplicationControllerCondition": "k8s.io/kubernetes/pkg/api/v1.ReplicationControllerCondition",
|
||||
"v1.DaemonEndpoint": "k8s.io/kubernetes/pkg/api/v1.DaemonEndpoint",
|
||||
"v1beta1.NetworkPolicyPort": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.NetworkPolicyPort",
|
||||
"v1.NodeSystemInfo": "k8s.io/kubernetes/pkg/api/v1.NodeSystemInfo",
|
||||
"v1.LimitRangeItem": "k8s.io/kubernetes/pkg/api/v1.LimitRangeItem",
|
||||
"v1.ConfigMapVolumeSource": "k8s.io/kubernetes/pkg/api/v1.ConfigMapVolumeSource",
|
||||
"v1beta1.ClusterRoleList": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.ClusterRoleList",
|
||||
"v1beta1.ResourceAttributes": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.ResourceAttributes",
|
||||
"v1.Pod": "k8s.io/kubernetes/pkg/api/v1.Pod",
|
||||
"v1.FCVolumeSource": "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource",
|
||||
"v1beta1.SubresourceReference": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.SubresourceReference",
|
||||
"v1.ResourceQuotaStatus": "k8s.io/kubernetes/pkg/api/v1.ResourceQuotaStatus",
|
||||
"v1alpha1.RoleBinding": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.RoleBinding",
|
||||
"v1.PodCondition": "k8s.io/kubernetes/pkg/api/v1.PodCondition",
|
||||
"v1.GroupVersionForDiscovery": "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery",
|
||||
"v1.NamespaceStatus": "k8s.io/kubernetes/pkg/api/v1.NamespaceStatus",
|
||||
"v1.Job": "k8s.io/kubernetes/pkg/apis/batch/v1.Job",
|
||||
"v1.PersistentVolumeClaimVolumeSource": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimVolumeSource",
|
||||
"v1.Handler": "k8s.io/kubernetes/pkg/api/v1.Handler",
|
||||
"v1.ComponentStatusList": "k8s.io/kubernetes/pkg/api/v1.ComponentStatusList",
|
||||
"v1.ServerAddressByClientCIDR": "k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR",
|
||||
"v1.PodAntiAffinity": "k8s.io/kubernetes/pkg/api/v1.PodAntiAffinity",
|
||||
"v1.ISCSIVolumeSource": "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource",
|
||||
"v1.ContainerStateRunning": "k8s.io/kubernetes/pkg/api/v1.ContainerStateRunning",
|
||||
"v1.WeightedPodAffinityTerm": "k8s.io/kubernetes/pkg/api/v1.WeightedPodAffinityTerm",
|
||||
"v1beta1.HostPortRange": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.HostPortRange",
|
||||
"v1.HorizontalPodAutoscalerSpec": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.HorizontalPodAutoscalerSpec",
|
||||
"v1.HorizontalPodAutoscalerList": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.HorizontalPodAutoscalerList",
|
||||
"v1beta1.RoleRef": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.RoleRef",
|
||||
"v1.Probe": "k8s.io/kubernetes/pkg/api/v1.Probe",
|
||||
"v1beta1.IngressTLS": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.IngressTLS",
|
||||
"v1beta1.ThirdPartyResourceList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ThirdPartyResourceList",
|
||||
"v1beta1.DaemonSet": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSet",
|
||||
"v1.APIGroup": "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup",
|
||||
"v1beta1.Subject": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.Subject",
|
||||
"v1beta1.DeploymentList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DeploymentList",
|
||||
"v1.NodeAffinity": "k8s.io/kubernetes/pkg/api/v1.NodeAffinity",
|
||||
"v1beta1.RollingUpdateDeployment": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.RollingUpdateDeployment",
|
||||
"v1beta1.APIVersion": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.APIVersion",
|
||||
"v1alpha1.CertificateSigningRequest": "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1.CertificateSigningRequest",
|
||||
"v1.CinderVolumeSource": "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource",
|
||||
"v1.NamespaceSpec": "k8s.io/kubernetes/pkg/api/v1.NamespaceSpec",
|
||||
"v1beta1.PodDisruptionBudgetSpec": "k8s.io/kubernetes/pkg/apis/policy/v1beta1.PodDisruptionBudgetSpec",
|
||||
"v1.Patch": "k8s.io/apimachinery/pkg/apis/meta/v1.Patch",
|
||||
"v1beta1.ClusterRoleBinding": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.ClusterRoleBinding",
|
||||
"v1beta1.HorizontalPodAutoscalerSpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.HorizontalPodAutoscalerSpec",
|
||||
"v1.PersistentVolumeClaimSpec": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimSpec",
|
||||
"v1.Secret": "k8s.io/kubernetes/pkg/api/v1.Secret",
|
||||
"v1.NodeCondition": "k8s.io/kubernetes/pkg/api/v1.NodeCondition",
|
||||
"v1.LocalObjectReference": "k8s.io/kubernetes/pkg/api/v1.LocalObjectReference",
|
||||
"runtime.RawExtension": "k8s.io/apimachinery/pkg/runtime.RawExtension",
|
||||
"v1.PreferredSchedulingTerm": "k8s.io/kubernetes/pkg/api/v1.PreferredSchedulingTerm",
|
||||
"v1.RBDVolumeSource": "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource",
|
||||
"v1.KeyToPath": "k8s.io/kubernetes/pkg/api/v1.KeyToPath",
|
||||
"v1.ScaleStatus": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.ScaleStatus",
|
||||
"v1alpha1.PolicyRule": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.PolicyRule",
|
||||
"v1.EndpointPort": "k8s.io/kubernetes/pkg/api/v1.EndpointPort",
|
||||
"v1beta1.IngressList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.IngressList",
|
||||
"v1.EndpointAddress": "k8s.io/kubernetes/pkg/api/v1.EndpointAddress",
|
||||
"v1.NodeSelector": "k8s.io/kubernetes/pkg/api/v1.NodeSelector",
|
||||
"v1beta1.StorageClassList": "k8s.io/kubernetes/pkg/apis/storage/v1beta1.StorageClassList",
|
||||
"v1.ServiceList": "k8s.io/kubernetes/pkg/api/v1.ServiceList",
|
||||
"v2alpha1.CronJobSpec": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.CronJobSpec",
|
||||
"v1.ContainerStateTerminated": "k8s.io/kubernetes/pkg/api/v1.ContainerStateTerminated",
|
||||
"v1beta1.TokenReview": "k8s.io/kubernetes/pkg/apis/authentication/v1beta1.TokenReview",
|
||||
"v1beta1.IngressBackend": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.IngressBackend",
|
||||
"v1.Time": "k8s.io/apimachinery/pkg/apis/meta/v1.Time",
|
||||
"v1beta1.IngressSpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.IngressSpec",
|
||||
"v2alpha1.JobTemplateSpec": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.JobTemplateSpec",
|
||||
"v1.LimitRange": "k8s.io/kubernetes/pkg/api/v1.LimitRange",
|
||||
"v1beta1.UserInfo": "k8s.io/kubernetes/pkg/apis/authentication/v1beta1.UserInfo",
|
||||
"v1.ResourceQuotaSpec": "k8s.io/kubernetes/pkg/api/v1.ResourceQuotaSpec",
|
||||
"v1.ContainerPort": "k8s.io/kubernetes/pkg/api/v1.ContainerPort",
|
||||
"v1beta1.HTTPIngressRuleValue": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.HTTPIngressRuleValue",
|
||||
"v1.AzureFileVolumeSource": "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource",
|
||||
"v1beta1.NetworkPolicySpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.NetworkPolicySpec",
|
||||
"v1.PodTemplateSpec": "k8s.io/kubernetes/pkg/api/v1.PodTemplateSpec",
|
||||
"v1.SecretVolumeSource": "k8s.io/kubernetes/pkg/api/v1.SecretVolumeSource",
|
||||
"v1.PodSpec": "k8s.io/kubernetes/pkg/api/v1.PodSpec",
|
||||
"v1.CephFSVolumeSource": "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource",
|
||||
"v1beta1.CPUTargetUtilization": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.CPUTargetUtilization",
|
||||
"v1.Volume": "k8s.io/kubernetes/pkg/api/v1.Volume",
|
||||
"v1beta1.Ingress": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.Ingress",
|
||||
"v1beta1.HorizontalPodAutoscalerList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.HorizontalPodAutoscalerList",
|
||||
"v1.PersistentVolumeStatus": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeStatus",
|
||||
"v1beta1.IDRange": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.IDRange",
|
||||
"v2alpha1.JobCondition": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.JobCondition",
|
||||
"v1beta1.IngressRule": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.IngressRule",
|
||||
"v1alpha1.RoleRef": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.RoleRef",
|
||||
"v1.PodAffinityTerm": "k8s.io/kubernetes/pkg/api/v1.PodAffinityTerm",
|
||||
"v1.ObjectReference": "k8s.io/kubernetes/pkg/api/v1.ObjectReference",
|
||||
"v1.ServiceStatus": "k8s.io/kubernetes/pkg/api/v1.ServiceStatus",
|
||||
"v1.APIResource": "k8s.io/apimachinery/pkg/apis/meta/v1.APIResource",
|
||||
"v1beta1.Scale": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.Scale",
|
||||
"v1.AzureDiskVolumeSource": "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource",
|
||||
"v1beta1.SubjectAccessReviewStatus": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.SubjectAccessReviewStatus",
|
||||
"v1.ConfigMap": "k8s.io/kubernetes/pkg/api/v1.ConfigMap",
|
||||
"v1.CrossVersionObjectReference": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.CrossVersionObjectReference",
|
||||
"v1.APIVersions": "k8s.io/apimachinery/pkg/apis/meta/v1.APIVersions",
|
||||
"v1alpha1.ClusterRoleList": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.ClusterRoleList",
|
||||
"v1.Node": "k8s.io/kubernetes/pkg/api/v1.Node",
|
||||
"resource.Quantity": "k8s.io/kubernetes/pkg/api/resource.Quantity",
|
||||
"v1.Event": "k8s.io/kubernetes/pkg/api/v1.Event",
|
||||
"v1.JobStatus": "k8s.io/kubernetes/pkg/apis/batch/v1.JobStatus",
|
||||
"v1.PersistentVolumeSpec": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeSpec",
|
||||
"v1beta1.SubjectAccessReviewSpec": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.SubjectAccessReviewSpec",
|
||||
"v1.ResourceFieldSelector": "k8s.io/kubernetes/pkg/api/v1.ResourceFieldSelector",
|
||||
"v1.EndpointSubset": "k8s.io/kubernetes/pkg/api/v1.EndpointSubset",
|
||||
"v1alpha1.CertificateSigningRequestSpec": "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1.CertificateSigningRequestSpec",
|
||||
"v1.HostPathVolumeSource": "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource",
|
||||
"v1.LoadBalancerStatus": "k8s.io/kubernetes/pkg/api/v1.LoadBalancerStatus",
|
||||
"v1beta1.HTTPIngressPath": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.HTTPIngressPath",
|
||||
"v1beta1.Role": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.Role",
|
||||
"v1beta1.DeploymentStrategy": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DeploymentStrategy",
|
||||
"v1beta1.RunAsUserStrategyOptions": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.RunAsUserStrategyOptions",
|
||||
"v1beta1.DeploymentSpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DeploymentSpec",
|
||||
"v1.ExecAction": "k8s.io/kubernetes/pkg/api/v1.ExecAction",
|
||||
"v1beta1.PodSecurityPolicySpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.PodSecurityPolicySpec",
|
||||
"v1.HorizontalPodAutoscalerStatus": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.HorizontalPodAutoscalerStatus",
|
||||
"v1.PersistentVolumeList": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeList",
|
||||
"v1alpha1.ClusterRole": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.ClusterRole",
|
||||
"v1.JobSpec": "k8s.io/kubernetes/pkg/apis/batch/v1.JobSpec",
|
||||
"v1beta1.DaemonSetSpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSetSpec",
|
||||
"v2alpha1.CronJobList": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.CronJobList",
|
||||
"v1.Endpoints": "k8s.io/kubernetes/pkg/api/v1.Endpoints",
|
||||
"v1.SELinuxOptions": "k8s.io/kubernetes/pkg/api/v1.SELinuxOptions",
|
||||
"v1beta1.SelfSubjectAccessReviewSpec": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.SelfSubjectAccessReviewSpec",
|
||||
"v1beta1.ScaleStatus": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ScaleStatus",
|
||||
"v1.NodeSelectorTerm": "k8s.io/kubernetes/pkg/api/v1.NodeSelectorTerm",
|
||||
"v1alpha1.CertificateSigningRequestStatus": "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1.CertificateSigningRequestStatus",
|
||||
"v1.StatusDetails": "k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails",
|
||||
"v2alpha1.JobStatus": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.JobStatus",
|
||||
"v1beta1.DeploymentRollback": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DeploymentRollback",
|
||||
"v1.GlusterfsVolumeSource": "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource",
|
||||
"v1.ServiceAccountList": "k8s.io/kubernetes/pkg/api/v1.ServiceAccountList",
|
||||
"v1.JobList": "k8s.io/kubernetes/pkg/apis/batch/v1.JobList",
|
||||
"v1.EventList": "k8s.io/kubernetes/pkg/api/v1.EventList",
|
||||
"v1.ContainerStateWaiting": "k8s.io/kubernetes/pkg/api/v1.ContainerStateWaiting",
|
||||
"v1.APIResourceList": "k8s.io/apimachinery/pkg/apis/meta/v1.APIResourceList",
|
||||
"v1.ContainerStatus": "k8s.io/kubernetes/pkg/api/v1.ContainerStatus",
|
||||
"v2alpha1.JobList": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.JobList",
|
||||
"v1.ConfigMapKeySelector": "k8s.io/kubernetes/pkg/api/v1.ConfigMapKeySelector",
|
||||
"v1.PhotonPersistentDiskVolumeSource": "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource",
|
||||
"v1.PodTemplateList": "k8s.io/kubernetes/pkg/api/v1.PodTemplateList",
|
||||
"v1.PersistentVolumeClaimStatus": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimStatus",
|
||||
"v1.ServiceAccount": "k8s.io/kubernetes/pkg/api/v1.ServiceAccount",
|
||||
"v1alpha1.CertificateSigningRequestList": "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1.CertificateSigningRequestList",
|
||||
"v1beta1.SupplementalGroupsStrategyOptions": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.SupplementalGroupsStrategyOptions",
|
||||
"v1.HTTPHeader": "k8s.io/kubernetes/pkg/api/v1.HTTPHeader",
|
||||
"version.Info": "k8s.io/apimachinery/pkg/version.Info",
|
||||
"v1.EventSource": "k8s.io/kubernetes/pkg/api/v1.EventSource",
|
||||
"v1alpha1.ClusterRoleBindingList": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.ClusterRoleBindingList",
|
||||
"v1.OwnerReference": "k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference",
|
||||
"v1beta1.ClusterRoleBindingList": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.ClusterRoleBindingList",
|
||||
"v1beta1.ScaleSpec": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ScaleSpec",
|
||||
"v1.GitRepoVolumeSource": "k8s.io/kubernetes/pkg/api/v1.GitRepoVolumeSource",
|
||||
"v1beta1.NetworkPolicy": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.NetworkPolicy",
|
||||
"v1.ConfigMapEnvSource": "k8s.io/kubernetes/pkg/api/v1.ConfigMapEnvSource",
|
||||
"v1.PodTemplate": "k8s.io/kubernetes/pkg/api/v1.PodTemplate",
|
||||
"v1beta1.DeploymentCondition": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DeploymentCondition",
|
||||
"v1beta1.PodDisruptionBudgetStatus": "k8s.io/kubernetes/pkg/apis/policy/v1beta1.PodDisruptionBudgetStatus",
|
||||
"v1.EnvVar": "k8s.io/kubernetes/pkg/api/v1.EnvVar",
|
||||
"v1.LimitRangeSpec": "k8s.io/kubernetes/pkg/api/v1.LimitRangeSpec",
|
||||
"v1.DownwardAPIVolumeSource": "k8s.io/kubernetes/pkg/api/v1.DownwardAPIVolumeSource",
|
||||
"v1.NodeDaemonEndpoints": "k8s.io/kubernetes/pkg/api/v1.NodeDaemonEndpoints",
|
||||
"v1.ComponentCondition": "k8s.io/kubernetes/pkg/api/v1.ComponentCondition",
|
||||
"v1alpha1.CertificateSigningRequestCondition": "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1.CertificateSigningRequestCondition",
|
||||
"v1.SecurityContext": "k8s.io/kubernetes/pkg/api/v1.SecurityContext",
|
||||
"v1beta1.LocalSubjectAccessReview": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.LocalSubjectAccessReview",
|
||||
"v1beta1.StatefulSetSpec": "k8s.io/kubernetes/pkg/apis/apps/v1beta1.StatefulSetSpec",
|
||||
"v1.NodeAddress": "k8s.io/kubernetes/pkg/api/v1.NodeAddress",
|
||||
"v1.QuobyteVolumeSource": "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource",
|
||||
"v1.Capabilities": "k8s.io/kubernetes/pkg/api/v1.Capabilities",
|
||||
"v1.GCEPersistentDiskVolumeSource": "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource",
|
||||
"v1beta1.ReplicaSet": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ReplicaSet",
|
||||
"v1beta1.HorizontalPodAutoscalerStatus": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.HorizontalPodAutoscalerStatus",
|
||||
"v1beta1.PolicyRule": "k8s.io/kubernetes/pkg/apis/rbac/v1beta1.PolicyRule",
|
||||
"v1.ConfigMapList": "k8s.io/kubernetes/pkg/api/v1.ConfigMapList",
|
||||
"v1.Lifecycle": "k8s.io/kubernetes/pkg/api/v1.Lifecycle",
|
||||
"v1beta1.SelfSubjectAccessReview": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.SelfSubjectAccessReview",
|
||||
"v2alpha1.CronJob": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.CronJob",
|
||||
"v2alpha1.CronJobStatus": "k8s.io/kubernetes/pkg/apis/batch/v2alpha1.CronJobStatus",
|
||||
"v1beta1.SubjectAccessReview": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1.SubjectAccessReview",
|
||||
"v1.Preconditions": "k8s.io/kubernetes/pkg/api/v1.Preconditions",
|
||||
"v1beta1.DaemonSetList": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.DaemonSetList",
|
||||
"v1.PersistentVolumeClaim": "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaim",
|
||||
"v1.Scale": "k8s.io/kubernetes/pkg/apis/autoscaling/v1.Scale",
|
||||
"v1beta1.StatefulSetStatus": "k8s.io/kubernetes/pkg/apis/apps/v1beta1.StatefulSetStatus",
|
||||
"v1.NFSVolumeSource": "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource",
|
||||
"v1.ObjectFieldSelector": "k8s.io/kubernetes/pkg/api/v1.ObjectFieldSelector",
|
||||
"v1.ResourceRequirements": "k8s.io/kubernetes/pkg/api/v1.ResourceRequirements",
|
||||
"v1.WatchEvent": "k8s.io/apimachinery/pkg/apis/meta/v1.WatchEvent",
|
||||
"v1.ReplicationControllerSpec": "k8s.io/kubernetes/pkg/api/v1.ReplicationControllerSpec",
|
||||
"v1.HTTPGetAction": "k8s.io/kubernetes/pkg/api/v1.HTTPGetAction",
|
||||
"v1beta1.RollbackConfig": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.RollbackConfig",
|
||||
"v1beta1.TokenReviewSpec": "k8s.io/kubernetes/pkg/apis/authentication/v1beta1.TokenReviewSpec",
|
||||
"v1.PodSecurityContext": "k8s.io/kubernetes/pkg/api/v1.PodSecurityContext",
|
||||
"v1beta1.PodDisruptionBudgetList": "k8s.io/kubernetes/pkg/apis/policy/v1beta1.PodDisruptionBudgetList",
|
||||
"v1.VolumeMount": "k8s.io/kubernetes/pkg/api/v1.VolumeMount",
|
||||
"v1.ReplicationController": "k8s.io/kubernetes/pkg/api/v1.ReplicationController",
|
||||
"v1.NamespaceList": "k8s.io/kubernetes/pkg/api/v1.NamespaceList",
|
||||
"v1alpha1.ClusterRoleBinding": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.ClusterRoleBinding",
|
||||
"v1.TCPSocketAction": "k8s.io/kubernetes/pkg/api/v1.TCPSocketAction",
|
||||
"v1.Binding": "k8s.io/kubernetes/pkg/api/v1.Binding",
|
||||
"v1beta1.ReplicaSetStatus": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.ReplicaSetStatus",
|
||||
"intstr.IntOrString": "k8s.io/kubernetes/pkg/util/intstr.IntOrString",
|
||||
"v1.EndpointsList": "k8s.io/kubernetes/pkg/api/v1.EndpointsList",
|
||||
"v1.Container": "k8s.io/kubernetes/pkg/api/v1.Container",
|
||||
"v1alpha1.RoleList": "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1.RoleList",
|
||||
"v1.VsphereVirtualDiskVolumeSource": "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource",
|
||||
"v1.NodeList": "k8s.io/kubernetes/pkg/api/v1.NodeList",
|
||||
"v1.EmptyDirVolumeSource": "k8s.io/kubernetes/pkg/api/v1.EmptyDirVolumeSource",
|
||||
"v1beta1.FSGroupStrategyOptions": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1.FSGroupStrategyOptions",
|
||||
"v1.Status": "k8s.io/apimachinery/pkg/apis/meta/v1.Status",
|
||||
}
|
||||
|
||||
for k, v := range compatibilityMap {
|
||||
if _, found := s.Definitions[v]; !found {
|
||||
continue
|
||||
}
|
||||
s.Definitions[k] = spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Ref: spec.MustCreateRef("#/definitions/" + openapi.EscapeJsonPointer(v)),
|
||||
Description: fmt.Sprintf("Deprecated. Please use %s instead.", v),
|
||||
},
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright 2016 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 openapi
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
type TestType struct {
|
||||
}
|
||||
|
||||
func (t TestType) GetObjectKind() schema.ObjectKind {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t TestType) SetGroupVersionKind(kind schema.GroupVersionKind) {
|
||||
}
|
||||
|
||||
func (t TestType) GroupVersionKind() schema.GroupVersionKind {
|
||||
return schema.GroupVersionKind{
|
||||
Group: "test",
|
||||
Version: "v1",
|
||||
Kind: "TestType",
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqual(t *testing.T, expected, actual interface{}) {
|
||||
var equal bool
|
||||
if expected == nil || actual == nil {
|
||||
equal = expected == actual
|
||||
} else {
|
||||
equal = reflect.DeepEqual(expected, actual)
|
||||
}
|
||||
if !equal {
|
||||
t.Errorf("%v != %v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDefinitionName(t *testing.T) {
|
||||
testType := TestType{}
|
||||
typePkgName := "k8s.io/kubernetes/pkg/genericapiserver/endpoints/openapi.TestType"
|
||||
typeFriendlyName := "io.k8s.kubernetes.pkg.genericapiserver.endpoints.openapi.TestType"
|
||||
if strings.HasSuffix(reflect.TypeOf(testType).PkgPath(), "go_default_test") {
|
||||
// the test is running inside bazel where the package name is changed and
|
||||
// "go_default_test" will add to package path.
|
||||
typePkgName = "k8s.io/kubernetes/pkg/genericapiserver/endpoints/openapi/go_default_test.TestType"
|
||||
typeFriendlyName = "io.k8s.kubernetes.pkg.genericapiserver.endpoints.openapi.go_default_test.TestType"
|
||||
}
|
||||
s := runtime.NewScheme()
|
||||
s.AddKnownTypeWithName(testType.GroupVersionKind(), &testType)
|
||||
namer := NewDefinitionNamer(s)
|
||||
n, e := namer.GetDefinitionName("", typePkgName)
|
||||
assertEqual(t, typeFriendlyName, n)
|
||||
assertEqual(t, e["x-kubernetes-group-version-kind"], []v1.GroupVersionKind{
|
||||
{
|
||||
Group: "test",
|
||||
Version: "v1",
|
||||
Kind: "TestType",
|
||||
},
|
||||
})
|
||||
n, e2 := namer.GetDefinitionName("", "test.com/another.Type")
|
||||
assertEqual(t, "com.test.another.Type", n)
|
||||
assertEqual(t, e2, spec.Extensions(nil))
|
||||
}
|
|
@ -213,7 +213,8 @@ func NewConfig() *Config {
|
|||
return config.ApplyOptions(defaultOptions)
|
||||
}
|
||||
|
||||
func DefaultOpenAPIConfig(definitions *openapicommon.OpenAPIDefinitions) *openapicommon.Config {
|
||||
func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions) *openapicommon.Config {
|
||||
defNamer := apiopenapi.NewDefinitionNamer(api.Scheme)
|
||||
return &openapicommon.Config{
|
||||
ProtocolList: []string{"https"},
|
||||
IgnorePrefixes: []string{"/swaggerapi"},
|
||||
|
@ -228,7 +229,9 @@ func DefaultOpenAPIConfig(definitions *openapicommon.OpenAPIDefinitions) *openap
|
|||
},
|
||||
},
|
||||
GetOperationIDAndTags: apiopenapi.GetOperationIDAndTags,
|
||||
Definitions: definitions,
|
||||
GetDefinitionName: defNamer.GetDefinitionName,
|
||||
GetDefinitions: getDefinitions,
|
||||
PostProcessSpec: apiopenapi.PostProcessSpec,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
|
|||
config.RequestContextMapper = genericapirequest.NewRequestContextMapper()
|
||||
config.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
||||
|
||||
config.OpenAPIConfig = DefaultOpenAPIConfig(openapigen.OpenAPIDefinitions)
|
||||
config.OpenAPIConfig = DefaultOpenAPIConfig(openapigen.GetOpenAPIDefinitions)
|
||||
config.OpenAPIConfig.Info = &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "Kubernetes",
|
||||
|
|
|
@ -40,6 +40,7 @@ type openAPI struct {
|
|||
swagger *spec.Swagger
|
||||
protocolList []string
|
||||
servePath string
|
||||
definitions map[string]openapi.OpenAPIDefinition
|
||||
}
|
||||
|
||||
// RegisterOpenAPIService registers a handler to provides standard OpenAPI specification.
|
||||
|
@ -79,6 +80,15 @@ func (o *openAPI) init(webServices []*restful.WebService) error {
|
|||
return r.Operation, nil, nil
|
||||
}
|
||||
}
|
||||
if o.config.GetDefinitionName == nil {
|
||||
o.config.GetDefinitionName = func(_, name string) (string, spec.Extensions) {
|
||||
return name[strings.LastIndex(name, "/")+1:], nil
|
||||
}
|
||||
}
|
||||
o.definitions = o.config.GetDefinitions(func(name string) spec.Ref {
|
||||
defName, _ := o.config.GetDefinitionName(o.servePath, name)
|
||||
return spec.MustCreateRef("#/definitions/" + openapi.EscapeJsonPointer(defName))
|
||||
})
|
||||
if o.config.CommonResponses == nil {
|
||||
o.config.CommonResponses = map[int]spec.Response{}
|
||||
}
|
||||
|
@ -90,15 +100,43 @@ func (o *openAPI) init(webServices []*restful.WebService) error {
|
|||
o.swagger.SecurityDefinitions = *o.config.SecurityDefinitions
|
||||
o.swagger.Security = o.config.DefaultSecurity
|
||||
}
|
||||
if o.config.PostProcessSpec != nil {
|
||||
o.swagger, err = o.config.PostProcessSpec(o.swagger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getCanonicalizeTypeName(t reflect.Type) string {
|
||||
if t.PkgPath() == "" {
|
||||
return t.Name()
|
||||
}
|
||||
path := t.PkgPath()
|
||||
if strings.Contains(path, "/vendor/") {
|
||||
path = path[strings.Index(path, "/vendor/")+len("/vendor/"):]
|
||||
}
|
||||
return path + "." + t.Name()
|
||||
}
|
||||
|
||||
func (o *openAPI) buildDefinitionRecursively(name string) error {
|
||||
if _, ok := o.swagger.Definitions[name]; ok {
|
||||
uniqueName, extensions := o.config.GetDefinitionName(o.servePath, name)
|
||||
if _, ok := o.swagger.Definitions[uniqueName]; ok {
|
||||
return nil
|
||||
}
|
||||
if item, ok := (*o.config.Definitions)[name]; ok {
|
||||
o.swagger.Definitions[name] = item.Schema
|
||||
if item, ok := o.definitions[name]; ok {
|
||||
schema := spec.Schema{
|
||||
SchemaProps: item.Schema.SchemaProps,
|
||||
SwaggerSchemaProps: item.Schema.SwaggerSchemaProps,
|
||||
}
|
||||
if extensions != nil {
|
||||
schema.Extensions = spec.Extensions{}
|
||||
for k, v := range extensions {
|
||||
schema.Extensions[k] = v
|
||||
}
|
||||
}
|
||||
o.swagger.Definitions[uniqueName] = schema
|
||||
for _, v := range item.Dependencies {
|
||||
if err := o.buildDefinitionRecursively(v); err != nil {
|
||||
return err
|
||||
|
@ -118,11 +156,12 @@ func (o *openAPI) buildDefinitionForType(sample interface{}) (string, error) {
|
|||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
name := t.String()
|
||||
name := getCanonicalizeTypeName(t)
|
||||
if err := o.buildDefinitionRecursively(name); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "#/definitions/" + name, nil
|
||||
defName, _ := o.config.GetDefinitionName(o.servePath, name)
|
||||
return "#/definitions/" + openapi.EscapeJsonPointer(defName), nil
|
||||
}
|
||||
|
||||
// buildPaths builds OpenAPI paths using go-restful's web services.
|
||||
|
@ -244,18 +283,12 @@ func (o *openAPI) buildOperations(route restful.Route, inPathCommonParamsMap map
|
|||
if len(ret.Responses.StatusCodeResponses) == 0 {
|
||||
ret.Responses.Default = o.config.DefaultResponse
|
||||
}
|
||||
// If there is a read sample, there will be a body param referring to it.
|
||||
if route.ReadSample != nil {
|
||||
if _, err := o.toSchema(reflect.TypeOf(route.ReadSample).String(), route.ReadSample); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
}
|
||||
|
||||
// Build non-common Parameters
|
||||
ret.Parameters = make([]spec.Parameter, 0)
|
||||
for _, param := range route.ParameterDocs {
|
||||
if _, isCommon := inPathCommonParamsMap[mapKeyFromParam(param)]; !isCommon {
|
||||
openAPIParam, err := o.buildParameter(param.Data())
|
||||
openAPIParam, err := o.buildParameter(param.Data(), route.ReadSample)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
@ -266,8 +299,7 @@ func (o *openAPI) buildOperations(route restful.Route, inPathCommonParamsMap map
|
|||
}
|
||||
|
||||
func (o *openAPI) buildResponse(model interface{}, description string) (spec.Response, error) {
|
||||
typeName := reflect.TypeOf(model).String()
|
||||
schema, err := o.toSchema(typeName, model)
|
||||
schema, err := o.toSchema(model)
|
||||
if err != nil {
|
||||
return spec.Response{}, err
|
||||
}
|
||||
|
@ -300,8 +332,9 @@ func (o *openAPI) findCommonParameters(routes []restful.Route) (map[interface{}]
|
|||
}
|
||||
}
|
||||
for key, count := range paramOpsCountByName {
|
||||
if count == len(routes) {
|
||||
openAPIParam, err := o.buildParameter(paramNameKindToDataMap[key])
|
||||
paramData := paramNameKindToDataMap[key]
|
||||
if count == len(routes) && paramData.Kind != restful.BodyParameterKind {
|
||||
openAPIParam, err := o.buildParameter(paramData, nil)
|
||||
if err != nil {
|
||||
return commonParamsMap, err
|
||||
}
|
||||
|
@ -311,8 +344,8 @@ func (o *openAPI) findCommonParameters(routes []restful.Route) (map[interface{}]
|
|||
return commonParamsMap, nil
|
||||
}
|
||||
|
||||
func (o *openAPI) toSchema(typeName string, model interface{}) (_ *spec.Schema, err error) {
|
||||
if openAPIType, openAPIFormat := openapi.GetOpenAPITypeFormat(typeName); openAPIType != "" {
|
||||
func (o *openAPI) toSchema(model interface{}) (_ *spec.Schema, err error) {
|
||||
if openAPIType, openAPIFormat := openapi.GetOpenAPITypeFormat(getCanonicalizeTypeName(reflect.TypeOf(model))); openAPIType != "" {
|
||||
return &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{openAPIType},
|
||||
|
@ -320,12 +353,9 @@ func (o *openAPI) toSchema(typeName string, model interface{}) (_ *spec.Schema,
|
|||
},
|
||||
}, nil
|
||||
} else {
|
||||
ref := "#/definitions/" + typeName
|
||||
if model != nil {
|
||||
ref, err = o.buildDefinitionForType(model)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref, err := o.buildDefinitionForType(model)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
|
@ -335,7 +365,7 @@ func (o *openAPI) toSchema(typeName string, model interface{}) (_ *spec.Schema,
|
|||
}
|
||||
}
|
||||
|
||||
func (o *openAPI) buildParameter(restParam restful.ParameterData) (ret spec.Parameter, err error) {
|
||||
func (o *openAPI) buildParameter(restParam restful.ParameterData, bodySample interface{}) (ret spec.Parameter, err error) {
|
||||
ret = spec.Parameter{
|
||||
ParamProps: spec.ParamProps{
|
||||
Name: restParam.Name,
|
||||
|
@ -345,9 +375,16 @@ func (o *openAPI) buildParameter(restParam restful.ParameterData) (ret spec.Para
|
|||
}
|
||||
switch restParam.Kind {
|
||||
case restful.BodyParameterKind:
|
||||
ret.In = "body"
|
||||
ret.Schema, err = o.toSchema(restParam.DataType, nil)
|
||||
return ret, err
|
||||
if bodySample != nil {
|
||||
ret.In = "body"
|
||||
ret.Schema, err = o.toSchema(bodySample)
|
||||
return ret, err
|
||||
} else {
|
||||
// There is not enough information in the body parameter to build the definition.
|
||||
// Body parameter has a data type that is a short name but we need full package name
|
||||
// of the type to create a definition.
|
||||
return ret, fmt.Errorf("restful body parameters are not supported: %v", restParam.DataType)
|
||||
}
|
||||
case restful.PathParameterKind:
|
||||
ret.In = "path"
|
||||
if !restParam.Required {
|
||||
|
@ -375,7 +412,7 @@ func (o *openAPI) buildParameter(restParam restful.ParameterData) (ret spec.Para
|
|||
func (o *openAPI) buildParameters(restParam []*restful.Parameter) (ret []spec.Parameter, err error) {
|
||||
ret = make([]spec.Parameter, len(restParam))
|
||||
for i, v := range restParam {
|
||||
ret[i], err = o.buildParameter(v.Data())
|
||||
ret[i], err = o.buildParameter(v.Data(), nil)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package openapi
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
|
@ -186,9 +187,22 @@ func getConfig(fullMethods bool) (*openapi.Config, *restful.Container) {
|
|||
Description: "Test API",
|
||||
},
|
||||
},
|
||||
Definitions: &openapi.OpenAPIDefinitions{
|
||||
"openapi.TestInput": *TestInput{}.OpenAPIDefinition(),
|
||||
"openapi.TestOutput": *TestOutput{}.OpenAPIDefinition(),
|
||||
GetDefinitions: func(_ openapi.ReferenceCallback) map[string]openapi.OpenAPIDefinition {
|
||||
return map[string]openapi.OpenAPIDefinition{
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/server/openapi.TestInput": *TestInput{}.OpenAPIDefinition(),
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/server/openapi.TestOutput": *TestOutput{}.OpenAPIDefinition(),
|
||||
// Bazel changes the package name, this is ok for testing, but we need to fix it if it happened
|
||||
// in the main code.
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/server/openapi/go_default_test.TestInput": *TestInput{}.OpenAPIDefinition(),
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/server/openapi/go_default_test.TestOutput": *TestOutput{}.OpenAPIDefinition(),
|
||||
}
|
||||
},
|
||||
GetDefinitionName: func(_ string, name string) (string, spec.Extensions) {
|
||||
friendlyName := name[strings.LastIndex(name, "/")+1:]
|
||||
if strings.HasPrefix(friendlyName, "go_default_test") {
|
||||
friendlyName = "openapi" + friendlyName[len("go_default_test"):]
|
||||
}
|
||||
return friendlyName, nil
|
||||
},
|
||||
}, container
|
||||
}
|
||||
|
@ -216,12 +230,18 @@ func getTestPathItem(allMethods bool, opPrefix string) spec.PathItem {
|
|||
}
|
||||
ret.Get.Parameters = getAdditionalTestParameters()
|
||||
if allMethods {
|
||||
ret.PathItemProps.Put = getTestOperation("put", opPrefix)
|
||||
ret.PathItemProps.Post = getTestOperation("post", opPrefix)
|
||||
ret.PathItemProps.Head = getTestOperation("head", opPrefix)
|
||||
ret.PathItemProps.Patch = getTestOperation("patch", opPrefix)
|
||||
ret.PathItemProps.Delete = getTestOperation("delete", opPrefix)
|
||||
ret.PathItemProps.Options = getTestOperation("options", opPrefix)
|
||||
ret.Put = getTestOperation("put", opPrefix)
|
||||
ret.Put.Parameters = getTestParameters()
|
||||
ret.Post = getTestOperation("post", opPrefix)
|
||||
ret.Post.Parameters = getTestParameters()
|
||||
ret.Head = getTestOperation("head", opPrefix)
|
||||
ret.Head.Parameters = getTestParameters()
|
||||
ret.Patch = getTestOperation("patch", opPrefix)
|
||||
ret.Patch.Parameters = getTestParameters()
|
||||
ret.Delete = getTestOperation("delete", opPrefix)
|
||||
ret.Delete.Parameters = getTestParameters()
|
||||
ret.Options = getTestOperation("options", opPrefix)
|
||||
ret.Options.Parameters = getTestParameters()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
@ -250,16 +270,8 @@ func getTestResponses() *spec.Responses {
|
|||
}
|
||||
|
||||
func getTestCommonParameters() []spec.Parameter {
|
||||
ret := make([]spec.Parameter, 3)
|
||||
ret := make([]spec.Parameter, 2)
|
||||
ret[0] = spec.Parameter{
|
||||
ParamProps: spec.ParamProps{
|
||||
Name: "body",
|
||||
In: "body",
|
||||
Required: true,
|
||||
Schema: getRefSchema("#/definitions/openapi.TestInput"),
|
||||
},
|
||||
}
|
||||
ret[1] = spec.Parameter{
|
||||
SimpleSchema: spec.SimpleSchema{
|
||||
Type: "string",
|
||||
},
|
||||
|
@ -273,7 +285,7 @@ func getTestCommonParameters() []spec.Parameter {
|
|||
UniqueItems: true,
|
||||
},
|
||||
}
|
||||
ret[2] = spec.Parameter{
|
||||
ret[1] = spec.Parameter{
|
||||
SimpleSchema: spec.SimpleSchema{
|
||||
Type: "string",
|
||||
},
|
||||
|
@ -289,9 +301,30 @@ func getTestCommonParameters() []spec.Parameter {
|
|||
return ret
|
||||
}
|
||||
|
||||
func getAdditionalTestParameters() []spec.Parameter {
|
||||
ret := make([]spec.Parameter, 2)
|
||||
func getTestParameters() []spec.Parameter {
|
||||
ret := make([]spec.Parameter, 1)
|
||||
ret[0] = spec.Parameter{
|
||||
ParamProps: spec.ParamProps{
|
||||
Name: "body",
|
||||
In: "body",
|
||||
Required: true,
|
||||
Schema: getRefSchema("#/definitions/openapi.TestInput"),
|
||||
},
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func getAdditionalTestParameters() []spec.Parameter {
|
||||
ret := make([]spec.Parameter, 3)
|
||||
ret[0] = spec.Parameter{
|
||||
ParamProps: spec.ParamProps{
|
||||
Name: "body",
|
||||
In: "body",
|
||||
Required: true,
|
||||
Schema: getRefSchema("#/definitions/openapi.TestInput"),
|
||||
},
|
||||
}
|
||||
ret[1] = spec.Parameter{
|
||||
ParamProps: spec.ParamProps{
|
||||
Name: "fparam",
|
||||
Description: "a test form parameter",
|
||||
|
@ -304,7 +337,7 @@ func getAdditionalTestParameters() []spec.Parameter {
|
|||
UniqueItems: true,
|
||||
},
|
||||
}
|
||||
ret[1] = spec.Parameter{
|
||||
ret[2] = spec.Parameter{
|
||||
SimpleSchema: spec.SimpleSchema{
|
||||
Type: "integer",
|
||||
},
|
||||
|
|
|
@ -43,7 +43,7 @@ func TestValidOpenAPISpec(t *testing.T) {
|
|||
defer etcdserver.Terminate(t)
|
||||
|
||||
config.GenericConfig.EnableIndex = true
|
||||
config.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapigen.OpenAPIDefinitions)
|
||||
config.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapigen.GetOpenAPIDefinitions)
|
||||
config.GenericConfig.OpenAPIConfig.Info = &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "Kubernetes",
|
||||
|
|
|
@ -19,6 +19,7 @@ package openapi
|
|||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/go-openapi/spec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// OpenAPIDefinition describes single type. Normally these definitions are auto-generated using gen-openapi.
|
||||
|
@ -27,8 +28,10 @@ type OpenAPIDefinition struct {
|
|||
Dependencies []string
|
||||
}
|
||||
|
||||
type ReferenceCallback func(path string) spec.Ref
|
||||
|
||||
// OpenAPIDefinitions is collection of all definitions.
|
||||
type OpenAPIDefinitions map[string]OpenAPIDefinition
|
||||
type GetOpenAPIDefinitions func(ReferenceCallback) map[string]OpenAPIDefinition
|
||||
|
||||
// OpenAPIDefinitionGetter gets openAPI definitions for a given type. If a type implements this interface,
|
||||
// the definition returned by it will be used, otherwise the auto-generated definitions will be used. See
|
||||
|
@ -59,11 +62,18 @@ type Config struct {
|
|||
|
||||
// OpenAPIDefinitions should provide definition for all models used by routes. Failure to provide this map
|
||||
// or any of the models will result in spec generation failure.
|
||||
Definitions *OpenAPIDefinitions
|
||||
GetDefinitions GetOpenAPIDefinitions
|
||||
|
||||
// GetOperationIDAndTags returns operation id and tags for a restful route. It is an optional function to customize operation IDs.
|
||||
GetOperationIDAndTags func(servePath string, r *restful.Route) (string, []string, error)
|
||||
|
||||
// GetDefinitionName returns a friendly name for a definition base on the serving path. parameter `name` is the full name of the definition.
|
||||
// It is an optional function to customize model names.
|
||||
GetDefinitionName func(servePath string, name string) (string, spec.Extensions)
|
||||
|
||||
// PostProcessSpec runs after the spec is ready to serve. It allows a final modification to the spec before serving.
|
||||
PostProcessSpec func(*spec.Swagger) (*spec.Swagger, error)
|
||||
|
||||
// SecurityDefinitions is list of all security definitions for OpenAPI service. If this is not nil, the user of config
|
||||
// is responsible to provide DefaultSecurity and (maybe) add unauthorized response to CommonResponses.
|
||||
SecurityDefinitions *spec.SecurityDefinitions
|
||||
|
@ -141,3 +151,10 @@ func GetOpenAPITypeFormat(typeName string) (string, string) {
|
|||
}
|
||||
return mapped[0], mapped[1]
|
||||
}
|
||||
|
||||
func EscapeJsonPointer(p string) string {
|
||||
// Escaping reference name using rfc6901
|
||||
p = strings.Replace(p, "~", "~0", -1)
|
||||
p = strings.Replace(p, "/", "~1", -1)
|
||||
return p
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv
|
|||
masterConfig = NewMasterConfig()
|
||||
masterConfig.GenericConfig.EnableProfiling = true
|
||||
masterConfig.GenericConfig.EnableMetrics = true
|
||||
masterConfig.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.OpenAPIDefinitions)
|
||||
masterConfig.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions)
|
||||
masterConfig.GenericConfig.OpenAPIConfig.Info = &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "Kubernetes",
|
||||
|
@ -195,7 +195,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv
|
|||
Description: "Default Response.",
|
||||
},
|
||||
}
|
||||
masterConfig.GenericConfig.OpenAPIConfig.Definitions = openapi.OpenAPIDefinitions
|
||||
masterConfig.GenericConfig.OpenAPIConfig.GetDefinitions = openapi.GetOpenAPIDefinitions
|
||||
masterConfig.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue