@@ -60,6 +60,10 @@ type Rule struct {
60
60
// If not set, the Rule belongs to the generated ClusterRole.
61
61
// If set, the Rule belongs to a Role, whose namespace is specified by this field.
62
62
Namespace string `marker:",optional"`
63
+ // FeatureGate specifies the feature gate that controls this RBAC rule.
64
+ // If not set, the rule is always included.
65
+ // If set, the rule is only included when the specified feature gate is enabled.
66
+ FeatureGate string `marker:"featureGate,optional"`
63
67
}
64
68
65
69
// ruleKey represents the resources and non-resources a Rule applies.
@@ -169,6 +173,10 @@ type Generator struct {
169
173
170
174
// Year specifies the year to substitute for " YEAR" in the header file.
171
175
Year string `marker:",optional"`
176
+
177
+ // FeatureGates is a comma-separated list of feature gates to enable (e.g., "alpha=true,beta=false").
178
+ // Only RBAC rules with matching feature gates will be included in the generated output.
179
+ FeatureGates string `marker:",optional"`
172
180
}
173
181
174
182
func (Generator ) RegisterMarkers (into * markers.Registry ) error {
@@ -179,9 +187,46 @@ func (Generator) RegisterMarkers(into *markers.Registry) error {
179
187
return nil
180
188
}
181
189
190
+ // FeatureGateMap represents enabled feature gates as a map for efficient lookup
191
+ type FeatureGateMap map [string ]bool
192
+
193
+ // parseFeatureGates parses a comma-separated feature gate string into a map
194
+ // Format: "gate1=true,gate2=false,gate3=true"
195
+ func parseFeatureGates (featureGates string ) FeatureGateMap {
196
+ gates := make (FeatureGateMap )
197
+ if featureGates == "" {
198
+ return gates
199
+ }
200
+
201
+ pairs := strings .Split (featureGates , "," )
202
+ for _ , pair := range pairs {
203
+ parts := strings .Split (strings .TrimSpace (pair ), "=" )
204
+ if len (parts ) != 2 {
205
+ continue
206
+ }
207
+ gateName := strings .TrimSpace (parts [0 ])
208
+ gateValue := strings .TrimSpace (parts [1 ])
209
+ gates [gateName ] = gateValue == "true"
210
+ }
211
+ return gates
212
+ }
213
+
214
+ // shouldIncludeRule determines if an RBAC rule should be included based on feature gates
215
+ func shouldIncludeRule (rule * Rule , enabledGates FeatureGateMap ) bool {
216
+ if rule .FeatureGate == "" {
217
+ // No feature gate specified, always include
218
+ return true
219
+ }
220
+
221
+ // Check if the feature gate is enabled
222
+ enabled , exists := enabledGates [rule .FeatureGate ]
223
+ return exists && enabled
224
+ }
225
+
182
226
// GenerateRoles generate a slice of objs representing either a ClusterRole or a Role object
183
227
// The order of the objs in the returned slice is stable and determined by their namespaces.
184
- func GenerateRoles (ctx * genall.GenerationContext , roleName string ) ([]interface {}, error ) {
228
+ func GenerateRoles (ctx * genall.GenerationContext , roleName string , featureGates string ) ([]interface {}, error ) {
229
+ enabledGates := parseFeatureGates (featureGates )
185
230
rulesByNSResource := make (map [string ][]* Rule )
186
231
for _ , root := range ctx .Roots {
187
232
markerSet , err := markers .PackageMarkers (ctx .Collector , root )
@@ -192,6 +237,12 @@ func GenerateRoles(ctx *genall.GenerationContext, roleName string) ([]interface{
192
237
// group RBAC markers by namespace and separate by resource
193
238
for _ , markerValue := range markerSet [RuleDefinition .Name ] {
194
239
rule := markerValue .(Rule )
240
+
241
+ // Apply feature gate filtering
242
+ if ! shouldIncludeRule (& rule , enabledGates ) {
243
+ continue
244
+ }
245
+
195
246
if len (rule .Resources ) == 0 {
196
247
// Add a rule without any resource if Resources is empty.
197
248
r := Rule {
@@ -201,6 +252,7 @@ func GenerateRoles(ctx *genall.GenerationContext, roleName string) ([]interface{
201
252
URLs : rule .URLs ,
202
253
Namespace : rule .Namespace ,
203
254
Verbs : rule .Verbs ,
255
+ FeatureGate : rule .FeatureGate ,
204
256
}
205
257
namespace := r .Namespace
206
258
rulesByNSResource [namespace ] = append (rulesByNSResource [namespace ], & r )
@@ -214,6 +266,7 @@ func GenerateRoles(ctx *genall.GenerationContext, roleName string) ([]interface{
214
266
URLs : rule .URLs ,
215
267
Namespace : rule .Namespace ,
216
268
Verbs : rule .Verbs ,
269
+ FeatureGate : rule .FeatureGate ,
217
270
}
218
271
namespace := r .Namespace
219
272
rulesByNSResource [namespace ] = append (rulesByNSResource [namespace ], & r )
@@ -367,7 +420,7 @@ func GenerateRoles(ctx *genall.GenerationContext, roleName string) ([]interface{
367
420
}
368
421
369
422
func (g Generator ) Generate (ctx * genall.GenerationContext ) error {
370
- objs , err := GenerateRoles (ctx , g .RoleName )
423
+ objs , err := GenerateRoles (ctx , g .RoleName , g . FeatureGates )
371
424
if err != nil {
372
425
return err
373
426
}
0 commit comments