Unverified Commit b18846cf authored by Kubernetes Prow Robot's avatar Kubernetes Prow Robot Committed by GitHub

Merge pull request #78426 from sttts/sttts-crd-conversion-beta

apiextensions: promote CRD conversion to beta
parents 59f0f2d2 c6928752
...@@ -16340,7 +16340,7 @@ ...@@ -16340,7 +16340,7 @@
"type": "array" "type": "array"
}, },
"strategy": { "strategy": {
"description": "`strategy` specifies the conversion strategy. Allowed values are: - `None`: The converter only change the apiVersion and would not touch any other field in the CR. - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information is needed for this option.", "description": "`strategy` specifies the conversion strategy. Allowed values are: - `None`: The converter only change the apiVersion and would not touch any other field in the CR. - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information\n is needed for this option. This requires spec.preserveUnknownFields to be false.",
"type": "string" "type": "string"
}, },
"webhookClientConfig": { "webhookClientConfig": {
...@@ -545,7 +545,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS ...@@ -545,7 +545,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
// unintentionally on either side: // unintentionally on either side:
apiextensionsfeatures.CustomResourceValidation: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourceValidation: {Default: true, PreRelease: featuregate.Beta},
apiextensionsfeatures.CustomResourceSubresources: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourceSubresources: {Default: true, PreRelease: featuregate.Beta},
apiextensionsfeatures.CustomResourceWebhookConversion: {Default: false, PreRelease: featuregate.Alpha}, apiextensionsfeatures.CustomResourceWebhookConversion: {Default: true, PreRelease: featuregate.Beta},
apiextensionsfeatures.CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.Beta},
apiextensionsfeatures.CustomResourceDefaulting: {Default: false, PreRelease: featuregate.Alpha}, apiextensionsfeatures.CustomResourceDefaulting: {Default: false, PreRelease: featuregate.Alpha},
......
...@@ -85,7 +85,8 @@ type CustomResourceDefinitionSpec struct { ...@@ -85,7 +85,8 @@ type CustomResourceDefinitionSpec struct {
type CustomResourceConversion struct { type CustomResourceConversion struct {
// `strategy` specifies the conversion strategy. Allowed values are: // `strategy` specifies the conversion strategy. Allowed values are:
// - `None`: The converter only change the apiVersion and would not touch any other field in the CR. // - `None`: The converter only change the apiVersion and would not touch any other field in the CR.
// - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information is needed for this option. // - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information
// is needed for this option. This requires spec.preserveUnknownFields to be false.
Strategy ConversionStrategyType Strategy ConversionStrategyType
// `webhookClientConfig` is the instructions for how to call the webhook if strategy is `Webhook`. // `webhookClientConfig` is the instructions for how to call the webhook if strategy is `Webhook`.
......
...@@ -107,7 +107,8 @@ message CustomResourceColumnDefinition { ...@@ -107,7 +107,8 @@ message CustomResourceColumnDefinition {
message CustomResourceConversion { message CustomResourceConversion {
// `strategy` specifies the conversion strategy. Allowed values are: // `strategy` specifies the conversion strategy. Allowed values are:
// - `None`: The converter only change the apiVersion and would not touch any other field in the CR. // - `None`: The converter only change the apiVersion and would not touch any other field in the CR.
// - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information is needed for this option. // - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information
// is needed for this option. This requires spec.preserveUnknownFields to be false.
optional string strategy = 1; optional string strategy = 1;
// `webhookClientConfig` is the instructions for how to call the webhook if strategy is `Webhook`. This field is // `webhookClientConfig` is the instructions for how to call the webhook if strategy is `Webhook`. This field is
......
...@@ -90,7 +90,8 @@ type CustomResourceDefinitionSpec struct { ...@@ -90,7 +90,8 @@ type CustomResourceDefinitionSpec struct {
type CustomResourceConversion struct { type CustomResourceConversion struct {
// `strategy` specifies the conversion strategy. Allowed values are: // `strategy` specifies the conversion strategy. Allowed values are:
// - `None`: The converter only change the apiVersion and would not touch any other field in the CR. // - `None`: The converter only change the apiVersion and would not touch any other field in the CR.
// - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information is needed for this option. // - `Webhook`: API Server will call to an external webhook to do the conversion. Additional information
// is needed for this option. This requires spec.preserveUnknownFields to be false.
Strategy ConversionStrategyType `json:"strategy" protobuf:"bytes,1,name=strategy"` Strategy ConversionStrategyType `json:"strategy" protobuf:"bytes,1,name=strategy"`
// `webhookClientConfig` is the instructions for how to call the webhook if strategy is `Webhook`. This field is // `webhookClientConfig` is the instructions for how to call the webhook if strategy is `Webhook`. This field is
......
...@@ -121,10 +121,10 @@ func ValidateCustomResourceDefinitionVersion(version *apiextensions.CustomResour ...@@ -121,10 +121,10 @@ func ValidateCustomResourceDefinitionVersion(version *apiextensions.CustomResour
// ValidateCustomResourceDefinitionSpec statically validates // ValidateCustomResourceDefinitionSpec statically validates
func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefinitionSpec, fldPath *field.Path) field.ErrorList { func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefinitionSpec, fldPath *field.Path) field.ErrorList {
allowDefaults := utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceDefaulting) allowDefaults := utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceDefaulting)
return validateCustomResourceDefinitionSpec(spec, true, allowDefaults, fldPath) return validateCustomResourceDefinitionSpec(spec, true, allowDefaults, false, fldPath)
} }
func validateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefinitionSpec, requireRecognizedVersion, allowDefaults bool, fldPath *field.Path) field.ErrorList { func validateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefinitionSpec, requireRecognizedVersion, allowDefaults, allowConversionWithPreserveUnknownFields bool, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if len(spec.Group) == 0 { if len(spec.Group) == 0 {
...@@ -237,11 +237,18 @@ func validateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi ...@@ -237,11 +237,18 @@ func validateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi
} }
} }
if !allowConversionWithPreserveUnknownFields && conversionAndPreserveUnknownFields(spec) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("conversion").Child("strategy"), spec.Conversion.Strategy, "must be None if spec.preserveUnknownFields is true"))
}
allErrs = append(allErrs, validateCustomResourceConversion(spec.Conversion, requireRecognizedVersion, fldPath.Child("conversion"))...) allErrs = append(allErrs, validateCustomResourceConversion(spec.Conversion, requireRecognizedVersion, fldPath.Child("conversion"))...)
return allErrs return allErrs
} }
func conversionAndPreserveUnknownFields(spec *apiextensions.CustomResourceDefinitionSpec) bool {
return (spec.Conversion != nil && spec.Conversion.Strategy != apiextensions.NoneConverter) && (spec.PreserveUnknownFields == nil || *spec.PreserveUnknownFields)
}
func validateEnumStrings(fldPath *field.Path, value string, accepted []string, required bool) field.ErrorList { func validateEnumStrings(fldPath *field.Path, value string, accepted []string, required bool) field.ErrorList {
if value == "" { if value == "" {
if required { if required {
...@@ -359,7 +366,7 @@ func ValidateCustomResourceDefinitionSpecUpdate(spec, oldSpec *apiextensions.Cus ...@@ -359,7 +366,7 @@ func ValidateCustomResourceDefinitionSpecUpdate(spec, oldSpec *apiextensions.Cus
// find out whether any schema had default before. Then we keep allowing it. // find out whether any schema had default before. Then we keep allowing it.
allowDefaults := utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceDefaulting) || specHasDefaults(oldSpec) allowDefaults := utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceDefaulting) || specHasDefaults(oldSpec)
allErrs := validateCustomResourceDefinitionSpec(spec, requireRecognizedVersion, allowDefaults, fldPath) allErrs := validateCustomResourceDefinitionSpec(spec, requireRecognizedVersion, allowDefaults, conversionAndPreserveUnknownFields(oldSpec), fldPath)
if established { if established {
// these effect the storage and cannot be changed therefore // these effect the storage and cannot be changed therefore
......
...@@ -71,7 +71,7 @@ func init() { ...@@ -71,7 +71,7 @@ func init() {
var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
CustomResourceValidation: {Default: true, PreRelease: featuregate.Beta}, CustomResourceValidation: {Default: true, PreRelease: featuregate.Beta},
CustomResourceSubresources: {Default: true, PreRelease: featuregate.Beta}, CustomResourceSubresources: {Default: true, PreRelease: featuregate.Beta},
CustomResourceWebhookConversion: {Default: false, PreRelease: featuregate.Alpha}, CustomResourceWebhookConversion: {Default: true, PreRelease: featuregate.Beta},
CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.Beta}, CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.Beta},
CustomResourceDefaulting: {Default: false, PreRelease: featuregate.Alpha}, CustomResourceDefaulting: {Default: false, PreRelease: featuregate.Alpha},
} }
...@@ -157,7 +157,6 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) { ...@@ -157,7 +157,6 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) { func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil { if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec oldCRDSpec = &oldCRD.Spec
......
...@@ -28,10 +28,6 @@ import ( ...@@ -28,10 +28,6 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
...@@ -48,6 +44,10 @@ import ( ...@@ -48,6 +44,10 @@ import (
"k8s.io/utils/pointer" "k8s.io/utils/pointer"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
"k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apiextensions-apiserver/test/integration/fixtures"
"k8s.io/apiextensions-apiserver/test/integration/storage" "k8s.io/apiextensions-apiserver/test/integration/storage"
) )
...@@ -59,18 +59,14 @@ func checks(checkers ...Checker) []Checker { ...@@ -59,18 +59,14 @@ func checks(checkers ...Checker) []Checker {
} }
func TestWebhookConverter(t *testing.T) { func TestWebhookConverter(t *testing.T) {
testWebhookConverter(t, false, false) testWebhookConverter(t, false)
}
func TestWebhookConverterWithPruning(t *testing.T) {
testWebhookConverter(t, true, false)
} }
func TestWebhookConverterWithDefaulting(t *testing.T) { func TestWebhookConverterWithDefaulting(t *testing.T) {
testWebhookConverter(t, true, true) testWebhookConverter(t, true)
} }
func testWebhookConverter(t *testing.T, pruning, defaulting bool) { func testWebhookConverter(t *testing.T, defaulting bool) {
tests := []struct { tests := []struct {
group string group string
handler http.Handler handler http.Handler
...@@ -115,7 +111,6 @@ func testWebhookConverter(t *testing.T, pruning, defaulting bool) { ...@@ -115,7 +111,6 @@ func testWebhookConverter(t *testing.T, pruning, defaulting bool) {
defer etcd3watcher.TestOnlySetFatalOnDecodeError(true) defer etcd3watcher.TestOnlySetFatalOnDecodeError(true)
// enable necessary features // enable necessary features
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
if defaulting { if defaulting {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceDefaulting, true)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceDefaulting, true)()
} }
...@@ -139,7 +134,6 @@ func testWebhookConverter(t *testing.T, pruning, defaulting bool) { ...@@ -139,7 +134,6 @@ func testWebhookConverter(t *testing.T, pruning, defaulting bool) {
defer tearDown() defer tearDown()
crd := multiVersionFixture.DeepCopy() crd := multiVersionFixture.DeepCopy()
crd.Spec.PreserveUnknownFields = pointer.BoolPtr(!pruning)
if !defaulting { if !defaulting {
for i := range crd.Spec.Versions { for i := range crd.Spec.Versions {
...@@ -994,7 +988,8 @@ var multiVersionFixture = &apiextensionsv1beta1.CustomResourceDefinition{ ...@@ -994,7 +988,8 @@ var multiVersionFixture = &apiextensionsv1beta1.CustomResourceDefinition{
ListKind: "MultiVersionList", ListKind: "MultiVersionList",
Categories: []string{"all"}, Categories: []string{"all"},
}, },
Scope: apiextensionsv1beta1.NamespaceScoped, Scope: apiextensionsv1beta1.NamespaceScoped,
PreserveUnknownFields: pointer.BoolPtr(false),
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
{ {
// storage version, same schema as v1alpha1 // storage version, same schema as v1alpha1
......
...@@ -25,18 +25,16 @@ import ( ...@@ -25,18 +25,16 @@ import (
"testing" "testing"
autoscaling "k8s.io/api/autoscaling/v1" autoscaling "k8s.io/api/autoscaling/v1"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
featuregatetesting "k8s.io/component-base/featuregate/testing"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
) )
var labelSelectorPath = ".status.labelSelector" var labelSelectorPath = ".status.labelSelector"
...@@ -148,7 +146,6 @@ func NewNoxuSubresourceInstance(namespace, name, version string) *unstructured.U ...@@ -148,7 +146,6 @@ func NewNoxuSubresourceInstance(namespace, name, version string) *unstructured.U
} }
func TestStatusSubresource(t *testing.T) { func TestStatusSubresource(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -261,7 +258,6 @@ func TestStatusSubresource(t *testing.T) { ...@@ -261,7 +258,6 @@ func TestStatusSubresource(t *testing.T) {
} }
func TestScaleSubresource(t *testing.T) { func TestScaleSubresource(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
groupResource := schema.GroupResource{ groupResource := schema.GroupResource{
Group: "mygroup.example.com", Group: "mygroup.example.com",
Resource: "noxus", Resource: "noxus",
...@@ -407,7 +403,6 @@ func TestScaleSubresource(t *testing.T) { ...@@ -407,7 +403,6 @@ func TestScaleSubresource(t *testing.T) {
} }
func TestValidationSchemaWithStatus(t *testing.T) { func TestValidationSchemaWithStatus(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, config, _, err := fixtures.StartDefaultServer(t) tearDown, config, _, err := fixtures.StartDefaultServer(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -455,7 +450,6 @@ func TestValidationSchemaWithStatus(t *testing.T) { ...@@ -455,7 +450,6 @@ func TestValidationSchemaWithStatus(t *testing.T) {
} }
func TestValidateOnlyStatus(t *testing.T) { func TestValidateOnlyStatus(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -562,7 +556,6 @@ func TestValidateOnlyStatus(t *testing.T) { ...@@ -562,7 +556,6 @@ func TestValidateOnlyStatus(t *testing.T) {
} }
func TestSubresourcesDiscovery(t *testing.T) { func TestSubresourcesDiscovery(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, config, _, err := fixtures.StartDefaultServer(t) tearDown, config, _, err := fixtures.StartDefaultServer(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -654,7 +647,6 @@ func TestSubresourcesDiscovery(t *testing.T) { ...@@ -654,7 +647,6 @@ func TestSubresourcesDiscovery(t *testing.T) {
} }
func TestGeneration(t *testing.T) { func TestGeneration(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -728,7 +720,6 @@ func TestGeneration(t *testing.T) { ...@@ -728,7 +720,6 @@ func TestGeneration(t *testing.T) {
} }
func TestSubresourcePatch(t *testing.T) { func TestSubresourcePatch(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
groupResource := schema.GroupResource{ groupResource := schema.GroupResource{
Group: "mygroup.example.com", Group: "mygroup.example.com",
Resource: "noxus", Resource: "noxus",
......
...@@ -21,7 +21,6 @@ import ( ...@@ -21,7 +21,6 @@ import (
"testing" "testing"
"time" "time"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
...@@ -29,13 +28,11 @@ import ( ...@@ -29,13 +28,11 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
featuregatetesting "k8s.io/component-base/featuregate/testing"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apiextensions-apiserver/test/integration/fixtures"
) )
...@@ -104,7 +101,6 @@ func newTableInstance(name string) *unstructured.Unstructured { ...@@ -104,7 +101,6 @@ func newTableInstance(name string) *unstructured.Unstructured {
} }
func TestTableGet(t *testing.T) { func TestTableGet(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, config, _, err := fixtures.StartDefaultServer(t) tearDown, config, _, err := fixtures.StartDefaultServer(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -262,7 +258,6 @@ func TestTableGet(t *testing.T) { ...@@ -262,7 +258,6 @@ func TestTableGet(t *testing.T) {
// TestColumnsPatch tests the case that a CRD was created with no top-level or // TestColumnsPatch tests the case that a CRD was created with no top-level or
// per-version columns. One should be able to PATCH the CRD setting per-version columns. // per-version columns. One should be able to PATCH the CRD setting per-version columns.
func TestColumnsPatch(t *testing.T) { func TestColumnsPatch(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, config, _, err := fixtures.StartDefaultServer(t) tearDown, config, _, err := fixtures.StartDefaultServer(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -307,7 +302,6 @@ func TestColumnsPatch(t *testing.T) { ...@@ -307,7 +302,6 @@ func TestColumnsPatch(t *testing.T) {
// One should be able to PATCH the CRD cleaning the top-level columns and setting per-version // One should be able to PATCH the CRD cleaning the top-level columns and setting per-version
// columns. // columns.
func TestPatchCleanTopLevelColumns(t *testing.T) { func TestPatchCleanTopLevelColumns(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, config, _, err := fixtures.StartDefaultServer(t) tearDown, config, _, err := fixtures.StartDefaultServer(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
......
...@@ -22,17 +22,14 @@ import ( ...@@ -22,17 +22,14 @@ import (
"testing" "testing"
"time" "time"
clientschema "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" clientschema "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme"
"k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apiextensions-apiserver/test/integration/fixtures"
) )
...@@ -224,7 +221,6 @@ func newNoxuValidationInstance(namespace, name string) *unstructured.Unstructure ...@@ -224,7 +221,6 @@ func newNoxuValidationInstance(namespace, name string) *unstructured.Unstructure
} }
func TestCustomResourceValidation(t *testing.T) { func TestCustomResourceValidation(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -256,7 +252,6 @@ func TestCustomResourceValidation(t *testing.T) { ...@@ -256,7 +252,6 @@ func TestCustomResourceValidation(t *testing.T) {
} }
func TestCustomResourceUpdateValidation(t *testing.T) { func TestCustomResourceUpdateValidation(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -310,7 +305,6 @@ func TestCustomResourceUpdateValidation(t *testing.T) { ...@@ -310,7 +305,6 @@ func TestCustomResourceUpdateValidation(t *testing.T) {
} }
func TestCustomResourceValidationErrors(t *testing.T) { func TestCustomResourceValidationErrors(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -411,7 +405,6 @@ func TestCustomResourceValidationErrors(t *testing.T) { ...@@ -411,7 +405,6 @@ func TestCustomResourceValidationErrors(t *testing.T) {
} }
func TestCRValidationOnCRDUpdate(t *testing.T) { func TestCRValidationOnCRDUpdate(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -483,7 +476,6 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { ...@@ -483,7 +476,6 @@ func TestCRValidationOnCRDUpdate(t *testing.T) {
} }
func TestForbiddenFieldsInSchema(t *testing.T) { func TestForbiddenFieldsInSchema(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -542,8 +534,6 @@ func TestForbiddenFieldsInSchema(t *testing.T) { ...@@ -542,8 +534,6 @@ func TestForbiddenFieldsInSchema(t *testing.T) {
} }
func TestNonStructuralSchemaConditionUpdate(t *testing.T) { func TestNonStructuralSchemaConditionUpdate(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -684,8 +674,6 @@ spec: ...@@ -684,8 +674,6 @@ spec:
} }
func TestNonStructuralSchemaCondition(t *testing.T) { func TestNonStructuralSchemaCondition(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t) tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
......
...@@ -27,13 +27,10 @@ import ( ...@@ -27,13 +27,10 @@ import (
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
featuregatetesting "k8s.io/component-base/featuregate/testing"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
"k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apiextensions-apiserver/test/integration/fixtures"
) )
...@@ -357,7 +354,6 @@ values: ...@@ -357,7 +354,6 @@ values:
} }
func TestYAMLSubresource(t *testing.T) { func TestYAMLSubresource(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)()
tearDown, config, _, err := fixtures.StartDefaultServer(t) tearDown, config, _, err := fixtures.StartDefaultServer(t)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
......
...@@ -19,11 +19,12 @@ package apimachinery ...@@ -19,11 +19,12 @@ package apimachinery
import ( import (
"time" "time"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
apps "k8s.io/api/apps/v1" apps "k8s.io/api/apps/v1"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/test/integration"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
...@@ -38,8 +39,8 @@ import ( ...@@ -38,8 +39,8 @@ import (
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
"k8s.io/utils/pointer" "k8s.io/utils/pointer"
"github.com/onsi/ginkgo" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"github.com/onsi/gomega" "k8s.io/apiextensions-apiserver/test/integration"
// ensure libs have a chance to initialize // ensure libs have a chance to initialize
_ "github.com/stretchr/testify/assert" _ "github.com/stretchr/testify/assert"
...@@ -60,11 +61,28 @@ var apiVersions = []v1beta1.CustomResourceDefinitionVersion{ ...@@ -60,11 +61,28 @@ var apiVersions = []v1beta1.CustomResourceDefinitionVersion{
Name: "v1", Name: "v1",
Served: true, Served: true,
Storage: true, Storage: true,
Schema: &v1beta1.CustomResourceValidation{
OpenAPIV3Schema: &v1beta1.JSONSchemaProps{
Type: "object",
Properties: map[string]v1beta1.JSONSchemaProps{
"hostPort": {Type: "string"},
},
},
},
}, },
{ {
Name: "v2", Name: "v2",
Served: true, Served: true,
Storage: false, Storage: false,
Schema: &v1beta1.CustomResourceValidation{
OpenAPIV3Schema: &v1beta1.JSONSchemaProps{
Type: "object",
Properties: map[string]v1beta1.JSONSchemaProps{
"host": {Type: "string"},
"port": {Type: "string"},
},
},
},
}, },
} }
...@@ -73,15 +91,32 @@ var alternativeAPIVersions = []v1beta1.CustomResourceDefinitionVersion{ ...@@ -73,15 +91,32 @@ var alternativeAPIVersions = []v1beta1.CustomResourceDefinitionVersion{
Name: "v1", Name: "v1",
Served: true, Served: true,
Storage: false, Storage: false,
Schema: &v1beta1.CustomResourceValidation{
OpenAPIV3Schema: &v1beta1.JSONSchemaProps{
Type: "object",
Properties: map[string]v1beta1.JSONSchemaProps{
"hostPort": {Type: "string"},
},
},
},
}, },
{ {
Name: "v2", Name: "v2",
Served: true, Served: true,
Storage: true, Storage: true,
Schema: &v1beta1.CustomResourceValidation{
OpenAPIV3Schema: &v1beta1.JSONSchemaProps{
Type: "object",
Properties: map[string]v1beta1.JSONSchemaProps{
"host": {Type: "string"},
"port": {Type: "string"},
},
},
},
}, },
} }
var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebhookConversion]", func() { var _ = SIGDescribe("CustomResourceConversionWebhook", func() {
var context *certContext var context *certContext
f := framework.NewDefaultFramework("crd-webhook") f := framework.NewDefaultFramework("crd-webhook")
...@@ -121,6 +156,7 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh ...@@ -121,6 +156,7 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh
}, },
}, },
} }
crd.Spec.PreserveUnknownFields = pointer.BoolPtr(false)
}) })
if err != nil { if err != nil {
return return
...@@ -144,6 +180,7 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh ...@@ -144,6 +180,7 @@ var _ = SIGDescribe("CustomResourceConversionWebhook [Feature:CustomResourceWebh
}, },
}, },
} }
crd.Spec.PreserveUnknownFields = pointer.BoolPtr(false)
}) })
if err != nil { if err != nil {
return return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment