Skip to content

Commit a4e68a7

Browse files
committed
use feature gate for toggling FsResizeAnnotation feature on/off
1 parent 14dd61d commit a4e68a7

25 files changed

+2049
-23
lines changed

cmd/csi-resizer/main.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"net/http"
2424
"os"
25+
"strings"
2526
"time"
2627

2728
"github.com/kubernetes-csi/csi-lib-utils/metrics"
@@ -38,7 +39,9 @@ import (
3839
"github.com/kubernetes-csi/external-resizer/pkg/util"
3940

4041
"k8s.io/apimachinery/pkg/util/wait"
42+
utilfeature "k8s.io/apiserver/pkg/util/feature"
4143
"k8s.io/client-go/informers"
44+
cflag "k8s.io/component-base/cli/flag"
4245
"k8s.io/klog/v2"
4346
)
4447

@@ -68,12 +71,13 @@ var (
6871

6972
handleVolumeInUseError = flag.Bool("handle-volume-inuse-error", true, "Flag to turn on/off capability to handle volume in use error in resizer controller. Defaults to true if not set.")
7073

71-
enableFSResizeAnnotation = flag.Bool("enable-fs-resize-annotation", true, "Flag to turn on/off capability to add an annotation to PV to denote its size prior to resize and to remove it upon completion of filesystem resize.")
74+
featureGates map[string]bool
7275

7376
version = "unknown"
7477
)
7578

7679
func main() {
80+
flag.Var(cflag.NewMapStringBool(&featureGates), "feature-gates", "A set of key=value paris that describe feature gates for alpha/experimental features for csi external resizer."+"Options are:\n"+strings.Join(utilfeature.DefaultFeatureGate.KnownFeatures(), "\n"))
7781
klog.InitFlags(nil)
7882
flag.Set("logtostderr", "true")
7983
flag.Parse()
@@ -92,6 +96,9 @@ func main() {
9296
if addr == "" {
9397
addr = *httpEndpoint
9498
}
99+
if err := utilfeature.DefaultMutableFeatureGate.SetFromMap(featureGates); err != nil {
100+
klog.Fatal(err)
101+
}
95102

96103
var config *rest.Config
97104
var err error
@@ -155,7 +162,7 @@ func main() {
155162
resizerName := csiResizer.Name()
156163
rc := controller.NewResizeController(resizerName, csiResizer, kubeClient, *resyncPeriod, informerFactory,
157164
workqueue.NewItemExponentialFailureRateLimiter(*retryIntervalStart, *retryIntervalMax),
158-
*handleVolumeInUseError, *enableFSResizeAnnotation)
165+
*handleVolumeInUseError)
159166
run := func(ctx context.Context) {
160167
informerFactory.Start(wait.NeverStop)
161168
rc.Run(*workers, ctx)

pkg/controller/controller.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"fmt"
2222
"time"
2323

24+
features "sigs.k8s.io/external-resizer/pkg/features" /* TO BE REPLACED WITH features "github.com/external-resizer/pkg/features once PR merged*/
25+
2426
"github.com/kubernetes-csi/external-resizer/pkg/resizer"
2527
"github.com/kubernetes-csi/external-resizer/pkg/util"
2628
"google.golang.org/grpc/codes"
@@ -31,6 +33,7 @@ import (
3133
"k8s.io/apimachinery/pkg/types"
3234
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3335
"k8s.io/apimachinery/pkg/util/wait"
36+
utilfeature "k8s.io/apiserver/pkg/util/feature"
3437
"k8s.io/client-go/informers"
3538
"k8s.io/client-go/kubernetes"
3639
"k8s.io/client-go/kubernetes/scheme"
@@ -66,9 +69,8 @@ type resizeController struct {
6669
// a cache to store PersistentVolume objects
6770
volumes cache.Store
6871
// a cache to store PersistentVolumeClaim objects
69-
claims cache.Store
70-
handleVolumeInUseError bool
71-
enableFSResizeAnnotation bool
72+
claims cache.Store
73+
handleVolumeInUseError bool
7274
}
7375

7476
// NewResizeController returns a ResizeController.
@@ -79,8 +81,7 @@ func NewResizeController(
7981
resyncPeriod time.Duration,
8082
informerFactory informers.SharedInformerFactory,
8183
pvcRateLimiter workqueue.RateLimiter,
82-
handleVolumeInUseError,
83-
enableFSResizeAnnotation bool) ResizeController {
84+
handleVolumeInUseError bool) ResizeController {
8485
pvInformer := informerFactory.Core().V1().PersistentVolumes()
8586
pvcInformer := informerFactory.Core().V1().PersistentVolumeClaims()
8687
eventBroadcaster := record.NewBroadcaster()
@@ -93,18 +94,17 @@ func NewResizeController(
9394
pvcRateLimiter, fmt.Sprintf("%s-pvc", name))
9495

9596
ctrl := &resizeController{
96-
name: name,
97-
resizer: resizer,
98-
kubeClient: kubeClient,
99-
pvSynced: pvInformer.Informer().HasSynced,
100-
pvcSynced: pvcInformer.Informer().HasSynced,
101-
claimQueue: claimQueue,
102-
volumes: pvInformer.Informer().GetStore(),
103-
claims: pvcInformer.Informer().GetStore(),
104-
eventRecorder: eventRecorder,
105-
usedPVCs: newUsedPVCStore(),
106-
handleVolumeInUseError: handleVolumeInUseError,
107-
enableFSResizeAnnotation: enableFSResizeAnnotation,
97+
name: name,
98+
resizer: resizer,
99+
kubeClient: kubeClient,
100+
pvSynced: pvInformer.Informer().HasSynced,
101+
pvcSynced: pvcInformer.Informer().HasSynced,
102+
claimQueue: claimQueue,
103+
volumes: pvInformer.Informer().GetStore(),
104+
claims: pvcInformer.Informer().GetStore(),
105+
eventRecorder: eventRecorder,
106+
usedPVCs: newUsedPVCStore(),
107+
handleVolumeInUseError: handleVolumeInUseError,
108108
}
109109

110110
// Add a resync period as the PVC's request size can be resized again when we handling
@@ -324,7 +324,7 @@ func (ctrl *resizeController) syncPVC(key string) error {
324324
return fmt.Errorf("expected volume but got %+v", volumeObj)
325325
}
326326

327-
if ctrl.enableFSResizeAnnotation && ctrl.isNodeExpandComplete(pvc, pv) && metav1.HasAnnotation(pv.ObjectMeta, util.AnnPreResizeCapacity) {
327+
if utilfeature.DefaultFeatureGate.Enabled(features.AnnotateFsResize) && ctrl.isNodeExpandComplete(pvc, pv) && metav1.HasAnnotation(pv.ObjectMeta, util.AnnPreResizeCapacity) {
328328
if err := ctrl.deletePreResizeCapAnnotation(pv); err != nil {
329329
return fmt.Errorf("failed removing annotation %s from pv %q: %v", util.AnnPreResizeCapacity, pv.Name, err)
330330
}
@@ -571,7 +571,7 @@ func (ctrl *resizeController) updatePVCapacity(pv *v1.PersistentVolume, oldCapac
571571
newPV := pv.DeepCopy()
572572
newPV.Spec.Capacity[v1.ResourceStorage] = newCapacity
573573

574-
if ctrl.enableFSResizeAnnotation && fsResizeRequired {
574+
if utilfeature.DefaultFeatureGate.Enabled(features.AnnotateFsResize) && fsResizeRequired {
575575
// only update annotation if there already isn't one
576576
if !metav1.HasAnnotation(pv.ObjectMeta, util.AnnPreResizeCapacity) {
577577
if newPV.ObjectMeta.Annotations == nil {

pkg/controller/controller_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"testing"
66
"time"
77

8+
features "sigs.k8s.io/external-resizer/pkg/features" /* TO BE REPLACED WITH features "github.com/external-resizer/pkg/features once PR merged*/
9+
810
"k8s.io/client-go/util/workqueue"
911

1012
"github.com/kubernetes-csi/external-resizer/pkg/csi"
@@ -16,9 +18,11 @@ import (
1618
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1719
"k8s.io/apimachinery/pkg/runtime"
1820
"k8s.io/apimachinery/pkg/types"
21+
utilfeature "k8s.io/apiserver/pkg/util/feature"
1922
"k8s.io/client-go/informers"
2023
"k8s.io/client-go/kubernetes"
2124
"k8s.io/client-go/kubernetes/fake"
25+
featuregatetesting "k8s.io/component-base/featuregate/testing"
2226
)
2327

2428
func TestController(t *testing.T) {
@@ -234,7 +238,8 @@ func TestController(t *testing.T) {
234238
t.Fatalf("Test %s: Unable to create resizer: %v", test.Name, err)
235239
}
236240

237-
controller := NewResizeController(driverName, csiResizer, kubeClient, time.Second, informerFactory, workqueue.DefaultControllerRateLimiter(), !test.disableVolumeInUseErrorHandler, test.enableFSResizeAnnotation)
241+
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnnotateFsResize, true)()
242+
controller := NewResizeController(driverName, csiResizer, kubeClient, time.Second, informerFactory, workqueue.DefaultControllerRateLimiter(), !test.disableVolumeInUseErrorHandler)
238243

239244
ctrlInstance, _ := controller.(*resizeController)
240245

@@ -365,7 +370,8 @@ func TestResizePVC(t *testing.T) {
365370
t.Fatalf("Test %s: Unable to create resizer: %v", test.Name, err)
366371
}
367372

368-
controller := NewResizeController(driverName, csiResizer, kubeClient, time.Second, informerFactory, workqueue.DefaultControllerRateLimiter(), true /* disableVolumeInUseErrorHandler*/, true /*enableFsResizeAnnotation*/)
373+
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnnotateFsResize, true)()
374+
controller := NewResizeController(driverName, csiResizer, kubeClient, time.Second, informerFactory, workqueue.DefaultControllerRateLimiter(), true /* disableVolumeInUseErrorHandler*/)
369375

370376
ctrlInstance, _ := controller.(*resizeController)
371377

pkg/features/features.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package features
18+
19+
import (
20+
utilfeature "k8s.io/apiserver/pkg/util/feature"
21+
"k8s.io/component-base/featuregate"
22+
)
23+
24+
const (
25+
// owner: @sunpa93
26+
// alpha: v1.22
27+
AnnotateFsResize featuregate.Feature = "AnnotateFsResize"
28+
)
29+
30+
func init() {
31+
utilfeature.DefaultMutableFeatureGate.Add(defaultResizerFeatureGates)
32+
}
33+
34+
var defaultResizerFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
35+
AnnotateFsResize: {Default: false, PreRelease: featuregate.Alpha},
36+
}

0 commit comments

Comments
 (0)