diff --git a/assets/overlays/aws-ebs/base/csidriver.yaml b/assets/overlays/aws-ebs/base/csidriver.yaml index 1b16edddb..a99906ae8 100644 --- a/assets/overlays/aws-ebs/base/csidriver.yaml +++ b/assets/overlays/aws-ebs/base/csidriver.yaml @@ -14,3 +14,9 @@ spec: seLinuxMount: true volumeLifecycleModes: - Persistent + # We set the field even though the field is not available by default. + # The API server will clear the field if the field is not enabled. + # It would be complicated to add the field conditionally in the operator + # by our usual ${xxx} replacement, because yaml fields cannot start with '$'. + # And StaticResourceController does not allow any programmatic hooks. + nodeAllocatableUpdatePeriodSeconds: 600 diff --git a/assets/overlays/aws-ebs/generated/hypershift/csidriver.yaml b/assets/overlays/aws-ebs/generated/hypershift/csidriver.yaml index 4440f9e58..d176d7537 100644 --- a/assets/overlays/aws-ebs/generated/hypershift/csidriver.yaml +++ b/assets/overlays/aws-ebs/generated/hypershift/csidriver.yaml @@ -13,6 +13,7 @@ metadata: spec: attachRequired: true fsGroupPolicy: File + nodeAllocatableUpdatePeriodSeconds: 600 podInfoOnMount: false requiresRepublish: false seLinuxMount: true diff --git a/assets/overlays/aws-ebs/generated/standalone/csidriver.yaml b/assets/overlays/aws-ebs/generated/standalone/csidriver.yaml index 4440f9e58..d176d7537 100644 --- a/assets/overlays/aws-ebs/generated/standalone/csidriver.yaml +++ b/assets/overlays/aws-ebs/generated/standalone/csidriver.yaml @@ -13,6 +13,7 @@ metadata: spec: attachRequired: true fsGroupPolicy: File + nodeAllocatableUpdatePeriodSeconds: 600 podInfoOnMount: false requiresRepublish: false seLinuxMount: true diff --git a/pkg/driver/aws-ebs/aws_ebs.go b/pkg/driver/aws-ebs/aws_ebs.go index 2e2e6a6b7..1840bb47f 100644 --- a/pkg/driver/aws-ebs/aws_ebs.go +++ b/pkg/driver/aws-ebs/aws_ebs.go @@ -183,6 +183,9 @@ func GetAWSEBSOperatorControllerConfig(ctx context.Context, flavour generator.Cl if featureGates.Enabled(configv1.FeatureGateName("VolumeAttributesClass")) { cfg.AddDeploymentHookBuilders(c, withVolumeAttributesClassHook) } + if featureGates.Enabled(configv1.FeatureGateName("MutableCSINodeAllocatableCount")) { + cfg.AddDeploymentHookBuilders(c, withMutableCSINodeAllocatableCount) + } cfg.AddDaemonSetHookBuilders(c, withCABundleDaemonSetHook) cfg.AddStorageClassHookBuilders(c, withKMSKeyHook) @@ -208,6 +211,14 @@ func GetAWSEBSOperatorControllerConfig(ctx context.Context, flavour generator.Cl cfg.ExtraControlPlaneControllers = append(cfg.ExtraControlPlaneControllers, ctrl) } + cfg.ExtraReplacementsFunc = func() []string { + if featureGates.Enabled(configv1.FeatureGateName("MutableCSINodeAllocatableCount")) { + return nil + } + // CLEAR the field when the feature gate is disabled + return []string{"nodeAllocatableUpdatePeriodSeconds: 600", ""} + } + if flavour == generator.FlavourHyperShift { volumeTagController := NewEBSVolumeTagsController(cfg.GetControllerName("EBSVolumeTagsController"), c, c.EventRecorder) cfg.ExtraControlPlaneControllers = append(cfg.ExtraControlPlaneControllers, volumeTagController) @@ -500,3 +511,20 @@ func withVolumeAttributesClassHook(c *clients.Clients) (dc.DeploymentHookFunc, [ } return hook, nil } + +// withMutableCSINodeAllocatableCount enables the MutableCSINodeAllocatableCount feature gate in the external attacher +// TODO: remove when MutableCSINodeAllocatableCount is GA +func withMutableCSINodeAllocatableCount(c *clients.Clients) (dc.DeploymentHookFunc, []factory.Informer) { + hook := func(spec *opv1.OperatorSpec, deployment *appsv1.Deployment) error { + fgArgument := "--feature-gates=MutableCSINodeAllocatableCount=true" + for i := range deployment.Spec.Template.Spec.Containers { + container := &deployment.Spec.Template.Spec.Containers[i] + if container.Name != "csi-attacher" { + continue + } + container.Args = append(container.Args, fgArgument) + } + return nil + } + return hook, nil +} diff --git a/pkg/driver/aws-ebs/aws_ebs_test.go b/pkg/driver/aws-ebs/aws_ebs_test.go index a721f7861..746a51036 100644 --- a/pkg/driver/aws-ebs/aws_ebs_test.go +++ b/pkg/driver/aws-ebs/aws_ebs_test.go @@ -363,3 +363,40 @@ func Test_WithKMSKeyHook(t *testing.T) { }) } } + +func Test_WithMutableCSINodeAllocatableCount(t *testing.T) { + cr := clients.GetFakeOperatorCR() + c := clients.NewFakeClients("clusters-test", cr) + + hook, _ := withMutableCSINodeAllocatableCount(c) + deployment := getTestDeployment() + // Arrange - inject custom infrastructure + + // Act + err := hook(&cr.Spec.OperatorSpec, deployment) + if err != nil { + t.Fatalf("unexpected hook error: %v", err) + } + + // Assert + found := false + expectedFeatureGatesArg := "--feature-gates=MutableCSINodeAllocatableCount=true" + for _, container := range deployment.Spec.Template.Spec.Containers { + if container.Name == "csi-attacher" { + found = true + // Collect env vars from struct EnvVar to map[string]string + featureGatesArg := "" + for _, arg := range container.Args { + if strings.HasPrefix(arg, "--feature-gates") { + featureGatesArg = arg + } + } + if featureGatesArg != expectedFeatureGatesArg { + t.Errorf("expected csi-driver feature gates argument %s, got %s", expectedFeatureGatesArg, featureGatesArg) + } + } + } + if !found { + t.Errorf("container csi-attacher not found") + } +}