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") +}
