Summary
Each deployer's Deploy method (most visibly pkg/keda/deployer.go) re-implements a large block of validation that Function.Validate() already performs (ValidateScale, ValidateKafkaSecurity, scale bounds, trigger type/dup/combination checks). Ideally a deployer is a minimal executor and only validates what is genuinely deploy-specific (k8s resource-name limits, secret/volume path resolution).
Why the duplication exists today
Client.Deploy (pkg/functions/client.go:847) does not call Function.Validate() before invoking c.deployer.Deploy(...) — it only checks Built, Name, ValidateExpose, and ValidateSwitch. So on the library path (client.Deploy(ctx, f) with an in-memory function), the deployer's own preflight is the only validation that runs. Some callers invoke deployer.Deploy directly, bypassing Client.Deploy entirely.
As a result, the keda deployer's guards are currently load-bearing: removing them would let the library path silently create partial/broken resources (a raw Deployment with no scaler, a ScaledObject that can't connect to any broker, a resource name that overflows the 63-char DNS limit and fails server-side).
Only the CLI (cmd/deploy.go:316) and Tekton (pkg/pipelines/tekton/pipelines_provider.go:201) paths call Function.Validate() up front — so for those, the deployer re-validation truly is duplication.
Proposed fix
Introduce a single validation choke point: call Function.Validate() inside Client.Deploy (once), then thin all deployers (knative / raw / keda) down to the checks that Function.Validate does not cover:
- k8s resource-name / DNS-label length limits (
validateBridgeName, validateKafkaResourceNames)
- secret / TLS-path resolution against
f.Run.Volumes (validateKafkaTLSPaths)
- nil-client guards
This removes the duplication and closes the latent gap where library consumers of Client.Deploy skip validation entirely.
Scope / notes
Summary
Each deployer's
Deploymethod (most visiblypkg/keda/deployer.go) re-implements a large block of validation thatFunction.Validate()already performs (ValidateScale,ValidateKafkaSecurity, scale bounds, trigger type/dup/combination checks). Ideally a deployer is a minimal executor and only validates what is genuinely deploy-specific (k8s resource-name limits, secret/volume path resolution).Why the duplication exists today
Client.Deploy(pkg/functions/client.go:847) does not callFunction.Validate()before invokingc.deployer.Deploy(...)— it only checksBuilt,Name,ValidateExpose, andValidateSwitch. So on the library path (client.Deploy(ctx, f)with an in-memory function), the deployer's own preflight is the only validation that runs. Some callers invokedeployer.Deploydirectly, bypassingClient.Deployentirely.As a result, the keda deployer's guards are currently load-bearing: removing them would let the library path silently create partial/broken resources (a raw Deployment with no scaler, a ScaledObject that can't connect to any broker, a resource name that overflows the 63-char DNS limit and fails server-side).
Only the CLI (
cmd/deploy.go:316) and Tekton (pkg/pipelines/tekton/pipelines_provider.go:201) paths callFunction.Validate()up front — so for those, the deployer re-validation truly is duplication.Proposed fix
Introduce a single validation choke point: call
Function.Validate()insideClient.Deploy(once), then thin all deployers (knative / raw / keda) down to the checks thatFunction.Validatedoes not cover:validateBridgeName,validateKafkaResourceNames)f.Run.Volumes(validateKafkaTLSPaths)This removes the duplication and closes the latent gap where library consumers of
Client.Deployskip validation entirely.Scope / notes
deployer.Deploycallers (e.g.pkg/deployer/testing/integration_test_helper.go) — they rely on the deployer validating today, so they'd need to validate up front (or keep going throughClient.Deploy).