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

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

commit f024bac42f80e5fb6a9333a418676dea5ab84d63
Author: Harsh Mehta <[email protected]>
AuthorDate: Tue Jun 16 12:54:55 2026 +0530

    feat(builder): add support for custom pipeline tasks and environment 
variable control
    
    Signed-off-by: Harsh Mehta <[email protected]>
---
 docs/modules/ROOT/pages/installation/builds.adoc |  4 +++
 docs/modules/traits/pages/builder.adoc           |  8 ++++-
 pkg/platform/env_platform.go                     |  8 +++++
 pkg/platform/env_platform_test.go                | 25 +++++++++++++++
 pkg/trait/builder.go                             | 19 ++++++-----
 pkg/trait/builder_test.go                        | 41 ++++++++++++++++++++++--
 6 files changed, 94 insertions(+), 11 deletions(-)

diff --git a/docs/modules/ROOT/pages/installation/builds.adoc 
b/docs/modules/ROOT/pages/installation/builds.adoc
index e8c3a0bd3..86d1d62b6 100644
--- a/docs/modules/ROOT/pages/installation/builds.adoc
+++ b/docs/modules/ROOT/pages/installation/builds.adoc
@@ -47,6 +47,10 @@ Here a quick resume of the parameters you can configure as 
environment variables
 | Maximum number of builds that can run concurrently.
 | `3` if build strategy is `routine`, `10` if `pod`
 
+| BUILDER_TASKS_ENABLED
+| Controls whether CR authors are permitted to inject custom pipeline tasks 
via the `builder.tasks` trait. Set to `false` to disable custom task injection 
for all integrations managed by this operator. When unset or set to any value 
other than `false`, custom tasks are allowed (default behavior).
+| `true`
+
 | BUILDER_NODE_SELECTOR_ALLOWED_LABELS
 | Comma-separated list of node-selector label keys that CR authors are 
permitted to set via the `builder.nodeSelector` trait. When unset or empty all 
keys are accepted. Unlisted keys are dropped and an info message is logged. 
Example: `kubernetes.io/hostname,topology.kubernetes.io/zone`.
 |
diff --git a/docs/modules/traits/pages/builder.adoc 
b/docs/modules/traits/pages/builder.adoc
index b4a820604..2778beffc 100755
--- a/docs/modules/traits/pages/builder.adoc
+++ b/docs/modules/traits/pages/builder.adoc
@@ -158,4 +158,10 @@ Node selectors can be specified when running an 
integration with the CLI:
 $ kamel run --trait builder.node-selector.'size'=large integration.yaml
 ----
 
-NOTE: Operators can restrict which node-selector label keys CR authors are 
permitted to use by setting the `BUILDER_NODE_SELECTOR_ALLOWED_LABELS` 
environment variable on the operator deployment to a comma-separated list of 
allowed keys (e.g. `kubernetes.io/hostname,topology.kubernetes.io/zone`). Any 
key not in the list is dropped and an info message is logged. When the variable 
is unset or empty, all keys are accepted (default behavior). See Camel K 
operator tuning documentation for details.
+NOTE: Operators can restrict which node-selector label keys CR authors are 
permitted to use by setting the `BUILDER_NODE_SELECTOR_ALLOWED_LABELS` 
environment variable on the operator deployment to a comma-separated list of 
allowed keys (e.g. `kubernetes.io/hostname,topology.kubernetes.io/zone`). Any 
key not in the list is dropped and an info message is logged. When the variable 
is unset or empty, all keys are accepted (default behavior). See 
xref:installation:builds.adoc#env-var-config[b [...]
+
+== Custom Pipeline Tasks
+
+The `builder.tasks` trait option lets CR authors inject arbitrary containers 
into the build pipeline (only when using the `pod` build strategy). Each task 
entry has the format `<name>;<image>;<command>[;<userID>]`.
+
+NOTE: Operators can disable custom task injection entirely by setting 
`BUILDER_TASKS_ENABLED=false` on the operator deployment. When disabled, any 
`builder.tasks` values provided by CR authors are silently ignored and an info 
message is logged. The default is `true` (tasks are allowed). See 
xref:installation:builds.adoc#env-var-config[build environment variables] for 
details.
diff --git a/pkg/platform/env_platform.go b/pkg/platform/env_platform.go
index ca2f596a8..04589b6bc 100644
--- a/pkg/platform/env_platform.go
+++ b/pkg/platform/env_platform.go
@@ -173,6 +173,14 @@ func publishStrategy() 
v1.IntegrationPlatformBuildPublishStrategy {
        return DefaultPublishStrategy
 }
 
+// BuilderTasksEnabled reports whether CR authors are permitted to inject 
custom pipeline tasks
+// via the builder.tasks trait. Controlled by the BUILDER_TASKS_ENABLED 
operator environment
+// variable (default true for backward compatibility). Set to "false" to 
prevent custom task
+// injection across all integrations managed by this operator.
+func BuilderTasksEnabled() bool {
+       return 
strings.ToLower(strings.TrimSpace(GetEnvOrDefault("BUILDER_TASKS_ENABLED", 
"true"))) != "false"
+}
+
 // BuilderNodeSelectorAllowList returns the list of node-selector keys that 
are allowed to be set
 // by the builder trait. When the list is empty 
(BUILDER_NODE_SELECTOR_ALLOWED_LABELS is unset or blank),
 // any key is permitted. When the list is non-empty only the listed keys are 
accepted; unlisted keys
diff --git a/pkg/platform/env_platform_test.go 
b/pkg/platform/env_platform_test.go
index 7710725be..0ea541518 100644
--- a/pkg/platform/env_platform_test.go
+++ b/pkg/platform/env_platform_test.go
@@ -168,3 +168,28 @@ func TestBuilderNodeSelectorAllowList_MultipleKeys(t 
*testing.T) {
        assert.Equal(t, []string{"kubernetes.io/hostname", 
"node-role.kubernetes.io/worker", "topology.kubernetes.io/zone"}, allowList)
 }
 
+func TestBuilderTasksEnabled_NotSet(t *testing.T) {
+       // env var not set – default is enabled
+       assert.True(t, BuilderTasksEnabled())
+}
+
+func TestBuilderTasksEnabled_True(t *testing.T) {
+       t.Setenv("BUILDER_TASKS_ENABLED", "true")
+       assert.True(t, BuilderTasksEnabled())
+}
+
+func TestBuilderTasksEnabled_False(t *testing.T) {
+       t.Setenv("BUILDER_TASKS_ENABLED", "false")
+       assert.False(t, BuilderTasksEnabled())
+}
+
+func TestBuilderTasksEnabled_FalseUpperCase(t *testing.T) {
+       t.Setenv("BUILDER_TASKS_ENABLED", "FALSE")
+       assert.False(t, BuilderTasksEnabled())
+}
+
+func TestBuilderTasksEnabled_Empty(t *testing.T) {
+       t.Setenv("BUILDER_TASKS_ENABLED", "")
+       // empty string is not "false" – treat as enabled
+       assert.True(t, BuilderTasksEnabled())
+}
diff --git a/pkg/trait/builder.go b/pkg/trait/builder.go
index d1eda3399..7353eb7b1 100644
--- a/pkg/trait/builder.go
+++ b/pkg/trait/builder.go
@@ -246,15 +246,18 @@ func (t *builderTrait) Apply(e *Environment) error {
 
        // Custom tasks
        if t.Tasks != nil {
-               ct, err := t.determineCustomTasks(e, builderTask, tasksConf)
-               if err != nil {
-                       return err
-               }
-               if ct == nil {
-                       return nil
+               if !platform.BuilderTasksEnabled() {
+                       t.L.Info("builder.tasks is disabled by operator 
configuration and will be ignored")
+               } else {
+                       ct, err := t.determineCustomTasks(e, builderTask, 
tasksConf)
+                       if err != nil {
+                               return err
+                       }
+                       if ct == nil {
+                               return nil
+                       }
+                       pipelineTasks = append(pipelineTasks, ct...)
                }
-
-               pipelineTasks = append(pipelineTasks, ct...)
        }
 
        // Packaging task
diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go
index 42b84861b..06555f116 100644
--- a/pkg/trait/builder_test.go
+++ b/pkg/trait/builder_test.go
@@ -652,8 +652,8 @@ func TestBuilderTraitOrderStrategy(t *testing.T) {
 func TestFilterNodeSelector_NoAllowList(t *testing.T) {
        bt := createNominalBuilderTraitTest()
        bt.NodeSelector = map[string]string{
-               "kubernetes.io/hostname":          "node-1",
-               "node-role.kubernetes.io/worker":  "true",
+               "kubernetes.io/hostname":         "node-1",
+               "node-role.kubernetes.io/worker": "true",
        }
 
        // env var not set – nil allow list means everything is allowed
@@ -753,3 +753,40 @@ func TestBuilderTraitNodeSelectorAppliedWithAllowList(t 
*testing.T) {
        assert.NotContains(t, ns, "node-role.kubernetes.io/worker")
 }
 
+// TestBuilderTraitTasksDisabledByOperator verifies that when 
BUILDER_TASKS_ENABLED=false the
+// custom tasks are not added to the pipeline even when the CR author sets 
builder.tasks.
+func TestBuilderTraitTasksDisabledByOperator(t *testing.T) {
+       t.Setenv("BUILDER_TASKS_ENABLED", "false")
+
+       env := createBuilderTestEnv(v1.BuildStrategyPod)
+       bt := createNominalBuilderTraitTest()
+       bt.Tasks = []string{"custom;alpine;echo hello"}
+
+       err := bt.Apply(env)
+       require.NoError(t, err)
+
+       // pipeline must contain only the builder task, no custom task appended
+       for _, task := range env.Pipeline {
+               assert.Nil(t, task.Custom, "custom task must not be present 
when builder.tasks is disabled")
+       }
+}
+
+// TestBuilderTraitTasksEnabledByDefault verifies that when 
BUILDER_TASKS_ENABLED is unset
+// custom tasks flow through normally.
+func TestBuilderTraitTasksEnabledByDefault(t *testing.T) {
+       env := createBuilderTestEnv(v1.BuildStrategyPod)
+       bt := createNominalBuilderTraitTest()
+       bt.Tasks = []string{"custom;alpine;echo hello"}
+
+       err := bt.Apply(env)
+       require.NoError(t, err)
+
+       found := false
+       for _, task := range env.Pipeline {
+               if task.Custom != nil && task.Custom.Name == "custom" {
+                       found = true
+                       break
+               }
+       }
+       assert.True(t, found, "custom task must be present when builder.tasks 
is enabled")
+}

Reply via email to