This is an automated email from the ASF dual-hosted git repository.

pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit a54f806e0a8693953c0651bd586734c4337a299f
Author: Pranjul Kalsi <[email protected]>
AuthorDate: Sun Dec 14 14:02:52 2025 +0530

    feat(trait): Add KEDA auto-discovery for Camel component URIs
---
 docs/modules/ROOT/partials/apis/camel-k-crds.adoc  |  12 +-
 docs/modules/traits/pages/keda.adoc                |   9 +-
 .../files/keda-it-kafkatopic-to-log-auto.yaml      |  17 +++
 e2e/kafka/files/keda-kafka-auto-discovery.yaml     |  37 +++++
 e2e/kafka/kafka_autoscale_keda_test.go             |  25 ++++
 e2e/support/test_support.go                        |  18 +++
 helm/camel-k/crds/camel-k-crds.yaml                |  88 +++++++-----
 pkg/apis/camel/v1/trait/keda.go                    |   3 +
 pkg/apis/camel/v1/trait/zz_generated.deepcopy.go   |   5 +
 .../camel.apache.org_integrationplatforms.yaml     |  22 +--
 .../camel.apache.org_integrationprofiles.yaml      |  22 +--
 .../crd/bases/camel.apache.org_integrations.yaml   |  22 +--
 .../config/crd/bases/camel.apache.org_pipes.yaml   |  22 +--
 pkg/trait/keda.go                                  |  25 ++++
 pkg/trait/keda_mapping.go                          | 125 ++++++++++++++++
 pkg/trait/keda_mapping_test.go                     | 159 +++++++++++++++++++++
 pkg/trait/keda_test.go                             | 126 ++++++++++++++++
 17 files changed, 669 insertions(+), 68 deletions(-)

diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc 
b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index ef2d79834..ae0916c91 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -8066,14 +8066,22 @@ int32
 
 Maximum number of replicas.
 
-|`triggers` +
-*xref:#_camel_apache_org_v1_trait_KedaTrigger[[\]KedaTrigger]*
+|`auto` +
+bool
 |
 
 
 Definition of triggers according to the KEDA format. Each trigger must contain 
`type` field corresponding
 to the name of a KEDA autoscaler and a key/value map named `metadata` 
containing specific trigger options
 and optionally a mapping of secrets, used by Keda operator to poll resources 
according to the autoscaler type.
+Automatically discover KEDA triggers from Camel component URIs.
+
+|`triggers` +
+*xref:#_camel_apache_org_v1_trait_KedaTrigger[[\]KedaTrigger]*
+|
+
+
+
 
 
 |===
diff --git a/docs/modules/traits/pages/keda.adoc 
b/docs/modules/traits/pages/keda.adoc
index f10a1987a..dba237792 100644
--- a/docs/modules/traits/pages/keda.adoc
+++ b/docs/modules/traits/pages/keda.adoc
@@ -47,11 +47,16 @@ The following configuration options are available:
 | int32
 | Maximum number of replicas.
 
-| keda.triggers
-| []github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait.KedaTrigger
+| keda.auto
+| bool
 | Definition of triggers according to the KEDA format. Each trigger must 
contain `type` field corresponding
 to the name of a KEDA autoscaler and a key/value map named `metadata` 
containing specific trigger options
 and optionally a mapping of secrets, used by Keda operator to poll resources 
according to the autoscaler type.
+Automatically discover KEDA triggers from Camel component URIs.
+
+| keda.triggers
+| []github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait.KedaTrigger
+| 
 
 |===
 
diff --git a/e2e/kafka/files/keda-it-kafkatopic-to-log-auto.yaml 
b/e2e/kafka/files/keda-it-kafkatopic-to-log-auto.yaml
new file mode 100644
index 000000000..018c93ec0
--- /dev/null
+++ b/e2e/kafka/files/keda-it-kafkatopic-to-log-auto.yaml
@@ -0,0 +1,17 @@
+apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  name: keda-kafka-auto-discovery
+  namespace: kafka
+spec:
+  sources:
+    - content: |
+        
from("kafka:my-topic?brokers=my-cluster-kafka-bootstrap.kafka.svc:9092&groupId=auto-group")
+          .log("${body}");
+      name: routes.java
+  traits:
+    keda:
+      enabled: true
+      minReplicaCount: 0
+      maxReplicaCount: 1
+      # No triggers - auto-discovery should create kafka scaler
\ No newline at end of file
diff --git a/e2e/kafka/files/keda-kafka-auto-discovery.yaml 
b/e2e/kafka/files/keda-kafka-auto-discovery.yaml
new file mode 100644
index 000000000..62e3f5661
--- /dev/null
+++ b/e2e/kafka/files/keda-kafka-auto-discovery.yaml
@@ -0,0 +1,37 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+# This integration tests KEDA auto-discovery - no manual triggers are 
specified,
+# the trait should automatically discover the kafka component and create a 
trigger.
+apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  name: keda-kafka-auto-discovery
+  namespace: kafka
+spec:
+  sources:
+    - content: |
+        
from("kafka:my-topic?brokers=my-cluster-kafka-bootstrap.kafka.svc:9092&groupId=auto-group")
+          .log("${body}");
+      name: routes.java
+  traits:
+    keda:
+      enabled: true
+      minReplicaCount: 0
+      maxReplicaCount: 1
+      cooldownPeriod: 20
+      pollingInterval: 10
+      # No triggers specified - auto-discovery should create kafka scaler
diff --git a/e2e/kafka/kafka_autoscale_keda_test.go 
b/e2e/kafka/kafka_autoscale_keda_test.go
index 8beb38d47..58dca1365 100644
--- a/e2e/kafka/kafka_autoscale_keda_test.go
+++ b/e2e/kafka/kafka_autoscale_keda_test.go
@@ -73,3 +73,28 @@ func TestKafkaKedaAutoscale(t *testing.T) {
                })
        })
 }
+
+func TestKafkaKedaAutoDiscovery(t *testing.T) {
+       WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) {
+               t.Run("Auto-discovery Kafka", func(t *testing.T) {
+                       ExpectExecSucceed(t, g, Kubectl("apply", "-f", 
"files/keda-kafka-auto-discovery.yaml"))
+                       ns := "kafka"
+                       integrationName := "keda-kafka-auto-discovery"
+
+                       // Wait for ScaledObject
+                       g.Eventually(ScaledObject(t, ctx, ns, integrationName), 
TestTimeoutMedium).
+                               ShouldNot(BeNil())
+
+                       // Verify the auto-discovered
+                       scaledObj := ScaledObject(t, ctx, ns, integrationName)()
+                       g.Expect(scaledObj).NotTo(BeNil())
+                       g.Expect(scaledObj.Spec.Triggers).To(HaveLen(1))
+                       
g.Expect(scaledObj.Spec.Triggers[0].Type).To(Equal("kafka"))
+                       
g.Expect(scaledObj.Spec.Triggers[0].Metadata["topic"]).To(Equal("my-topic"))
+                       
g.Expect(scaledObj.Spec.Triggers[0].Metadata["bootstrapServers"]).To(Equal("my-cluster-kafka-bootstrap.kafka.svc:9092"))
+                       
g.Expect(scaledObj.Spec.Triggers[0].Metadata["consumerGroup"]).To(Equal("auto-group"))
+
+                       g.Expect(Kamel(t, ctx, "delete", integrationName, "-n", 
ns).Execute()).To(Succeed())
+               })
+       })
+}
diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index dbacf8cd9..021b6b44a 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -75,6 +75,7 @@ import (
        "github.com/apache/camel-k/v2/e2e/support/util"
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
        traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
+       kedav1alpha1 "github.com/apache/camel-k/v2/pkg/apis/duck/keda/v1alpha1"
        "github.com/apache/camel-k/v2/pkg/client"
        "github.com/apache/camel-k/v2/pkg/cmd"
        "github.com/apache/camel-k/v2/pkg/platform"
@@ -192,6 +193,7 @@ func init() {
        client.FastMapperAllowedAPIGroups["operators.coreos.com"] = true
        client.FastMapperAllowedAPIGroups["config.openshift.io"] = true
        client.FastMapperAllowedAPIGroups["policy"] = true
+       client.FastMapperAllowedAPIGroups["keda.sh"] = true
 
        var err error
 
@@ -3110,3 +3112,19 @@ func DefaultOperatorSecurityContext() 
*corev1.SecurityContext {
 
        return &sc
 }
+
+// ScaledObject retrieves a KEDA ScaledObject by name from a namespace.
+func ScaledObject(t *testing.T, ctx context.Context, ns, name string) func() 
*kedav1alpha1.ScaledObject {
+       return func() *kedav1alpha1.ScaledObject {
+               scaledObject := kedav1alpha1.ScaledObject{}
+               key := ctrl.ObjectKey{
+                       Namespace: ns,
+                       Name:      name,
+               }
+               if err := TestClient(t).Get(ctx, key, &scaledObject); err != 
nil {
+                       log.Error(err, "Error while retrieving ScaledObject 
"+name)
+                       return nil
+               }
+               return &scaledObject
+       }
+}
diff --git a/helm/camel-k/crds/camel-k-crds.yaml 
b/helm/camel-k/crds/camel-k-crds.yaml
index 2ceed0549..0ad56a8db 100644
--- a/helm/camel-k/crds/camel-k-crds.yaml
+++ b/helm/camel-k/crds/camel-k-crds.yaml
@@ -4807,6 +4807,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -4840,10 +4847,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -7216,6 +7219,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -7249,10 +7259,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -9527,6 +9533,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -9560,10 +9573,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -11815,6 +11824,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -11848,10 +11864,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -20937,6 +20949,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -20970,10 +20989,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -23179,6 +23194,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -23212,10 +23234,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -33663,6 +33681,13 @@ spec:
                       keda:
                         description: The configuration of Keda trait
                         properties:
+                          auto:
+                            description: |-
+                              Definition of triggers according to the KEDA 
format. Each trigger must contain `type` field corresponding
+                              to the name of a KEDA autoscaler and a key/value 
map named `metadata` containing specific trigger options
+                              and optionally a mapping of secrets, used by 
Keda operator to poll resources according to the autoscaler type.
+                              Automatically discover KEDA triggers from Camel 
component URIs.
+                            type: boolean
                           configuration:
                             description: |-
                               Legacy trait configuration parameters.
@@ -33697,10 +33722,6 @@ spec:
                             format: int32
                             type: integer
                           triggers:
-                            description: |-
-                              Definition of triggers according to the KEDA 
format. Each trigger must contain `type` field corresponding
-                              to the name of a KEDA autoscaler and a key/value 
map named `metadata` containing specific trigger options
-                              and optionally a mapping of secrets, used by 
Keda operator to poll resources according to the autoscaler type.
                             items:
                               properties:
                                 metadata:
@@ -35837,6 +35858,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -35870,10 +35898,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
diff --git a/pkg/apis/camel/v1/trait/keda.go b/pkg/apis/camel/v1/trait/keda.go
index e1bcb8335..2d92a9432 100644
--- a/pkg/apis/camel/v1/trait/keda.go
+++ b/pkg/apis/camel/v1/trait/keda.go
@@ -36,6 +36,9 @@ type KedaTrait struct {
        // Definition of triggers according to the KEDA format. Each trigger 
must contain `type` field corresponding
        // to the name of a KEDA autoscaler and a key/value map named 
`metadata` containing specific trigger options
        // and optionally a mapping of secrets, used by Keda operator to poll 
resources according to the autoscaler type.
+       // Automatically discover KEDA triggers from Camel component URIs.
+       // +kubebuilder:validation:Optional
+       Auto     *bool         `json:"auto,omitempty" property:"auto"`
        Triggers []KedaTrigger `json:"triggers,omitempty" property:"triggers"`
 }
 
diff --git a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go 
b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go
index 10bb5627b..c194c65e3 100644
--- a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go
@@ -731,6 +731,11 @@ func (in *KedaTrait) DeepCopyInto(out *KedaTrait) {
                *out = new(int32)
                **out = **in
        }
+       if in.Auto != nil {
+               in, out := &in.Auto, &out.Auto
+               *out = new(bool)
+               **out = **in
+       }
        if in.Triggers != nil {
                in, out := &in.Triggers, &out.Triggers
                *out = make([]KedaTrigger, len(*in))
diff --git 
a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
index 2a8131651..bb9b3ce73 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
@@ -1558,6 +1558,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -1591,10 +1598,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -3967,6 +3970,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -4000,10 +4010,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
diff --git 
a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
index 924a60f7c..b0770c973 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
@@ -1426,6 +1426,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -1459,10 +1466,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -3714,6 +3717,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -3747,10 +3757,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
index 097df5642..3b9a080fd 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
@@ -8240,6 +8240,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -8273,10 +8280,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
@@ -10482,6 +10485,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -10515,10 +10525,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
index 147c06e12..a9bc05167 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
@@ -8296,6 +8296,13 @@ spec:
                       keda:
                         description: The configuration of Keda trait
                         properties:
+                          auto:
+                            description: |-
+                              Definition of triggers according to the KEDA 
format. Each trigger must contain `type` field corresponding
+                              to the name of a KEDA autoscaler and a key/value 
map named `metadata` containing specific trigger options
+                              and optionally a mapping of secrets, used by 
Keda operator to poll resources according to the autoscaler type.
+                              Automatically discover KEDA triggers from Camel 
component URIs.
+                            type: boolean
                           configuration:
                             description: |-
                               Legacy trait configuration parameters.
@@ -8330,10 +8337,6 @@ spec:
                             format: int32
                             type: integer
                           triggers:
-                            description: |-
-                              Definition of triggers according to the KEDA 
format. Each trigger must contain `type` field corresponding
-                              to the name of a KEDA autoscaler and a key/value 
map named `metadata` containing specific trigger options
-                              and optionally a mapping of secrets, used by 
Keda operator to poll resources according to the autoscaler type.
                             items:
                               properties:
                                 metadata:
@@ -10470,6 +10473,13 @@ spec:
                   keda:
                     description: The configuration of Keda trait
                     properties:
+                      auto:
+                        description: |-
+                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
+                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
+                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
+                          Automatically discover KEDA triggers from Camel 
component URIs.
+                        type: boolean
                       configuration:
                         description: |-
                           Legacy trait configuration parameters.
@@ -10503,10 +10513,6 @@ spec:
                         format: int32
                         type: integer
                       triggers:
-                        description: |-
-                          Definition of triggers according to the KEDA format. 
Each trigger must contain `type` field corresponding
-                          to the name of a KEDA autoscaler and a key/value map 
named `metadata` containing specific trigger options
-                          and optionally a mapping of secrets, used by Keda 
operator to poll resources according to the autoscaler type.
                         items:
                           properties:
                             metadata:
diff --git a/pkg/trait/keda.go b/pkg/trait/keda.go
index 9e4d27b41..0eb438019 100644
--- a/pkg/trait/keda.go
+++ b/pkg/trait/keda.go
@@ -24,6 +24,7 @@ import (
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
        traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
        "github.com/apache/camel-k/v2/pkg/apis/duck/keda/v1alpha1"
+       "github.com/apache/camel-k/v2/pkg/metadata"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/utils/ptr"
@@ -49,6 +50,12 @@ func (t *kedaTrait) Configure(e *Environment) (bool, 
*TraitCondition, error) {
                return false, nil, nil
        }
 
+       if ptr.Deref(t.Auto, true) && len(t.Triggers) == 0 {
+               if err := t.autoDiscoverTriggers(e); err != nil {
+                       return false, nil, err
+               }
+       }
+
        return len(t.Triggers) > 0, nil, nil
 }
 
@@ -148,3 +155,21 @@ func (t *kedaTrait) getScaleTarget(it *v1.Integration) 
*corev1.ObjectReference {
                Name:       it.Name,
        }
 }
+
+// Auto-discover triggers if Auto is enabled (default) and no manual triggers 
specified
+func (t *kedaTrait) autoDiscoverTriggers(e *Environment) error {
+       meta, err := metadata.ExtractAll(e.CamelCatalog, 
e.Integration.AllSources())
+       if err != nil {
+               return err
+       }
+       for _, fromURI := range meta.FromURIs {
+               trigger, err := mapToKedaTrigger(fromURI)
+               if err != nil {
+                       return err
+               }
+               if trigger != nil {
+                       t.Triggers = append(t.Triggers, *trigger)
+               }
+       }
+       return nil
+}
diff --git a/pkg/trait/keda_mapping.go b/pkg/trait/keda_mapping.go
new file mode 100644
index 000000000..cc1c7ac0f
--- /dev/null
+++ b/pkg/trait/keda_mapping.go
@@ -0,0 +1,125 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package trait
+
+import (
+       "net/url"
+       "strings"
+
+       traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
+       "github.com/apache/camel-k/v2/pkg/util/uri"
+)
+
+type CamelToKedaMapping struct {
+       KedaScalerType string
+       // Maps Camel URI Param names to KEDA metadata keys.
+       ParameterMap map[string]string
+       // Params that are taken from URI path, (component:path?queryParams)
+       PathParamName string
+}
+
+// camelToKedaMappings maps Camel component URI parameters to KEDA scaler 
metadata.
+// Only components available in Camel-K catalog 
(pkg/resources/resources/camel-catalog-*.yaml)
+// that have corresponding KEDA scalers are included.
+var camelToKedaMappings = map[string]CamelToKedaMapping{
+       "kafka": {
+               KedaScalerType: "kafka",
+               PathParamName:  "topic",
+               ParameterMap: map[string]string{
+                       "brokers": "bootstrapServers",
+                       "groupId": "consumerGroup",
+               },
+       },
+       "aws2-sqs": {
+               KedaScalerType: "aws-sqs-queue",
+               PathParamName:  "queueURL",
+               ParameterMap: map[string]string{
+                       "region": "awsRegion",
+               },
+       },
+       "spring-rabbitmq": {
+               KedaScalerType: "rabbitmq",
+               PathParamName:  "",
+               ParameterMap: map[string]string{
+                       "queues":    "queueName",
+                       "addresses": "host",
+               },
+       },
+}
+
+// parseComponentURI extracts the component scheme, path value, and query 
parameters from a Camel URI.
+func parseComponentURI(rawURI string) (string, string, map[string]string, 
error) {
+       scheme := uri.GetComponent(rawURI)
+       if scheme == "" {
+               return "", "", nil, nil
+       }
+
+       params := make(map[string]string)
+
+       // extract path
+       remainder := strings.TrimPrefix(rawURI, scheme+":")
+       var pathValue string
+       if idx := strings.Index(remainder, "?"); idx >= 0 {
+               pathValue = remainder[:idx]
+               queryString := remainder[idx+1:]
+
+               values, parseErr := url.ParseQuery(queryString)
+               if parseErr != nil {
+                       return "", "", nil, parseErr
+               }
+               for k, v := range values {
+                       if len(v) > 0 {
+                               params[k] = v[0]
+                       }
+               }
+       } else {
+               pathValue = remainder
+       }
+
+       return scheme, pathValue, params, nil
+}
+
+// mapToKedaTrigger converts a Camel URI to a KEDA trigger if the component is 
supported.
+func mapToKedaTrigger(rawURI string) (*traitv1.KedaTrigger, error) {
+       scheme, pathValue, params, err := parseComponentURI(rawURI)
+       if err != nil {
+               return nil, err
+       }
+
+       mapping, found := camelToKedaMappings[scheme]
+       if scheme == "" || !found {
+               return nil, nil // no trigger for this URI
+       }
+
+       metadata := make(map[string]string)
+
+       if mapping.PathParamName != "" && pathValue != "" {
+               metadata[mapping.PathParamName] = pathValue
+       }
+
+       for camelParam, kedaParam := range mapping.ParameterMap {
+               if val, ok := params[camelParam]; ok {
+                       metadata[kedaParam] = val
+               }
+       }
+
+       return &traitv1.KedaTrigger{
+               Type:     mapping.KedaScalerType,
+               Metadata: metadata,
+       }, nil
+}
diff --git a/pkg/trait/keda_mapping_test.go b/pkg/trait/keda_mapping_test.go
new file mode 100644
index 000000000..b60956de5
--- /dev/null
+++ b/pkg/trait/keda_mapping_test.go
@@ -0,0 +1,159 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package trait
+
+import (
+       "testing"
+
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+)
+
+func TestParseComponentURI(t *testing.T) {
+       tests := []struct {
+               name      string
+               uri       string
+               scheme    string
+               pathValue string
+               params    map[string]string
+       }{
+               {
+                       name:      "kafka with params",
+                       uri:       
"kafka:orders?brokers=localhost:9092&groupId=myGroup",
+                       scheme:    "kafka",
+                       pathValue: "orders",
+                       params:    map[string]string{"brokers": 
"localhost:9092", "groupId": "myGroup"},
+               },
+               {
+                       name:      "aws2-sqs",
+                       uri:       "aws2-sqs:myQueue?region=us-east-1",
+                       scheme:    "aws2-sqs",
+                       pathValue: "myQueue",
+                       params:    map[string]string{"region": "us-east-1"},
+               },
+               {
+                       name:      "spring-rabbitmq",
+                       uri:       
"spring-rabbitmq:exchange?queues=myQueue&addresses=localhost:5672",
+                       scheme:    "spring-rabbitmq",
+                       pathValue: "exchange",
+                       params:    map[string]string{"queues": "myQueue", 
"addresses": "localhost:5672"},
+               },
+               {
+                       name:      "timer unsupported",
+                       uri:       "timer:tick?period=1000",
+                       scheme:    "timer",
+                       pathValue: "tick",
+                       params:    map[string]string{"period": "1000"},
+               },
+               {
+                       name:      "no query params",
+                       uri:       "direct:start",
+                       scheme:    "direct",
+                       pathValue: "start",
+                       params:    map[string]string{},
+               },
+               {
+                       name:      "empty uri",
+                       uri:       "",
+                       scheme:    "",
+                       pathValue: "",
+                       params:    nil,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       scheme, pathValue, params, err := 
parseComponentURI(tt.uri)
+                       require.NoError(t, err)
+                       assert.Equal(t, tt.scheme, scheme)
+                       assert.Equal(t, tt.pathValue, pathValue)
+                       assert.Equal(t, tt.params, params)
+               })
+       }
+}
+
+func TestMapToKedaTrigger(t *testing.T) {
+       tests := []struct {
+               name         string
+               uri          string
+               expectNil    bool
+               expectedType string
+               expectedMeta map[string]string
+       }{
+               {
+                       name:         "kafka trigger",
+                       uri:          
"kafka:orders?brokers=broker:9092&groupId=grp",
+                       expectNil:    false,
+                       expectedType: "kafka",
+                       expectedMeta: map[string]string{
+                               "topic":            "orders",
+                               "bootstrapServers": "broker:9092",
+                               "consumerGroup":    "grp",
+                       },
+               },
+               {
+                       name:         "aws2-sqs trigger",
+                       uri:          "aws2-sqs:myQueue?region=us-east-1",
+                       expectNil:    false,
+                       expectedType: "aws-sqs-queue",
+                       expectedMeta: map[string]string{
+                               "queueURL":  "myQueue",
+                               "awsRegion": "us-east-1",
+                       },
+               },
+               {
+                       name:         "spring-rabbitmq trigger",
+                       uri:          
"spring-rabbitmq:exchange?queues=myQueue&addresses=localhost:5672",
+                       expectNil:    false,
+                       expectedType: "rabbitmq",
+                       expectedMeta: map[string]string{
+                               "queueName": "myQueue",
+                               "host":      "localhost:5672",
+                       },
+               },
+               {
+                       name:      "timer no trigger",
+                       uri:       "timer:tick",
+                       expectNil: true,
+               },
+               {
+                       name:      "direct no trigger",
+                       uri:       "direct:start",
+                       expectNil: true,
+               },
+               {
+                       name:      "empty uri no trigger",
+                       uri:       "",
+                       expectNil: true,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       trigger, err := mapToKedaTrigger(tt.uri)
+                       require.NoError(t, err)
+                       if tt.expectNil {
+                               assert.Nil(t, trigger)
+                       } else {
+                               require.NotNil(t, trigger)
+                               assert.Equal(t, tt.expectedType, trigger.Type)
+                               assert.Equal(t, tt.expectedMeta, 
trigger.Metadata)
+                       }
+               })
+       }
+}
diff --git a/pkg/trait/keda_test.go b/pkg/trait/keda_test.go
index 20c57a6f9..5def6174c 100644
--- a/pkg/trait/keda_test.go
+++ b/pkg/trait/keda_test.go
@@ -58,6 +58,66 @@ func TestKeda(t *testing.T) {
        assert.Equal(t, "10", 
scaledObject.Spec.Triggers[0].Metadata["lagThreshold"])
 }
 
+func TestKedaAutoDiscovery(t *testing.T) {
+       tests := []struct {
+               name           string
+               source         string
+               expectedType   string
+               expectedParams map[string]string
+       }{
+               {
+                       name:         "kafka",
+                       source:       
`from("kafka:my-topic?brokers=my-broker:9092&groupId=my-group").log("${body}");`,
+                       expectedType: "kafka",
+                       expectedParams: map[string]string{
+                               "topic":            "my-topic",
+                               "bootstrapServers": "my-broker:9092",
+                               "consumerGroup":    "my-group",
+                       },
+               },
+               {
+                       name:         "aws2-sqs",
+                       source:       
`from("aws2-sqs:my-queue?region=us-east-1").log("${body}");`,
+                       expectedType: "aws-sqs-queue",
+                       expectedParams: map[string]string{
+                               "queueURL":  "my-queue",
+                               "awsRegion": "us-east-1",
+                       },
+               },
+               {
+                       name:         "spring-rabbitmq",
+                       source:       
`from("spring-rabbitmq:exchange?queues=my-queue&addresses=rabbit:5672").log("${body}");`,
+                       expectedType: "rabbitmq",
+                       expectedParams: map[string]string{
+                               "queueName": "my-queue",
+                               "host":      "rabbit:5672",
+                       },
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       environment := autoDiscoveryEnvWithSource(t, tt.source)
+                       environment.Platform.ResyncStatusFullConfig()
+                       traitCatalog := environment.Catalog
+
+                       _, _, err := traitCatalog.apply(&environment)
+
+                       require.NoError(t, err)
+                       assert.NotEmpty(t, environment.ExecutedTraits)
+                       assert.NotNil(t, environment.GetTrait("keda"))
+
+                       scaledObject := 
getKedaScaledObject(environment.Resources)
+                       require.NotNil(t, scaledObject)
+                       require.Len(t, scaledObject.Spec.Triggers, 1)
+                       assert.Equal(t, tt.expectedType, 
scaledObject.Spec.Triggers[0].Type)
+                       for k, v := range tt.expectedParams {
+                               assert.Equal(t, v, 
scaledObject.Spec.Triggers[0].Metadata[k], "metadata key %s mismatch", k)
+                       }
+               })
+       }
+}
+
 func TestKedaAuthentication(t *testing.T) {
        environment := nominalEnv(t)
        environment.Integration.Spec.Traits.Keda.Triggers[0].Secrets = 
[]*traitv1.KedaSecret{
@@ -208,3 +268,69 @@ func nominalEnv(t *testing.T) Environment {
                Resources:      kubernetes.NewCollection(),
        }
 }
+
+// autoDiscoveryEnvWithSource creates an environment with the given source but 
NO manual triggers.
+func autoDiscoveryEnvWithSource(t *testing.T, source string) Environment {
+       t.Helper()
+       catalog, err := camel.DefaultCatalog()
+       require.NoError(t, err)
+
+       client, _ := internal.NewFakeClient()
+       traitCatalog := NewCatalog(nil)
+
+       return Environment{
+               CamelCatalog: catalog,
+               Catalog:      traitCatalog,
+               Client:       client,
+               Integration: &v1.Integration{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Name:      "test",
+                               Namespace: "ns",
+                       },
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseDeploying,
+                       },
+                       Spec: v1.IntegrationSpec{
+                               Sources: []v1.SourceSpec{
+                                       {
+                                               DataSpec: v1.DataSpec{
+                                                       Name:        
"routes.java",
+                                                       Content:     source,
+                                                       Compression: false,
+                                               },
+                                               Language: v1.LanguageJavaSource,
+                                       },
+                               },
+                               Traits: v1.Traits{
+                                       Keda: &traitv1.KedaTrait{
+                                               Trait: traitv1.Trait{
+                                                       Enabled: ptr.To(true),
+                                               },
+                                               // No triggers - auto-discovery 
should kick in
+                                       },
+                               },
+                       },
+               },
+               IntegrationKit: &v1.IntegrationKit{
+                       Status: v1.IntegrationKitStatus{
+                               Phase: v1.IntegrationKitPhaseReady,
+                       },
+               },
+               Platform: &v1.IntegrationPlatform{
+                       Spec: v1.IntegrationPlatformSpec{
+                               Cluster: v1.IntegrationPlatformClusterOpenShift,
+                               Build: v1.IntegrationPlatformBuildSpec{
+                                       PublishStrategy: 
v1.IntegrationPlatformBuildPublishStrategyJib,
+                                       Registry:        
v1.RegistrySpec{Address: "registry"},
+                                       RuntimeVersion:  
catalog.Runtime.Version,
+                               },
+                       },
+                       Status: v1.IntegrationPlatformStatus{
+                               Phase: v1.IntegrationPlatformPhaseReady,
+                       },
+               },
+               EnvVars:        make([]corev1.EnvVar, 0),
+               ExecutedTraits: make([]Trait, 0),
+               Resources:      kubernetes.NewCollection(),
+       }
+}

Reply via email to