1
16
17 package options
18
19 import (
20 "strings"
21 "testing"
22
23 kubeapiserveradmission "k8s.io/apiserver/pkg/admission"
24 genericoptions "k8s.io/apiserver/pkg/server/options"
25 utilfeature "k8s.io/apiserver/pkg/util/feature"
26 "k8s.io/component-base/featuregate"
27 basemetrics "k8s.io/component-base/metrics"
28 "k8s.io/kubernetes/pkg/features"
29
30 peerreconcilers "k8s.io/apiserver/pkg/reconcilers"
31 featuregatetesting "k8s.io/component-base/featuregate/testing"
32 kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
33 )
34
35 func TestValidateAPIPriorityAndFairness(t *testing.T) {
36 const conflict = "conflicts with --enable-priority-and-fairness=true"
37 tests := []struct {
38 runtimeConfig string
39 errShouldContain string
40 }{
41 {
42 runtimeConfig: "api/all=false",
43 errShouldContain: conflict,
44 },
45 {
46 runtimeConfig: "api/beta=false",
47 errShouldContain: "",
48 },
49 {
50 runtimeConfig: "api/ga=false",
51 errShouldContain: conflict,
52 },
53 {
54 runtimeConfig: "api/ga=true",
55 errShouldContain: "",
56 },
57 {
58 runtimeConfig: "flowcontrol.apiserver.k8s.io/v1beta1=false",
59 errShouldContain: "",
60 },
61 {
62 runtimeConfig: "flowcontrol.apiserver.k8s.io/v1beta2=false",
63 errShouldContain: "",
64 },
65 {
66 runtimeConfig: "flowcontrol.apiserver.k8s.io/v1beta3=false",
67 errShouldContain: "",
68 },
69 {
70 runtimeConfig: "flowcontrol.apiserver.k8s.io/v1beta3=true",
71 errShouldContain: "",
72 },
73 {
74 runtimeConfig: "flowcontrol.apiserver.k8s.io/v1=true",
75 errShouldContain: "",
76 },
77 {
78 runtimeConfig: "flowcontrol.apiserver.k8s.io/v1=false",
79 errShouldContain: conflict,
80 },
81 {
82 runtimeConfig: "flowcontrol.apiserver.k8s.io/v1beta3=true,flowcontrol.apiserver.k8s.io/v1=false",
83 errShouldContain: conflict,
84 },
85 }
86
87 for _, test := range tests {
88 t.Run(test.runtimeConfig, func(t *testing.T) {
89 options := &Options{
90 Features: &genericoptions.FeatureOptions{
91 EnablePriorityAndFairness: true,
92 },
93 APIEnablement: genericoptions.NewAPIEnablementOptions(),
94 }
95 options.APIEnablement.RuntimeConfig.Set(test.runtimeConfig)
96
97 var errMessageGot string
98 if errs := validateAPIPriorityAndFairness(options); len(errs) > 0 {
99 errMessageGot = errs[0].Error()
100 }
101
102 switch {
103 case len(test.errShouldContain) == 0:
104 if len(errMessageGot) > 0 {
105 t.Errorf("Expected no error, but got: %q", errMessageGot)
106 }
107 default:
108 if !strings.Contains(errMessageGot, test.errShouldContain) {
109 t.Errorf("Expected error message to contain: %q, but got: %q", test.errShouldContain, errMessageGot)
110 }
111 }
112 })
113 }
114 }
115
116 func TestValidateUnknownVersionInteroperabilityProxy(t *testing.T) {
117 tests := []struct {
118 name string
119 featureEnabled bool
120 errShouldContain string
121 peerCAFile string
122 peerAdvertiseAddress peerreconcilers.PeerAdvertiseAddress
123 }{
124 {
125 name: "feature disabled but peerCAFile set",
126 featureEnabled: false,
127 peerCAFile: "foo",
128 errShouldContain: "--peer-ca-file requires UnknownVersionInteroperabilityProxy feature to be turned on",
129 },
130 {
131 name: "feature disabled but peerAdvertiseIP set",
132 featureEnabled: false,
133 peerAdvertiseAddress: peerreconcilers.PeerAdvertiseAddress{PeerAdvertiseIP: "1.2.3.4"},
134 errShouldContain: "--peer-advertise-ip requires UnknownVersionInteroperabilityProxy feature to be turned on",
135 },
136 {
137 name: "feature disabled but peerAdvertisePort set",
138 featureEnabled: false,
139 peerAdvertiseAddress: peerreconcilers.PeerAdvertiseAddress{PeerAdvertisePort: "1"},
140 errShouldContain: "--peer-advertise-port requires UnknownVersionInteroperabilityProxy feature to be turned on",
141 },
142 }
143
144 for _, test := range tests {
145 t.Run(test.name, func(t *testing.T) {
146 options := &Options{
147 PeerCAFile: test.peerCAFile,
148 PeerAdvertiseAddress: test.peerAdvertiseAddress,
149 }
150 if test.featureEnabled {
151 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.UnknownVersionInteroperabilityProxy, true)()
152 }
153 var errMessageGot string
154 if errs := validateUnknownVersionInteroperabilityProxyFlags(options); len(errs) > 0 {
155 errMessageGot = errs[0].Error()
156 }
157 if !strings.Contains(errMessageGot, test.errShouldContain) {
158 t.Errorf("Expected error message to contain: %q, but got: %q", test.errShouldContain, errMessageGot)
159 }
160
161 })
162 }
163 }
164
165 func TestValidateUnknownVersionInteroperabilityProxyFeature(t *testing.T) {
166 const conflict = "UnknownVersionInteroperabilityProxy feature requires StorageVersionAPI feature flag to be enabled"
167 tests := []struct {
168 name string
169 featuresEnabled []featuregate.Feature
170 }{
171 {
172 name: "enabled: UnknownVersionInteroperabilityProxy, disabled: StorageVersionAPI",
173 featuresEnabled: []featuregate.Feature{features.UnknownVersionInteroperabilityProxy},
174 },
175 }
176
177 for _, test := range tests {
178 t.Run(test.name, func(t *testing.T) {
179 for _, feature := range test.featuresEnabled {
180 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, feature, true)()
181 }
182 var errMessageGot string
183 if errs := validateUnknownVersionInteroperabilityProxyFeature(); len(errs) > 0 {
184 errMessageGot = errs[0].Error()
185 }
186 if !strings.Contains(errMessageGot, conflict) {
187 t.Errorf("Expected error message to contain: %q, but got: %q", conflict, errMessageGot)
188 }
189 })
190 }
191 }
192
193 func TestValidateOptions(t *testing.T) {
194 testCases := []struct {
195 name string
196 options *Options
197 expectErrors bool
198 }{
199 {
200 name: "validate master count equal 0",
201 expectErrors: true,
202 options: &Options{
203 GenericServerRunOptions: &genericoptions.ServerRunOptions{},
204 Etcd: &genericoptions.EtcdOptions{},
205 SecureServing: &genericoptions.SecureServingOptionsWithLoopback{},
206 Audit: &genericoptions.AuditOptions{},
207 Admission: &kubeoptions.AdmissionOptions{
208 GenericAdmission: &genericoptions.AdmissionOptions{
209 EnablePlugins: []string{"foo"},
210 Plugins: kubeapiserveradmission.NewPlugins(),
211 },
212 PluginNames: []string{"foo"},
213 },
214 Authentication: &kubeoptions.BuiltInAuthenticationOptions{
215 APIAudiences: []string{"bar"},
216 ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
217 Issuers: []string{"baz"},
218 },
219 },
220 APIEnablement: genericoptions.NewAPIEnablementOptions(),
221 Metrics: &basemetrics.Options{},
222 ServiceAccountSigningKeyFile: "",
223 Features: &genericoptions.FeatureOptions{},
224 },
225 },
226 {
227 name: "validate token request enable not attempted",
228 expectErrors: true,
229 options: &Options{
230 GenericServerRunOptions: &genericoptions.ServerRunOptions{},
231 Etcd: &genericoptions.EtcdOptions{},
232 SecureServing: &genericoptions.SecureServingOptionsWithLoopback{},
233 Audit: &genericoptions.AuditOptions{},
234 Admission: &kubeoptions.AdmissionOptions{
235 GenericAdmission: &genericoptions.AdmissionOptions{
236 EnablePlugins: []string{""},
237 Plugins: kubeapiserveradmission.NewPlugins(),
238 },
239 PluginNames: []string{""},
240 },
241 Authentication: &kubeoptions.BuiltInAuthenticationOptions{
242 ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{},
243 },
244 APIEnablement: genericoptions.NewAPIEnablementOptions(),
245 Metrics: &basemetrics.Options{},
246 ServiceAccountSigningKeyFile: "",
247 Features: &genericoptions.FeatureOptions{},
248 },
249 },
250 }
251
252 for _, tc := range testCases {
253 t.Run(tc.name, func(t *testing.T) {
254 errs := tc.options.Validate()
255 if len(errs) > 0 && !tc.expectErrors {
256 t.Errorf("expected no errors, errors found %+v", errs)
257 }
258
259 if len(errs) == 0 && tc.expectErrors {
260 t.Errorf("expected errors, no errors found")
261 }
262 })
263 }
264 }
265
View as plain text