Merge pull request #105057 from jiahuif-forks/feature/enum-types-feature-enablement

Add Support for OpenAPIEnum in OpenAPI v2

Kubernetes-commit: e14bdbaa1c4ed2b31dbce1b03160402483d26889
This commit is contained in:
Kubernetes Publisher 2021-11-16 16:35:55 -08:00
commit e7910294ba
4 changed files with 210 additions and 20 deletions

19
go.mod
View File

@ -12,7 +12,6 @@ require (
github.com/emicklei/go-restful v2.9.5+incompatible
github.com/evanphx/json-patch v4.12.0+incompatible
github.com/fsnotify/fsnotify v1.4.9
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/gogo/protobuf v1.3.2
@ -44,12 +43,12 @@ require (
google.golang.org/grpc v1.40.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/square/go-jose.v2 v2.2.2
k8s.io/api v0.0.0-20211116232201-3ba85978261d
k8s.io/apimachinery v0.0.0-20211116191949-10158cf6d3ff
k8s.io/client-go v0.0.0-20211116232531-d9ceca58715c
k8s.io/component-base v0.0.0-20211115192801-2ba78dffde88
k8s.io/api v0.0.0-20211117032144-b7adf12040d3
k8s.io/apimachinery v0.0.0-20211117031931-f3cf56ed60da
k8s.io/client-go v0.0.0-20211117032455-e2c9d634d6ba
k8s.io/component-base v0.0.0-20211117033035-2a12018533a2
k8s.io/klog/v2 v2.30.0
k8s.io/kube-openapi v0.0.0-20211105084753-ee342a809c29
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.25
sigs.k8s.io/structured-merge-diff/v4 v4.2.0
@ -57,8 +56,8 @@ require (
)
replace (
k8s.io/api => k8s.io/api v0.0.0-20211116232201-3ba85978261d
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20211116191949-10158cf6d3ff
k8s.io/client-go => k8s.io/client-go v0.0.0-20211116232531-d9ceca58715c
k8s.io/component-base => k8s.io/component-base v0.0.0-20211115192801-2ba78dffde88
k8s.io/api => k8s.io/api v0.0.0-20211117032144-b7adf12040d3
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20211117031931-f3cf56ed60da
k8s.io/client-go => k8s.io/client-go v0.0.0-20211117032455-e2c9d634d6ba
k8s.io/component-base => k8s.io/component-base v0.0.0-20211117033035-2a12018533a2
)

22
go.sum
View File

@ -147,6 +147,7 @@ github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -255,6 +256,7 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@ -951,21 +953,21 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.0.0-20211116232201-3ba85978261d h1:1nPNhVa28WnzWaJ42b49kcwa05Z2qqxcqPYD0OEHQJ8=
k8s.io/api v0.0.0-20211116232201-3ba85978261d/go.mod h1:EgyfCRAySNu6W9i8g81nY2/AJR7UVniCSHwGWPDshGs=
k8s.io/apimachinery v0.0.0-20211116191949-10158cf6d3ff h1:48ZHXvUs3bTxiEDlE97wNDgMMCRLmVdqV+/W2d7Hvpg=
k8s.io/apimachinery v0.0.0-20211116191949-10158cf6d3ff/go.mod h1:/fTTuFZJpMy6M4dc6F6QbWWj88D/Yd/ZdqJMvTIcbkE=
k8s.io/client-go v0.0.0-20211116232531-d9ceca58715c h1:SDq4/91oIjf7l+P75rjlP5jOa+XP56qTzaD9RcQheDU=
k8s.io/client-go v0.0.0-20211116232531-d9ceca58715c/go.mod h1:ucUV9EL6PE378vUCjYaoKbFsIcXbO4ObSfCOKgoj/88=
k8s.io/component-base v0.0.0-20211115192801-2ba78dffde88 h1:Vx0Rn2Mw8GS2IlGhN5SMRhU9WIm4jnCkruJwGZLYYGE=
k8s.io/component-base v0.0.0-20211115192801-2ba78dffde88/go.mod h1:1FNCGI8+JFGNYTnOJidyT0C6gBaT3hZp0P5Nv/9NKr8=
k8s.io/api v0.0.0-20211117032144-b7adf12040d3 h1:OUKo3mc2wSOr2GGk0MiMWhZOca1INVHD0Ol0zHOmlKU=
k8s.io/api v0.0.0-20211117032144-b7adf12040d3/go.mod h1:B1McGV/Uyv/c0sGZKsHMP4FArbyZZ8Emx+a7h5d/tMs=
k8s.io/apimachinery v0.0.0-20211117031931-f3cf56ed60da h1:7W2cMPNnhm4snbd4zGcOBzi233V4+x1jHHeDq2Fr/nE=
k8s.io/apimachinery v0.0.0-20211117031931-f3cf56ed60da/go.mod h1:SqloDTPqePPNhEp8K4qUgqpKc3tE+ymn05iIUbSAQ7g=
k8s.io/client-go v0.0.0-20211117032455-e2c9d634d6ba h1:50gtTEoxTr6LY/cqZ5POZzXjpIH9ls1r+LlioQz7r7E=
k8s.io/client-go v0.0.0-20211117032455-e2c9d634d6ba/go.mod h1:/6rSxWdcMfCPQ+BnsLCvWe5BDUArFuNGE4x2m7q2zqc=
k8s.io/component-base v0.0.0-20211117033035-2a12018533a2 h1:Eq5F+Yl0w7BUS2I1rrij995N9L/QaHUuv+wmjCNy1jQ=
k8s.io/component-base v0.0.0-20211117033035-2a12018533a2/go.mod h1:M8S6yaytGn7h1Xxa64Mk0MrYcKPEDf2R1ynxXfbUKDM=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20211105084753-ee342a809c29 h1:SgxutK76kGA2O/LIjRjoJ2ABggpGJlaJOiLyOdCjEsU=
k8s.io/kube-openapi v0.0.0-20211105084753-ee342a809c29/go.mod h1:X90lRFlqk35/w9FG4WIvZqMPfG3WrZGzdlSaL6uh7rc=
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4=
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs=
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=

View File

@ -0,0 +1,83 @@
/*
Copyright 2021 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 (
"strings"
genericfeatures "k8s.io/apiserver/pkg/features"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kube-openapi/pkg/common"
"k8s.io/kube-openapi/pkg/schemamutation"
"k8s.io/kube-openapi/pkg/validation/spec"
)
// enumTypeDescriptionHeader is the header of enum section in schema description.
const enumTypeDescriptionHeader = "Possible enum values:"
// GetOpenAPIDefinitionsWithoutDisabledFeatures wraps a GetOpenAPIDefinitions to revert
// any change to the schema that was made by disabled features.
func GetOpenAPIDefinitionsWithoutDisabledFeatures(GetOpenAPIDefinitions common.GetOpenAPIDefinitions) common.GetOpenAPIDefinitions {
return func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
defs := GetOpenAPIDefinitions(ref)
restoreDefinitions(defs)
return defs
}
}
// restoreDefinitions restores any changes by disabled features from definition map.
func restoreDefinitions(defs map[string]common.OpenAPIDefinition) {
// revert changes from OpenAPIEnums
if !utilfeature.DefaultFeatureGate.Enabled(genericfeatures.OpenAPIEnums) {
for gvk, def := range defs {
orig := &def.Schema
if ret := pruneEnums(orig); ret != orig {
def.Schema = *ret
defs[gvk] = def
}
}
}
}
func pruneEnums(schema *spec.Schema) *spec.Schema {
walker := schemamutation.Walker{
SchemaCallback: func(schema *spec.Schema) *spec.Schema {
orig := schema
clone := func() {
if orig == schema { // if schema has not been mutated yet
schema = new(spec.Schema)
*schema = *orig // make a clone from orig to schema
}
}
if headerIndex := strings.Index(schema.Description, enumTypeDescriptionHeader); headerIndex != -1 {
// remove the enum section from description.
// note that the new lines before the header should be removed too,
// thus the slice range.
clone()
schema.Description = schema.Description[:headerIndex]
}
if len(schema.Enum) != 0 {
// remove the enum field
clone()
schema.Enum = nil
}
return schema
},
RefCallback: schemamutation.RefCallbackNoop,
}
return walker.WalkSchema(schema)
}

View File

@ -0,0 +1,106 @@
/*
Copyright 2021 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 (
"strings"
"testing"
"k8s.io/kube-openapi/pkg/common"
"k8s.io/kube-openapi/pkg/validation/spec"
)
func schema_k8sio_api_apps_v1_DeploymentCondition(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "DeploymentCondition describes the state of a deployment at a certain point.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"type": {
SchemaProps: spec.SchemaProps{
Description: "Type of deployment condition.\n\nPossible enum values:\n - `Available`: Available means the deployment is available, ie. at least the minimum available replicas required are up and running for at least minReadySeconds.\n - `Progressing`: Progressing means the deployment is progressing. Progress for a deployment is considered when a new replica set is created or adopted, and when new pods scale up or old pods scale down. Progress is not estimated for paused deployments or when progressDeadlineSeconds is not specified.\n - `ReplicaFailure`: ReplicaFailure is added in a deployment when one of its pods fails to be created or deleted.",
Default: "",
Type: []string{"string"},
Format: "",
Enum: []interface{}{"Available", "Progressing", "ReplicaFailure"}},
},
"status": {
SchemaProps: spec.SchemaProps{
Description: "Status of the condition, one of True, False, Unknown.\n\nPossible enum values:\n - `False`:\n - `True`:\n - `Unknown`:",
Default: "",
Type: []string{"string"},
Format: "",
Enum: []interface{}{"False", "True", "Unknown"}},
},
"lastUpdateTime": {
SchemaProps: spec.SchemaProps{
Description: "The last time this condition was updated.",
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},
"lastTransitionTime": {
SchemaProps: spec.SchemaProps{
Description: "Last time the condition transitioned from one status to another.",
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},
"reason": {
SchemaProps: spec.SchemaProps{
Description: "The reason for the condition's last transition.",
Type: []string{"string"},
Format: "",
},
},
"message": {
SchemaProps: spec.SchemaProps{
Description: "A human readable message indicating details about the transition.",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"type", "status"},
},
},
Dependencies: []string{
"k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
var getOpenAPIDefs common.GetOpenAPIDefinitions = func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"k8s.io/api/apps/v1.DeploymentCondition": schema_k8sio_api_apps_v1_DeploymentCondition(ref),
}
}
func TestGetOpenAPIDefinitionsWithoutDisabledFeatures(t *testing.T) {
defs := GetOpenAPIDefinitionsWithoutDisabledFeatures(getOpenAPIDefs)(func(path string) spec.Ref {
return spec.Ref{}
})
def := defs["k8s.io/api/apps/v1.DeploymentCondition"]
for _, prop := range def.Schema.Properties {
if strings.Contains(prop.Description, "enum") {
t.Errorf("enum in description: %s", prop.Description)
}
if len(prop.Enum) != 0 {
t.Errorf("unexpected enum: %v", prop.Enum)
}
}
}