diff --git a/pkg/functions/function.go b/pkg/functions/function.go index 09d2506273..429128f53b 100644 --- a/pkg/functions/function.go +++ b/pkg/functions/function.go @@ -227,6 +227,12 @@ type DeploySpec struct { // Defaults to "knative" for backwards compatibility Deployer string `yaml:"deployer,omitempty" jsonschema:"enum=knative,enum=raw,enum=keda"` + // ClusterDomain specifies the cluster domain used for building internal service URLs. + // Defaults to "cluster.local" if not specified. + // This is particularly useful for KEDA deployments where the interceptor proxy + // service URL needs to match the cluster's actual domain configuration. + ClusterDomain string `yaml:"clusterDomain,omitempty"` + Subscriptions []KnativeSubscription `yaml:"subscriptions,omitempty"` } diff --git a/pkg/keda/deployer.go b/pkg/keda/deployer.go index 17300bfda1..f97be194d8 100644 --- a/pkg/keda/deployer.go +++ b/pkg/keda/deployer.go @@ -204,6 +204,14 @@ func (d *Deployer) interceptorBridgeServiceName(f fn.Function) string { } func (d *Deployer) interceptorBridgeService(f fn.Function, namespace string, deployment *v1.Deployment) *corev1.Service { + // Use configured cluster domain, default to "cluster.local" + clusterDomain := f.Deploy.ClusterDomain + if clusterDomain == "" { + clusterDomain = "cluster.local" + } + + externalName := fmt.Sprintf("keda-add-ons-http-interceptor-proxy.keda.svc.%s", clusterDomain) + return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: d.interceptorBridgeServiceName(f), @@ -220,7 +228,7 @@ func (d *Deployer) interceptorBridgeService(f fn.Function, namespace string, dep }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeExternalName, - ExternalName: "keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local", + ExternalName: externalName, }, } } diff --git a/pkg/keda/deployer_test.go b/pkg/keda/deployer_test.go new file mode 100644 index 0000000000..4e00bec296 --- /dev/null +++ b/pkg/keda/deployer_test.go @@ -0,0 +1,86 @@ +package keda + +import ( + "testing" + + v1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + fn "knative.dev/func/pkg/functions" +) + +func TestDeployer_interceptorBridgeService(t *testing.T) { + tests := []struct { + name string + function fn.Function + expectedExternalName string + }{ + { + name: "uses default cluster.local when ClusterDomain is empty", + function: fn.Function{ + Name: "test-func", + Deploy: fn.DeploySpec{ + ClusterDomain: "", + }, + }, + expectedExternalName: "keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local", + }, + { + name: "uses custom cluster domain when specified", + function: fn.Function{ + Name: "test-func", + Deploy: fn.DeploySpec{ + ClusterDomain: "custom.domain", + }, + }, + expectedExternalName: "keda-add-ons-http-interceptor-proxy.keda.svc.custom.domain", + }, + { + name: "uses cluster.local explicitly when specified", + function: fn.Function{ + Name: "test-func", + Deploy: fn.DeploySpec{ + ClusterDomain: "cluster.local", + }, + }, + expectedExternalName: "keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := NewDeployer() + deployment := &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: tt.function.Name, + UID: "test-uid", + }, + } + + service := d.interceptorBridgeService(tt.function, "test-namespace", deployment) + + if service.Spec.ExternalName != tt.expectedExternalName { + t.Errorf("interceptorBridgeService() ExternalName = %v, want %v", + service.Spec.ExternalName, tt.expectedExternalName) + } + + // Verify service name + expectedServiceName := d.interceptorBridgeServiceName(tt.function) + if service.Name != expectedServiceName { + t.Errorf("interceptorBridgeService() Name = %v, want %v", + service.Name, expectedServiceName) + } + + // Verify namespace + if service.Namespace != "test-namespace" { + t.Errorf("interceptorBridgeService() Namespace = %v, want %v", + service.Namespace, "test-namespace") + } + + // Verify service type + if service.Spec.Type != "ExternalName" { + t.Errorf("interceptorBridgeService() Type = %v, want %v", + service.Spec.Type, "ExternalName") + } + }) + } +}