@@ -15,6 +15,7 @@ import (
15
15
"strconv"
16
16
17
17
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
18
+ "github.com/redpanda-data/redpanda/src/go/k8s/pkg/utils"
18
19
corev1 "k8s.io/api/core/v1"
19
20
apierrors "k8s.io/apimachinery/pkg/api/errors"
20
21
"k8s.io/apimachinery/pkg/api/resource"
@@ -277,6 +278,12 @@ func (r *Cluster) validateAdminListeners() field.ErrorList {
277
278
r .Spec .Configuration .AdminAPI ,
278
279
"bootstrap loadbalancer not available for http admin api" ))
279
280
}
281
+ if externalAdmin != nil && externalAdmin .External .EndpointTemplate != "" {
282
+ allErrs = append (allErrs ,
283
+ field .Invalid (field .NewPath ("spec" ).Child ("configuration" ).Child ("adminApi" ),
284
+ r .Spec .Configuration .AdminAPI ,
285
+ "cannot provide an endpoint template for admin listener" ))
286
+ }
280
287
281
288
// for now only one listener can have TLS to be backward compatible with v1alpha1 API
282
289
foundListenerWithTLS := false
@@ -306,6 +313,7 @@ func (r *Cluster) validateKafkaListeners() field.ErrorList {
306
313
}
307
314
308
315
var external * KafkaAPI
316
+ var externalIdx int
309
317
for i , p := range r .Spec .Configuration .KafkaAPI {
310
318
if p .External .Enabled {
311
319
if external != nil {
@@ -315,6 +323,7 @@ func (r *Cluster) validateKafkaListeners() field.ErrorList {
315
323
"only one kafka api listener can be marked as external" ))
316
324
}
317
325
external = & r .Spec .Configuration .KafkaAPI [i ]
326
+ externalIdx = i
318
327
}
319
328
}
320
329
@@ -357,10 +366,36 @@ func (r *Cluster) validateKafkaListeners() field.ErrorList {
357
366
r .Spec .Configuration .KafkaAPI ,
358
367
"bootstrap port cannot be empty" ))
359
368
}
369
+ //nolint:dupl // not identical
370
+ if external != nil && external .External .EndpointTemplate != "" {
371
+ if external .External .Subdomain == "" {
372
+ allErrs = append (allErrs ,
373
+ field .Invalid (field .NewPath ("spec" ).Child ("configuration" ).Child ("kafkaApi" ).Index (externalIdx ).Child ("external" ),
374
+ external .External ,
375
+ "endpointTemplate can only be used in combination with subdomain" ))
376
+ }
377
+
378
+ err := checkValidEndpointTemplate (external .External .EndpointTemplate )
379
+ if err != nil {
380
+ log .Error (err , "Invalid endpoint template received" , "template" , external .External .EndpointTemplate )
381
+ allErrs = append (allErrs ,
382
+ field .Invalid (field .NewPath ("spec" ).Child ("configuration" ).Child ("kafkaApi" ).Index (externalIdx ).Child ("external" ).Child ("endpointTemplate" ),
383
+ external .External .EndpointTemplate ,
384
+ fmt .Sprintf ("template is invalid: %v" , err )))
385
+ }
386
+ }
360
387
361
388
return allErrs
362
389
}
363
390
391
+ func checkValidEndpointTemplate (tmpl string ) error {
392
+ // Using an example input to ensure that the template expression is allowed
393
+ data := utils .NewEndpointTemplateData (0 , "1.2.3.4" )
394
+ _ , err := utils .ComputeEndpoint (tmpl , data )
395
+ return err
396
+ }
397
+
398
+ //nolint:funlen,gocyclo // it's a sequence of checks
364
399
func (r * Cluster ) validatePandaproxyListeners () field.ErrorList {
365
400
var allErrs field.ErrorList
366
401
var proxyExternal * PandaproxyAPI
@@ -412,6 +447,25 @@ func (r *Cluster) validatePandaproxyListeners() field.ErrorList {
412
447
r .Spec .Configuration .PandaproxyAPI [i ],
413
448
"sudomain of external pandaproxy must be the same as kafka's" ))
414
449
}
450
+ //nolint:dupl // not identical
451
+ if kafkaExternal != nil && proxyExternal .External .EndpointTemplate != "" {
452
+ if proxyExternal .External .Subdomain == "" {
453
+ allErrs = append (allErrs ,
454
+ field .Invalid (field .NewPath ("spec" ).Child ("configuration" ).Child ("pandaproxyApi" ).Index (i ).Child ("external" ),
455
+ proxyExternal .External ,
456
+ "endpointTemplate can only be used in combination with subdomain" ))
457
+ }
458
+
459
+ err := checkValidEndpointTemplate (proxyExternal .External .EndpointTemplate )
460
+ if err != nil {
461
+ log .Error (err , "Invalid endpoint template received" , "template" , proxyExternal .External .EndpointTemplate )
462
+ allErrs = append (allErrs ,
463
+ field .Invalid (field .NewPath ("spec" ).Child ("configuration" ).Child ("pandaproxyApi" ).Index (i ).
464
+ Child ("external" ).Child ("endpointTemplate" ),
465
+ proxyExternal .External .EndpointTemplate ,
466
+ fmt .Sprintf ("template is invalid: %v" , err )))
467
+ }
468
+ }
415
469
}
416
470
417
471
// for now only one listener can have TLS to be backward compatible with v1alpha1 API
@@ -510,6 +564,13 @@ func (r *Cluster) validateSchemaRegistryListener() field.ErrorList {
510
564
r .Spec .Configuration .SchemaRegistry .External ,
511
565
"bootstrap loadbalancer not available for schema reigstry" ))
512
566
}
567
+ if schemaRegistry .External .EndpointTemplate != "" {
568
+ allErrs = append (allErrs ,
569
+ field .Invalid (field .NewPath ("spec" ).Child ("configuration" ).Child ("schemaRegistry" ).Child ("external" ).Child ("endpointTemplate" ),
570
+ r .Spec .Configuration .SchemaRegistry .External .EndpointTemplate ,
571
+ "cannot provide an endpoint template for schema registry" ))
572
+ }
573
+
513
574
return allErrs
514
575
}
515
576
0 commit comments