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
The following commit(s) were added to refs/heads/main by this push:
new 25479a76d Fix #6663: skip auto-inferred trait defaults in
.status.traits (#6667)
25479a76d is described below
commit 25479a76d3002677d616ba5ac75002f8c46fd6b4
Author: Davy <[email protected]>
AuthorDate: Wed Jun 10 23:05:29 2026 -0700
Fix #6663: skip auto-inferred trait defaults in .status.traits (#6667)
* fix(trait): stop auto-inferred defaults from leaking into .status.traits
Fixes #6663
---
pkg/trait/container.go | 17 +++++--
pkg/trait/container_test.go | 2 +-
pkg/trait/mount_test.go | 2 +-
pkg/trait/route_test.go | 4 +-
pkg/trait/security_context_test.go | 2 +-
pkg/trait/service.go | 5 +-
pkg/trait/service_test.go | 5 +-
pkg/trait/trait_test.go | 96 ++++++++++++++++++++++++++++++++++++++
8 files changed, 119 insertions(+), 14 deletions(-)
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 77fa58fdf..db817188e 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -66,6 +66,7 @@ type containerTrait struct {
traitv1.ContainerTrait `property:",squash"`
containerPorts []containerPort
+ expose *bool
}
// containerPort is supporting port parsing.
@@ -93,7 +94,7 @@ func (t *containerTrait) Configure(e *Environment) (bool,
*TraitCondition, error
if ptr.Deref(t.Auto, true) {
if t.Expose == nil {
if e.Resources.GetServiceForIntegration(e.Integration)
!= nil {
- t.Expose = new(true)
+ t.expose = new(true)
}
}
}
@@ -214,7 +215,7 @@ func (t *containerTrait) configureContainer(e *Environment)
error {
// Knative does not like anybody touching the container ports
t.configurePorts(&container)
}
- if knative || ptr.Deref(t.Expose, false) {
+ if knative || t.isExpose() {
t.configureService(e, &container, knative)
}
t.configureCapabilities(e)
@@ -356,9 +357,7 @@ func (t *containerTrait) setSecurityContext(e *Environment,
container *corev1.Co
return err
}
- t.RunAsUser = runAsUser
-
- sc.RunAsUser = t.RunAsUser
+ sc.RunAsUser = runAsUser
container.SecurityContext = &sc
return nil
@@ -386,6 +385,14 @@ func (t *containerTrait) getUser(e *Environment) (*int64,
error) {
return runAsUser, nil
}
+func (t *containerTrait) isExpose() bool {
+ if t.Expose != nil {
+ return *t.Expose
+ }
+
+ return ptr.Deref(t.expose, false)
+}
+
func (t *containerTrait) getPort() int32 {
if t.Port == 0 {
return defaultContainerPort
diff --git a/pkg/trait/container_test.go b/pkg/trait/container_test.go
index 7a5465ced..c90db6c6d 100644
--- a/pkg/trait/container_test.go
+++ b/pkg/trait/container_test.go
@@ -144,7 +144,7 @@ func TestContainerWithOpenshift(t *testing.T) {
conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
- assert.NotEmpty(t, traits)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
diff --git a/pkg/trait/mount_test.go b/pkg/trait/mount_test.go
index 55bc076b9..7753fd544 100644
--- a/pkg/trait/mount_test.go
+++ b/pkg/trait/mount_test.go
@@ -47,7 +47,7 @@ func TestMountVolumesEmpty(t *testing.T) {
conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
- assert.NotEmpty(t, traits)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("mount"))
diff --git a/pkg/trait/route_test.go b/pkg/trait/route_test.go
index 26590b9e3..4be9d133c 100644
--- a/pkg/trait/route_test.go
+++ b/pkg/trait/route_test.go
@@ -198,7 +198,7 @@ func TestRoute_Default(t *testing.T) {
conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
- assert.NotEmpty(t, traits)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("container"))
@@ -235,7 +235,7 @@ func TestRoute_Disabled(t *testing.T) {
traitsCatalog := environment.Catalog
conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
- assert.NotEmpty(t, traits)
+ assert.Empty(t, traits)
assert.Contains(t, conditions, expectedCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.Nil(t, environment.GetTrait("route"))
diff --git a/pkg/trait/security_context_test.go
b/pkg/trait/security_context_test.go
index bc3331d06..c70130be2 100644
--- a/pkg/trait/security_context_test.go
+++ b/pkg/trait/security_context_test.go
@@ -78,7 +78,7 @@ func TestDefaultPodOpenshiftSecurityContext(t *testing.T) {
conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
- assert.NotEmpty(t, traits)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
diff --git a/pkg/trait/service.go b/pkg/trait/service.go
index 6de61b7dc..336d5b957 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -86,6 +86,7 @@ func (t *serviceTrait) Configure(e *Environment) (bool,
*TraitCondition, error)
return false, nil, nil
}
+ enabled := ptr.Deref(t.Enabled, false)
if ptr.Deref(t.Auto, true) {
exposeHTTPServices, err := e.ConsumeMeta(false, func(meta
metadata.IntegrationMetadata) bool {
return meta.ExposesHTTPServices
@@ -103,7 +104,7 @@ func (t *serviceTrait) Configure(e *Environment) (bool,
*TraitCondition, error)
return false, condition, err
}
- t.Enabled = new(exposeHTTPServices)
+ enabled = exposeHTTPServices
}
servicePorts, err := t.parseServicePorts()
@@ -112,7 +113,7 @@ func (t *serviceTrait) Configure(e *Environment) (bool,
*TraitCondition, error)
}
t.servicePorts = servicePorts
- return ptr.Deref(t.Enabled, false) || len(t.servicePorts) > 0, nil, nil
+ return enabled || len(t.servicePorts) > 0, nil, nil
}
func (t *serviceTrait) Apply(e *Environment) error {
diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go
index 5afd3625b..74ad9b5e0 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/service_test.go
@@ -578,11 +578,11 @@ func
TestServiceWithKnativeServiceDisabledInIntegrationPlatform(t *testing.T) {
conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
- assert.NotEmpty(t, traits)
assert.Contains(t, conditions, expectedCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait(serviceTraitID))
assert.Nil(t, environment.GetTrait(knativeServiceTraitID))
+ assert.Nil(t, traits.Service)
}
func TestServiceAutoConfiguration(t *testing.T) {
@@ -633,7 +633,8 @@ func TestServiceAutoConfiguration(t *testing.T) {
}
_, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
- assert.Equal(t, ptr.To(true), traits.Service.Enabled)
+ assert.NotNil(t, environment.GetTrait(serviceTraitID))
+ assert.Nil(t, traits.Service)
}
func TestServiceAnnotationsAndLables(t *testing.T) {
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index 9fb4f7598..550f06f59 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -345,6 +345,102 @@ func TestDefaultIntegrationErrorTraitsSetting(t
*testing.T) {
testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseError)
}
+func TestAutoInferredServiceTraitsDoNotLeakIntoStatus(t *testing.T) {
+ it := &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-it",
+ Namespace: "ns",
+ },
+ Spec: v1.IntegrationSpec{
+ Sources: []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "file.java",
+ Content:
`from("servlet:http").to("log:info")`,
+ },
+ Language: v1.LanguageJavaSource,
+ },
+ },
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseRunning,
+ Conditions: []v1.IntegrationCondition{
+ {
+ Type:
v1.IntegrationConditionDeploymentAvailable,
+ Status: corev1.ConditionTrue,
+ },
+ },
+ },
+ }
+ // Load the default catalog
+ camelCatalogData, err :=
resources.Resource(fmt.Sprintf("/resources/camel-catalog-%s.yaml",
defaults.CamelKRuntimeCatalogVersion))
+ require.NoError(t, err)
+ var cat v1.CamelCatalog
+ err = yaml.Unmarshal(camelCatalogData, &cat)
+ require.NoError(t, err)
+ cat.Namespace = "default"
+ platform.SingletonPlatform.CatalogNamespace = cat.Namespace
+
+ client, err := internal.NewFakeClient(&cat)
+ require.NoError(t, err)
+ env, err := Apply(context.Background(), client, it, nil)
+ require.NoError(t, err)
+ require.NotNil(t, env.Resources.GetServiceForIntegration(it))
+ assert.Equal(t, &v1.Traits{}, env.Integration.Status.Traits)
+}
+
+func TestUserSpecifiedTraitValuesStillAppearInStatus(t *testing.T) {
+ it := &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-it",
+ Namespace: "ns",
+ },
+ Spec: v1.IntegrationSpec{
+ Sources: []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "file.java",
+ Content:
`from("servlet:http").to("log:info")`,
+ },
+ Language: v1.LanguageJavaSource,
+ },
+ },
+ Traits: v1.Traits{
+ Container: &traitv1.ContainerTrait{
+ Port: 9090,
+ },
+ },
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseRunning,
+ Conditions: []v1.IntegrationCondition{
+ {
+ Type:
v1.IntegrationConditionDeploymentAvailable,
+ Status: corev1.ConditionTrue,
+ },
+ },
+ },
+ }
+ camelCatalogData, err :=
resources.Resource(fmt.Sprintf("/resources/camel-catalog-%s.yaml",
defaults.CamelKRuntimeCatalogVersion))
+ require.NoError(t, err)
+ var cat v1.CamelCatalog
+ err = yaml.Unmarshal(camelCatalogData, &cat)
+ require.NoError(t, err)
+ cat.Namespace = "default"
+ platform.SingletonPlatform.CatalogNamespace = cat.Namespace
+
+ client, err := internal.NewFakeClient(&cat)
+ require.NoError(t, err)
+ env, err := Apply(context.Background(), client, it, nil)
+ require.NoError(t, err)
+ require.NotNil(t, env.Resources.GetServiceForIntegration(it))
+ assert.Equal(t, &v1.Traits{
+ Container: &traitv1.ContainerTrait{
+ Port: 9090,
+ },
+ }, env.Integration.Status.Traits)
+}
+
func TestIntegrationTraitsSetting(t *testing.T) {
it := &v1.Integration{
ObjectMeta: metav1.ObjectMeta{