@@ -54,7 +54,7 @@ func newGatewayProxy() *v1alpha1.GatewayProxy {
5454 Provider : & v1alpha1.GatewayProxyProvider {
5555 Type : v1alpha1 .ProviderTypeControlPlane ,
5656 ControlPlane : & v1alpha1.ControlPlaneProvider {
57- Service : & v1alpha1.ProviderService {Name : "control-plane" },
57+ Service : & v1alpha1.ProviderService {Name : "control-plane" , Port : 9180 },
5858 Auth : v1alpha1.ControlPlaneAuth {
5959 Type : v1alpha1 .AuthTypeAdminKey ,
6060 AdminKey : & v1alpha1.AdminKeyAuth {
@@ -72,6 +72,41 @@ func newGatewayProxy() *v1alpha1.GatewayProxy {
7272 }
7373}
7474
75+ func newGatewayProxyWithEndpoints (name string , endpoints []string ) * v1alpha1.GatewayProxy {
76+ gp := newGatewayProxy ()
77+ gp .Name = name
78+ gp .Spec .Provider .ControlPlane .Service = nil
79+ gp .Spec .Provider .ControlPlane .Endpoints = endpoints
80+ return gp
81+ }
82+
83+ func setInlineAdminKey (gp * v1alpha1.GatewayProxy , value string ) {
84+ if gp == nil || gp .Spec .Provider == nil || gp .Spec .Provider .ControlPlane == nil {
85+ return
86+ }
87+ if gp .Spec .Provider .ControlPlane .Auth .AdminKey == nil {
88+ gp .Spec .Provider .ControlPlane .Auth .AdminKey = & v1alpha1.AdminKeyAuth {}
89+ }
90+ gp .Spec .Provider .ControlPlane .Auth .AdminKey .Value = value
91+ gp .Spec .Provider .ControlPlane .Auth .AdminKey .ValueFrom = nil
92+ }
93+
94+ func setSecretAdminKey (gp * v1alpha1.GatewayProxy , name , key string ) {
95+ if gp == nil || gp .Spec .Provider == nil || gp .Spec .Provider .ControlPlane == nil {
96+ return
97+ }
98+ if gp .Spec .Provider .ControlPlane .Auth .AdminKey == nil {
99+ gp .Spec .Provider .ControlPlane .Auth .AdminKey = & v1alpha1.AdminKeyAuth {}
100+ }
101+ gp .Spec .Provider .ControlPlane .Auth .AdminKey .Value = ""
102+ gp .Spec .Provider .ControlPlane .Auth .AdminKey .ValueFrom = & v1alpha1.AdminKeyValueFrom {
103+ SecretKeyRef : & v1alpha1.SecretKeySelector {
104+ Name : name ,
105+ Key : key ,
106+ },
107+ }
108+ }
109+
75110func TestGatewayProxyValidator_MissingService (t * testing.T ) {
76111 gp := newGatewayProxy ()
77112 gp .Spec .Provider .ControlPlane .Auth .AdminKey = nil
@@ -150,3 +185,179 @@ func TestGatewayProxyValidator_NoWarnings(t *testing.T) {
150185 require .NoError (t , err )
151186 require .Empty (t , warnings )
152187}
188+
189+ func TestGatewayProxyValidator_DetectsServiceConflict (t * testing.T ) {
190+ existing := newGatewayProxy ()
191+ existing .Name = "existing"
192+
193+ service := & corev1.Service {
194+ ObjectMeta : metav1.ObjectMeta {
195+ Name : "control-plane" ,
196+ Namespace : "default" ,
197+ },
198+ }
199+ secret := & corev1.Secret {
200+ ObjectMeta : metav1.ObjectMeta {
201+ Name : "admin-key" ,
202+ Namespace : "default" ,
203+ },
204+ Data : map [string ][]byte {
205+ "token" : []byte ("value" ),
206+ },
207+ }
208+
209+ validator := buildGatewayProxyValidator (t , existing , service , secret )
210+
211+ candidate := newGatewayProxy ()
212+ candidate .Name = "candidate"
213+
214+ warnings , err := validator .ValidateCreate (context .Background (), candidate )
215+ require .Error (t , err )
216+ require .Len (t , warnings , 0 )
217+ require .Contains (t , err .Error (), "gateway group conflict" )
218+ require .Contains (t , err .Error (), "Service default/control-plane port 9180" )
219+ require .Contains (t , err .Error (), "AdminKey secret default/admin-key key token" )
220+ }
221+
222+ func TestGatewayProxyValidator_DetectsEndpointConflict (t * testing.T ) {
223+ existing := newGatewayProxyWithEndpoints ("existing" , []string {"https://127.0.0.1:9443" , "https://10.0.0.1:9443" })
224+ secret := & corev1.Secret {
225+ ObjectMeta : metav1.ObjectMeta {
226+ Name : "admin-key" ,
227+ Namespace : "default" ,
228+ },
229+ Data : map [string ][]byte {
230+ "token" : []byte ("value" ),
231+ },
232+ }
233+ validator := buildGatewayProxyValidator (t , existing , secret )
234+
235+ candidate := newGatewayProxyWithEndpoints ("candidate" , []string {"https://10.0.0.1:9443" , "https://127.0.0.1:9443" })
236+
237+ warnings , err := validator .ValidateCreate (context .Background (), candidate )
238+ require .Error (t , err )
239+ require .Len (t , warnings , 0 )
240+ require .Contains (t , err .Error (), "gateway group conflict" )
241+ require .Contains (t , err .Error (), "endpoints [https://10.0.0.1:9443, https://127.0.0.1:9443]" )
242+ require .Contains (t , err .Error (), "AdminKey secret default/admin-key key token" )
243+ }
244+
245+ func TestGatewayProxyValidator_AllowsDistinctGatewayGroups (t * testing.T ) {
246+ existing := newGatewayProxyWithEndpoints ("existing" , []string {"https://127.0.0.1:9443" })
247+ secret := & corev1.Secret {
248+ ObjectMeta : metav1.ObjectMeta {
249+ Name : "admin-key" ,
250+ Namespace : "default" ,
251+ },
252+ Data : map [string ][]byte {
253+ "token" : []byte ("value" ),
254+ },
255+ }
256+ service := & corev1.Service {
257+ ObjectMeta : metav1.ObjectMeta {
258+ Name : "control-plane" ,
259+ Namespace : "default" ,
260+ },
261+ }
262+ validator := buildGatewayProxyValidator (t , existing , secret , service )
263+
264+ candidate := newGatewayProxy ()
265+ candidate .Name = "candidate"
266+ candidate .Spec .Provider .ControlPlane .Service = & v1alpha1.ProviderService {
267+ Name : "control-plane" ,
268+ Port : 9180 ,
269+ }
270+
271+ warnings , err := validator .ValidateCreate (context .Background (), candidate )
272+ require .NoError (t , err )
273+ require .Empty (t , warnings )
274+ }
275+
276+ func TestGatewayProxyValidator_AllowsServiceConflictWithDifferentAdminSecret (t * testing.T ) {
277+ existing := newGatewayProxy ()
278+ existing .Name = "existing"
279+
280+ candidate := newGatewayProxy ()
281+ candidate .Name = "candidate"
282+ setSecretAdminKey (candidate , "admin-key-alt" , "token" )
283+
284+ service := & corev1.Service {
285+ ObjectMeta : metav1.ObjectMeta {
286+ Name : "control-plane" ,
287+ Namespace : "default" ,
288+ },
289+ }
290+ existingSecret := & corev1.Secret {
291+ ObjectMeta : metav1.ObjectMeta {
292+ Name : "admin-key" ,
293+ Namespace : "default" ,
294+ },
295+ Data : map [string ][]byte {
296+ "token" : []byte ("value" ),
297+ },
298+ }
299+ altSecret := & corev1.Secret {
300+ ObjectMeta : metav1.ObjectMeta {
301+ Name : "admin-key-alt" ,
302+ Namespace : "default" ,
303+ },
304+ Data : map [string ][]byte {
305+ "token" : []byte ("value" ),
306+ },
307+ }
308+
309+ validator := buildGatewayProxyValidator (t , existing , service , existingSecret , altSecret )
310+
311+ warnings , err := validator .ValidateCreate (context .Background (), candidate )
312+ require .NoError (t , err )
313+ require .Empty (t , warnings )
314+ }
315+
316+ func TestGatewayProxyValidator_DetectsInlineAdminKeyConflict (t * testing.T ) {
317+ existing := newGatewayProxyWithEndpoints ("existing" , []string {"https://127.0.0.1:9443" , "https://10.0.0.1:9443" })
318+ setInlineAdminKey (existing , "inline-cred" )
319+
320+ candidate := newGatewayProxyWithEndpoints ("candidate" , []string {"https://10.0.0.1:9443" })
321+ setInlineAdminKey (candidate , "inline-cred" )
322+
323+ validator := buildGatewayProxyValidator (t , existing )
324+
325+ warnings , err := validator .ValidateCreate (context .Background (), candidate )
326+ require .Error (t , err )
327+ require .Len (t , warnings , 0 )
328+ require .Contains (t , err .Error (), "gateway group conflict" )
329+ require .Contains (t , err .Error (), "control plane endpoints [https://10.0.0.1:9443]" )
330+ require .Contains (t , err .Error (), "inline AdminKey value" )
331+ }
332+
333+ func TestGatewayProxyValidator_AllowsEndpointOverlapWithDifferentAdminKey (t * testing.T ) {
334+ existing := newGatewayProxyWithEndpoints ("existing" , []string {"https://127.0.0.1:9443" , "https://10.0.0.1:9443" })
335+
336+ candidate := newGatewayProxyWithEndpoints ("candidate" , []string {"https://10.0.0.1:9443" , "https://192.168.0.1:9443" })
337+ setSecretAdminKey (candidate , "admin-key-alt" , "token" )
338+
339+ existingSecret := & corev1.Secret {
340+ ObjectMeta : metav1.ObjectMeta {
341+ Name : "admin-key" ,
342+ Namespace : "default" ,
343+ },
344+ Data : map [string ][]byte {
345+ "token" : []byte ("value" ),
346+ },
347+ }
348+ altSecret := & corev1.Secret {
349+ ObjectMeta : metav1.ObjectMeta {
350+ Name : "admin-key-alt" ,
351+ Namespace : "default" ,
352+ },
353+ Data : map [string ][]byte {
354+ "token" : []byte ("value" ),
355+ },
356+ }
357+
358+ validator := buildGatewayProxyValidator (t , existing , existingSecret , altSecret )
359+
360+ warnings , err := validator .ValidateCreate (context .Background (), candidate )
361+ require .NoError (t , err )
362+ require .Empty (t , warnings )
363+ }
0 commit comments