Skip to content

Commit 6477e1e

Browse files
committed
🌱 Remove deprecated ClusterResourceSet feature gate
1 parent 4d7fffc commit 6477e1e

File tree

5 files changed

+189
-235
lines changed

5 files changed

+189
-235
lines changed

.golangci.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,6 @@ linters:
261261
- linters:
262262
- staticcheck
263263
text: 'SA1019: (clusterv1alpha3.*|clusterv1alpha4.*) is deprecated: This type will be removed in one of the next releases.'
264-
# Specific exclude rules for deprecated feature flags
265-
- linters:
266-
- staticcheck
267-
text: 'SA1019: feature.ClusterResourceSet is deprecated: ClusterResourceSet feature is now GA and the corresponding feature flag will be removed in 1.12 release.'
268264
# v1Beta1 deprecated fields
269265
- linters:
270266
- staticcheck

feature/feature.go

Lines changed: 61 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -18,86 +18,76 @@ limitations under the License.
1818
package feature
1919

2020
import (
21-
"k8s.io/apimachinery/pkg/util/runtime"
22-
"k8s.io/component-base/featuregate"
21+
"k8s.io/apimachinery/pkg/util/runtime"
22+
"k8s.io/component-base/featuregate"
2323
)
2424

2525
const (
26-
// Every feature gate should add method here following this template:
27-
//
28-
// // owner: @username
29-
// // alpha: v1.X
30-
// MyFeature featuregate.Feature = "MyFeature".
31-
32-
// MachinePool is a feature gate for MachinePool functionality.
33-
//
34-
// alpha: v0.3
35-
// beta: v1.7
36-
MachinePool featuregate.Feature = "MachinePool"
37-
38-
// ClusterResourceSet is a feature gate for the ClusterResourceSet functionality.
39-
//
40-
// alpha: v0.3
41-
// beta: v0.4
42-
// GA: v1.10
43-
//
44-
// Deprecated: ClusterResourceSet feature is now GA and the corresponding feature flag will be removed in 1.12 release.
45-
ClusterResourceSet featuregate.Feature = "ClusterResourceSet"
46-
47-
// ClusterTopology is a feature gate for the ClusterClass and managed topologies functionality.
48-
//
49-
// alpha: v0.4
50-
ClusterTopology featuregate.Feature = "ClusterTopology"
51-
52-
// RuntimeSDK is a feature gate for the Runtime hooks and extensions functionality.
53-
//
54-
// alpha: v1.2
55-
RuntimeSDK featuregate.Feature = "RuntimeSDK"
56-
57-
// KubeadmBootstrapFormatIgnition is a feature gate for the Ignition bootstrap format
58-
// functionality.
59-
//
60-
// alpha: v1.1
61-
KubeadmBootstrapFormatIgnition featuregate.Feature = "KubeadmBootstrapFormatIgnition"
62-
63-
// MachineSetPreflightChecks is a feature gate for the MachineSet preflight checks functionality.
64-
//
65-
// alpha: v1.5
66-
// beta: v1.9
67-
MachineSetPreflightChecks featuregate.Feature = "MachineSetPreflightChecks"
68-
69-
// MachineWaitForVolumeDetachConsiderVolumeAttachments is a feature gate that controls if the Machine controller
70-
// also considers VolumeAttachments in addition to Nodes.status.volumesAttached when waiting for volumes to be detached.
71-
//
72-
// beta: v1.9
73-
MachineWaitForVolumeDetachConsiderVolumeAttachments featuregate.Feature = "MachineWaitForVolumeDetachConsiderVolumeAttachments"
74-
75-
// PriorityQueue is a feature gate that controls if the controller uses the controller-runtime PriorityQueue
76-
// instead of the default queue implementation.
77-
//
78-
// alpha: v1.10
79-
PriorityQueue featuregate.Feature = "PriorityQueue"
80-
81-
// InPlaceUpdates is a feature gate for the in-place machine updates functionality.
82-
// alpha: v1.12
83-
InPlaceUpdates featuregate.Feature = "InPlaceUpdates"
26+
// Every feature gate should add method here following this template:
27+
//
28+
// // owner: @username
29+
// // alpha: v1.X
30+
// MyFeature featuregate.Feature = "MyFeature".
31+
32+
// MachinePool is a feature gate for MachinePool functionality.
33+
//
34+
// alpha: v0.3
35+
// beta: v1.7
36+
MachinePool featuregate.Feature = "MachinePool"
37+
38+
// ClusterTopology is a feature gate for the ClusterClass and managed topologies functionality.
39+
//
40+
// alpha: v0.4
41+
ClusterTopology featuregate.Feature = "ClusterTopology"
42+
43+
// RuntimeSDK is a feature gate for the Runtime hooks and extensions functionality.
44+
//
45+
// alpha: v1.2
46+
RuntimeSDK featuregate.Feature = "RuntimeSDK"
47+
48+
// KubeadmBootstrapFormatIgnition is a feature gate for the Ignition bootstrap format
49+
// functionality.
50+
//
51+
// alpha: v1.1
52+
KubeadmBootstrapFormatIgnition featuregate.Feature = "KubeadmBootstrapFormatIgnition"
53+
54+
// MachineSetPreflightChecks is a feature gate for the MachineSet preflight checks functionality.
55+
//
56+
// alpha: v1.5
57+
// beta: v1.9
58+
MachineSetPreflightChecks featuregate.Feature = "MachineSetPreflightChecks"
59+
60+
// MachineWaitForVolumeDetachConsiderVolumeAttachments is a feature gate that controls if the Machine controller
61+
// also considers VolumeAttachments in addition to Nodes.status.volumesAttached when waiting for volumes to be detached.
62+
//
63+
// beta: v1.9
64+
MachineWaitForVolumeDetachConsiderVolumeAttachments featuregate.Feature = "MachineWaitForVolumeDetachConsiderVolumeAttachments"
65+
66+
// PriorityQueue is a feature gate that controls if the controller uses the controller-runtime PriorityQueue
67+
// instead of the default queue implementation.
68+
//
69+
// alpha: v1.10
70+
PriorityQueue featuregate.Feature = "PriorityQueue"
71+
72+
// InPlaceUpdates is a feature gate for the in-place machine updates functionality.
73+
// alpha: v1.12
74+
InPlaceUpdates featuregate.Feature = "InPlaceUpdates"
8475
)
8576

8677
func init() {
87-
runtime.Must(MutableGates.Add(defaultClusterAPIFeatureGates))
78+
runtime.Must(MutableGates.Add(defaultClusterAPIFeatureGates))
8879
}
8980

9081
// defaultClusterAPIFeatureGates consists of all known cluster-api-specific feature keys.
9182
// To add a new feature, define a key for it above and add it here.
9283
var defaultClusterAPIFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
93-
// Every feature should be initiated here:
94-
ClusterResourceSet: {Default: true, PreRelease: featuregate.GA},
95-
MachinePool: {Default: true, PreRelease: featuregate.Beta},
96-
MachineSetPreflightChecks: {Default: true, PreRelease: featuregate.Beta},
97-
MachineWaitForVolumeDetachConsiderVolumeAttachments: {Default: true, PreRelease: featuregate.Beta},
98-
PriorityQueue: {Default: false, PreRelease: featuregate.Alpha},
99-
ClusterTopology: {Default: false, PreRelease: featuregate.Alpha},
100-
KubeadmBootstrapFormatIgnition: {Default: false, PreRelease: featuregate.Alpha},
101-
RuntimeSDK: {Default: false, PreRelease: featuregate.Alpha},
102-
InPlaceUpdates: {Default: false, PreRelease: featuregate.Alpha},
84+
// Every feature should be initiated here:
85+
MachinePool: {Default: true, PreRelease: featuregate.Beta},
86+
MachineSetPreflightChecks: {Default: true, PreRelease: featuregate.Beta},
87+
MachineWaitForVolumeDetachConsiderVolumeAttachments: {Default: true, PreRelease: featuregate.Beta},
88+
PriorityQueue: {Default: false, PreRelease: featuregate.Alpha},
89+
ClusterTopology: {Default: false, PreRelease: featuregate.Alpha},
90+
KubeadmBootstrapFormatIgnition: {Default: false, PreRelease: featuregate.Alpha},
91+
RuntimeSDK: {Default: false, PreRelease: featuregate.Alpha},
92+
InPlaceUpdates: {Default: false, PreRelease: featuregate.Alpha},
10393
}

internal/webhooks/clusterresourceset.go

Lines changed: 83 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,31 @@ limitations under the License.
1717
package webhooks
1818

1919
import (
20-
"context"
21-
"fmt"
22-
"reflect"
23-
24-
apierrors "k8s.io/apimachinery/pkg/api/errors"
25-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26-
"k8s.io/apimachinery/pkg/runtime"
27-
"k8s.io/apimachinery/pkg/util/validation/field"
28-
ctrl "sigs.k8s.io/controller-runtime"
29-
"sigs.k8s.io/controller-runtime/pkg/webhook"
30-
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
31-
32-
addonsv1 "sigs.k8s.io/cluster-api/api/addons/v1beta2"
33-
"sigs.k8s.io/cluster-api/feature"
20+
"context"
21+
"fmt"
22+
"reflect"
23+
24+
apierrors "k8s.io/apimachinery/pkg/api/errors"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/runtime"
27+
"k8s.io/apimachinery/pkg/util/validation/field"
28+
ctrl "sigs.k8s.io/controller-runtime"
29+
"sigs.k8s.io/controller-runtime/pkg/webhook"
30+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
31+
32+
addonsv1 "sigs.k8s.io/cluster-api/api/addons/v1beta2"
33+
// "sigs.k8s.io/cluster-api/feature" // This import is no longer needed
3434
)
3535

3636
// ClusterResourceSet implements a validation and defaulting webhook for ClusterResourceSet.
3737
type ClusterResourceSet struct{}
3838

3939
func (webhook *ClusterResourceSet) SetupWebhookWithManager(mgr ctrl.Manager) error {
40-
return ctrl.NewWebhookManagedBy(mgr).
41-
For(&addonsv1.ClusterResourceSet{}).
42-
WithDefaulter(webhook).
43-
WithValidator(webhook).
44-
Complete()
40+
return ctrl.NewWebhookManagedBy(mgr).
41+
For(&addonsv1.ClusterResourceSet{}).
42+
WithDefaulter(webhook).
43+
WithValidator(webhook).
44+
Complete()
4545
}
4646

4747
// +kubebuilder:webhook:verbs=create;update,path=/validate-addons-cluster-x-k8s-io-v1beta2-clusterresourceset,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=addons.cluster.x-k8s.io,resources=clusterresourcesets,versions=v1beta2,name=validation.clusterresourceset.addons.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
@@ -52,90 +52,83 @@ var _ webhook.CustomValidator = &ClusterResourceSet{}
5252

5353
// Default implements webhook.Defaulter so a webhook will be registered for the type.
5454
func (webhook *ClusterResourceSet) Default(_ context.Context, obj runtime.Object) error {
55-
crs, ok := obj.(*addonsv1.ClusterResourceSet)
56-
if !ok {
57-
return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", obj))
58-
}
59-
// ClusterResourceSet Strategy defaults to ApplyOnce.
60-
if crs.Spec.Strategy == "" {
61-
crs.Spec.Strategy = string(addonsv1.ClusterResourceSetStrategyApplyOnce)
62-
}
63-
return nil
55+
crs, ok := obj.(*addonsv1.ClusterResourceSet)
56+
if !ok {
57+
return apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", obj))
58+
}
59+
// ClusterResourceSet Strategy defaults to ApplyOnce.
60+
if crs.Spec.Strategy == "" {
61+
crs.Spec.Strategy = string(addonsv1.ClusterResourceSetStrategyApplyOnce)
62+
}
63+
return nil
6464
}
6565

6666
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
6767
func (webhook *ClusterResourceSet) ValidateCreate(_ context.Context, newObj runtime.Object) (admission.Warnings, error) {
68-
newCRS, ok := newObj.(*addonsv1.ClusterResourceSet)
69-
if !ok {
70-
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", newObj))
71-
}
72-
return nil, webhook.validate(nil, newCRS)
68+
newCRS, ok := newObj.(*addonsv1.ClusterResourceSet)
69+
if !ok {
70+
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", newObj))
71+
}
72+
return nil, webhook.validate(nil, newCRS)
7373
}
7474

7575
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
7676
func (webhook *ClusterResourceSet) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
77-
oldCRS, ok := oldObj.(*addonsv1.ClusterResourceSet)
78-
if !ok {
79-
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", oldObj))
80-
}
81-
newCRS, ok := newObj.(*addonsv1.ClusterResourceSet)
82-
if !ok {
83-
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", newObj))
84-
}
85-
return nil, webhook.validate(oldCRS, newCRS)
77+
oldCRS, ok := oldObj.(*addonsv1.ClusterResourceSet)
78+
if !ok {
79+
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", oldObj))
80+
}
81+
newCRS, ok := newObj.(*addonsv1.ClusterResourceSet)
82+
if !ok {
83+
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterResourceSet but got a %T", newObj))
84+
}
85+
return nil, webhook.validate(oldCRS, newCRS)
8686
}
8787

8888
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
8989
func (webhook *ClusterResourceSet) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
90-
return nil, nil
90+
return nil, nil
9191
}
9292

9393
func (webhook *ClusterResourceSet) validate(oldCRS, newCRS *addonsv1.ClusterResourceSet) error {
94-
var allErrs field.ErrorList
95-
96-
// NOTE: ClusterResourceSet is behind ClusterResourceSet feature gate flag; the web hook
97-
// must prevent creating new objects when the feature flag is disabled.
98-
if !feature.Gates.Enabled(feature.ClusterResourceSet) {
99-
return field.Forbidden(
100-
field.NewPath("spec"),
101-
"can be set only if the ClusterResourceSet feature flag is enabled",
102-
)
103-
}
104-
105-
// Validate selector parses as Selector
106-
selector, err := metav1.LabelSelectorAsSelector(&newCRS.Spec.ClusterSelector)
107-
if err != nil {
108-
allErrs = append(
109-
allErrs,
110-
field.Invalid(field.NewPath("spec", "clusterSelector"), newCRS.Spec.ClusterSelector, err.Error()),
111-
)
112-
}
113-
114-
// Validate that the selector isn't empty as null selectors do not select any objects.
115-
if selector != nil && selector.Empty() {
116-
allErrs = append(
117-
allErrs,
118-
field.Invalid(field.NewPath("spec", "clusterSelector"), newCRS.Spec.ClusterSelector, "selector must not be empty"),
119-
)
120-
}
121-
122-
if oldCRS != nil && oldCRS.Spec.Strategy != "" && oldCRS.Spec.Strategy != newCRS.Spec.Strategy {
123-
allErrs = append(
124-
allErrs,
125-
field.Invalid(field.NewPath("spec", "strategy"), newCRS.Spec.Strategy, "field is immutable"),
126-
)
127-
}
128-
129-
if oldCRS != nil && !reflect.DeepEqual(oldCRS.Spec.ClusterSelector, newCRS.Spec.ClusterSelector) {
130-
allErrs = append(
131-
allErrs,
132-
field.Invalid(field.NewPath("spec", "clusterSelector"), newCRS.Spec.ClusterSelector, "field is immutable"),
133-
)
134-
}
135-
136-
if len(allErrs) == 0 {
137-
return nil
138-
}
139-
140-
return apierrors.NewInvalid(addonsv1.GroupVersion.WithKind("ClusterResourceSet").GroupKind(), newCRS.Name, allErrs)
94+
var allErrs field.ErrorList
95+
96+
// NOTE: The "if !feature.Gates.Enabled(feature.ClusterResourceSet)" block has been removed.
97+
98+
// Validate selector parses as Selector
99+
selector, err := metav1.LabelSelectorAsSelector(&newCRS.Spec.ClusterSelector)
100+
if err != nil {
101+
allErrs = append(
102+
allErrs,
103+
field.Invalid(field.NewPath("spec", "clusterSelector"), newCRS.Spec.ClusterSelector, err.Error()),
104+
)
105+
}
106+
107+
// Validate that the selector isn't empty as null selectors do not select any objects.
108+
if selector != nil && selector.Empty() {
109+
allErrs = append(
110+
allErrs,
111+
field.Invalid(field.NewPath("spec", "clusterSelector"), newCRS.Spec.ClusterSelector, "selector must not be empty"),
112+
)
113+
}
114+
115+
if oldCRS != nil && oldCRS.Spec.Strategy != "" && oldCRS.Spec.Strategy != newCRS.Spec.Strategy {
116+
allErrs = append(
117+
allErrs,
118+
field.Invalid(field.NewPath("spec", "strategy"), newCRS.Spec.Strategy, "field is immutable"),
119+
)
120+
}
121+
122+
if oldCRS != nil && !reflect.DeepEqual(oldCRS.Spec.ClusterSelector, newCRS.Spec.ClusterSelector) {
123+
allErrs = append(
124+
allErrs,
125+
field.Invalid(field.NewPath("spec", "clusterSelector"), newCRS.Spec.ClusterSelector, "field is immutable"),
126+
)
127+
}
128+
129+
if len(allErrs) == 0 {
130+
return nil
131+
}
132+
133+
return apierrors.NewInvalid(addonsv1.GroupVersion.WithKind("ClusterResourceSet").GroupKind(), newCRS.Name, allErrs)
141134
}

0 commit comments

Comments
 (0)