...
1 package v1
2
3 import (
4 "fmt"
5
6 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7 )
8
9
10
11
12
13
14
15
16
17 type FeatureGate struct {
18 metav1.TypeMeta `json:",inline"`
19
20
21
22 metav1.ObjectMeta `json:"metadata,omitempty"`
23
24
25
26
27 Spec FeatureGateSpec `json:"spec"`
28
29
30 Status FeatureGateStatus `json:"status"`
31 }
32
33 type FeatureSet string
34
35 var (
36
37 Default FeatureSet = ""
38
39
40
41 TechPreviewNoUpgrade FeatureSet = "TechPreviewNoUpgrade"
42
43
44
45
46 CustomNoUpgrade FeatureSet = "CustomNoUpgrade"
47
48
49 LatencySensitive FeatureSet = "LatencySensitive"
50 )
51
52 type FeatureGateSpec struct {
53 FeatureGateSelection `json:",inline"`
54 }
55
56
57 type FeatureGateSelection struct {
58
59
60
61
62 FeatureSet FeatureSet `json:"featureSet,omitempty"`
63
64
65
66
67
68
69 CustomNoUpgrade *CustomFeatureGates `json:"customNoUpgrade,omitempty"`
70 }
71
72 type CustomFeatureGates struct {
73
74
75 Enabled []FeatureGateName `json:"enabled,omitempty"`
76
77
78 Disabled []FeatureGateName `json:"disabled,omitempty"`
79 }
80
81
82
83 type FeatureGateName string
84
85 type FeatureGateStatus struct {
86
87
88
89
90 Conditions []metav1.Condition `json:"conditions,omitempty"`
91
92
93
94
95
96
97
98
99
100
101
102 FeatureGates []FeatureGateDetails `json:"featureGates"`
103 }
104
105 type FeatureGateDetails struct {
106
107
108
109 Version string `json:"version"`
110
111
112 Enabled []FeatureGateAttributes `json:"enabled"`
113
114
115 Disabled []FeatureGateAttributes `json:"disabled"`
116 }
117
118 type FeatureGateAttributes struct {
119
120
121 Name FeatureGateName `json:"name"`
122
123
124
125
126 }
127
128
129
130
131
132 type FeatureGateList struct {
133 metav1.TypeMeta `json:",inline"`
134
135
136
137 metav1.ListMeta `json:"metadata"`
138
139 Items []FeatureGate `json:"items"`
140 }
141
142 type FeatureGateEnabledDisabled struct {
143 Enabled []FeatureGateDescription
144 Disabled []FeatureGateDescription
145 }
146
147
148
149
150
151
152
153
154
155
156
157
158
159 var FeatureSets = map[FeatureSet]*FeatureGateEnabledDisabled{
160 Default: defaultFeatures,
161 CustomNoUpgrade: {
162 Enabled: []FeatureGateDescription{},
163 Disabled: []FeatureGateDescription{},
164 },
165 TechPreviewNoUpgrade: newDefaultFeatures().
166 with(externalCloudProvider).
167 with(externalCloudProviderAzure).
168 with(externalCloudProviderGCP).
169 with(csiDriverSharedResource).
170 with(buildCSIVolumes).
171 with(nodeSwap).
172 with(machineAPIProviderOpenStack).
173 with(insightsConfigAPI).
174 with(matchLabelKeysInPodTopologySpread).
175 with(retroactiveDefaultStorageClass).
176 with(pdbUnhealthyPodEvictionPolicy).
177 with(dynamicResourceAllocation).
178 with(admissionWebhookMatchConditions).
179 with(azureWorkloadIdentity).
180 with(gateGatewayAPI).
181 toFeatures(defaultFeatures),
182 LatencySensitive: newDefaultFeatures().
183 toFeatures(defaultFeatures),
184 }
185
186 var defaultFeatures = &FeatureGateEnabledDisabled{
187 Enabled: []FeatureGateDescription{
188 openShiftPodSecurityAdmission,
189 },
190 Disabled: []FeatureGateDescription{
191 retroactiveDefaultStorageClass,
192 },
193 }
194
195 type featureSetBuilder struct {
196 forceOn []FeatureGateDescription
197 forceOff []FeatureGateDescription
198 }
199
200 func newDefaultFeatures() *featureSetBuilder {
201 return &featureSetBuilder{}
202 }
203
204 func (f *featureSetBuilder) with(forceOn FeatureGateDescription) *featureSetBuilder {
205 for _, curr := range f.forceOn {
206 if curr.FeatureGateAttributes.Name == forceOn.FeatureGateAttributes.Name {
207 panic(fmt.Errorf("coding error: %q enabled twice", forceOn.FeatureGateAttributes.Name))
208 }
209 }
210 f.forceOn = append(f.forceOn, forceOn)
211 return f
212 }
213
214 func (f *featureSetBuilder) without(forceOff FeatureGateDescription) *featureSetBuilder {
215 for _, curr := range f.forceOff {
216 if curr.FeatureGateAttributes.Name == forceOff.FeatureGateAttributes.Name {
217 panic(fmt.Errorf("coding error: %q disabled twice", forceOff.FeatureGateAttributes.Name))
218 }
219 }
220 f.forceOff = append(f.forceOff, forceOff)
221 return f
222 }
223
224 func (f *featureSetBuilder) isForcedOff(needle FeatureGateDescription) bool {
225 for _, forcedOff := range f.forceOff {
226 if needle.FeatureGateAttributes.Name == forcedOff.FeatureGateAttributes.Name {
227 return true
228 }
229 }
230 return false
231 }
232
233 func (f *featureSetBuilder) isForcedOn(needle FeatureGateDescription) bool {
234 for _, forceOn := range f.forceOn {
235 if needle.FeatureGateAttributes.Name == forceOn.FeatureGateAttributes.Name {
236 return true
237 }
238 }
239 return false
240 }
241
242 func (f *featureSetBuilder) toFeatures(defaultFeatures *FeatureGateEnabledDisabled) *FeatureGateEnabledDisabled {
243 finalOn := []FeatureGateDescription{}
244 finalOff := []FeatureGateDescription{}
245
246
247 for _, defaultOn := range defaultFeatures.Enabled {
248 if !f.isForcedOff(defaultOn) {
249 finalOn = append(finalOn, defaultOn)
250 }
251 }
252 for _, currOn := range f.forceOn {
253 if f.isForcedOff(currOn) {
254 panic("coding error, you can't have features both on and off")
255 }
256 found := false
257 for _, alreadyOn := range finalOn {
258 if alreadyOn.FeatureGateAttributes.Name == currOn.FeatureGateAttributes.Name {
259 found = true
260 }
261 }
262 if found {
263 continue
264 }
265
266 finalOn = append(finalOn, currOn)
267 }
268
269
270 for _, defaultOff := range defaultFeatures.Disabled {
271 if !f.isForcedOn(defaultOff) {
272 finalOff = append(finalOff, defaultOff)
273 }
274 }
275 for _, currOff := range f.forceOff {
276 finalOff = append(finalOff, currOff)
277 }
278
279 return &FeatureGateEnabledDisabled{
280 Enabled: finalOn,
281 Disabled: finalOff,
282 }
283 }
284
View as plain text