@@ -5,19 +5,25 @@ import (
55 "encoding/json"
66 "fmt"
77 "regexp"
8+ "sort"
89 "strconv"
910 "strings"
1011
1112 "github.com/openshift/library-go/pkg/operator/v1helpers"
1213
1314 appsv1 "k8s.io/api/apps/v1"
1415 "k8s.io/apimachinery/pkg/util/sets"
16+ _ "k8s.io/apiserver/pkg/features"
17+ "k8s.io/apiserver/pkg/util/feature"
1518 "k8s.io/client-go/kubernetes"
19+ "k8s.io/component-base/featuregate"
1620 "k8s.io/klog/v2"
1721
22+ configv1 "github.com/openshift/api/config/v1"
1823 operatorv1 "github.com/openshift/api/operator/v1"
1924 "github.com/openshift/library-go/pkg/controller/factory"
2025 libgoetcd "github.com/openshift/library-go/pkg/operator/configobserver/etcd"
26+ "github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
2127 "github.com/openshift/library-go/pkg/operator/events"
2228 "github.com/openshift/library-go/pkg/operator/resource/resourceapply"
2329 "github.com/openshift/library-go/pkg/operator/resource/resourcehash"
@@ -51,6 +57,8 @@ type OAuthAPIServerWorkload struct {
5157 operatorImagePullSpec string
5258 kubeClient kubernetes.Interface
5359 versionRecorder status.VersionGetter
60+
61+ featureGates featuregates.FeatureGate
5462}
5563
5664// NewOAuthAPIServerWorkload creates new OAuthAPIServerWorkload struct
@@ -61,6 +69,7 @@ func NewOAuthAPIServerWorkload(
6169 targetNamespace string ,
6270 targetImagePullSpec string ,
6371 operatorImagePullSpec string ,
72+ featureGates featuregates.FeatureGate ,
6473 kubeClient kubernetes.Interface ,
6574 versionRecorder status.VersionGetter ,
6675) * OAuthAPIServerWorkload {
@@ -71,6 +80,7 @@ func NewOAuthAPIServerWorkload(
7180 targetNamespace : targetNamespace ,
7281 targetImagePullSpec : targetImagePullSpec ,
7382 operatorImagePullSpec : operatorImagePullSpec ,
83+ featureGates : featureGates ,
7484 kubeClient : kubeClient ,
7585 versionRecorder : versionRecorder ,
7686 }
@@ -157,6 +167,15 @@ func (c *OAuthAPIServerWorkload) syncDeployment(ctx context.Context, operatorSpe
157167 // log level verbosity is taken from the spec always
158168 args ["v" ] = []string {loglevelToKlog (operatorSpec .LogLevel )}
159169
170+ // Set feature gates
171+ features , err := getFeatureGates (c .featureGates )
172+ if err != nil {
173+ return nil , err
174+ }
175+ if len (features ) > 0 {
176+ args ["feature-gates" ] = []string {strings .Join (features , "," )}
177+ }
178+
160179 // use string replacer for simple things
161180 r := strings .NewReplacer (
162181 "${IMAGE}" , c .targetImagePullSpec ,
@@ -287,3 +306,36 @@ func GetAPIServerArgumentsRaw(authOperatorSpec operatorv1.OperatorSpec) (map[str
287306
288307 return cfgUnstructured .APIServerArguments , nil
289308}
309+
310+ func getFeatureGates (featureGates featuregates.FeatureGate ) ([]string , error ) {
311+ if featureGates == nil {
312+ return nil , fmt .Errorf ("featureGates cannot be nil" )
313+ }
314+
315+ // Get a list of known Kubernetes feature gates
316+ known := feature .DefaultMutableFeatureGate .GetAll ()
317+
318+ // Filter out OCP-specific feature gates
319+ filteredFeatures := []string {}
320+ for _ , feature := range featureGates .KnownFeatures () {
321+ _ , ok := known [featuregate .Feature (feature )]
322+ if ! ok {
323+ continue
324+ }
325+ filteredFeatures = append (filteredFeatures , string (feature ))
326+ }
327+ sort .Strings (filteredFeatures )
328+
329+ // Format feature gates statuses
330+ formattedFeatures := []string {}
331+ for _ , featureGate := range filteredFeatures {
332+ fgName := configv1 .FeatureGateName (featureGate )
333+ if featureGates .Enabled (fgName ) {
334+ formattedFeatures = append (formattedFeatures , fmt .Sprintf ("%s=true" , featureGate ))
335+ } else {
336+ formattedFeatures = append (formattedFeatures , fmt .Sprintf ("%s=false" , featureGate ))
337+ }
338+ }
339+
340+ return formattedFeatures , nil
341+ }
0 commit comments