mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-02-22 07:03:28 +00:00
stop using util.ToRESTFriendlyName in favor of declared model names
Signed-off-by: Joe Betz <jpbetz@google.com>
This commit is contained in:
@@ -22,7 +22,6 @@ import (
|
||||
"os"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/util"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"k8s.io/kubernetes/pkg/generated/openapi"
|
||||
)
|
||||
@@ -38,7 +37,7 @@ func main() {
|
||||
|
||||
func output() error {
|
||||
refFunc := func(name string) spec.Ref {
|
||||
return spec.MustCreateRef(fmt.Sprintf("#/definitions/%s", util.ToRESTFriendlyName(name)))
|
||||
return spec.MustCreateRef(fmt.Sprintf("#/definitions/%s", name))
|
||||
}
|
||||
defs := openapi.GetOpenAPIDefinitions(refFunc)
|
||||
schemaDefs := make(map[string]spec.Schema, len(defs))
|
||||
@@ -50,12 +49,12 @@ func output() error {
|
||||
// the type.
|
||||
if schema, ok := v.Schema.Extensions[common.ExtensionV2Schema]; ok {
|
||||
if v2Schema, isOpenAPISchema := schema.(spec.Schema); isOpenAPISchema {
|
||||
schemaDefs[util.ToRESTFriendlyName(k)] = v2Schema
|
||||
schemaDefs[k] = v2Schema
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
schemaDefs[util.ToRESTFriendlyName(k)] = v.Schema
|
||||
schemaDefs[k] = v.Schema
|
||||
}
|
||||
data, err := json.Marshal(&spec.Swagger{
|
||||
SwaggerProps: spec.SwaggerProps{
|
||||
|
||||
@@ -19,6 +19,7 @@ package builder
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
v1 "k8s.io/api/autoscaling/v1"
|
||||
apiextensionshelpers "k8s.io/apiextensions-apiserver/pkg/apihelpers"
|
||||
apiextensionsinternal "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
@@ -57,8 +59,8 @@ const (
|
||||
objectMetaSchemaRef = "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||
listMetaSchemaRef = "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta"
|
||||
|
||||
typeMetaType = "k8s.io/apimachinery/pkg/apis/meta/v1.TypeMeta"
|
||||
objectMetaType = "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
|
||||
typeMetaType = "io.k8s.apimachinery.pkg.apis.meta.v1.TypeMeta"
|
||||
objectMetaType = "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||
|
||||
definitionPrefix = "#/definitions/"
|
||||
v3DefinitionPrefix = "#/components/schemas/"
|
||||
@@ -225,7 +227,7 @@ type CRDCanonicalTypeNamer struct {
|
||||
|
||||
// OpenAPICanonicalTypeName returns canonical type name for given CRD
|
||||
func (c *CRDCanonicalTypeNamer) OpenAPICanonicalTypeName() string {
|
||||
return fmt.Sprintf("%s/%s.%s", c.group, c.version, c.kind)
|
||||
return gvkToModelName(c.group, c.version, c.kind)
|
||||
}
|
||||
|
||||
// builder contains validation schema and basic naming information for a CRD in
|
||||
@@ -383,7 +385,11 @@ func (b *builder) buildKubeNative(crd *apiextensionsv1.CustomResourceDefinition,
|
||||
// and forbid anything outside of apiVersion, kind and metadata. We have to fix kubectl to stop doing this, e.g. by
|
||||
// adding additionalProperties=true support to explicitly allow additional fields.
|
||||
// TODO: fix kubectl to understand additionalProperties=true
|
||||
if schema == nil || (opts.V2 && (schema.XPreserveUnknownFields || crdPreserveUnknownFields)) {
|
||||
if schema == nil {
|
||||
ret = &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
|
||||
}
|
||||
} else if opts.V2 && (schema.XPreserveUnknownFields || crdPreserveUnknownFields) {
|
||||
ret = &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
|
||||
}
|
||||
@@ -497,7 +503,7 @@ func addTypeMetaProperties(s *spec.Schema, v2 bool) {
|
||||
|
||||
// buildListSchema builds the list kind schema for the CRD
|
||||
func (b *builder) buildListSchema(crd *apiextensionsv1.CustomResourceDefinition, opts Options) *spec.Schema {
|
||||
name := definitionPrefix + util.ToRESTFriendlyName(fmt.Sprintf("%s/%s/%s", b.group, b.version, b.kind))
|
||||
name := definitionPrefix + gvkToModelName(b.group, b.version, b.kind)
|
||||
doc := fmt.Sprintf("List of %s. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md", b.plural)
|
||||
s := new(spec.Schema).
|
||||
Typed("object", "").
|
||||
@@ -522,6 +528,13 @@ func (b *builder) buildListSchema(crd *apiextensionsv1.CustomResourceDefinition,
|
||||
return s
|
||||
}
|
||||
|
||||
func gvkToModelName(g, v, k string) string {
|
||||
groupParts := strings.Split(g, ".")
|
||||
slices.Reverse(groupParts)
|
||||
g = strings.Join(groupParts, ".")
|
||||
return fmt.Sprintf("%s.%s.%s", g, v, k)
|
||||
}
|
||||
|
||||
// getOpenAPIConfig builds config which wires up generated definitions for kube-openapi to consume
|
||||
func (b *builder) getOpenAPIConfig() *common.Config {
|
||||
return &common.Config{
|
||||
@@ -546,11 +559,11 @@ func (b *builder) getOpenAPIConfig() *common.Config {
|
||||
},
|
||||
GetDefinitions: func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
|
||||
def := utilopenapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(generatedopenapi.GetOpenAPIDefinitions)(ref)
|
||||
def[fmt.Sprintf("%s/%s.%s", b.group, b.version, b.kind)] = common.OpenAPIDefinition{
|
||||
def[gvkToModelName(b.group, b.version, b.kind)] = common.OpenAPIDefinition{
|
||||
Schema: *b.schema,
|
||||
Dependencies: []string{objectMetaType},
|
||||
}
|
||||
def[fmt.Sprintf("%s/%s.%s", b.group, b.version, b.listKind)] = common.OpenAPIDefinition{
|
||||
def[gvkToModelName(b.group, b.version, b.listKind)] = common.OpenAPIDefinition{
|
||||
Schema: *b.listSchema,
|
||||
}
|
||||
return def
|
||||
@@ -580,11 +593,11 @@ func (b *builder) getOpenAPIV3Config() *common.OpenAPIV3Config {
|
||||
},
|
||||
GetDefinitions: func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
|
||||
def := utilopenapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(generatedopenapi.GetOpenAPIDefinitions)(ref)
|
||||
def[fmt.Sprintf("%s/%s.%s", b.group, b.version, b.kind)] = common.OpenAPIDefinition{
|
||||
def[gvkToModelName(b.group, b.version, b.kind)] = common.OpenAPIDefinition{
|
||||
Schema: *b.schema,
|
||||
Dependencies: []string{objectMetaType},
|
||||
}
|
||||
def[fmt.Sprintf("%s/%s.%s", b.group, b.version, b.listKind)] = common.OpenAPIDefinition{
|
||||
def[gvkToModelName(b.group, b.version, b.listKind)] = common.OpenAPIDefinition{
|
||||
Schema: *b.listSchema,
|
||||
}
|
||||
return def
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kube-openapi/pkg/util"
|
||||
)
|
||||
|
||||
// Scheme defines methods for serializing and deserializing API objects, a type
|
||||
@@ -752,6 +753,9 @@ var internalPackages = []string{"k8s.io/apimachinery/pkg/runtime/scheme.go"}
|
||||
// The OpenAPI definition name is the canonical name of the type, with the group and version removed.
|
||||
// For example, the OpenAPI definition name of Pod is `io.k8s.api.core.v1.Pod`.
|
||||
//
|
||||
// This respects the util.OpenAPIModelNamer interface and will return the name returned by
|
||||
// OpenAPIModelName() if it is defined on the type.
|
||||
//
|
||||
// A known type that is registered as an unstructured.Unstructured type is treated as a custom resource and
|
||||
// which has an OpenAPI definition name of the form `<reversed-group>.<version.<kind>`.
|
||||
// For example, the OpenAPI definition name of `group: stable.example.com, version: v1, kind: Pod` is
|
||||
@@ -764,6 +768,12 @@ func (s *Scheme) ToOpenAPIDefinitionName(groupVersionKind schema.GroupVersionKin
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Use a namer if provided
|
||||
if namer, ok := example.(util.OpenAPIModelNamer); ok {
|
||||
return namer.OpenAPIModelName(), nil
|
||||
}
|
||||
|
||||
if _, ok := example.(Unstructured); ok {
|
||||
if groupVersionKind.Group == "" || groupVersionKind.Kind == "" {
|
||||
return "", fmt.Errorf("unable to convert GroupVersionKind with empty fields to unstructured type to an OpenAPI definition name: %v", groupVersionKind)
|
||||
|
||||
@@ -19,7 +19,6 @@ package openapi
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
@@ -29,6 +28,7 @@ import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kube-openapi/pkg/util"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
@@ -133,31 +133,28 @@ func gvkConvert(gvk schema.GroupVersionKind) v1.GroupVersionKind {
|
||||
}
|
||||
}
|
||||
|
||||
func typeName(t reflect.Type) string {
|
||||
path := t.PkgPath()
|
||||
if strings.Contains(path, "/vendor/") {
|
||||
path = path[strings.Index(path, "/vendor/")+len("/vendor/"):]
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", path, t.Name())
|
||||
}
|
||||
|
||||
// NewDefinitionNamer constructs a new DefinitionNamer to be used to customize OpenAPI spec.
|
||||
func NewDefinitionNamer(schemes ...*runtime.Scheme) *DefinitionNamer {
|
||||
ret := &DefinitionNamer{
|
||||
typeGroupVersionKinds: map[string]groupVersionKinds{},
|
||||
}
|
||||
for _, s := range schemes {
|
||||
for gvk, rtype := range s.AllKnownTypes() {
|
||||
for gvk := range s.AllKnownTypes() {
|
||||
newGVK := gvkConvert(gvk)
|
||||
exists := false
|
||||
for _, existingGVK := range ret.typeGroupVersionKinds[typeName(rtype)] {
|
||||
name, err := s.ToOpenAPIDefinitionName(gvk)
|
||||
if err != nil {
|
||||
klog.Fatalf("failed to get OpenAPI definition name for %v: %v", gvk, err)
|
||||
continue
|
||||
}
|
||||
for _, existingGVK := range ret.typeGroupVersionKinds[name] {
|
||||
if newGVK == existingGVK {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
ret.typeGroupVersionKinds[typeName(rtype)] = append(ret.typeGroupVersionKinds[typeName(rtype)], newGVK)
|
||||
ret.typeGroupVersionKinds[name] = append(ret.typeGroupVersionKinds[name], newGVK)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,9 +167,9 @@ func NewDefinitionNamer(schemes ...*runtime.Scheme) *DefinitionNamer {
|
||||
// GetDefinitionName returns the name and tags for a given definition
|
||||
func (d *DefinitionNamer) GetDefinitionName(name string) (string, spec.Extensions) {
|
||||
if groupVersionKinds, ok := d.typeGroupVersionKinds[name]; ok {
|
||||
return util.ToRESTFriendlyName(name), spec.Extensions{
|
||||
return name, spec.Extensions{
|
||||
extensionGVK: groupVersionKinds.JSON(),
|
||||
}
|
||||
}
|
||||
return util.ToRESTFriendlyName(name), nil
|
||||
return name, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user