@@ -92,136 +92,36 @@ func TestConfigFileOtherFields(t *testing.T) {
92
92
assert .Equal (t , false , cfg .SocketOpts .ReuseAddress , "ReuseAddress does not match" )
93
93
}
94
94
95
+ // TestConfigFileFeatureGates ensures that experimental flags migrate to feature gate.
95
96
func TestConfigFileFeatureGates (t * testing.T ) {
96
- testCases := []struct {
97
- name string
98
- serverFeatureGatesJSON string
99
- experimentalStopGRPCServiceOnDefrag string
100
- experimentalInitialCorruptCheck string
101
- expectErr bool
102
- expectedFeatures map [featuregate.Feature ]bool
103
- }{
97
+ testCases := []featureTestCase {
104
98
{
105
- name : "default" ,
106
- expectedFeatures : map [featuregate.Feature ]bool {
107
- features .DistributedTracing : false ,
108
- features .StopGRPCServiceOnDefrag : false ,
109
- features .InitialCorruptCheck : false ,
110
- },
99
+ name : "default" ,
100
+ expectedFeatures : defaultFeatureGates (),
111
101
},
112
102
{
113
- name : "cannot set both experimental flag and feature gate flag" ,
114
- serverFeatureGatesJSON : "StopGRPCServiceOnDefrag=true" ,
115
- experimentalStopGRPCServiceOnDefrag : "false" ,
116
- expectErr : true ,
117
- },
118
- {
119
- name : "cannot set both experimental flag and feature gate flag for InitialCorruptCheck" ,
120
- serverFeatureGatesJSON : "InitialCorruptCheck=true" ,
121
- experimentalInitialCorruptCheck : "false" ,
122
- expectErr : true ,
123
- },
124
- {
125
- name : "ok to set different experimental flag and feature gate flag" ,
126
- serverFeatureGatesJSON : "DistributedTracing=true" ,
127
- experimentalStopGRPCServiceOnDefrag : "true" ,
128
- expectedFeatures : map [featuregate.Feature ]bool {
129
- features .DistributedTracing : true ,
130
- features .StopGRPCServiceOnDefrag : true ,
131
- features .InitialCorruptCheck : false ,
132
- },
133
- },
134
- {
135
- name : "can set feature gate to true from experimental flag" ,
136
- experimentalStopGRPCServiceOnDefrag : "true" ,
137
- expectedFeatures : map [featuregate.Feature ]bool {
138
- features .StopGRPCServiceOnDefrag : true ,
139
- features .DistributedTracing : false ,
140
- features .InitialCorruptCheck : false ,
141
- },
142
- },
143
- {
144
- name : "can set feature gate to false from experimental flag" ,
145
- experimentalStopGRPCServiceOnDefrag : "false" ,
146
- expectedFeatures : map [featuregate.Feature ]bool {
147
- features .StopGRPCServiceOnDefrag : false ,
148
- features .DistributedTracing : false ,
149
- features .InitialCorruptCheck : false ,
150
- },
151
- },
152
- {
153
- name : "can set feature gate experimentalInitialCorruptCheck to true from experimental flag" ,
154
- experimentalInitialCorruptCheck : "true" ,
155
- expectedFeatures : map [featuregate.Feature ]bool {
156
- features .StopGRPCServiceOnDefrag : false ,
157
- features .DistributedTracing : false ,
158
- features .InitialCorruptCheck : true ,
159
- },
160
- },
161
- {
162
- name : "can set feature gate experimentalInitialCorruptCheck to false from experimental flag" ,
163
- experimentalInitialCorruptCheck : "false" ,
164
- expectedFeatures : map [featuregate.Feature ]bool {
165
- features .StopGRPCServiceOnDefrag : false ,
166
- features .DistributedTracing : false ,
167
- features .InitialCorruptCheck : false ,
168
- },
169
- },
170
- {
171
- name : "can set feature gate StopGRPCServiceOnDefrag to true from feature gate flag" ,
172
- serverFeatureGatesJSON : "StopGRPCServiceOnDefrag=true" ,
173
- expectedFeatures : map [featuregate.Feature ]bool {
174
- features .StopGRPCServiceOnDefrag : true ,
175
- features .DistributedTracing : false ,
176
- features .InitialCorruptCheck : false ,
177
- },
178
- },
179
- {
180
- name : "can set feature gate InitialCorruptCheck to true from feature gate flag" ,
181
- serverFeatureGatesJSON : "InitialCorruptCheck=true" ,
182
- expectedFeatures : map [featuregate.Feature ]bool {
183
- features .StopGRPCServiceOnDefrag : false ,
184
- features .DistributedTracing : false ,
185
- features .InitialCorruptCheck : true ,
186
- },
187
- },
188
- {
189
- name : "can set feature gate to false from feature gate flag" ,
190
- serverFeatureGatesJSON : "StopGRPCServiceOnDefrag=false" ,
191
- expectedFeatures : map [featuregate.Feature ]bool {
192
- features .StopGRPCServiceOnDefrag : false ,
193
- features .DistributedTracing : false ,
194
- features .InitialCorruptCheck : false ,
195
- },
103
+ name : "ok to set different experimental flag and feature gate flag" ,
104
+ serverFeatureGatesJSON : "DistributedTracing=true" ,
105
+ experimentalFlagName : "experimental-stop-grpc-service-on-defrag" ,
106
+ experimentalValue : true ,
107
+ expectedFeatures : defaultFeatureGatesWithFeaturegates ([]featuregate.Feature {features .StopGRPCServiceOnDefrag , features .DistributedTracing }, true ),
196
108
},
197
109
}
110
+
111
+ //add a new experimental flag here when migrating a new experimental flag to feature
112
+ testCases = append (testCases , testCasesForFeaturegate ("experimental-stop-grpc-service-on-defrag" , "StopGRPCServiceOnDefrag" , features .StopGRPCServiceOnDefrag )... )
113
+ testCases = append (testCases , testCasesForFeaturegate ("experimental-initial-corrupt-check" , "InitialCorruptCheck" , features .InitialCorruptCheck )... )
114
+
198
115
for _ , tc := range testCases {
199
116
t .Run (tc .name , func (t * testing.T ) {
200
- yc := struct {
201
- ExperimentalStopGRPCServiceOnDefrag * bool `json:"experimental-stop-grpc-service-on-defrag,omitempty"`
202
- ExperimentalInitialCorruptCheck * bool `json:"experimental-initial-corrupt-check,omitempty"`
203
- ServerFeatureGatesJSON string `json:"feature-gates"`
204
- }{
205
- ServerFeatureGatesJSON : tc .serverFeatureGatesJSON ,
206
- }
117
+ configurationMap := make (map [string ]interface {})
118
+ configurationMap ["feature-gates" ] = tc .serverFeatureGatesJSON
207
119
208
- if tc .experimentalInitialCorruptCheck != "" {
209
- experimentalInitialCorruptCheck , err := strconv .ParseBool (tc .experimentalInitialCorruptCheck )
210
- if err != nil {
211
- t .Fatal (err )
212
- }
213
- yc .ExperimentalInitialCorruptCheck = & experimentalInitialCorruptCheck
120
+ if tc .experimentalFlagName != "" {
121
+ configurationMap [tc .experimentalFlagName ] = tc .experimentalValue
214
122
}
215
123
216
- if tc .experimentalStopGRPCServiceOnDefrag != "" {
217
- experimentalStopGRPCServiceOnDefrag , err := strconv .ParseBool (tc .experimentalStopGRPCServiceOnDefrag )
218
- if err != nil {
219
- t .Fatal (err )
220
- }
221
- yc .ExperimentalStopGRPCServiceOnDefrag = & experimentalStopGRPCServiceOnDefrag
222
- }
223
-
224
- b , err := yaml .Marshal (& yc )
124
+ b , err := yaml .Marshal (configurationMap )
225
125
if err != nil {
226
126
t .Fatal (err )
227
127
}
@@ -248,6 +148,71 @@ func TestConfigFileFeatureGates(t *testing.T) {
248
148
}
249
149
}
250
150
151
+ type featureTestCase struct {
152
+ name string
153
+ serverFeatureGatesJSON string
154
+ expectErr bool
155
+ expectedFeatures map [featuregate.Feature ]bool
156
+ experimentalFlagName string
157
+ experimentalValue bool
158
+ }
159
+
160
+ func testCasesForFeaturegate (experimentalFlagName , fgname string , fg featuregate.Feature ) []featureTestCase {
161
+ return []featureTestCase {
162
+ {
163
+ name : "cannot set both experimental flag and feature gate flag" ,
164
+ serverFeatureGatesJSON : fgname + "=true" ,
165
+ experimentalFlagName : experimentalFlagName ,
166
+ experimentalValue : false ,
167
+ expectErr : true ,
168
+ },
169
+ {
170
+ name : "can set feature gate to true from experimental flag" ,
171
+ experimentalFlagName : experimentalFlagName ,
172
+ experimentalValue : true ,
173
+ expectedFeatures : defaultFeatureGatesWithFeaturegate (fg , true ),
174
+ },
175
+ {
176
+ name : "can set feature gate to false from experimental flag" ,
177
+ experimentalFlagName : experimentalFlagName ,
178
+ experimentalValue : false ,
179
+ expectedFeatures : defaultFeatureGatesWithFeaturegate (fg , false ),
180
+ },
181
+ {
182
+ name : "can set feature gate " + fgname + " to true from feature gate flag" ,
183
+ serverFeatureGatesJSON : fgname + "=true" ,
184
+ expectedFeatures : defaultFeatureGatesWithFeaturegate (fg , true ),
185
+ },
186
+ {
187
+ name : "can set feature gate to false from feature gate flag" ,
188
+ serverFeatureGatesJSON : fgname + "=false" ,
189
+ expectedFeatures : defaultFeatureGatesWithFeaturegate (fg , false ),
190
+ },
191
+ }
192
+ }
193
+
194
+ func defaultFeatureGates () map [featuregate.Feature ]bool {
195
+ fgs := make (map [featuregate.Feature ]bool )
196
+ for fg , fgspec := range features .DefaultEtcdServerFeatureGates {
197
+ fgs [fg ] = fgspec .Default
198
+ }
199
+ return fgs
200
+ }
201
+
202
+ func defaultFeatureGatesWithFeaturegate (fg featuregate.Feature , enabled bool ) map [featuregate.Feature ]bool {
203
+ fgs := defaultFeatureGates ()
204
+ fgs [fg ] = enabled
205
+ return fgs
206
+ }
207
+
208
+ func defaultFeatureGatesWithFeaturegates (fgs2 []featuregate.Feature , enabled bool ) map [featuregate.Feature ]bool {
209
+ fgs := defaultFeatureGates ()
210
+ for _ , f := range fgs2 {
211
+ fgs [f ] = enabled
212
+ }
213
+ return fgs
214
+ }
215
+
251
216
// TestUpdateDefaultClusterFromName ensures that etcd can start with 'etcd --name=abc'.
252
217
func TestUpdateDefaultClusterFromName (t * testing.T ) {
253
218
cfg := NewConfig ()
0 commit comments